C++11&QT复习 (十)

Day7-4 基类与派生类之间的转换

一、问题回顾

  1. 继承的形式有哪些?
    • 三种继承方式的特点?
    • 派生类的生成过程?
    • 继承的局限?
  2. 派生类对象的创建和销毁的特点是什么?
  3. 多继承的问题有哪些?如何解决?

二、基类与派生类间的转换

1. 类型适应(Upcasting)

在这里插入图片描述
派生类对象可以适用于基类对象,即一个派生类的实例可以用基类的引用或指针来操作。C++ 允许以下转换:

  1. 赋值转换

    Base base;
    Derived derived;
    base = derived; // 允许,但发生对象切片
    

    注意:派生类特有的数据会被丢弃。

  2. 引用转换(推荐):

    Base& ref = derived; // 允许,ref 绑定到 derived 的基类部分
    
  3. 指针转换(推荐):

    Base* pBase = &derived; // 允许,pBase 指向 derived 的基类部分
    
2. 逆向转换(Downcasting)

基类对象不能直接转换为派生类对象,除非使用强制转换

Derived* pDerived = static_cast<Derived*>(&base); // 不安全!

原因:基类对象可能不包含派生类的数据,强制转换可能导致非法访问。

使用 dynamic_cast 在多态类中更安全:

Derived* pDerived = dynamic_cast<Derived*>(&base);
if (pDerived) {
   
    // 转换成功,pDerived 可用于 Derived 类型的操作
}

三、代码示例

#include <iostream>
using namespace std;

class Base {
   
public:
    Base(double base = 0.0) : _base(base) {
   
        cout << "Base(double base = 0.0)" << endl;
    }
    virtual ~Base() {
    cout << "~Base()" << endl; }
    void print() const {
    cout << "Base::_base = " << _base << endl; }
private:
    double _base;
};

class Derived : public Base {
   
public:
    Derived(double base = 0.0, double derived = 0.0) : Base(base), _derived(derived) {
   
        cout << "Derived(double = 0.0, double = 0.0)" << endl;
    }
    ~Derived() {
    cout << "~Derived()" << endl; }
    void show() const {
    cout << "Derived::_derived = " << _derived << endl; }
private:
    double _derived;
};

int main()
{
   
	Base base(11.11);
	base.print();

	Derived derived(22.22, 33.33);
	derived.show();

	cout << "派生类向基类转换";
	base = derived;//1.可以将派生类对象赋值给基类对象
	base.print();

	/*与用基类对象直接初始化不同(这时会发生对象切片),引用绑定不会拷贝对象,只是为派生类对象的基类部分创建了一个别名。*/
	Base& ref = derived;//2.基类的引用可以绑定到派生类对象
	ref.print();

	Base* pbase = &derived;//3.基类的指针可以指向派生类对象(向上转型)
	pbase->print();

	cout << " 基类向派生类转化" << endl;
	Base base1(100);
	Derived derived1(200, 300);
	//derived1 = base1;//error! 1.不能将基类对象赋值给派生类对象
	//等价转换的形式如下:ERROR!!!
	//Derived& operator=(const Derived & rhs);
	//derived1.operator=(base1);//不存在用户定义的从 "Base" 到 "const Derived" 的适当转换
	//const Derived& rhs = base1;

	//Derived& dref = base1; //error! 2.派生类的引用不能绑定到基类对象
	//Derived* pref = &base1;//error! 3.派生类的指针不能指向基类对象,只指向Base基类的前8个字节,后面的指针操纵了非法内存,有内存越界的风险

	//语法层面不支持向下转型 基类-->派生类 ,使用强制转换(本质上是不安全的)
	Derived* pderived1 = static_cast<Derived*>(&base1) ;

	//间接的表明了pderived2指向pderived1(可以认为是安全的)
	Derived* pderived2 = static_cast<Derived*>(&base1);

	test();
	return 0;
}

输出示例

Base(double base = 0.0)
Derived(double = 0.0, double = 0.0)
Base::_base = 22.22
Base::_base = 22.22
~Derived()
~Base()

四、派生类间的复制控制

在继承体系中,复制控制

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值