我有一个关于使用虚方法和多重继承来调用函数的问题。 我有以下代码:
#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*)
答案 0 :(得分:4)
对于要选择的重载函数,它必须是接受每个单独参数的“最佳”,包括变为this
的隐式参数。 Best是根据将参数(在调用者中)转换为参数(在被调用者中)所需的最少转换来定义的。
virtual void f(C*) const
与C*
类型的参数完全一致,但最后的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的所有重载都是可接受的,因此调用是不明确的。
解决歧义的方法:
答案 2 :(得分:0)
void f(C *){std :: cout&lt;&lt; “X :: F(C *)\ n” 个;在基类中 由于名称隐藏而无法看到。
使用
using X::f;
在派生类中,它按预期工作。