将派生类指针赋值给基类的指针
除了可以將派生類對(duì)象賦值給基類對(duì)象(對(duì)象變量之間的賦值),還可以將派生類指針賦值給基類指針(對(duì)象指針之間的賦值)。我們先來(lái)看一個(gè)多繼承的例子,繼承關(guān)系為:
#include <iostream>using namespace std;//基類class A{public:A(int a);int m_a; public:void display();};A::A(int a):m_a(a) {}void A::display() {cout<<"Class A:m_a="<<m_a<<endl; }//派生類class B:public A{public:B(int a1,int b);public:void display();protected:int m_b; };B::B(int a, int b):A(a),m_b(b) {}void B::display() {cout<<"Class B:m_a="<<m_a<<", m_b"<<m_b<<endl;}class C{ public:C(int c);public:void display();protected:int m_c;};C::C(int c):m_c(c){}void C::display() {cout<<"Class C: m_c="<<m_c<<endl;}class D:public B,public C{public:D(int a,int b,int c,int d);public:void display();private:int m_d;};D::D(int a, int b, int c, int d) :B(a,b),C(c),m_d(d){}void D::display() {cout<<"Class D: m_a="<<m_a<<", m_b="<<m_b<<", m_c="<<m_c<<", m_d="<<m_d<<endl; }int main(){A *pa =new A(1);B *pb =new B(2,20);C *pc =new C(3);D *pd =new D(4,40,400,4000);pa=pd;pa ->display();pb=pd;pb ->display();pc=pd;pd ->display();cout<<"-----------------------"<<endl;cout<<"pa="<<pa<<endl;cout<<"pb="<<pb<<endl;cout<<"pc="<<pc<<endl;cout<<"pd="<<pd<<endl;return 0;} Class A:m_a=4 Class B:m_a=4, m_b40 Class D: m_a=4, m_b=40, m_c=400, m_d=4000 ----------------------- pa=0x55a33ea0ced0 pb=0x55a33ea0ced0 pc=0x55a33ea0ced8 pd=0x55a33ea0ced0本例中定義了多個(gè)對(duì)象指針,并嘗試將派生類指針賦值給基類指針。與對(duì)象變量之間的賦值不同的是,對(duì)象指針之間的賦值并沒(méi)有拷貝對(duì)象的成員,也沒(méi)有修改對(duì)象本身的數(shù)據(jù),僅僅是改變了指針的指向。
- 通過(guò)基類指針訪問(wèn)派生類的成員
請(qǐng)讀者先關(guān)注第 68 行代碼,我們將派生類指針 pd 賦值給了基類指針 pa,從運(yùn)行結(jié)果可以看出,調(diào)用 display() 函數(shù)時(shí)雖然使用了派生類的成員變量,但是 display() 函數(shù)本身卻是基類的。也就是說(shuō),將派生類指針賦值給基類指針時(shí),通過(guò)基類指針只能使用派生類的成員變量,但不能使用派生類的成員函數(shù),這看起來(lái)有點(diǎn)不倫不類,究竟是為什么呢?第 71、74 行代碼也是類似的情況。
pa 本來(lái)是基類 A 的指針,現(xiàn)在指向了派生類 D 的對(duì)象,這使得隱式指針 this 發(fā)生了變化,也指向了 D 類的對(duì)象,所以最終在 display() 內(nèi)部使用的是 D 類對(duì)象的成員變量,相信這一點(diǎn)不難理解。
編譯器雖然通過(guò)指針的指向來(lái)訪問(wèn)成員變量,但是卻不通過(guò)指針的指向來(lái)訪問(wèn)成員函數(shù):編譯器通過(guò)指針的類型來(lái)訪問(wèn)成員函數(shù)。對(duì)于 pa,它的類型是 A,不管它指向哪個(gè)對(duì)象,使用的都是 A 類的成員函數(shù),具體原因已在《C++函數(shù)編譯原理和成員函數(shù)的實(shí)現(xiàn)》中做了詳細(xì)講解。
概括起來(lái)說(shuō)就是:編譯器通過(guò)指針來(lái)訪問(wèn)成員變量,指針指向哪個(gè)對(duì)象就使用哪個(gè)對(duì)象的數(shù)據(jù);編譯器通過(guò)指針的類型來(lái)訪問(wèn)成員函數(shù),指針屬于哪個(gè)類的類型就使用哪個(gè)類的函數(shù)。
本例中我們將最終派生類的指針 pd 分別賦值給了基類指針 pa、pb、pc,按理說(shuō)它們的值應(yīng)該相等,都指向同一塊內(nèi)存,但是運(yùn)行結(jié)果卻有力地反駁了這種推論,只有 pa、pb、pd 三個(gè)指針的值相等,pc 的值比它們都大。也就是說(shuō),執(zhí)行pc = pd;語(yǔ)句后,pc 和 pd 的值并不相等。
將派生類引用賦值給基類引用
引用在本質(zhì)上是通過(guò)指針的方式實(shí)現(xiàn)的,這一點(diǎn)已在《引用在本質(zhì)上是什么,它和指針到底有什么區(qū)別》中進(jìn)行了講解,既然基類的指針可以指向派生類的對(duì)象,那么我們就有理由推斷:基類的引用也可以指向派生類的對(duì)象,并且它的表現(xiàn)和指針是類似的。
修改上例中 main() 函數(shù)內(nèi)部的代碼,用引用取代指針:
int main(){D d(4, 40, 400, 4000);A &ra = d;B &rb = d;C &rc = d;ra.display();rb.display();rc.display();return 0; } Class A: m_a=4 Class B: m_a=4, m_b=40 Class C: m_c=400ra、rb、rc 是基類的引用,它們都引用了派生類對(duì)象 d,并調(diào)用了 display() 函數(shù),從運(yùn)行結(jié)果可以發(fā)現(xiàn),雖然使用了派生類對(duì)象的成員變量,但是卻沒(méi)有使用派生類的成員函數(shù),這和指針的表現(xiàn)是一樣的。
引用和指針的表現(xiàn)之所以如此類似,是因?yàn)橐煤椭羔槻](méi)有本質(zhì)上的區(qū)別,引用僅僅是對(duì)指針進(jìn)行了簡(jiǎn)單封裝,讀者可以猛擊《引用在本質(zhì)上是什么,它和指針到底有什么區(qū)別》一文深入了解。
最后需要注意的是,向上轉(zhuǎn)型后通過(guò)基類的對(duì)象、指針、引用只能訪問(wèn)從基類繼承過(guò)去的成員(包括成員變量和成員函數(shù)),不能訪問(wèn)派生類新增的成員。
總結(jié)
以上是生活随笔為你收集整理的将派生类指针赋值给基类的指针的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C++将派生类赋值给基类(向上转型)(一
- 下一篇: 多态的用途