说我有这部分代码:
#include<iostream>
using namespace std;
class A {
public:
virtual int f(const A& other) const { return 1; }
};
class B : public A {
public:
int f(const A& other) const { return 2; }
virtual int f(const B& other) const { return 3; }
};
void go(const A& a, const A& a1, const B& b) {
cout << a1.f(a) << endl; //Prints 2
cout << a1.f(a1) << endl; //Prints 2
cout << a1.f(b) << endl; //Prints 2
}
int main() {
go(A(), B(), B());
system("pause");
return 0;
}
我能理解为什么前两个会打印2.但我不明白为什么最后一个打印也是2.为什么它不喜欢B
中的重载函数?
答案 0 :(得分:4)
int B::f(const B& other) const
不会override int A::f(const A& other) const
,因为参数类型不同。然后,在引用基类f()
时,不会通过调用A
来调用它。
如果某个成员函数vf在a中声明为virtual class Base,以及派生的一些类Derived,直接或派生 间接地,来自Base,有一个成员函数声明 相同
name parameter type list (but not the return type) cv-qualifiers ref-qualifiers
然后Derived类中的这个函数也是虚函数(无论是否为 不是关键字virtual在其声明中使用)和覆盖 Base :: vf(无论是否使用单词覆盖) 声明)。
如果使用override specifier(自C ++ 11起),编译器将生成错误。
class B : public A {
public:
int f(const A& other) const { return 2; }
virtual int f(const B& other) const override { return 3; }
};
例如Clang:
source_file.cpp:10:17: error: 'f' marked 'override' but does not override any member functions
virtual int f(const B& other) const override { return 3; }
^
如果在基类中为它添加重载,则可能得到所需的内容。请注意,将需要类B
的前向声明。
class B;
class A {
public:
virtual int f(const A& other) const { return 1; }
virtual int f(const B& other) const { return 1; }
};
答案 1 :(得分:1)
这很容易,真的。您在具有静态类型f
的对象上调用A
。 A
只有一个f
,因此vtable
中只有一个条目用于该功能。重载解析发生在编译时。只有在静态类型为B
答案 2 :(得分:0)
混乱来自你的:
int f(const A& other) const { return 2; }
行实际上也是虚拟的,并且覆盖了你的行:
virtual int f(const A& other) const { return 1; }
同时,行:
virtual int f(const B& other) const { return 3; }
最终被完全忽略,因为所有内容都与“返回1”行匹配,然后在链上以多态方式跟随“返回2”行。正如另一张海报所说,const B
部分意味着它与多态方法调用不匹配。
顺便说一句:如果你在第一行获得2,我怀疑不受欢迎的堆栈行为。我期待一个1.也许尝试这样分配:
A a1;
B b1, b2;
go(a1, b1, b2);