cpp——隐式转换——类类型

概述

#pragma pack(4)

class CAnimal
{
public:
    char name[3];
    short age;
    int color;
    char gender;
};

class CDog : public CAnimal
{
public:
    int hurt;
};

void mem_offset()
{
    CAnimal animal;
    CDog dog;
    
    cout << "-----animal-----" << endl;
    cout << "sizeof(animal) = " << sizeof(animal) << endl;
    cout << "name offset = " << (char*)animal.name - (char*)&animal << endl;
    cout << "age offset = " << (char*)&animal.age - (char*)&animal << endl;
    cout << "color offset = " << (char*)&animal.color - (char*)&animal << endl;
    cout << "gender offset = " << (char*)&animal.gender - (char*)&animal << endl;
    
    cout << "-----dog-----" << endl;
    cout << "sizeof(dog) = " << sizeof(dog) << endl;
    cout << "name offset = " << (char*)dog.name - (char*)&dog << endl;
    cout << "age offset = " << (char*)&dog.age - (char*)&dog << endl;
    cout << "color offset = " << (char*)&dog.color - (char*)&dog << endl;
    cout << "gender offset = " << (char*)&dog.gender - (char*)&dog << endl;
    cout << "hurt offset = " << (char*)&dog.hurt - (char*)&dog << endl;
}
output:
-----animal-----
sizeof(animal) = 16
name offset = 0
age offset = 4
color offset = 8
gender offset = 12
-----dog-----
sizeof(dog) = 20
name offset = 0
age offset = 4
color offset = 8
gender offset = 12
hurt offset = 16
分析:
  • 每个类会生成对应的c struct,c struct中的数据成员在内存中布局顺序与数据成员在类定义中的顺序一致
  • 子类的c struct在父类的c struct末尾添加自身的数据成员
类的这种内存布局确保了子类不会改变父类数据成员相对于父类struct首地址的offset,因此把子类指针赋值给父类指针是安全的,因为父类指针通过数据成员的offset能寻址到正确的内存空间

类隐式转换

子类指针隐式转换为父类指针是安全的,引用的本质是const对象,因此子类赋值给父类引用也是安全的
class CAnimal
{
public:
    CAnimal()
    {
        cout << "CAnimal()" << endl;
    }
    
    CAnimal(const CAnimal &other)
    {
        cout << "CAnimal(const CAnimal &other)" << endl;
    }
    
public:
    CAnimal& operator=(const CAnimal &other)
    {
        cout << "CAnimal operator=" << endl;
        return *this;
    }
    
public:
    void info()
    {
        cout << "CAnimal info()" << endl;
    }
};

class CDog : public CAnimal
{
public:
    CDog()
    {
        cout << "CDog()" << endl;
    }
    
    CDog(const CDog &other) : CAnimal(other)
    {
        cout << "CDog(const CDog &other)" << endl;
    }
    
public:
    CDog& operator=(const CDog &other)
    {
        CAnimal::operator=(other);
        cout << "CDog operator=" << endl;
        return *this;
    }
};

void class_convert()
{
    CDog dog;
    
    CAnimal* pAnimal = &dog;
    CAnimal* rAnimal = &dog;
    
    pAnimal->info();
    rAnimal->info();
    
    CAnimal animal = dog;
    animal = dog;
}
output:
CAnimal()
CDog()
CAnimal info()
CAnimal info()
CAnimal(const CAnimal &other)
CAnimal operator=
结论:
  • 子类对象初始化父类对象的本质是调用父类的复制构造函数
  • 子类对象赋值给父类对象的本质是调用父类的赋值操作符函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值