C ++:没有指针的协变返回类型

时间:2017-12-28 04:46:18

标签: c++ pointers covariant-return-types

我通过继承创建了两个简单的类,并在子类中添加了一个虚函数和覆盖。

class Parent
{
public:
    virtual Parent foo();
};

class Child : public Parent
{
public:
    Child foo() override;
};

在这种情况下,我的重写函数会出错:error C2555: 'Child::foo': overriding virtual function return type differs and is not covariant from 'Parent::foo'

如果我用指针改变返回类型:

class Parent
{
public:
    virtual Parent* foo();
};

class Child : public Parent
{
public:
    Child* foo() override;
};

错误消失了! 我不明白为什么返回类型的协方差必须用指针完成,我不能使用值类型或引用。 一些网站或论坛解释说,因为返回的值是函数中使用的值的副本,编译器知道指针的常量大小,但必须指示被覆盖函数和父函数的不同大小,这显然是不可能的。

那么,为什么我不能在这种情况下使用除指针以外的任何东西? 如果我希望子类型在不使用指针的情况下键入重写函数,那么我必须为每个函数返回基类并将返回的类型转换为子类型吗?

2 个答案:

答案 0 :(得分:5)

协变返回类型的概念是多态返回类型。而在C ++中,没有指针或引用就不能有运行时多态性。让我们忽略了大部分的艰辛,并假装它是可能的。以下是我的Task.yield界面处理内容的代码:

Parent

什么是void bar(Parent * p) { auto o = p->foo(); } ?嗯,当然是o。在Parent的返回类型中说的是这样的。但是如果Parent::foo指向p怎么办?推导出的Child类型仍然是o,所以我最多得到一个切片对象。没有多态行为,因此整个练习毫无意义。

在最坏的情况下,我很可能会得到未定义的行为。

这就是为什么共变量返回类型必须是指针或引用。

答案 1 :(得分:0)

这是因为派生类型会返回派生实例但调用者期望父类,这与使用指针时不同,在指针情况下,派生指针可以滑入为父指针保留的空间但是在谈论实际情况时,情况并非如此。你还有一个问题,派生的方法会返回一个派生的实例,但使用父指针的调用者不知道这一点,因此可能只会破坏父部分。

您可以找到this有用的