概念
定義類時,代碼中有共性的成員,還有自己的屬性,使用繼承可以減少重復的代碼,
繼承的語法
class 子類:繼承方式 父類
繼承方式有:public,private,protected
公共繼承:父類的公有成員到子類也是公有的,父類的保護成員在子類是受保護的
保護繼承:父類中共有的權限內容和保護權限內容,在子類都變為保護權限
私有繼承:父類中公有和保護權限內容,在子類都變為私有權限
其中,父類的私有成員,子類不管哪種繼承方式都無法訪問。
繼承中的對象模型
父類中所有的非靜態成員屬性,子類都會繼承,私有成員也會繼承,只是私有成員被編譯器隱藏了。
繼承中構造和析構順序
#include <iostream>
using namespace std;
class Base
{
public:Base(){cout << "父類構造函數" << endl;}~Base(){cout << "父類析構函數" << endl;}
};
class son :public Base
{
public:son(){cout << "子類構造函數" << endl;}~son(){cout << "子類析構函數" << endl;}
};
int main()
{son s;
}
繼承中的構造順序是,先構造父類,再構造子類,析構則相反,因為創建子類對象的時候,會先創建父類對象,然后繼承。
繼承同名成員的處理方式
當子類和父類出現同名的成員時,如果需要訪問子類,可以直接訪問,如果需要訪問父類,需要加作用域。
#include <iostream>
using namespace std;
class Base
{
public:int m_a;Base(){m_a = 10;}~Base(){}
};
class son :public Base
{
public:int m_a;son(){m_a = 20;}~son(){}
};
int main()
{son s;cout << s.m_a << endl;//20cout << s.Base::m_a << endl;//10
}
繼承中同名成員函數的處理方式
思想和同名成員函數處理方式相同,但需要注意的是,子類的同名函數會隱藏父類中所有的同名函數,解決方法就是加作用域。
#include <iostream>
using namespace std;
class Base
{
public:int m_a;Base(){m_a = 10;}void func(){cout << "父類函數的調用" << endl;}~Base(){}
};
class son :public Base
{
public:int m_a;son(){m_a = 20;}void func(){cout << "子類函數的調用" << endl;}~son(){}
};
int main()
{son s;s.func();//直接調用是子類的函數s.Base::func();//加作用域后就是調用父類的函數
}
繼承中同名靜態成員的處理方式
靜態成員變量的特點是:所有對象共享同一份數據,編譯階段就分配內存,類內聲明,類外初始化。
靜態成員定義的語法:
static int a;
靜態成員函數的特點是:只能訪問靜態成員變量,不能訪問非靜態成員變量,也是只有一份,所有對象共享一份函數實例。
靜態成員和非靜態成員出現同名時,處理方式一致,訪問子類直接訪問,訪問父類需要加上作用域,因為靜態成員不屬于對象上,因此也可以通過類名直接訪問,靜態成員屬性。
靜態成員函數處理方式一致,也可以通過類名方式訪問,子類也會隱藏父類同名函數,需要訪問被隱藏的父類同名函數,需要加上作用域。
靜態成員和非靜態成員處理方式是一樣的,只是靜態成員可以通過對象和類名訪問。
多繼承
語法:
class 子類:繼承方式 父類1,繼承方式 父類2......
子類中如果有多個同名成員,需要加作用域區分。(實際開發中很少使用)