2014-07-11 139 views
-1

我在其他問題中閱讀了它,但其中沒有一個是類似的,有的在構造函數中調用虛方法,有的在純虛方法中調用,但這裏的問題是關於vituais方法純粹的,但是關於不需要在所有派生類中實現的虛擬方法。如果實例化的類沒有實現該方法,如果我們調用它,它從邏輯上從基地調用方法,並且它有時會崩潰。 我在想,爲什麼?什麼是VTABLE(它進入的地方)?什麼是解決問題的最好方法。在調用虛擬方法時崩潰

這是一個簡單的例子,(避免像純虛擬答案)。

#include <iostream> 

class Foo 
{ 
public: 
    virtual std::string myString() {} 
}; 

class Bar : public Foo 
{ 
public: 
}; 

int main(int argc, char ** argv) 
{ 
    Foo * bar = new Foo; 
    bar->myString(); 

    return 0; 
} 

什麼是最佳解決方案?

  1. 拋出一個異常
  2. 使用斷言(假)
  3. 返回默認值
  4. 避免執行主體,它會導致 編譯時錯誤
  5. 無替代

最好的答案將是一個解釋,爲什麼出現這種情況根據VTABLE,當然,那些選擇一個解決方案並解釋原因。這個想法不是基於意見。

+0

這個例子不會崩潰,是嗎?顯示一個。編輯:哦,我的,它的確如此。我很困惑。 –

+0

你是什麼意思的「最佳解決方案」? –

+0

@PeterSchneider - 至少在這裏。 –

回答

2

的基類確實實現的功能,它只是實現它錯了。它與vtables或任何複雜的東西無關。解決方案4首選(因爲它可以防止構建錯誤的程序),如果不可能/需要1或2的順序。

請注意,錯誤與虛擬功能或一般繼承無關(您不使用Bar,您有沒有注意到?)。它甚至與班級沒有關係,但也可能發生在任何獨立功能上。考慮:

#include <iostream> 
#include <string> 

// Note: UB -- nothing returned 
int getInt() {} 
std::string getStr() {} 

int main(int argc, char ** argv) 
{ 
    // This probably works (read access from an arbitrary 
    // location on the stack which is in the prog's address space) 
    std::cout << getInt() << std::endl; 

    // This will crash. operator<< will try to access memory through 
    // a pointer value which is some arbitrary byte pattern on the stack. 
    // Probably not in the prog's address space. 
    // Then the destructor for the temporary string will 
    // try to delete the same 
    // memory which will crash in any case, even if it happens to 
    // point to valid memory (which, alas, was never allocated). 
    std::cout << getStr(); 

    std::cout << "Still alive?\n"; // never printed 
    std::cout.flush(); 

    return 0; 
} 

爲了防止您的原始代碼發生錯誤,只需返回一個值即可。如果實現的功能,不要扔或中止(這是三種選擇),即如果您返回時,你必須返回值:

#include <iostream> 

class Foo 
{ 
public: 
    virtual std::string myString() { return "test\n";} 
}; 

class Bar : public Foo 
{ 
public: 
}; 

int main(int argc, char ** argv) 
{ 
    Foo * bar = new Foo(); 
    std::cout << bar->myString(); 

    return 0; 
} 
+0

爲什麼選擇返回默認值?還有其他方法可以「解決」它。 –

+1

@ SH.0x90 vtable是當今編譯器多態的經典實現。根據C++,這是依賴於實現的。有可能編譯器可以發明另一種不使用vtable的技術。 –

+0

好吧,如果你正在實現它,你必須返回一個值,或拋出或中止。我只是想表明崩潰發生了,因爲沒有字符串是調用者期望的字符串。 –

0

mystring函數返回一個字符串。

+0

你爲什麼選擇返回默認值?還有其他方法可以「解決」它。 –

+0

你想以什麼方式工作? 你可以返回一些其他的值,它可以調用一些其他的函數和類似的東西。 VTABLE,你問的是完全不同的東西。當您聲明基類虛擬隱含的成員函數時,會發生VTABLE查找,如果派生類的指針由爲基類分配的內存創建,請查看父類。 –

+0

我不想用純虛擬的基類,因爲我想要它的一個實例,而其他類從那個擴展而來,並沒有實現基類的所有方法,但我們知道不小心有人可以調用一個方法沒有實現,它需要調用基地的一個。 –

1

VTABLE是指向虛擬方法的指針表。通常,指向VTABLE的指針在視圖中是隱藏的,但它通常作爲類實例中的第一個元素實現。

當派生類沒有其父類實現爲虛擬的成員函數時,父類的方法將被調用。

相關問題