C++-類與對象(2)-繼承 繼承 一個小引子 有些類之間存在特殊的關係,像下麵的圖一樣: 定義這些類時,下級的成員除了有向上一級類的共性,還有自己的特性,這時,就可以用繼承的技術,減少代碼的重覆 繼承的基本語法 class 子類 : 繼承方式 父類 子類:也叫派生類 父類:也叫基類 #includ ...
C++-類與對象(2)-繼承
繼承
一個小引子
有些類之間存在特殊的關係,像下麵的圖一樣:
定義這些類時,下級的成員除了有向上一級類的共性,還有自己的特性,這時,就可以用繼承的技術,減少代碼的重覆
繼承的基本語法
class 子類 : 繼承方式 父類
- 子類:也叫派生類
- 父類:也叫基類
#include<iostream>
using namespace std;
//普通頁面實現
//java頁面
//class Java{
//public:
// void header(){
// cout << "首頁,登錄,註冊(公共頭部)" << endl;
// }
//
// void footer(){
// cout << "幫助中心,站內地圖(公共底部)" << endl;
// }
//
// void lefter(){
// cout << "C++,Java,Phthon(公共分類列表)" << endl;
// }
//
// void conter(){
// cout << "Java學科的視頻" << endl;
// }
//};
//class Python{
//public:
// ...和前面一樣
// void conter(){
// cout << "Python學科的視頻" << endl;
// }
//};
//class Cpp{
//public:
// ...和前面一樣
// void conter(){
// cout << "C++學科的視頻" << endl;
// }
//};
//繼承實現頁面
//公共頁面類
class BagePage{
public:
void header(){
cout << "首頁,登錄,註冊(公共頭部)" << endl;
}
void footer(){
cout << "幫助中心,站內地圖(公共底部)" << endl;
}
void lefter(){
cout << "C++,Java,Phthon(公共分類列表)" << endl;
}
};
//Java頁面
class Java:public BagePage{
public:
void conter(){
cout << "Java學科的視頻" << endl;
}
};
//Python頁面
class Python:public BagePage{
public:
void conter(){
cout << "Python學科的視頻" << endl;
}
};
//Cpp頁面
class Cpp:public BagePage{
public:
void conter(){
cout << "C++學科的視頻" << endl;
}
};
void test01(){
cout << "Java界面下載" << endl;
Java ja;
ja.header();
ja.lefter();
ja.footer();
ja.conter();
cout << "=========================" << endl;
cout << "Python界面下載" << endl;
Python py;
py.header();
py.lefter();
py.footer();
py.conter();
cout << "=========================" << endl;
cout << "C++界面下載" << endl;
Cpp cpp;
cpp.header();
cpp.lefter();
cpp.footer();
cpp.conter();
}
int main(){
test01();
return 0;
}
兩次結果均是
子類中包含兩大成員:1是自己增加的成員(共性) 2.是從父類中繼承的過來的(共性)
繼承方式
繼承一共3種方式
- 公共繼承
- 保護繼承
- 私有繼承
繼承中的對象模型
從父類繼承到子類的成員,那些屬於子類的對象中
父類中非靜態的成員屬性都會被子類繼承下去(私有屬性只是被編譯器隱藏了)
#include<iostream>
using namespace std;
class Base{
public:
int m_a;
protected:
int m_b;
private:
int m_c;
};
class Son:public Base{
public:
int m_d;
};
void test01(){
cout << "size of Son is " << sizeof(Son) << endl;
}
int main(){
test01();
return 0;
}
查看對象模型
利用開發人員命令提示工具
- 跳轉盤符
- 跳轉文件路徑 cd 具體路徑
- 查看:cl /dl reportSlingleClassLayout類名 文件名(回車)
繼承中構造和析構順序
構造:先父類後子類
析構:先子類後父類
繼承中同名成員處理 方式
當我們的子類和父類出現同名的成員,如何通過子類對象來訪問到子類或父類中同名的數據呢
- 訪問子類同名成員:直接訪問即可
- 訪問父類同名成員:需要加作用域
同名的成員屬性
#include<iostream>
using namespace std;
//父類:m_a = 100
//子類:m_a = 200
class Base{//父類
public:
int m_a;
Base(){
m_a = 100;
}
};
class Son:public Base{//子類
public:
int m_a;
Son(){
m_a = 200;
}
};
void test01(){
Son s;
/*=====================================================*/
cout << "子類的m_a:"<< s.m_a << endl;//直接訪問
cout << "父類的m_a:" << s.Base::m_a << endl;//添加父類的作用域
/*=====================================================*/
}
int main(){
test01();
return 0;
}
同名的成員函數
如果出現同名的情況,子類中的同名函數會隱藏掉父類中所有的同名函數(包括重載函數)
#include<iostream>
using namespace std;
class Base{
public:
int m_a;
Base(){
m_a = 100;
}
void func(){
cout << "父類的m_a:" << m_a << endl;
}
};
class Son:public Base{
public:
int m_a;
Son(){
m_a = 200;
}
void func(){
cout << "子類的m_a:" << m_a << endl;
}
};
void test02(){
Son s;
/*=====================================================*/
s.func();
s.Base::func();
/*=====================================================*/
}
int main(){
test02();
return 0;
}
小總結
- 子類對象可以直接訪問子類中同名的成員
- 子類加作用域可以訪問父類中的成員
- 如果出現同名的情況,子類中的同名函數會隱藏掉父類中所有的同名函數
繼承中同名靜態處理方法
和上面是一樣的哦...
- 訪問子類同名成員:直接訪問即可
- 訪問父類同名成員:需要加作用域
我就不寫嘍(嘿嘿)
emmm,複習一下訪問方法
//成員
Son s;
//通過對象訪問
cout << "子類的m_a:"<< s.m_a << endl;//直接訪問
cout << "父類的m_a:" << s.Base::m_a << endl;//添加父類的作用域
//通過類名來訪問
cout << Son::m_a << endl;
cout << Son::Base::m_a << endl;
//函數
Son s;
s.func();
s.Base::func();
Son::func();
Son::Base::func();
多繼承語法
C++可以一個類繼承多個類(一個兒子認多個父親...)
多繼承更會觸發同名的問題,要註意加作用域區分
實際開發不建議使用(經典白學)
語法
class 類名:繼承方式1 父類1,繼承方式2 父類2...
例子
#include<iostream>
using namespace std;
//父類1是100
//父類2是200
//子類是300
class Base1{//父類1
public:
int m_a;
Base1(){
m_a = 100;
}
};
class Base2{//父類2
public:
int m_a;
Base2(){
m_a = 200;
}
};
class Son:public Base1,public Base2{//子類
public:
int m_a;
Son(){
m_a = 300;
}
};
void test01(){
Son s;
cout << "子類的m_a:" << s.m_a << endl;
cout << "父類1的m_a:" << s.Base1::m_a << endl;
cout << "父類2的m_a:" << s.Base2::m_a << endl;
}
int main(){
test01();
return 0;
}
菱形繼承
概念
-
兩個派生類繼承同一基類
-
又有某個類同時繼承兩個派生類
這樣就叫做菱形繼承啦,或是叫做鑽石繼承
但是會出現一些問題:
- 若有同名數據,要加作用域區分
- 子類相同數據可能會有多份,既浪費,又沒用(用虛繼承來解決,關鍵字:virtual)
例子
沒有虛繼承:
#include<iostream>
using namespace std;
class Base{//虛基類
public:
int m_age;
};
class Son1: public Base{};
class Son2: public Base{};
class GrandSon:public Son1,public Son2{};
void test01(){
GrandSon gs;
gs.Son1::m_age = 18;
gs.Son2::m_age = 28;
cout << "Son1的年齡" <<gs.Son1::m_age << endl;
cout << "Son2的年齡" <<gs.Son2::m_age << endl;
//但是GrandSon的年齡只要一個就好了,但現在有兩份
//利用虛繼承解決:
//繼承前加關鍵字
cout << gs.m_age;
}
int main(){
test01();
return 0;
}
加上虛繼承
class Son1:virtual public Base{};
class Son2:virtual public Base{};
void test01(){
...
cout << gs.m_age;
}