目錄
- 普通繼承關系的菱形繼承如下
- 虛基類
- 虛繼承
- 利用虛繼承解決,儲存多份不同成員變量的問題
普通繼承關系的菱形繼承如下
基類Person被public繼承以後會生成2份成員變量,再給孫子類的會儲存,代碼如下,通過代碼能看到,孫子類的FarmerWorker的 3個age的記憶體位址不同,這個不是我們想要的結果.我們想要的結果是基類Person裡面的成員變量age在子類和孫子類中都隻儲存一份.
#include <iostream>
using namespace::std;
class Person{
public:
int age;
};
class Farmer:public Person{
public:
void farm(){
cout<< "農民種地"<<endl;
}
};
class Worker:public Person{
public:
void work() {
cout<< "勞工工作"<<endl;
}
};
class FarmerWorker:public Farmer, public Worker {
//農名工繼承Farmer和worker,同僚擁有2個類的方法
public:
int age;
void hardWork(){
cout <<"農名工努力工作"<<endl;
}
};
int main(int argc, const char * argv[]) {
FarmerWorker fw = FarmerWorker();
fw.Farmer::age = 10;//2個父類都有同名的成員age,通過命名空間區分.這個不是我們想要的結果,因為這個age都是從Person繼承過來的.希望隻得到一份age,而不是2份.解決方法是把Worker和Farmer都虛繼承 Person,看後面的代碼
fw.Worker::age = 11;
fw.age = 12;
cout<< &fw.age <<endl; //普通的菱形繼承,基類産生的成員變量被2個子類繼承以後,到孫子類再繼承,變成了不同的成員變量
cout<< &fw.Farmer::age <<endl;
cout<< &fw.Worker::age <<endl;
cout << sizeof(fw) <<endl;
}
虛基類
繼承關鍵字前面添加 virtual 就是虛繼承 ,被虛繼承的類,叫虛基類,例如下圖Person被2個類虛繼承, Person就是虛基類
虛繼承
用virtual 關鍵字修飾的繼承方式是虛繼承,繼承原理如下面圖和代碼所示.繼承的成員變量隻儲存一份,而不是被儲存多份.生成虛表
利用虛繼承解決,儲存多份不同成員變量的問題
先不要管圖中虛表的問題,隻看2個子類Farmer和Worker通過virtual關鍵字繼承以後變成了虛繼承,這樣,記憶體空間中隻儲存了一份age成員變量,到了孫子類的繼承也是隻有一份age.這個就能解決我們要的,隻儲存一份基類成員變量的問題.
上面圖的代碼如下,代碼證明到孫子類的FarmerWorker裡面的3個age位址相同,隻儲存了一份age,問題解決.
#include <iostream>
using namespace::std;
class Person{ //虛基類,因為被2個類虛繼承
public:
int age;
// int age2;
// int age3;
void show(){
cout << "Person::show()"<<endl;
}
};
class Farmer: virtual public Person{
public:
int money;
void farm(){
cout<< "農民種地"<<endl;
}
};
class Worker: virtual public Person{ //virtual關鍵字 虛繼承,被繼承的基類,成員變量隻儲存一份,放在記憶體最後
public:
int Id;
void work() {
cout<< "勞工工作"<<endl;
}
};
class FarmerWorker:public Farmer, public Worker {
//農名工繼承Farmer和worker,同僚擁有2個類的方法
public:
void hardWork(){
cout <<"農名工努力工作"<<endl;
}
};
int main(int argc, const char * argv[]) {
FarmerWorker fw = FarmerWorker();
fw.age = 10;
fw.Farmer::age = 20;
fw.Worker::age = 30;
cout<< "fw.age=" <<fw.age<<endl;
cout<< "fw.Farmer::age=" <<fw.Farmer::age<<endl;
cout<< "fw.Worker::age=" <<fw.Worker::age<<endl;
cout << &fw.age << endl <<&fw.Farmer::age <<endl<< &fw.Worker::age<<endl;
//虛繼承以後3個age位址都是一樣的,因為成員變量age是從虛基類裡面繼承過來的,隻生成了一份
/*
fw中的的記憶體中布局如下
Farmer的虛表位址
Farmer的money
Worker的虛表
Worker的Id
Person的age 4
*/
cout << sizeof(fw) <<endl;
}