大家學了C++之后都知道C++是一種面向對象的語言,因此,面向對象程序設計的主要特征也是C++的主要特點,具體如下:
1.封裝性:所謂封裝性就是將一組數據與這組數據有關的操作集合組裝在一起,形成一個能動的實體,也就是對象。C++中通過建立類這個數據類型來支持封裝性。
2.繼承性:繼承性是指一個類具有另一個類的屬性和行為。這個類既具有另一個類的全部特征,又具有自身的獨有特征。C++中將其稱為派生類(或子類),而將其所繼承的類稱為基類(或父類)。
3.多態性:多態性是指不同的對象調用相同名稱的函數,并可導致完全不同的行為。C++中的多態性通過使用函數重載、模板和虛函數等概念來實現。
通過以上簡單的介紹,相信大家對C++的三大特性也有了簡單的了解,下面著重介紹一下關于繼承的一些小結。
(1)繼承分為單繼承、多繼承和菱形繼承:看下面的圖大家會一目了然的。


菱形繼承:
class B
{
public:
int data1;
};
class B1: public B
{
public:
int data2;
};
class B2: public B
{
public:
int data3;
};
class D:public B1, public B2
{
public:
int data4;
};有上述代碼分析可知:B1和B2都繼承了B,所以D中就有兩份B。這樣造成了main()函數在調用時不知道該調用哪一個B,即造成了二義性。同時也造成了數據冗余。如何解決這個問題呢?下面引入了虛繼承。
(2)虛繼承:
定義格式:
class 派生類名:virtual [繼承方式] 基類名
class B
{
public:
int data1;
};
class B1: virtual public B
{
public:
int data2;
};
class B2: virtual public B
{
public:
int data3;
};
class D:public B1, public B2
{
public:
int data4;
};通過在繼承時加上virtual構成虛基類解決了二義性和數據冗余問題。
(3)繼承的定義格式:
class 派生類名:[繼承方式] 基類名
{
派生類新增加的成員
};
繼承方式:a.公有繼承(public)
b.保護繼承 (protected)
c.私有繼承 (private)
注意:如果沒有指定派生方式,默認為私有繼承。
下面通過簡單的例子來建立派生類:
class Base//基類
{
public:
Base()
{
cout << "Base() " << this << endl;
}
~Base()
{
cout << "~Base()" << endl;
}
private:
int _pri;
protected:
int _pro;
public:
int _pub;
};
class Derive : public Base//派生類以公有繼承的方式繼承基類
{
public:
Derive()
{
cout << "Derive() " << this << endl;
}
~Derive()
{
cout << "~Derive()" << endl;
}
private:
int _dPri;
protected:
int _dPro;
public:
int _dPub;
};
int main()
{
cout<<sizeof(Base)<<endl;//12
cout<<sizeof(Derive)<<endl;//24 派生類的sizeof()大小等于(基類大小+派生類大?。? return 0;
}(4)繼承關系&訪問限定符
看下圖可以直觀的了解訪問限定符與繼承關系:


總結:
a.為了記憶方便,可以簡單的記作:基類中私有成員不可訪問,公有繼承不變,私有繼承私有,保護繼承保護。
b.派生類的對象只可訪問公有繼承方式下基類中的公有成員。派生類的派生類可以訪問公有繼承方式和保護繼承方式下基類中的公有成員和保護成員。
c.在實際運用中一般使用都是public繼承,極少場景下才會使用protetced/private繼承。
(5)派生類的默認成員函數
我們知道類的默認的六個成員函數有:構造函數、拷貝構造函數、析構函數、賦值運算符重載函數、取地址操作符重載函數、const修飾的取地址操作符重載函數。
在繼承關系里面,在派生類中如果沒有顯示定義這六個成員函數,編譯系統則會默認合成這六個默認的成員函數。
通過對以上例子的調試與分析,可以得出繼承關系中構造函數與析構函數分別的調用順序為:
構造函數調用順序:

析構函數調用順序:

(6)繼承體系中的作用域
a.在繼承體系中基類和派生類是兩個不同作用域。
b.子類和父類中有同名成員,子類成員將屏蔽父類對成員的直接訪問。(在子類成員函數中,可以使用 基類::基類成員 訪問)
c.注意在實際中在繼承體系里面最好不要定義同名的成員。
class Base
{
public:
int x;
void Show()
{
cout << "This is Base, x= " << x << endl;
}
};
class Derived :public Base
{
public:
int x;//同名數據成員
void Show()//同名成員函數
{
cout << "This is derived , x= " << x << endl;
}
};
int main()
{
Derived d;
d.x = 5;//使用同名覆蓋原則
d.Show();//使用同名覆蓋原則
d.Base::x = 67;//使用作用域運算符訪問基類成員
d.Base::Show();//使用作用域運算符訪問基類成員函數
}(7)繼承與轉換--賦值兼容規則--public繼承
a.子類對象可以賦值給父類對象(切割/切片)
b.父類對象不能賦值給子類對象
c.父類的指針/引用可以指向子類對象
d.子類的指針/引用不能指向父類對象(可以通過強制類型轉換完成)
(8)友元與繼承
友元關系不能繼承,也就是說基類友元不能訪問子類私有和保護成員。
若要訪問,在派生類中也加友元函數的聲明,這樣就可以訪問了。
(9)繼承與靜態成員
基類定義了static成員,則整個繼承體系里面只有一個這樣的成員。無論派生出多少個子類,都只有一個static成員實例。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。