【问题标题】:Virtual method causes compilation error in Derived class虚拟方法导致派生类中的编译错误
【发布时间】:2011-09-01 18:25:16
【问题描述】:

考虑下一个代码:

#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 &lt;&lt;"A:: f()\n"; return 1;}

谢谢,罗南

【问题讨论】:

    标签: c++ inheritance virtual


    【解决方案1】:

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

    你的类定义相当于:

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

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

    但是,请考虑:

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

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

    相反,不涉及多态性,

    A a;
    a.f();
    

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

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

    【讨论】:

      【解决方案2】:

      如果f() 有一个不同的参数列表,或者没有在基类上声明为虚拟,你就会隐藏。在前一种情况下,由于重载不会跨越继承边界,Af 将被隐藏。但事实并非如此,因为您在两个类上都有 f(),它们仅在返回值上有所不同。返回值协方差是唯一允许的差异,因为它不是这种情况(void 不从 int 继承),你会得到错误。

      【讨论】:

      • 您不需要不同的参数列表来隐藏基本函数。
      • @Luchian,是的,你也可以使用不同的常量来隐藏。你是这么想的吗?有没有其他方法可以隐藏虚函数?
      猜你喜欢
      • 1970-01-01
      • 2013-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多