1. 程式人生 > 其它 >C++(繼承)

C++(繼承)

繼承

struct Person {
 int age;
 int sex;
 };

 struct Teacher {
 int age;
 int sex;
 int level;
 int classId;
 };

如上程式碼中可以看見,Teacher類Person類都存在著相同的2個成員agesex,那麼這就相當於重複編寫了,
我們可以通過繼承的方式避免這樣重複的編寫(當前類名稱:要繼承的類名稱):
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的順序,誰在前,誰就在記憶體分佈中的前面;不推薦使用多重繼承,這會增加程式的複雜度。