1. 程式人生 > >cpp——隱式轉換——類型別

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=
結論:
  • 子類物件初始化父類物件的本質是呼叫父類的複製建構函式
  • 子類物件賦值給父類物件的本質是呼叫父類的賦值操作符函式