C++(繼承)
繼承
struct Person {
int age;
int sex;
};
struct Teacher {
int age;
int sex;
int level;
int classId;
};
如上程式碼中可以看見,Teacher類與Person類都存在著相同的2個成員age和sex,那麼這就相當於重複編寫了,
我們可以通過繼承的方式避免這樣重複的編寫(當前類名稱:要繼承的類名稱):
Teacher類繼承Person類
struct Teacher:Person {
int level;
int classId;
};
建立物件的對應反彙編程式碼如下,可以清晰的看見與我們正常的記憶體佈局是一樣的:
那麼繼承是什麼?這就很好理解了,繼承的本質就是資料複製,子類(派生類)繼承(複製)父類(基類)的
資料,在這裡Person父類(基類),Teacher為子類(派生類);繼承可以減少重複程式碼的編寫。
假設,子類中存在一個與父類中相同的成員會如何?
struct Person {
int age;
int sex;
};
struct Teacher:Person { // Inherit
int age;
int classId;
};
我們可以建立一個物件來看一下對應的寬度和反彙編程式碼:
void main() { Teacher t; t.age = 30; t.sex = 1; t.classId = 20; printf("%d", sizeof(t)); printf("%d", sizeof(t)); return; }
首先看下資料寬度,我們會發現是16,那也就是說這裡不管如何你只要繼承了,在編譯器中兩個成員還是會直接新增過來,Teacher的成員依然是4個「4成員*4資料寬度(int型別) = 16
再來看下反彙編程式碼:
之前我們已經看過了正常的記憶體佈局了,在這裡,很明顯,少了一個0x10位置的成員,那麼按照記憶體佈局應該是這樣的:
0x10 → Person.age
0x0C → Person.sex
0x08 → Teacher.age
0x04 → Teacher.classId
而在這裡建立物件編譯器使用的age成員預設就是當前類Teacher的成員;想要使用父類中的成員可以使用這種
方式(物件名.父類名稱::成員名稱
void main() {
Teacher t;
t.Person::age = 30; // Father
t.age = 30;
t.sex = 1;
t.classId = 20;
return;
}
我們可以多次繼承麼,或者說繼承僅僅侷限於子、父關係麼?如下程式碼,B繼承了A,C繼承了B,C是否只繼承了B的v和n?
struct A {
int x;
int y;
};
struct B:A {
int v;
int n;
};
struct C:B {
int p;
int o;
};
我們可以來列印一下C的資料寬度:
結果是24,那麼就說明C不僅僅繼承了B,還繼承了A;再換個說法就是,繼承的本質是資料的複製,那也就是說當複製完(繼承)後才是其本身,B的本身就是4個成員x、y、v、n。
除了這種方式以外,我們想實現同樣的效果可以使用多重繼承(當前類:繼承的類A, 繼承的類B):
struct A {
int x;
int y;
};
struct B {
int v;
int n;
};
struct C:A,B { // Multiple
int p;
int o;
};
但這種方式在很多面向物件語言中是不允許出現的,在C++中是可以使用的,其記憶體分佈也與第一種方式不一樣:
最後:繼承的類A和繼承的類B的順序,誰在前,誰就在記憶體分佈中的前面;不推薦使用多重繼承,這會增加程式的複雜度。