[英]c++ static member function overloading with inheritance
我有以下代碼:
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
{};
當我嘗試調用Derived :: foo(/ 任何變量類型 /)或Derived 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(/ 任何變量類型 /)或'bar'都很好。
有很多解決方案可以解決第一個代碼塊( 模板特征等)。 我特別想要的是通過繼承重載方法。 而且我不明白為什么來自Derived的調用是模棱兩可的(因為輸入參數具有不同的類型,從編譯器的角度來看,這些函數是不同的。例如在DifferentHandler中)
注意:我已經嘗試了MinGW5.8(在Qt Creator中)和VS2015中的MSVC2015。 兩種編譯器均產生相同的錯誤。
干得好:
struct Derived : CommonHandler, AnotherHandler
{
using CommonHandler::foo;
using CommonHandler::bar;
using AnotherHandler::foo;
using AnotherHandler::bar;
};
解決您的問題。
C ++標准中找到了原始代碼無法正常工作的原因。 這是有趣的報價:
在10/2中:
據說基類成員是派生類繼承的。 可以以與派生類的其他成員相同的方式在表達式中引用繼承的成員,除非其名稱是隱藏的或不明確的(10.2)。
繼續閱讀10.2:
成員名稱查找確定類作用域(3.3.7)中名稱(id-表達式)的含義。 名稱查找可能導致歧義,在這種情況下,程序格式不正確。
...由兩個組件集組成:聲明集,一組名為 f ...的成員
如果明確找到了重載函數的名稱,則在訪問控制之前也會發生重載解析(13.3)。
基本上,它先命名,然后再應用解析。 通過using
聲明將它們引入派生類,將它們全部置於派生類的范圍內,在這里正常解析規則起作用。
在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
用於指定您要調用基類版本的語法,但這在現實世界中很少見。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.