2016-02-24 59 views
1

原諒不明確的標題。這可能是重複的,但我找不到正確的詞組。具有不同簽名的兩個函數的繼承隱藏非虛函數

考慮以下繼承層次結構。

class A 
{ 
public: 
    virtual void Foo(int i) { printf("A::Foo(int i)\n"); } 
    void Foo(int a, int b) { Foo(a + b); } 
}; 

class B : public A 
{ 
public: 
    void Foo(int i) override { printf("B::Foo(int i)\n"); } 
}; 

class C : public B 
{ 
public: 
    void Bar() { Foo(1, 2); } //error C2660: function does not take two arguments 
}; 

A有一個名爲Foo用不同數量的參數兩種方法。其中只有一個是虛擬的。
B覆蓋虛擬方法。
C嘗試調用非虛方法並遇到錯誤。

調用該方法爲A::Foo(1, 2)確實工作正常。

問題: 爲什麼編譯器不能推斷在A上找到了正確的方法?

這似乎很奇怪,我們將不得不在一個調用,如明確添加A::

C c; 
c.A::Foo(1, 2); 
+4

您可以添加使用'A ::富;''在B',然後重載'Foo'是沒有尷尬的語法進行訪問。 – davidhigh

+0

@davidhigh很好的解決方法,謝謝! – Rotem

回答

2

因爲命名Foo成員函數是在B類範圍內發現的,然後命名查詢停止,所以A中的Foo是不可見的,即使類A中的版本更合適,也不會被視爲重載分辨率。這是名稱隱藏。

您可以使用using將它們引入到相同的作用域中,並按照您的預期進行重載解析。如:

class C : public B 
{ 
    using A::Foo; 
    using B::Foo; 
public: 
    void Bar() { Foo(1, 2); } 
}; 

Unqualified name lookup

LIVE

+0

是的,這顯然是這種情況,但爲什麼?標準要求名稱查找是否在第一次匹配時停止,或者更適應性的編譯器是否能夠找到正確的簽名? – Rotem

+0

@Rotem:https://en.wikipedia.org/wiki/Dominance_%28C%2B%2B%29 <<<就是你的問題。這是設計。這可能是一個「更容納」的編譯器接受它,就像編譯器接受void main一樣。還有另一個詞來描述這樣的編譯器:「不正確」。一個好的編譯器是嚴格的。 – Aziuth

+1

http://en.cppreference.com/w/cpp/language/unqualified_lookup –