为什么具有相同名称但不同签名的多重继承函数不被视为重载函数?

以下代码段在编译过程中产生了对 foo 的模棱两可的调用"错误,我想知道在不完全限定对 foo 的调用的情况下是否有任何方法可以解决此问题:

The following snippet produces an "ambigious call to foo" error during compilation, and I'd like to know if there is any way around this problem without fully qualifying the call to foo:

#include <iostream>

struct Base1{
    void foo(int){
    }
};

struct Base2{
    void foo(float){
    }
};

struct Derived : public Base1, public Base2{
};

int main(){
    Derived d;
    d.foo(5);

    std::cin.get();
    return 0;
}

所以,问题正如标题所说.想法?我的意思是,以下工作完美无缺:

So, question is as the title says. Ideas? I mean, the following works flawlessly:

#include <iostream>

struct Base{
    void foo(int){
    }
};

struct Derived : public Base{
    void foo(float){
    }
};

int main(){
    Derived d;
    d.foo(5);

    std::cin.get();
    return 0;
}

推荐答案

成员查找规则在第 10.2/2 节中定义

Member lookup rules are defined in Section 10.2/2

以下步骤定义了在类范围 C 中名称查找的结果.首先,考虑类及其每个基类子对象中名称的每个声明.子对象B中的成员名f隐藏子对象A中的成员名f,如果AB 的基类子对象.任何如此隐藏的声明都将被排除在外.通过 using 声明引入的这些声明中的每一个都被认为来自 C 的每个子对象,这些子对象属于包含 using 声明指定的声明的类型.如果声明的结果集并非全部来自同一类型的子对象,或者该集合具有非静态成员并包含来自不同子对象的成员,则存在歧义且程序格式错误.否则,该集合是查找的结果.

The following steps define the result of name lookup in a class scope, C. First, every declaration for the name in the class and in each of its base class sub-objects is considered. A member name f in one sub-object B hides a member name f in a sub-object A if A is a base class sub-object of B. Any declarations that are so hidden are eliminated from consideration. Each of these declarations that was introduced by a using-declaration is considered to be from each sub-object of C that is of the type containing the declara-tion designated by the using-declaration. If the resulting set of declarations are not all from sub-objects of the same type, or the set has a nonstatic member and includes members from distinct sub-objects, there is an ambiguity and the program is ill-formed. Otherwise that set is the result of the lookup.

class A {
public:
  int f(int);

};
class B {
public:
   int f();

};
class C : public A, public B {};
int main()
{
     C c;
     c.f(); // ambiguous
}

所以你可以使用 using 声明 A::fB::f 来解决歧义

So you can use the using declarations A::f and B::f to resolve that ambiguity

class C : public A, public B {
     using A::f;
     using B::f;

};

int main()
{
     C c;
     c.f(); // fine
}

第二个代码完美无缺,因为 void foo(float) 在 C 的范围内.实际上 d.foo(5); 调用的是 void foo(float) 而不是 int 版本.

The second code works flawlessly because void foo(float) is inside C's scope. Actually d.foo(5); calls void foo(float) and not the int version.

相关文章