簡體   English   中英

帶有繼承的C ++靜態成員函數重載

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM