2011-04-11 46 views
2

在問之前,我已經參考了這個older question。但我仍然有疑問。爲什麼純虛擬機制不考慮繼承函數?

struct B1 { 
    virtual void fun() = 0; 
}; 
struct B2 { 
    void fun() { cout<<"B2::fun()\n"; } 
    void fun (int i) {} 
}; 
struct D : B1, B2 { 
    using B2::fun; // This line doesn't help 
}; 

int main() 
{ 
    B1 *pB1 = new D; // Error: cannot allocate 'D' because 'B1::fun()' is abstract 
    pB1->fun(); 
} 
  1. 任何原因C++標準不接受,繼承的成員函數來解決pure virtual機制?
  2. 爲什麼using關鍵字沒有幫助解決該錯誤? (編譯器:linux-64 g ++)
  3. 哪個函數用於using關鍵字,B2::fun()B2::fun(int)? (有該行沒有歧義)

回答

0

哪個函數用於使用關鍵字,B2 ::樂趣()或B2 ::樂趣(INT)?(沒有 歧義的
該行)

從ISO/IEC 14882:2003(E)7.3.3.12

當使用聲明從帶來的名字基類轉換爲派生類作用域,派生類中的成員函數會覆蓋和/或隱藏基類中具有相同名稱和參數類型的成員函數(而不是衝突)。

[Example: 
    struct B { 
     virtual void f(int); 
     virtual void f(char); 
     void g(int); 
     void h(int); 
    }; 

    struct D : B { 
     using B::f; 
     void f(int); // OK: D::f(int) overrides B::f(int); 

     using B::g; 
     void g(char); // OK 

     using B::h; 
     void h(int); // OK: D::h(int) hides B::h(int) 
    }; 

    void k(D* p) { 
     p->f(1); //calls D::f(int) 
     p->f(’a’); //calls B::f(char) // Notice the call being resolved 
     p->g(1); //calls B::g(int) 
     p->g(’a’); //calls D::g(char) 
    } 

— end example] 

[注:2使用-聲明可能與 相同的名稱和相同的參數類型介紹的功能。如果對於一個不合格的 函數名稱的調用,函數重載決議選擇由這樣的使用聲明引入的功能 ,函數調用是格式不正確的。 ]

因此,在您提供的示例中,根本沒有含糊之處。根據傳遞的參數,可以決定調用方法。

2
using B2::fun; 

只是允許你使用B2::fun方法,但由於B1是一個抽象類,你必須實現該類的純虛函數fun到能夠創建它的對象。

+0

由於B1是虛擬的,所以必須在D中定義方法。或者,您可以使用B2:B1,然後使用D:B2。 – Jess 2011-04-11 05:37:08

+0

@Jess:兩者都可以工作,請檢查RageD的答案,它解釋了它是如何工作的。 – 2011-04-11 05:45:21

0

好的。儘管我只是基於邏輯推理得出了第一個答案。假設,標準接受繼承的方法來解決pure virtual機制,那麼對於普通的「虛擬」功能將存在不明確性。

即即假設B1::fun()是正常的虛擬函數,那麼B1::fun()B2::fun()之間會有選擇混淆。所以最好避免考慮遺傳成員,至少對於virtual機制。

0

using只調整名稱查找過程。它不會將函數導入給定範圍,或者定義一個新函數。

所以,你只需要定義一個新的覆蓋virtual

0

我絕不是一個C++編程專家,但讓我試一試:

  1. 我認爲,B1和B2,從編譯器的角度來看,是碰巧有一個方法,兩個完全不同的類每個中都有相同的名字。即使涉及到D的範圍,編譯器也沒有理由使用B2的fun()實現來實現B1中的fun()。我們可以看到爲什麼B2 :: fun()對B1的樂趣沒有幫助()。)

  2. 「using 「指令只是使符號」有趣「在D的範圍內可見。 「使用」不會將任何fun()實現附加到D類(但是D需要針對B1 :: fun())的實現。

  3. 嗯......「使用」這裏指令實際上並沒有「使用」(或者說「援引」)二者中的任何。 「使用」只是向D的範圍引入了名稱(在D範圍內使名稱可見,類似於再次聲明它們)。