2012-12-04 108 views
4

對不起,如果這個答案已經在這個網站上,但我已經找遍了,找不到解決我的問題。它適用於來自繼承類的同名函數。這裏是我的代碼:具有相同函數名稱的C++繼承

class A 
{ 
public: 
    int foo(int c) { c = c+1; return c; }; 
}; 

class B : public A 
{ 
public: 
    int foo(int c) { c = c-1; return c; }; 
}; 

int main() 
{ 
    A array[2]; 
    array[0] = A item1; 
    array[1] = B item2; 
    for (int n=0;n<2;n++) 
    { 
     cout << array[n].foo(10) << endl; 
    } 
    return 0; 
} 

我期望的輸出:

11 // foo() from A class [10 + 1 = 11] 
9  // foo() from B class [10 - 1 = 9 ] 

而是我得到

11 
11 

從測試了這一點,我發現,把foo() B類中的函數不會在for循環中調用。而是調用A類中的foo()函數,即使在array [1]上的B對象上也是如此。

這是因爲我已經將數組定義爲僅包含A類的對象?如果是這樣,有沒有辦法讓我可以從B類的foo()函數調用該for-loop中的第二個對象?

非常感謝您的幫助!

+4

三個詞:對象切片,'虛擬'。 – chris

+1

您正在存儲一個'A'類型的數組,所以如果B包含額外的成員,則'B'將被切片爲'A',並且您僅限於調用'A'的mebers。 – Joe

+2

'array [0] = item1;'不是任何一種C++。 –

回答

7

我會忘記,array[0] = A item1;是無效的C++,只是假設你要指定A類型的對象,以array[0]B類型的對象array[1]。好的,所以你有兩個問題。

第一個被稱爲對象切片。將類型B的對象複製到A類型的對象時,只能複製該對象的A部分。因此,您在array[1]中所擁有的全部不是B,它只是一個A。如果你想要多態(你這麼做),那麼你需要使用提供多態行爲的指針或引用。這意味着讓你的陣列成爲A* array[2];並做array[0] = &item1; array[1] = &item2;

現在,當您調用指向A的指針指向B時,它仍然只會調用Afoo成員函數。爲什麼?因爲默認情況下,該功能將在對象的靜態類型上查找。該靜態類型是A。如果你想告訴編譯器在你的對象的動態類型上查找你的函數 - true你的對象的類型,即B - 你需要使該成員函數爲虛擬。因此,在A,做到:

virtual int foo(int c) { c = c+1; return c; }; 

現在,當你的編譯器看到你在一個A*調用foo,它會看到,它是虛擬的,並說:「哦,沒事,我應該查查這個函數動態」和它會發現Bfoo的實現。

+0

非常感謝!我知道這是不恰當的語法,但感謝您將它說出來。我應用了你的建議,代碼就像我想的那樣運行。 –

4

您錯過了virtual關鍵字。

class A 
{ 
    virtual int foo(int c) { c = c+1; return c; }; 
}; 

另外,爲了避免slicing,代替A使用陣列的指針的數組A

A* array[2]; 
array[0] = new A; 
array[1] = new B; 
for (size_t i=0; i<2; ++i) 
    cout << array[i]->foo(10) << endl; 

,或者更好的是,使其指針到A(std::vector<A*>)的載體。另外,根據經驗,基類的析構函數也應該是虛擬的 - 對於這個特定的例子來說這不是問題,但是如果派生類添加了新的成員,它們在銷燬時應該釋放,使得基類析構函數虛擬將確保層次結構中的所有析構函數都被調用。

另一件事,這:

array[1] = B item2; 

將無法​​編譯。如果聲明數組作爲指針數組A(或載體指針到A),你將能夠做到:

array[1] = new B; 
+4

不僅如此.. –

+1

'虛擬'不是唯一缺少的東西。 –

+0

謝謝!代碼現在正確運行。 –

5

你要分配給一個A類型的空間分配給您的B實例。這導致「切片」。因此,首先,您必須通過指針或引用允許其他類型。例如:

A* a = new B; 
a->foo(10); 

你必須做的另一件事是提醒foo()可以重寫編譯器。在C++中,聲明爲virtual功能:

virtual int foo(int c) { c = c+1; return c; }; 
+1

非常感謝您的幫助。 –

相關問題