虚拟表和继承c ++

时间:2014-02-08 10:37:23

标签: c++ inheritance

我有一个关于使用虚方法和多重继承来调用函数的问题。 我有以下代码:

#include<iostream>
using namespace std;
class A{};
class B:public A{};
class C:public B{};
class AA:public A{};
struct X
{
    void f(A*) { std::cout<< "X::f(A*)\n";}
    virtual void f(B*) { std::cout<< "X::f(B*)\n";}
    void f(C*) { std::cout<< "X::f(C*)\n";}
    virtual void f(C*) const { std::cout<< "const X::f(C*)\n";}
};
struct Y:public X {
    virtual void f(B*) { std::cout<< "Y::f(B*)\n";}
    void f(A*) { std::cout<< "Y::f(A*)\n";}
    virtual void f(C*) const { std::cout<< "const Y::f(C*)\n";}
};
int main() {   
    Y* y=new Y();
    y->f(new C);
}

我无法理解为什么这会变得含糊不清并且有两个候选人:

 Y::f(B*)
 Y::f(C*)

3 个答案:

答案 0 :(得分:4)

对于要选择的重载函数,它必须是接受每个单独参数的“最佳”,包括变为this的隐式参数。 Best是根据将参数(在调用者中)转换为参数(在被调用者中)所需的最少转换来定义的。

virtual void f(C*) constC*类型的参数完全一致,但最后的const限定符要求this转换为非常量Y*Y const *。这就是编译器所抱怨的。如果你施放

static_cast< Y const * >( y )->f(new C);

问题消失了(虽然这不是立即说明的,因为额外的资格取消了其他超载的资格)。

请注意,X中的所有重载都不会被检查。找到要考虑的所有重载的名称解析从派生类开始,继续继承分支,直到找到匹配的名称​​,然后停止。要将多个类中的函数合并到一个重载集中,请在using Y内使用using X::f;声明。

这个问题的实际解决方案可能是在最后引入更多匹配的重载而没有const限定符,因此调用指针的const限定不会发挥如此不直观的作用。

答案 1 :(得分:2)

C的重载是唯一的const成员函数。 y是非常量的,并且f的所有重载都是可接受的,因此调用是不明确的。

解决歧义的方法:

  • 为C
  • 添加非常量重载
  • 制作y const
  • 为A和B const设置重载

答案 2 :(得分:0)

void f(C *){std :: cout&lt;&lt; “X :: F(C *)\ n” 个;在基类中 由于名称隐藏而无法看到。

使用 using X::f; 在派生类中,它按预期工作。