C++基础13-类和对象之继承2
總結:
1、子類對象可以當做父類對象使用
2、子類對象可以直接賦值給父類對象
3、子類對象能夠直接初始化父類對象
4、父類指針可以直接指向子類對象
5、凡是繼承過來的屬性和函數都可以在子類中用this->? 進行訪問
6、默認構造函數并不會初始化數據成員
7、如果子類數據成員和父類數據成員名稱相同。在子類用利用:: 訪問父類數據成員,this-> 默認為子類數據成員
8、構造函數和析構函數不會被繼承
一、類型兼容性規則
類型兼容規則是指在需要基類對象的任何地方,都可以使用公有派生類的對象來替代。通過公有繼承,派生類得到了基類中除構造函數、析構函數之外的所有成員。這樣,公有派生類實際就具備了基類的所有功能,凡是基類能解決的問題,公有派生類都可以解決。
類型兼容規則中所指的替代包括以下情況:
???????????? <1>子類對象可以當作父類對象使用
???????????? <2>子類對象可以直接賦值給父類對象
???????????? <3>子類對象可以直接初始化父類對象
???????????? <4>父類指針可以直接指向子類對象
???????????? <5>父類引用可以直接引用子類對象
繼承模型:
在子類對象構造時,需要調用父類構造函數對其繼承得來的成員進行初始化.
在子類對象析構時,需要調用父類析構函數對其繼承得來的成員進行清理.
二、繼承中構造析構調用原則
??????? 1、子類對象在創建時會首先調用父類的構造函數
??????? 2、父類構造函數執行結束后,執行子類的構造函數
??????? 3、當父類的構造函數有參數時,需要在子類的初始化列表中顯示調用
??????? 4、析構函數調用的先后順序與構造函數相反
總原則:
????????????????????? 先構造父類,再構造成員變量、最后構造自己
????????????????????? 先析構自己,在析構成員變量、最后析構父類
三、繼承中同名成員變量處理方法
1、當子類成員變量與父類成員變量同名時 ,子類依然從父類繼承同名成員
2、在子類中通過作用域分辨符::進行同名成員區分(在派生類中使用基類的同名成員,顯式地使用類名限定符)
注:同名成員存儲在內存中的不同位置
四、派生類中的static關鍵字
1、基類定義的靜態成員,將被所有派生類共享
2、根據靜態成員自身的訪問特性和派生類的繼承方式,在類層次體系中具有不同的訪問性質 (遵守派生類的訪問控制)
3、 派生類中訪問靜態成員,用以下形式顯式說明:
????????????????????????????????? ? ? 類名 :: 成員
?????? 或通過對象訪問????? 對象名 . 成員
示例:
1、類的兼容性規則
#if 1 #include<iostream> using namespace std;class Parent { public:void printP() {cout << "a:" << this->a << endl;}int a; }; class Child :public Parent { public:/*void printP() {cout << "b:" << this->b << endl;}*/void printC() {cout << "b:" << this->b << endl;}int b; }; void test01() {Parent *p = new Child;p->printP(); //子類和父類都有printP函數時,調用父類的成員函數 } //子類對象可以當做父類對象使用 //子類對象可以直接賦值給父類對象 //子類對象能夠直接初始化父類對象 void test02() {Parent p; //父類空間小//Child c = p; //子類空間大于父類,不能夠全部初始化,所以報錯Child c;Parent p = c; //c對象占用空間>=p對象占用空間 //能夠填充可以通過編譯//子類對象能夠直接初始化父類對象c.printP(); //c能夠當做父類p來使用} //父類指針可以直接指向子類對象 //好處: void test03() {Parent *pp = NULL; //父類指針Child *cp = NULL; //子類指針Parent p; //父類對象Child c; //子類對象cp = &c;//cp = &p; 子類指針指向父類對象 錯誤 子類指針訪問范圍大于父類對象的范圍//原來cp的訪問權限為cp->a,cp->b,cp->printP.cp->printC//cp指向p時,cp的訪問權限只能為cp->a,cp->printP//會訪問越界pp = &p;pp = &c; //通過編譯 父類指針指向子類對象//原來cp的訪問權限為pp->a; pp->printP//pp指向c時,cp的訪問權限扔為pp->a; pp->printP//c內存布局能夠滿足父類指針的全部需求 可以用一個兒子的對象地址給父類指針賦值} int main() {return 0; } #endif2、構造函數和析構函數
#if 0 #include<iostream> using namespace std; //在調用子類的構造函數時 一定會調用父類的構造函數 //父類先構造,子類再構造 //析構和構造順序相反 class Parent { public:Parent() {cout << "Parent()... " << endl;a = 0;}Parent(int a) {cout << "Parent(int a)..." << endl;this->a = a;}int a;~Parent() {cout << "~Parent()..." << endl;} }; class Child :public Parent { public://在調用子類的構造函數時 編譯器會默認調用父類無參構造 #if 0Child(int a,int b) {cout << "Child(int a,int b)..." << endl;this->a = a;this->b = b;} #endif//顯示調用父類有參構造Child(int a ,int b):Parent(a){cout << "Child(int a,int b)..." << endl;this->b = b;}~Child() {cout << "~Child()... " << endl;}void printC() {cout << "b=" << b << endl;}int b; };//在調用子類時 編譯器會默認調用父類無參構造 void test01() {Child c(10, 20);c.printC(); } /* Parent()... Child(int a,int b)... b=20 ~Child()... ~Parent()... */ //顯示調用父類有參構造 void test02() {Child c(10, 20);c.printC(); } /* Parent(int a)... Child(int a,int b)... b=20 ~Child()... ~Parent()... */ int main() {test01();return 0; } #endif3、子類和父類成員重名
#if 0 #include<iostream> using namespace std; #if 0 class Parent { public:Parent() {cout << "Parent() " << endl;this->a = 0;}Parent(int a) {cout << "Parent(int a) " << endl;this->a = a;}~Parent() {cout << "析構父類a:" << this->a << endl;}int a; }; class Child :public Parent { public:int a;Child(int a) {cout << "Child(int a)" << endl;this->a = a;}~Child() {cout << "析構子類a:" << this->a << endl;} };void test01() {Child c(2); } /* Parent() Child(int a) 析構子類a:2 析構父類a:0 */ #endif #if 0 class Parent { public:Parent(int a) {cout << "Parent(int a) " << endl;this->a = a;}~Parent() {cout << "析構父類a:" << this->a << endl;}int a; }; class Child :public Parent { public:int a;Child(int p_a,int c_a):Parent(p_a){cout << "Child(int a)" << endl;this->a = c_a;}~Child() {cout << "析構子類a:" << this->a << endl;}void print() {cout << "父類a:"<<Parent::a << endl;cout <<"子類a:" <<this->a << endl; //子類的a} };void test01() {Child c(2,3);c.print(); } /* Parent(int a) Child(int a) 父類a:2 子類a:3 析構子類a:3 析構父類a:2 */ #endif //子類和父類函數名相同調用 class Parent { public:Parent(int a) {cout << "Parent(int a) " << endl;this->a = a;}void print() {cout << "父類print" << endl;}~Parent() {cout << "析構父類a:" << this->a << endl;}int a; }; class Child :public Parent { public:int a;Child(int p_a, int c_a) :Parent(p_a) {cout << "Child(int a)" << endl;this->a = c_a;}~Child() {cout << "析構子類a:" << this->a << endl;}void print() {cout << "子類print" << endl; //子類的a} };void test01() {Parent p(1);p.print();cout << "------" << endl;Child c(2, 3);c.Parent::print();c.print(); } /* Parent(int a) 父類print ------ Parent(int a) Child(int a) 父類print 子類print 析構子類a:3 析構父類a:2 析構父類a:1 */ int main() {test01();return 0; } #endif4、繼承中的static成員
#if 1 #include<iostream> using namespace std; #if 0 class A { public:static int a; private: }; int A::a = 0; //靜態成員變量 初始化void test01() {A a1;A a2;cout << a1.a << endl;cout << a2.a << endl;a1.a = 300;cout << a1.a << endl;cout << a2.a << endl; } /* 0 0 300 300 */ #endifclass A { public:static int a; private: }; class B :public A { public: private: }; int A::a = 0; //靜態成員變量 初始化void test01() {A a1;A a2;cout << a1.a << endl;cout << a2.a << endl;a1.a = 300;cout << a1.a << endl;cout << a2.a << endl;B b1;B b2;cout << b1.a << endl;cout << b2.a << endl;A::a = 400;cout << b1.a << endl;cout << b2.a << endl; } /* 0 0 300 300 300 300 400 400 */ int main() {test01();return 0; } #endif?
總結
以上是生活随笔為你收集整理的C++基础13-类和对象之继承2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python-类与文件读取结合
- 下一篇: C++基础11-类和对象之操作符重载1