2017-04-24 151 views
0

我有以下代碼:C++靜態成員函數具有繼承重載

struct CommonVariables 
{/*some common variables that need to be proceed*/}; 

struct CommonHandler 
{ 
    static void foo(const CommonVariables& vars) {/*processed vars*/} 
    void bar(const CommonVariables& vars) {/*processed vars*/} 
}; 

struct AnotherVariables 
{/*another variables*/}; 

struct AnotherHandler 
{ 
    static void foo(const AnotherVariables& vars) {/*processed vars*/} 
    void bar(const AnotherVariables& vars) {/*processed vars*/} 
}; 

struct Derived : CommonHandler, AnotherHandler 
{}; 

當我嘗試調用派生:: foo的(/ 任何變量類型 /)或衍生d; d.bar(/ 任何變量類型 /),編譯器給我一個錯誤:「引用'foo(或bar)'是不明確的」。

然而,下面我幾乎同樣的情況:

struct DifferentHandler 
{ 
static void foo(const CommonVariables& vars) {} 
static void foo(const AnotherVariables& vars) {} 
void bar(const AnotherVariables& vars) {} 
void bar(const CommonVariables& vars) {} 
}; 

,並呼籲DifferentHandler :: foo的(/ 任何變量類型 /)或 '酒吧' 工作得很好。

有很多解決方案可以解決第一個代碼塊(template traits等)的問題。我特別想要的是通過繼承來重載方法。我不明白爲什麼來自Derived的調用是模棱兩可的(因爲輸入參數有不同的類型,從編譯器的角度來看這些函數是不同的,就像在DifferentHandler中一樣)

注意:我試過MinGW5.8(在Qt Creator)以及VS2015中的MSVC2015。兩個編譯器都會產生相同的錯誤

+1

重複:http://stackoverflow.com/questions/5365689/c-overload-static-function-with-non-static-function我不知道如何或沒有特權標記爲這樣。 –

+0

@ChristopherPisz,這是你鏈接的帖子的副本?我沒有看到相似之處。 – SergeyA

+2

這個問題爲什麼downvoted?什麼人不喜歡它? – SergeyA

回答

2

在這裏你去:

struct Derived : CommonHandler, AnotherHandler 
{ 
    using CommonHandler::foo; 
    using CommonHandler::bar; 
    using AnotherHandler::foo; 
    using AnotherHandler::bar; 
}; 

解決您的問題。

原始代碼不工作的原因可以在C++標準中找到。這裏是有趣的報價:

在10/2:

The base class members are said to be inherited by the derived class. Inherited members can be referred to in expressions in the same manner as other members of the derived class, unless their names are hidden or ambiguous (10.2).

繼續閱讀以10.2:

Member name lookup determines the meaning of a name (id-expression) in a class scope (3.3.7). Name lookup can result in an ambiguity, in which case the program is ill-formed....

...consists of two component sets: the declaration set, a set of members named f...

If the name of an overloaded function is unambiguously found, overloading resolution (13.3) also takes place before access control

基本上,它會首先按名稱,後來應用的分辨率。通過using聲明將它們引入派生類,將它們全部放在派生類的範圍內,其中正常解析規則引入。

+1

你能解釋一下這個問題究竟是什麼以及爲什麼解決這個問題?在最初的代碼中,編譯器只是首先按名稱搜索(而不是完整原型),並且不能決定先查看CommonHandler還是AnotherHandler?或者是其他東西? – Kevin

+0

@SergeyA,謝謝!這真的按計劃運作。 –

+0

@凱文,看到更新的答案。 – SergeyA

0

在C++中,如果派生類的成員函數與基類的成員函數名稱相同,則派生類的版本將隱藏的基本版本 - 即使函數簽名不同,並且否則你會期望它們超載。 (如果基類成員函數是虛擬的,那麼派生類的簽名必須完全匹配*,否則它將(通常無意地)隱藏基類的版本 - 這就是C++ 11添加了override psuedo-keyword的原因。

例如:

struct base { 
    void foo(std::string s) {} 
}; 

struct derived : base { 
    void foo(int i) {} 
}; 

int main() { 
    derived d; 
    d.foo("hello"); // Error -- cannot convert const char* to int 
} 

的解決方案是使用一個using指令,以使基類的成員函數到派生類範圍,即

struct derived : base { 
    using base::foo; 
    void foo(int i) {} 
}; 

(另一種方法是使用晦澀

derived d; 
d.base::foo("hello"); // works 

語法指定要調用基類的版本,但是這是在現實世界中很少見到。)

+0

Thnx簡化說明! –