虚方法导致Derived类中的编译错误

时间:2011-09-01 18:25:16

标签: c++ inheritance virtual

考虑下一个代码:

#include <iostream>
using namespace std;

class A
{
public:
    virtual int f() {cout <<"A:: f()\n"; return 1;}
    virtual void f(int) {cout <<"A:: f(int)\n";}
    virtual void g() {cout <<"A::g()\n";}
};

class B3 : public A
{
public:
    void f() {cout <<"B3::f ()\n";}
};

int main()
{
    return 0;
}

它会产生以下错误:

..\main.cpp:17: error: conflicting return type specified for 'virtual void B3::f()'
..\main.cpp:9: error:   overriding 'virtual int A::f()'

但为什么呢?在最糟糕的情况下,我认为我有一个隐藏案例,但我得到关于A virtual int f() {cout <<"A:: f()\n"; return 1;}的编译错误

谢谢,Ronen

2 个答案:

答案 0 :(得分:0)

不要混淆覆盖与隐藏。你覆盖虚拟。

您的班级定义相当于:

class B3 : public A
{
public:
    virtual void f() {cout <<"B3::f ()\n";}
};

一旦函数声明为虚拟,它将对从基类派生的所有类保持虚拟,无论您是否明确声明它是虚拟的。因此,您尝试覆盖虚函数并更改其返回类型,这在C ++中是非法的。如果函数不是虚函数,则只需隐藏基类实现,因此更改返回类型是有效的。没有歧义,因为编译器会知道从哪里调用函数以及期望返回的类型。

但是,请考虑:

A* a;
....
a->f();

a-f()将返回什么? a是指向A的指针,但可以指向B3类型的对象。所以它要么返回一个int,要么不返回任何东西。看到这里的含糊不清?

相反,没有涉及多态,

A a;
a.f();

将从a得到cal f,与b3.f相同,将从B3调用f。 总而言之,覆盖基类函数意味着保持相同的返回类型。如果要创建具有不同返回类型的新函数,请更改其签名(其名称或参数 - 或两者)。

无论如何,你甚至不应该这样做...为什么你想要一个具有相同名称的功能,没有参数返回不同的东西?不会添加单独的函数更具可读性吗?

答案 1 :(得分:0)

如果f()具有不同的参数列表,或者未在基类上声明为虚拟,则会隐藏。在前一种情况下,由于重载不会跨越继承边界,A的{​​{1}}将被隐藏。但事实并非如此,因为这两个类都有f,只有返回值不同。返回值协方差是唯一允许的差异,因为情况并非如此(void不从int继承),就会出现错误。