2015-06-30 98 views
5

我已經閱讀了關於vtable並且理解了指向基類和派生類對象的基類指針的概念。 當基類和派生類都是對象並且派生類對象被分配給基類對象時,有人可以解釋如何創建vtable。情況3在下面的示例中使用基礎和派生對象的虛函數

#include <iostream> 
#include <exception> 
using namespace std; 


class Base 
{ 
public: 
    virtual void function1() { cout<<"Base - func1"<<endl; } 
    virtual void function2() { cout<<"Base - func2"<<endl; } 
}; 

class Derived1: public Base 
{ 
public: 
    virtual void function1() { cout<<"Derived1 - func1"<<endl; } 
}; 

class Derived2: public Base 
{ 
public: 
    virtual void function2() { cout<<"Derived2 - func2"<<endl; } 
}; 

int main() 
{ 
    // Case 1 
    Base* B1 = new Derived1(); 
    B1->function1(); 
    B1->function2(); 

    // Case 2 
    cout<<endl; 
    Base* B2 = new Derived2(); 
    B2->function1(); 
    B2->function2(); 

    // Case 3 
    cout<<endl; 
    Base B3; 
    Derived1 D1; 
    B3=D1; 
    B3.function1(); 
    B3.function2(); 
} 

輸出:

Derived1 - func1 
Base - func2 

Base - func1 
Derived2 - func2 

Base - func1 
Base - func2 
+1

您正在切割「B3」。 – Jarod42

+1

只是指出,命名你的類D1,D2,然後你的變量B1,B2,B3可能會引起混淆。至少用變量名的小寫字母來表示它們不是類名。在你的代碼中使用某些約定可以幫助你和任何讀取它的人。 – aslg

+2

除非您正在討論專門使用vtables技術來實現虛擬功能的實現,否則不應該使用「vtable」一詞。 C++語言本身沒有vtables的概念。 –

回答

2
B3=Derived;

對象切片的一例...只有基類的數據成員被分配給,並且V表指針繼續指向基類函數。

你應該避免切片 - 它可能是危險的(參見this answer的解釋)。現在你知道的名詞,你會很容易找到大量的閱讀對象切片....

0
Base B3; 
D1 Derived; 
B3=Derived; //There is called default assignment operator 

它就是這樣定義:

Base& operator=(const Base &objectToCopy) {...} 

運營商採取Base類型的參數,因此D1類型的對象被視爲Base類型的對象。這意味着賦值運算符只能看到類BaseDerived的字段。 但是,指向vtable(技術上它是一個隱藏字段)的指針仍然未被複制,因爲它始終在構造函數中創建,並且它與實際對象類型永久關聯。

+1

運算符接受一個'const Base&'類型的參數,它不*將*隱式地轉換爲'Base'。轉換髮生在分配過程中,而不是在向運營商的呼叫期間發生。 – EJP

+0

@EJP對不起。我表達不好。這現在好嗎? –

+0

它仍然與參數類型無關(你仍然錯誤地陳述)。它與運營商方法中發生的事情有關。 – EJP

相關問題