一、繼承:ide
經過繼承定義一個類,它們的類型之間的關係建模,共享共有的東西,實現各自本質不一樣的東西。函數
C++的「繼承」特性能夠提升程序的可複用性。ui
繼承定義格式:this
二、類的大小:spa
class Base3d
{指針
public:orm
Base(int data)對象
{blog
cout << data << endl;
cout << "Base()" << this << endl;
}
~Base()
{
cout << "~Base()" << endl;
}
private:
int _pri;
protected:
int _pro;
public:
int _pub;
};
//求類大小時,只求數據成員的大小三個int類型的數據成員,因此大小爲12
class Base1
{
public:
Base1(int data)
{
cout << "Base1()" << endl;
}
~Base1()
{
cout << "~Base1()" << endl;
}
};
//當類沒有數據成員時,一般系統都會給一個值爲1的空間,由於類的大小不可能爲0,可是系統又要給類分配空間,爲了節省空間,會分配最小空間
class Test
{
public:
Test(int data)
{
cout << "Test()" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
};
class Derive :public Base, public Base1
{
public:
Derive()
:d(10)
, Base1(10)
, Base(20)
{
cout << "Derive()" << this << endl;
}
~Derive()
{
cout << "~Derive()" << endl;
}
private:
int _dPri;
protected:
int _dPro;
public:
int _dPub;
int _pri;
Test d;
};
int main()
{
cout << sizeof(Base) << endl; //12
cout << sizeof(Base1) << endl; //1
cout << sizeof(Derive) << endl; //32
system("pause");
return 0;
}
三、類的訪問:
class Base
{
public:
Base(int data)
{
cout << data << endl;
cout << "Base()" << this << endl;
}
void Show()
{
cout << "Base::Show()" << endl;
cout << "_pri=" << _pri << endl;
cout << "_pro=" << _pro << endl;
cout << "_pub=" << _pub << endl;
}
~Base()
{
cout << "~Base()" << endl;
}
private:
int _pri;
protected:
int _pro;
public:
int _pub;
};
class Base1
{
public:
Base1(int data)
{
cout << "Base1()" << endl;
}
~Base1()
{
cout << "~Base1()" << endl;
}
};
class Test
{
public:
Test(int data)
{
cout << "Test()" << endl;
}
~Test()
{
cout << "~Test()" << endl;
}
};
class Derive :public Base, public Base1
{
public:
Derive()
:d(10)
, Base1(10)
, Base(20)
{
cout << "Derive()" << this << endl;
}
~Derive()
{
cout << "~Derive()" << endl;
}
void Display()
{
cout << "_pri=" << _pri << endl;
cout << "_pro=" <<& _pro << endl;
cout << "-pub=" << &_pub << endl;
cout << "_dPri=" << &_dPri << endl;
cout << "_dPro=" << &_dPro << endl;
cout << "_dPub=" << &_dPub << endl;
}
void Show()
{
_pri = 10;
//Base::_pri = 10;
//私有成員只能在基類訪問,在派生類和其餘地方都不能訪問
cout << "Derive::Show()" << endl;
}
private:
int _dPri;
protected:
int _dPro;
public:
int _dPub;
int _pri;
Test d;
};
int main()
{
cout << sizeof(Base) << endl; //12
cout << sizeof(Base1) << endl; //1
cout << sizeof(Derive) << endl; //32
Derive d;
//調用構造函數時,先進Base類調用構造函數初始化Base,再進Base1初始化Base1
//最後再進Test類初始化對象d,由於d是在派生類中建立的,因此要最後初始化,
//Base和Base1初始化順序按照繼承順序執行,並不按照派生類中初始化列表中的順序進行
d.Show();
//調用派生類中的函數Show(),在函數中_pri(派生類中的公有成員_pri)被賦值爲10,
//子類和父類中有同名成員,子類成員將屏蔽父類對成員的直接訪問
d.Base::Show();
//調用基類Base中的Show(),由於都未賦值,因此顯示的都爲隨機值
d.Display();
//_pri(派生類中的)顯示爲10,其餘顯示的地址,都相差4字節,說明在類中,開闢的地址是連續的
d._dPub = 10;
d.Show();
//d._dPro = 20; //保護成員在類外不能夠訪問
system("pause");
return 0;
}
運行結果:(運行環境是VS2013)
總結:
一、基類的private成員在派生類中是不能被訪問的。 二、若是基類成員不想在類外直接被訪問,但須要在派生類中能訪問,就定義爲protected。保護成員限定符是因繼承纔出現的。 三、public繼承是一個接口繼承,保持is-a原則,每一個父類可用的成員對子類也可用,由於每一個子類對象也都是一個父類對象。 四、protetced/private繼承是一個實現繼承,基類的部分紅員並不是徹底成爲子類接口的一部分,是 has-a 的關係原則,因此非特殊狀況下不會使用這兩種繼承關係,在絕大多數的場景下使用的都是公有繼承。 五、不論是哪一種繼承方式,在派生類內部均可以訪問基類的公有成員和保護成員,基類的私有成員存在可是在子類中不可見(不能訪問)。 六、使用關鍵字class時默認的繼承方式是private,使用struct時默認的繼承方式是public,不過最好顯示的寫出繼承方式。 七、在實際運用中通常使用都是public繼承,極少場景下才會使用protetced/private繼承. 一、私有成員只能在基類訪問,在派生類和其餘地方都不能訪問 二、保護成員在類外不能夠訪問 三、在派生類中初始化基類時,系統會按照繼承的前後順序依次調用相應的構造函數來初始化,而不是根據初始化列表中的順序 一、在繼承體系中基類和派生類是兩個不一樣做用域。 二、子類和父類中有同名成員,子類成員將屏蔽父類對成員的直接訪問。(在子類成員函數中,可使用 基類::基類成員 訪問)--隱藏 --重定義 三、注意在實際中在繼承體系裏面最好不要定義同名的成員。 |
【繼承關係中構造函數調用順序】
【說明】
一、基類沒有缺省構造函數,派生類必需要在初始化列表中顯式給出基類名和參數列表。
class Base
{
public:
Base(int data)
{ }
};
class Base1
{
public:
Base1(int data)
{ }
};
class Derive: public Base, public Base1
{
public:
Derive()
: Base1(10)
, Base(20)
{ }
};
二、基類沒有定義構造函數,則派生類也能夠不用定義,所有使用缺省構造函數。
三、基類定義了帶有形參表構造函數,派生類就必定定義構造函數。
【繼承關係中析構函數調用順序】
四、友元與繼承及其賦值兼容:
class Base
{
public:
friend void Display(Base b);
Base(int data)
{
cout << data << endl;
cout << "Base()" << this << endl;
}
~Base()
{
cout << "~Base()" << endl;
}
private:
int _pri;
protected:
int _pro;
public:
int _pub;
};
class Derive :public Base
{
public:
friend void Display(Base b);
Derive()
:Base(20)
{
cout << "Derive()" << this << endl;
}
~Derive()
{
cout << "~Derive()" << endl;
}
private:
int _dPri;
protected:
int _dPro;
public:
int _dPub;
int _pri;
//子類和父類中有同名成員,子類成員將屏蔽父類對成員的直接訪問
};
void Display(Base b)
{
cout << b._pri << endl;
cout << b._pro << endl;
cout << b._pub << endl;
Derive d;
//cout << d._dPri << endl;
//友元關係不能繼承,基類友元不能訪問子類私有和保護成員
//若是Display是基類Base的友元函數,則不能訪問派生類的私有和保護成員
//若是Display是派生類的友元函數,則能夠訪問
}
int main()
{
Derive d; //子類對象
Base b(0); //父類對象
b = d; //子類對象能夠賦值給父類對象
//d = b; //父類對象不能夠賦值給子類對象
Base*pBase = &d; //父類指針
Derive *pd = (Derive*)&b; //子類指針
pBase = pd; //父類的指針/引用能夠指向子類對象
//pd = pBase; //子類的指針/引用不能指向父類對象 (能夠經過強制類型轉換實現)
return 0;
}
系統給出的錯誤提示:
總結:
一、友元關係不能繼承,基類友元不能訪問子類私有和保護成員
二、子類對象能夠賦值給父類對象
三、父類對象不能夠賦值給子類對象
四、父類的指針/引用能夠指向子類對象
五、子類的指針/引用不能指向父類對象 (能夠經過強制類型轉換實現)
六、基類定義了static成員,則整個繼承體系裏面只有一個這樣的成員。
除了單繼承,還有多繼承和菱形繼承,如下可區別它們之間的區別: