c ++静态成员函数重载与继承

时间:2017-04-24 19:44:29

标签: c++ inheritance static-methods

我有以下代码:

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'都可以正常工作。

有很多解决方案可以解决第一个代码块(template traits等)。我特别想要的是通过继承来重载方法。我不明白为什么来自Derived的调用是模糊的(因为输入参数有不同的类型,从编译器的角度看这些函数是不同的。就像在DifferentHandler中一样)

注意:我在VS2015中尝试过MinGW5.8(在Qt Creator中)和MSVC2015。两个编译器都生成了相同的错误。

2 个答案:

答案 0 :(得分:2)

你走了:

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

修复您的问题。

原始代码不起作用的原因可以在C ++标准中找到。以下是有趣的引语:

在10/2:

  

基类成员据说由派生类继承。   可以以相同的方式在表达式中引用继承的成员   作为派生类的其他成员,除非它们的名称被隐藏   或含糊不清(10.2)。

继续阅读10.2:

  

成员名称查找确定名称(id-expression)的含义   一个范围(3.3.7)。名称查找可能导致歧义   该案件的格式错误......

     

...由两个组件集组成:声明集,a   成员名为 f ...

     

如果明确找到重载函数的名称,则在访问控制之前也会发生重载分辨率(13.3)

基本上,它首先按名称命名并稍后应用解决方案。通过using声明将它们引入派生类会将它们全部放在派生类的范围内,其中正常的解析规则会被启动。

答案 1 :(得分: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

语法指定您要调用基类版本,但这在现实世界中很少见。)