2009-09-26 64 views
4

這不起作用:這裏用C++重載和重載是怎麼回事?

class Foo 
{ 
public: 
    virtual int A(int); 
    virtual int A(int,int); 
}; 
class Bar : public Foo 
{ 
public: 
    virtual int A(int); 
}; 

Bar b; 
int main() 
{ 
    b.A(0,0); 
} 

看來,通過覆蓋Foo::A(int)Bar::A(int)我莫名其妙地隱藏Foo::A(int,int)。如果我添加一個Bar::A(int,int)的東西的工作。

有沒有人有鏈接到這裏發生了什麼好的描述?

+0

可能重複:http://stackoverflow.com/questions/411103/function-with-same-name-but-different-signature-in-derived-class –

回答

5

本質上,名稱查找發生在重載解析之前,因此派生類中的函數A將覆蓋基類中的虛函數,但會隱藏所有其他基類中具有相同名稱的函數。

可能的解決方案包括將using Foo::A;指令添加到派生類中,以使所有基類成員在派生類中都可見或稱爲A,或者使用具有不同簽名的函數使用不同名稱。

另請參閱here

+0

很高興讓我的懷疑證實。你知道有關C++這個角落完整描述的鏈接嗎? – BCS

+1

標準的3.3.7 [basic.scope.hiding]中描述了名稱隱藏,名稱查找是3.4 [basic.lookup]的全部內容,並且有超載和重載解析的整個章節(13 [over])。儘管如此,您的情況的基本規則正如我所描述的那樣。 –

2

有在這兒有討論:http://bojolais.livejournal.com/222428.html

的癥結是:在C++中,當你有一個重載的方法(成員函數,無論你怎麼稱呼它)一類,然後您擴展和覆蓋這種方法,必須重寫所有的重載方法

一種解決方法是改變調用的:

b.Foo::A(0, 0); 
0

想着這個的最簡單方法是要記住,永遠超載發生在一個單一的範圍內,同時overrid ing在範圍之間出現。當找出要調用哪個函數時,編譯器FIRST會查找最接近的具有該名稱的作用域,然後解析該作用域中定義之間的重載。

0

要添加上述反應,

你也可以定義在酒吧的範圍,它總是調用美孚的範圍相同功能的重載函數,如果這是預期的結果。這可以更容易地看到代碼按預期運行。

2
// I think this kind of approach is best to avoid this kind of problems. 

class Foo 
{ 
private: 
    virtual int A_impl(int);  // note the private declaration 
    virtual int A_impl(int,int); // of the actual implementation. 
           // clients have access through the 
           // non-virtual interface. 

public: 
    inline int A(int x) 
    {       // the non virtual interface will always be visible. 
     return A_impl(x);  // and consistent. 
    } 
    inline int A(int x, int y) 
    { 
     if (x != y) {   // also permits global parameter validation 
      return A_impl(x, y); // and it's easier to set breakpoints on a 
     }      // single entry point. 
     return 0; 
    } 
}; 
class Bar : public Foo 
{ 
private: 
    virtual int A_impl(int); 
}; 

Bar b; 
int main() 
{ 
    b.A(0,0);     // never again stuff like: ((A*)&b)->A(0,0) 
}