调用覆盖的虚函数而不是重载

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 的对象上调用 fA 只有一个 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; }
};

LIVE

令人困惑的是你的:

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);