2010-08-22 64 views
5

我知道這個問題必須被覆蓋無盡的時間,但我已經搜索了以前的問題,沒有任何東西似乎彈出。在超類的子類中調用虛函數

這是關於繼承和虛函數我C++。我在調用超類的子類中的虛函數時遇到了問題。

讓我舉個例子。從三個類開始,它們相互繼承。

class A { 

    void foo() { bar() } 
    virtual void bar() { } 

}; 

class B : public A { 

    virtual void bar() { } 

}; 

class C : public B { 

    virtual void bar() { // do something } 

}; 

現在我想要一個聲明爲B *的變量,但實例化爲C *。當我這樣做,並在myObject上調用foo(),然後A :: foo()調用bar()。但是隻調用B :: bar(),而不是C :: Bar() - 實際上myObject是這樣的,即使它被聲明爲B,這又會影響「//不做任何事」不會被執行。

我該如何告訴A :: foo(),它需要看最低的實現?

有意義嗎?

// Trenskow

編輯:

Ç:: foo是沒有問題的。 Foo被稱爲A級,因爲它是唯一實施的地方。問題出現時,A:Foo調用Bar()。然後B:Bar被調用,而不是C :: Bar。

也許問題是,在我的實現,我只得到一個void *指針對象A.

像這樣:

void A:Foo(void *a) { 

    A* tmpA = static_cast<A*> (a); 
    tmpA->bar(); 

} 

現在,編譯器認爲,這TMPA是答:但不知何故,它設法確定它是一個B *,並且調用B :: Bar,實際上tmpA是一個C *,它應該調用C :: Bar。

+1

如果你發佈了真實的代碼,那麼我們可以告訴問題是。你不需要做任何特別的事情。如果語法錯誤得到解決,代碼('myObject-> foo();')將調用'C :: bar()'。 – UncleBens 2010-08-22 09:23:20

+0

......但是如果我猜測,要麼'C'並沒有真正覆蓋'bar'(具有不同的簽名),或者你在某處切分對象(通過執行諸如'* variable = * myObject;' – UncleBens 2010-08-22 09:33:21

+0

我仍然不會購買它,爲什麼不調用C :: bar()?你能發佈實際的代碼嗎? – EboMike 2010-08-22 09:43:17

回答

5

下面按預期顯示「A :: foo C :: bar」。你有不同的東西嗎? B::bar永遠不會被調用,因爲C是對象的實際運行時類型。在C::bar中,您可以通過在其正文中添加B::bar();明確地呼叫B::bar

#include <iostream> 
using namespace std; 

class A { 
public: 
    void foo() { cout << "A::foo "; bar(); } 
    virtual void bar() { } 
}; 

class B : public A { 
public: 
    virtual void bar() { cout << "B::bar" << endl; } 
}; 

class C : public B { 
public: 
    virtual void bar() { cout << "C::bar" << endl; } 
}; 

int main() 
{ 
    B* c = new C(); 
    c->foo(); 
    return 0; 
} 
0

假設輸入錯誤的代碼的最後一塊的名稱相匹配:

B* variable = new C(); 
variable->foo(); 

那麼C :: Foo中的方法被調用,或者你使用非常糟糕的編譯器。

(這還假定你實際上並不在C ::美孚編譯器錯誤,並且該評論確實是一樣的東西std::cout << "Hi mom!" << std::endl;

0

你不是說:

B* myObject = new C(); 
myObject->foo(); // not variable->foo() 

class A 
{ 
public: 
    void foo() { bar(); } 
    virtual void bar() { std::cout << "A"; }; 
}; 

class B : public A 
{ 
public: 
    virtual void bar() { std::cout << "B";}; 
}; 

class C : public B 
{ 
public: 
    virtual void bar() { std::cout << "C"; } 
}; 

按預期打印「C」。

+0

哦,拍攝是啊。在編輯中更改變量名稱,而不是將其稱爲變量。必須忘記第二行。編輯 – Trenskow 2010-08-22 09:38:47

0

我不關注。你說

但只有B ::巴()被調用,而不是 Ç::酒吧()

號你調用C類的構造函數,這意味着V表使bar()指向C :: bar(),所以在這種情況下調用foo()會直接到C :: bar()。

如果要強制A :: foo的()明確只調用的實現,你可以做到這一點僅通過寫

void foo() { A::bar(); } 

究竟是你想做些什麼?

0

你使用什麼編譯器? Visual Studio(IIRC)通常默認關閉運行時類型信息,所以它可能就是這麼簡單?

2
void A:Foo(void *a) { 

    A* tmpA = static_cast<A*> (a); 
    tmpA->bar(); 

} 

這是未定義的行爲。你不能將B *轉換爲void *,然後將該void *轉換回A *。如果你想讓它正常工作,你必須拋棄void *。或者,您可以嘗試dynamic_cast。

+0

或者您先將B *轉換爲A *,然後將A *轉換爲void *。 – Tomek 2010-08-22 18:03:36