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

Xeo*_*Xeo 49 c++ scope overloading multiple-inheritance

下面的代码片段在编译过程中会产生一个"foo的foo调用"错误,我想知道如果没有完全限定对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;
}
Run Code Online (Sandbox Code Playgroud)

所以,问题就像标题所说的那样.想法?我的意思是,以下工作完美无瑕:

#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;
}
Run Code Online (Sandbox Code Playgroud)

Pra*_*rav 48

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

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

class A {
public:
  int f(int);

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

};
class C : public A, public B {};
int main()
{
     C c;
     c.f(); // ambiguous
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用using声明A::fB::f解决这种歧义

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

};

int main()
{
     C c;
     c.f(); // fine
}
Run Code Online (Sandbox Code Playgroud)

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

  • 被调用的`void foo(float)`版本真的让我在那里..感谢您的广泛回答.:) (2认同)
  • **如果生成的声明集合包括来自不同子对象的成员,则存在歧义并且程序格式错误**此规则的原因是什么?否则会发生什么的例子会很好. (2认同)

M.M*_*M.M 6

名称查找重载解析的单独阶段。

名称查找首先发生。这是确定名称适用于哪个范围的过程。在这种情况下,我们必须决定是否为d.foo均值d.D::foo,或d.B1::food.B2::foo。名称查找规则不考虑功能参数或其他任何内容;它纯粹是关于名称和范围的。

仅在做出决定后,我们才对找到名称的作用域中函数的不同重载执行重载解析。

在您的示例中,调用d.foo()将查找D::foo()是否存在这样的功能。但是没有。因此,向后扩展范围,它将尝试基类。现在,foo同样可以查找到B1::fooB2::foo因此它是不明确的。

出于同样的原因,foo(5);D成员函数内部调用unqualified会引起歧义。


推荐解决方案的效果:

struct Derived : public Base1, public Base2{
    using Base1::foo;
    using Base2::foo;
Run Code Online (Sandbox Code Playgroud)

是它创建了名称D::foo,并使其标识两个功能。结果是d.foo解析为d.D::foo,然后对标识的这两个函数可能会发生重载解析D::foo

注意:在此示例中D::foo(int)Base1::foo(int)是一个功能的两个标识符;但是总的来说,对于名称查找和重载解析过程,它们是否是两个独立的函数并没有什么区别。