2011-11-06 93 views
-2

我剛剛意識到,我簡化了代碼太多,它並沒有反映我真正的問題。我很抱歉沒有更具體。我實際上是嘗試做的是以下幾點:如何從基類函數調用被覆蓋的虛函數?

online Demo

#include<iostream> 

class A 
{ 
    public: 
     A(); 

     virtual void f()= 0; 
     void g(); 
}; 

A::A() 
{ 
    g(); 
} 

void A::g() 
{ 
    f(); 
} 

class B : public A 
{ 
    public: 
     B() {}; 
     void f() {}; 
}; 

int main() 
{ 
    B b; 
    return 0; 
} 

我猜程序調用自BA::f已經在構造函數被調用尚未創建的純虛函數。

這是正確的,我該如何克服這個問題?

請原諒我早些提供過於簡化的問題。

+1

我也在等待迴應。對於我所瞭解的C++,你不能構造一個類實例,其中類仍然有一些未實現的純虛方法。 – Heisenbug

+0

幾乎肯定存在你刪除的代碼中的一個錯誤。 –

+0

-1不是真實代碼 –

回答

0

如果B :: f的函數簽名與A :: f匹配,那麼在A :: g中使用f()應該按照你的意願調用B :: f。在你上面的例子中,它們匹配,A :: g應該調用B :: f。

如果您的實際函數簽名比上面給出的示例更復雜,請確保它們的簽名完全匹配,否則編譯器會認爲B :: f是一個新函數而不是A :: f的重寫。

*:嚴格來說,返回類型可能會稍有不同,但我相信這不是與此有關

5

Working sample你的代碼後,我刪除了很多其他的錯誤。

#include<iostream> 

class A 
{ 
    virtual void f()=0; 
    public: 
    void g(); 
}; 

void A::g() 
{ 
    f(); 
} 

class B : public A 
{ 

    void f(){std::cout<<"Inside B::f";} 
}; 

int main() 
{ 
    B b; 
    b.g(); 
    return 0; 
} 

輸出:

內B ::˚F

安置自己的真正代碼,以獲得真正的答案


編輯:
現在,你向我們展示你真正的代碼(它有編譯錯誤,我固定他們爲你)。我明白你的問題。

當您使用B b;創建類B的對象時,它會導致調用基類構造函數A::A(),該函數繼而調用方法g()。請注意,g()只是一個基類方法,因此會導致致電A::g()。這進一步稱爲f()。現在你的期望是這個應該叫B::f()但它沒有。

爲什麼?
注意規則,
在構造函數中或析構對象的類型this點始終是它的構造/析構函數被調用的類型。

應用上面的規則,由於f()被稱爲在A構造,
this->f()電話A::f()而不是B::f()。另外,由於A::f()沒有一個定義(因爲你沒有提供一個),這導致運行時異常:叫 終止所謂的不存在活躍異常

純虛方法。因爲virtual要調用的函數是在運行時根據什麼this點,而不是靜態確定

編譯器檢測不到這是編譯時錯誤。編譯器無法檢測到這一點。

我該如何克服這個問題?
你不能通過構造函數中的動態分派來完成它。
如果您使用除構造函數/析構函數之外的其他方法調用它,您可以實現並期望您期望的行爲。

避免在構造函數和析構函數中調用虛函數,因爲它們不會調用他們可能調用的認爲是的版本。

0

從概念上講,這應該工作。我還沒有在年齡C++,但是這不應該是從這個場景完全不同的C#:

void B::f() 
{ 
    printf("im B::f\n"); 
} 

和程序:

public class MyBase 
{ 
    public virtual void PrintName() { } 
    public void DoWork() 
    { 
     PrintName(); 
    } 
} 

public class MyDerivative : MyBase 
{ 
    public override void PrintName() 
    { 
     Console.WriteLine("MyDerivative"); 
    } 
} 
+0

當然,在C#中,您會將MyBase和MyBase :: PrintName標記爲抽象。 – xanadont

0
#include <iostream> 

class A { 
public: 
    virtual void f() = 0; 
    void g(); 
}; 

void A::g() { 
    std::cout << "A::g" << std::endl; 
    this->f(); 
} 

class B : public A { 
public: 
    virtual void f(); 
}; 

void B::f() 
{ 
    std::cout << "B::f" << std::endl; 
} 

int main() { 
    B b; 
    b.g(); 
    return 0; 
} 
0

源添加此應該管用。

由於存在純粹的虛擬方法,因此無法創建A的實例。