深度揭秘C++面向對象編程中繼承的核心概念
一.繼承
1.繼承與面向對象
我們知道C語言是面向過程的編程語言,C++在C語言的基礎上進化出了面向對象的模型。而繼承就是面向對象的重要屬性。繼承使得我們在一個基礎屬性上能夠加以拓展,用來描述很多具有相同基本屬性又各有不同的事務。
2.繼承方式訪問權限
繼承方式與訪問權限相同都有三種:public、private、protected繼承,再結合基類的三種訪問權限,在派生類中就有九種不同的情況,可以總結為:基類為私有的成員在派生類一律不可見,其余權限按照與繼承方式相比較小的來。
3.切片(賦值轉換)
在實際應用場景中我們常用基類代表幾種事務共同的基本屬性,派生類用來代表自己獨特的屬性,這就會導致派生類對象一定是包含父類對象的,所以子類對象可以賦給父類對象/指針/引用,過程會將子類中獨特屬性的成員切出,剩余賦給父類對象,所以稱為切片,不僅如此基類的指針可以通過強制類型轉換賦值給派生類的指針,代碼演示如下:
class Person
{
protected:
string _name;
string _sex;
int _age;
};
class Student : public Person
{
public:
int _No;
};
void Test()
{
Student sobj;
// 子類對象可以賦值給父類對象/指針/引用
Person pobj = sobj;
Person* pp = &sobj;
Person& rp = sobj;
// 基類的指針可以通過強制類型轉換賦值給派生類的指針
pp = &sobj;
Student * ps1 = (Student*)pp; // 這種情況轉換時可以的。
ps1->_No = 10;
pp = &pobj;
Student* ps2 = (Student*)pp; // 這種情況轉換時雖然可以,但是會存在越界訪問的問
ps2->_No = 10;
}
int main()
{
Test();
return 0;
}4.作用域
如果在基類和派生類定義了同名函數(shù)就會構成隱藏/重定義,子類成員將屏蔽父類對同名成員的直接訪問,如下所示;
class A
{
public:
A(int num = 0)
:_num(num)
{}
void func()
{
cout << _num << endl;
}
private:
int _num;
};
class B : public A
{
public:
B(int val = 1)
:_val(val)
{}
void func()
{
cout << _val<< endl;
}
private:
int _val;
};
int main()
{
B b;
b.func();
b.A::func();
return 0;
}5.默認成員函數(shù)
繼承這里遵循著一個規(guī)則:構造先父后子,析構先子后父。因為派生類中一定包含基類的對象所以派生類的構造函數(shù)必須調用基類的構造函數(shù)初始化基類的那一部分成員,如果基類沒有默認的構造函數(shù)(無參、全缺省、編譯器默認生成),則必須在派生類構造函數(shù)的初始化列表階段顯示調用。
派生類的拷貝構造函數(shù)必須調用基類的拷貝構造完成基類的拷貝初始化。
派生類的operator=必須要調用基類的operator=完成基類的復制。
基類的析構函數(shù)調用后會自動調用基類的析構函數(shù),不能在派生類顯示調用不然無法保證析構先子后父的順序。
6.友元與靜態(tài)函數(shù)
友元關系不會繼承,靜態(tài)函數(shù)不會多次實例化。
7.解決菱形繼承的二義性與數(shù)據(jù)冗余
菱形繼承是多繼承的一種特殊情況,我們在編寫代碼時應要避免菱形繼承:

如上圖所示就是一個菱形繼承,這樣會導致A類中會有兩份P類中的成員,這樣不僅會浪費空間,而且會產(chǎn)生二義性,如果我通過A對象訪問P中的成員,因為A類中有兩份P中的成員所有會有歧義。為了解決此問題,出現(xiàn)了虛擬繼承。如下圖所示:

那虛繼承是如何完成的呢:在d類中建立虛基表,將原來冗余的對象放在d對象空間最下面,B、C原來存儲A的位置存儲當前位置與空間最下面A對象的偏移量,保證指定B或者C對象訪問_a時都能訪問到。
8.繼承與組合
與繼承相比組合的耦合度更低,更適合我們使用!繼承又稱為白箱復用,組合稱為黑盒復用,因為使用組合的話是無法看到類內部的設計。

到此這篇關于深度揭秘C++面向對象編程中繼承的核心概念的文章就介紹到這了,更多相關C++繼承內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++17文件系統(tǒng)庫之std::filesystem 示例詳解
std::filesystem是C++17引入的一個強大且易用的文件系統(tǒng)操作庫,它提供了跨平臺的文件系統(tǒng)操作接口,簡化了文件和目錄操作的代碼實現(xiàn),本文給大家介紹C++17文件系統(tǒng)庫之std::filesystem 示例詳解,感興趣的朋友一起看看吧2025-03-03
C++實現(xiàn)十進制數(shù)轉換為二進制數(shù)的數(shù)學算法
這篇文章和大家分享一下我個人對十進制數(shù)轉換為二進制數(shù)的想法,目前暫時更新只整數(shù)十進制的轉換,后續(xù)會更新帶有小數(shù)的進制轉換,代碼使用c++實現(xiàn)2021-09-09

