国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

c++ - 將基底類別指標(biāo)賦給衍生類別的問題
曾經(jīng)蠟筆沒有小新
曾經(jīng)蠟筆沒有小新 2017-06-05 11:11:46
0
3
1323

將衍生類別位址賦給基底類別指針,也就是基底類別指標(biāo)指派生類別對象,也就是我們平常說的多態(tài)

但是反過來的時(shí)候,必須經(jīng)過強(qiáng)制型別轉(zhuǎn)換才可以編譯通過,

下來直接程式碼:

#include<iostream>

usingnamespacestd;

class Base
{
public:
virtual void print()
{
    cout<<"base"<<endl;
}
};

class Derived:public Base
{
public:
void print()
{
cout<<"derived"<<endl;
}
};
int main(void)
{

Base * pb=newB ase();//定義基類指針

Derived * pd=(Derived*)pb;//賦值給派生類指針

pd->print();//調(diào)用基類的print輸出base

pd->Derived::print();//調(diào)用派生類的print輸出derived

return 0;
}

我想問用pd->print()為什麼呼叫的是基底類別的print

然後為什麼將基底類別的virtual去掉之後,呼叫的便是衍生類別的print

曾經(jīng)蠟筆沒有小新
曾經(jīng)蠟筆沒有小新

全部回覆(3)
滿天的星座

呼叫哪個(gè)虛函數(shù)是由物件所指的虛擬函數(shù)表所決定的,當(dāng)你new Base()的時(shí)候pb所指向的虛函數(shù)表中的虛函數(shù)是Base的,用(Derived*)強(qiáng)制轉(zhuǎn)換並沒改變,而非虛函數(shù)主要根據(jù)指標(biāo)類型,也就是說pd一開始就是Derived,所以用Derived的函數(shù),成員函數(shù)在呼叫時(shí)其實(shí)是呼叫了this指標(biāo)的。

劉奇

The virtual specifier specifies that a non-static member function is virtual and supports dynamic binding. It may only appear in the decl-specifier-seq of the initial declaration of a non-static member function (i.ic member function . class definition).

Virtual functions are member functions whose behavior can be overridden in derived classes.

使用virtual的意思是這個(gè)函數(shù)可以被子類別override,使指向子類別的父類別指標(biāo)不會跟據(jù)指標(biāo)本身的類別來呼叫這個(gè)函數(shù),而(透過查虛函數(shù)表V-Table)呼叫被子類別override後的函數(shù)。
值得一提的是

Base * pb=new Base();//定義基類指針
Derived * pd=(Derived*)pb;//賦值給派生類指針

這樣寫是不正確,至少也是不安全的,不應(yīng)該將指向父類別物件的父類別指標(biāo)賦給子類別指標(biāo)。

此處的pd->print指向的是虛函數(shù)表中父類別的print,所以

pd->print();                    //調(diào)用父類的print,輸出base

呼叫的是Base::print

接下來

pd->Derived::print();

這是強(qiáng)行在父類別物件上呼叫子類別的函數(shù)(或者說以父類別物件為this,強(qiáng)行呼叫虛擬函數(shù)表中的子類別print),一般不建議這麼做。

伊謝爾倫

還真是這樣,剛運(yùn)行了一下,確實(shí)很難理解。

我說一下我的思路,不知道對不對,大家可以參考一下:

第一種情況,寫了virtual,如果成員函數(shù)加virtual,表示是動態(tài)綁定,只有在執(zhí)行時(shí)候才會找到被調(diào)函數(shù)的位址。但是在哪裡找呢?似乎每個(gè)物件的記憶體中都會存在一份虛表(也有說法是每個(gè)類別有一份虛表,物件共享),因?yàn)槟愕腄erived指標(biāo)指向的是Base物件的那塊內(nèi)存,所以系統(tǒng)就去那塊在記憶體的虛表??中找print函數(shù),那塊記憶體中虛表中的print函數(shù)的位址就是Base類別的print函數(shù)的位址,所以呼叫了基底類別的print函數(shù)

第二種情況:把virtual給去了,那就不涉及動態(tài)綁定,函數(shù)的位址是編譯時(shí)候決定的。編譯時(shí)候函數(shù)位址怎麼確定:是透過在原始程式符號表中找出所得。那麼主程式中pd->print(),很明顯,pd是Derived類,pd->print()相當(dāng)於Derived::print,那編譯器就到Derived類別找嘍,所以編譯期間把pd-> print()中print()的位址被替換成Derived::print的位址,所以就呼叫了子類別的print函數(shù)。

不知道你懂我說啥不

最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板