在保护继承中基类的共有成员_C++学习大纲:继承方式的调整
C++ 繼承方式的調(diào)整
在任何繼承方式中,除了基類的private成員外,都可以在派生類中分別調(diào)整其訪問(wèn)控制。
調(diào)整格式
[public: | protected: | private: ] :: ;
class A
{
public:
void f1();
void f2();
void f3();
protected:
void g1();
void g2();
void g3();
}
class B: private A
{
public:
A::f1;//把f1調(diào)整為public
A::g1;//把g1調(diào)整為public,是否允許弱化基類的訪問(wèn)控制要視具體的實(shí)現(xiàn)而定
protected:
A::f2;//把f2調(diào)整為protected
A::g2;//把g2調(diào)整為protected
}
class C: class B
{
public:
void h()
{
f1(); f2(); g1(); g2();//OK
f3(); g3(); //Error,此時(shí)f3,g3是基類B的private成員
}
}
————————————————
C++繼承及其特點(diǎn)
繼承
繼承機(jī)制是面向?qū)ο蟪绦蛟O(shè)計(jì),使代碼可以復(fù)用最重要手段,它允許在保持原有類的基礎(chǔ)上進(jìn)行擴(kuò)展,增加功能,這樣產(chǎn)生的類,叫做派生類,被派生類繼承的類叫做基類。繼承呈現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計(jì)的層次結(jié)構(gòu)。體現(xiàn)了由簡(jiǎn)單到復(fù)雜的認(rèn)知過(guò)程。
繼承方式
派生類名字: 繼承權(quán)限:父類的名字
例如:已存在類class A
那么派生類定義為
class Derived: public A
繼承權(quán)限三種格式
繼承的權(quán)限跟類中成員的權(quán)限一樣,有三種權(quán)限
public. protected. pritave
默認(rèn)派生類的繼承方式為私有繼承方式
如果基類為class,派生類默認(rèn)繼承方式私有
如果基類為struct,派生類默認(rèn)繼承方式為共有
派生類定義方式
//Base //基類 父類
//Derived //派生類 子類
class Base
{
public:
int _b;
};
class Derived : public Base//派生類: 繼承方式 基類
{
public:
int _d;
};
繼承類型
基類的成員的三種類型,繼承到派生類。保護(hù)的類型,繼承的子類也是保護(hù)類型,在類外不可訪問(wèn)。類內(nèi)可以。非本類不可訪問(wèn)。私有成員在派生類中不可訪問(wèn)。
public(公有方式)
子類Derived繼承Base父類的數(shù)據(jù)。
共有的繼承方式,可以訪問(wèn)父類的共有成員與保護(hù)成員。但是無(wú)法訪問(wèn)私有成員。
基類中public類的 在 子類中也是public
基類中protected類的成員 在 子類中也是 protected
基類中私有成員,仍然歸父類私有,雖然子類繼承,但是無(wú)法訪問(wèn)。但是可以調(diào)用父類中共有的方法來(lái)訪問(wèn)。
protected(保護(hù)方式)
保護(hù)的繼承方式
基類中:共有的權(quán)限 如果是保護(hù)的繼承方式, 到了子類中,已經(jīng)從public類改變?yōu)閜rotected類。
基類中保護(hù)的成員在子類中訪問(wèn)的權(quán)限不變。
基類中的私有成員, 子類繼承下來(lái)了,但是就是用不了。
派生類里可以訪問(wèn) 保護(hù)類成員。 類外不行。私有類只能本類中訪問(wèn)。
private(私有方式)
私有的繼承方式,基類中所有的成員變量/函數(shù),在派生類中全部變?yōu)樗接袑傩浴?/p>
繼承的特點(diǎn)
對(duì)象模型: 類中成員變量在內(nèi)存中的布局形式(非靜態(tài)成員變量)
class Base
{
public:
int _a;
int _b;
int _c;
};
class Derived : public Base
{
public:
int a;
int b;
int c;
};
以上的基類與派生類在對(duì)象存儲(chǔ)形式為:
派生類與基類的關(guān)系
共有的繼承方式,可以將基類對(duì)象,當(dāng)做是派生類對(duì)象。
使用角度:所有用到基類的地方,都可以用派生類來(lái)代替。
保護(hù)的繼承方式,protected/private: 子類—基類 相當(dāng)于has-a的關(guān)系
相當(dāng)于在子類中創(chuàng)建了一個(gè)基類對(duì)象,基類擁有自己的作用域以及對(duì)成員的保護(hù)權(quán)限。
基類/派生類賦值:切片/切割
子類可以給父類賦值。反過(guò)來(lái)則不行。(這種方式叫切片/切割)
子類本身就是父類的延伸,因此子類中擁有父類擁有的東西。
派生類給基類賦值時(shí),可以將自己切開(kāi),將上半部分的name賦值給基類對(duì)象。這種方式叫切片/切割
切片/切割一個(gè)天然的行為,并沒(méi)有伴隨著隱式的類型轉(zhuǎn)換,如下證實(shí):
class Base
{
public:
int _a;
int _b;
int _c;
};
class Derived : public Base
{
public:
int a;
int b;
int c;
};
int main()
{
Base B;
Derived D;
B = D;
Base& b = D;
//基類引用對(duì)象引用派生類是沒(méi)有問(wèn)題的。這個(gè)引用變量只能訪問(wèn)到屬于基類的數(shù)據(jù)
//此時(shí)沒(méi)有發(fā)生類型轉(zhuǎn)換,引用的是派生類切出來(lái)的基類對(duì)象,不是類型轉(zhuǎn)換后的數(shù)據(jù)。
int a = 1;
double d = i;//這里發(fā)生隱式類型轉(zhuǎn)換,但是不影響,因?yàn)檫@只是用常量給變量賦值
//double& d1 = i;//因?yàn)榘l(fā)生隱式類型轉(zhuǎn)換時(shí),會(huì)產(chǎn)生一個(gè)臨時(shí)變量
//此時(shí)的double類型的引用變量,引用的是i類型轉(zhuǎn)換后的臨時(shí)變量的值
//臨時(shí)變量具有常屬性,因此必須將引用類型用const修飾
//與常量的屬性保持一致,才可以通過(guò)編譯。
const double& d1 = i;//此時(shí)可以通過(guò)編譯。
}
基類 = 派生類:
基類訪問(wèn)派生類中基類需要的數(shù)據(jù),基類指針可以指向派生類對(duì)象。這時(shí)的指針可以訪問(wèn)基類的成員。基類的引用,可以引用派生類對(duì)象。這是也只是可以訪問(wèn)基類的數(shù)據(jù)。
派生類 = 基類:
基類對(duì)象不能強(qiáng)轉(zhuǎn)為派生類對(duì)象,賦值給派生類。賦值時(shí),派生類會(huì)訪了基類中沒(méi)有的數(shù)據(jù), 會(huì)造成越界訪問(wèn)。發(fā)生錯(cuò)誤。
派生類指針或引用不可以指向或引用基類對(duì)象??赡軙?huì)發(fā)生越界訪問(wèn),所以不允許指向或者引用基類。如果給基類進(jìn)行強(qiáng)轉(zhuǎn),將基類引用強(qiáng)轉(zhuǎn)為派生類,強(qiáng)行訪問(wèn)派生類對(duì)象,訪問(wèn)到不允許訪問(wèn)的內(nèi)容,直接出錯(cuò)。除非這個(gè)基類對(duì)象的指針之前就是指向派生類的指針。
同名隱藏
基類中繼承下來(lái)的函數(shù),與派生類中的同名函數(shù)不能形成重載,而且同名函數(shù)還會(huì)發(fā)生沖突。如果訪問(wèn)相同名稱的函數(shù),派生類中只能調(diào)用自己類中的函數(shù)或者成員。如果想在派生類中訪問(wèn)基類中的同名(成員函數(shù)||成員變量)。只能通過(guò)加基類類作用域的方式去訪問(wèn)相同名稱的基類成員。
d.Base::fun();
同名函數(shù)不能形成重載,因?yàn)楹瘮?shù)重載的條件就是同名函數(shù)必須要在同一作用域,盡管基類與派生類函數(shù)名相同但參數(shù)信息不同, 他們沒(méi)有在同一個(gè)作用域,因此不能形成重載。誤當(dāng)做重載函數(shù)調(diào)用時(shí),肯定出錯(cuò)。
其實(shí)編譯器在編譯期間會(huì)為基類和派生類成員加上對(duì)應(yīng)的作用域限定符,派生類的成員前會(huì)加上派生類的作用域限定符,基類的成員會(huì)加上基類的作用域限定符。
Base::基類成員 Derived::派生類成員
派生類對(duì)象構(gòu)造函數(shù)
派生類對(duì)象構(gòu)造時(shí),先調(diào)用派生類構(gòu)造函數(shù),在派生類構(gòu)造函數(shù)的初始化列表中會(huì)調(diào)用基類的構(gòu)造函數(shù),在進(jìn)入派生類對(duì)象的函數(shù)體之前,會(huì)先在初始化列表中完成派生類中成員的初始化,而這個(gè)初始化列表中就有基類的初始化,因此它會(huì)先初始化基類中成員(構(gòu)造基類成員,調(diào)用基類的構(gòu)造函數(shù)),之后再初始化派生類的成員。
默認(rèn)的派生類構(gòu)造函數(shù)只會(huì)調(diào)用基類的默認(rèn)構(gòu)造函數(shù)。所以基類的構(gòu)造函數(shù)如果是定義的有參數(shù)的,這時(shí)必須在派生類的構(gòu)造函數(shù)初始化列表中給出定義。否則構(gòu)造派生類對(duì)象時(shí),找不到默認(rèn)的基類構(gòu)造函數(shù),代碼不能編譯。
派生類的析構(gòu)函數(shù)
(先析構(gòu)自己的,在最后一個(gè)括號(hào)處調(diào)用基類的析構(gòu)函數(shù))
如果要銷毀派生類的對(duì)象,則需要掉用派生類析構(gòu)函數(shù)來(lái)清理派生類對(duì)象中的資源,在派生類析構(gòu)函數(shù)的最后,需要調(diào)用基類的析構(gòu)函數(shù),以完成基類部分資源的銷毀。
final修飾的類
final修飾的類,不能被繼承
將類的構(gòu)造函數(shù)定義為私有的, 則變?yōu)椴豢衫^承的類。(C++11)中 被final修飾的類,不能被繼承。
繼承與友元函數(shù)
友元關(guān)系不能繼承,基類友元不能訪問(wèn)子類私有和保護(hù)成員。因?yàn)橛言瘮?shù)不是類的成員,所以不能繼承?;惖挠言瘮?shù)因此無(wú)法訪問(wèn)派生類的任何成員。
派生類的友元函數(shù),不能訪問(wèn)基類的私有成員,如果是私有的繼承方式,那么基類的所有成員都不能訪問(wèn)。就跟派生類的訪問(wèn)權(quán)限一致,派生類可以訪問(wèn)到的基類對(duì)象,友元函數(shù)也能訪問(wèn)到。
靜態(tài)成員
靜態(tài)成員變量可以被繼承。并且派生類與基類公用這個(gè)靜態(tài)成員。
多繼承
多繼承方式:
class B1; class B2; //已有的類
class D: public B1,public B2;
B1;
B2;
D;
先繼承的基類在上,后繼承的基類在下, 派生類在最下。
菱形繼承模型:
虛擬繼承
虛擬繼承
class D: virtual public B//關(guān)鍵字 virtual
1
為了解決菱形繼承中的二義性問(wèn)題,大佬們?cè)O(shè)計(jì)出了虛擬繼承。虛擬繼承的派生類中,不管派生類中有多少個(gè)公用的基類,都公用一個(gè)基類。因此在派生類中,前4個(gè)字節(jié)首先存了一個(gè)指針,這個(gè)指針指向一個(gè)類似數(shù)組的區(qū)域,里面裝著要訪問(wèn)基類對(duì)象時(shí),該指針要偏移的偏移量。細(xì)節(jié)如下:
虛擬繼承存儲(chǔ)
虛擬繼承的派生類,存儲(chǔ)方式會(huì)先存放派生類對(duì)象,將基類對(duì)象放在后面存放。
代碼表現(xiàn)
#include
using namespace std;
class A
{
public:
int a;
};
class B:virtual public A
{
public:
int b;
};
class C:virtual public A
{
public:
int c;
};
class D:public B, public C
{
public:
int d;
};
int main()
{
D d;
d.B::a = 2;
d.C::a = 1;
d.b = 3;
d.c = 4;
d.d = 5;
cout << sizeof(d) << endl;
}
內(nèi)存中體現(xiàn)
如果有不對(duì)的地方,希望大佬批評(píng)。
————————————————
通過(guò)分享實(shí)用的計(jì)算機(jī)編程語(yǔ)言干貨,推動(dòng)中國(guó)編程到2025年基本實(shí)現(xiàn)普及化,使編程變得全民皆知,最終實(shí)現(xiàn)中國(guó)編程之崛起,這里是中國(guó)編程2025,感謝大家的支持。
原文鏈接:https://blog.csdn.net/haitaolang/article/details/70844494
原文鏈接:https://blog.csdn.net/qq_41804778/article/details/81561547
總結(jié)
以上是生活随笔為你收集整理的在保护继承中基类的共有成员_C++学习大纲:继承方式的调整的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 丰田bZ4X中国不吃香降价6万 美国竟有
- 下一篇: c++ 传入回调函数 参数没有传入_一文