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

时间:2016-06-29 10:10:28

标签: c++ override overloading

说我有这部分代码:

#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中的重载函数?

我已经查看了thisthis,但我无法理解这些内容。

3 个答案:

答案 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; }
};

LIVE

答案 1 :(得分:1)

这很容易,真的。您在具有静态类型f的对象上调用AA只有一个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);