调用覆盖的虚函数而不是重载
Calling overrided virtual function instead of overloaded
假设我有这部分代码:
#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
中的重载函数?
我已经看过 this and this 但我无法从中理解。
真的很简单。您在静态类型为 A
的对象上调用 f
。 A
只有一个 f
,因此 vtable
中只有一个条目用于该函数。重载解析发生在编译时。只有在 static 类型为 B
的对象上调用重载才会被解析
int B::f(const B& other) const
没有 override int A::f(const A& other) const
因为参数类型不一样。然后它不会通过调用 f()
基数 class A
.
的引用来调用
If some member function vf is declared as virtual in a
class Base, and some class Derived, which is derived, directly or
indirectly, from Base, has a declaration for member function with the
same
name
parameter type list (but not the return type)
cv-qualifiers
ref-qualifiers
Then this function in the class Derived is also virtual (whether or
not the keyword virtual is used in its declaration) and overrides
Base::vf (whether or not the word override is used in its
declaration).
如果您使用 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; }
^
如果您在基础 class 中为它添加一个重载,您可能会得到您想要的。请注意,需要 class B
的前向声明。
class B;
class A {
public:
virtual int f(const A& other) const { return 1; }
virtual int f(const B& other) const { return 1; }
};
令人困惑的是你的:
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; }
最终被完全忽略,因为所有内容都匹配 "return 1" 行,然后多态地沿着链向上到达 "return 2" 行。正如另一位发帖人所说,const B
部分意味着它不会匹配多态方法调用。
顺便说一句:如果您在第一行得到 2,我怀疑是意外的堆栈行为。我希望是 1。也许尝试这样分配:
A a1;
B b1, b2;
go(a1, b1, b2);
假设我有这部分代码:
#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
中的重载函数?
我已经看过 this and this 但我无法从中理解。
真的很简单。您在静态类型为 A
的对象上调用 f
。 A
只有一个 f
,因此 vtable
中只有一个条目用于该函数。重载解析发生在编译时。只有在 static 类型为 B
int B::f(const B& other) const
没有 override int A::f(const A& other) const
因为参数类型不一样。然后它不会通过调用 f()
基数 class A
.
If some member function vf is declared as virtual in a class Base, and some class Derived, which is derived, directly or indirectly, from Base, has a declaration for member function with the same
name parameter type list (but not the return type) cv-qualifiers ref-qualifiers
Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration) and overrides Base::vf (whether or not the word override is used in its declaration).
如果您使用 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; }
^
如果您在基础 class 中为它添加一个重载,您可能会得到您想要的。请注意,需要 class B
的前向声明。
class B;
class A {
public:
virtual int f(const A& other) const { return 1; }
virtual int f(const B& other) const { return 1; }
};
令人困惑的是你的:
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; }
最终被完全忽略,因为所有内容都匹配 "return 1" 行,然后多态地沿着链向上到达 "return 2" 行。正如另一位发帖人所说,const B
部分意味着它不会匹配多态方法调用。
顺便说一句:如果您在第一行得到 2,我怀疑是意外的堆栈行为。我希望是 1。也许尝试这样分配:
A a1;
B b1, b2;
go(a1, b1, b2);