虚函数的返回类型不同

时间:2011-01-28 08:47:27

标签: c++ override virtual-functions return-type covariant

虚函数的返回类型应与基类或协变中的类型相同。但为什么我们有这个限制?

4 个答案:

答案 0 :(得分:13)

由于随之而来的废话:

struct foo
{
    virtual int get() const { return 0; }
};

struct bar : foo
{
    std::string get() const { return "this certainly isn't an int"; }
};

int main()
{
    bar b;
    foo* f = &b;

    int result = f->get(); // int, right? ...right?
}

让派生类返回完全不相关的东西是不明智的。

答案 1 :(得分:5)

因为使用返回值的代码如何处理各种不相关的类型? e.g:

class A
{
public:
    virtual float func();
};

class B: public A
{
public:
    virtual char *func();
};

A *p = (some_condition) ? new A() : new B();
p->func();  // Oh no! What is the type?

答案 2 :(得分:3)

根据C ++标准:

  

重写函数的返回类型应与重写函数的返回类型相同 -   与函数类相关或协变。如果函数D :: f覆盖函数B :: f,则   如果函数的返回类型满足以下条件,则它们是协变的:

     

1)都是指向类的引用或类的引用

     

2) B :: f的返回类型中的类与返回类型D :: f中的类相同,或者是   返回类型为D :: f

的类的明确且可访问的直接或间接基类      

3)指针或引用在D :: f的返回类型中具有相同的cv-qualification和类类型   与B :: f的返回类型中的类类型具有相同的cv资格或更少的cv资格。

答案 3 :(得分:1)

答案与Bjarne Stroustrup常见问题解答"Why can't I assign a vector<Apple*> to a vector<Fruit*>?"给出的答案非常类似。

在处理多态类型时,修改返回类型的能力会导致语言类型安全漏洞(请参阅@GManNickG的答案,了解具体示例)。

当影响返回类型时,有一种相当常见的情况是理想的:从基类型的虚方法返回多态指针时。例如,

class Base {
public:
    virtual Base* parent() = 0;
};

class Child : public Base {
public:
    Base* parent() override
    {
        return parent_;
    }
private:
    Parent* parent_;  // Assume `Parent` type exists.
};

我们丢失了Child了解parent_成员的类型信息。这导致大量的铸造,即使该类型在一个定义明确的位置。我们可以使用Curiously Recurring Template Parameter(CRTP)习语

来解决这个问题
template<class ParentType>
class Base {
public:
    virtual ParentType* parent()
    {
        return parent_;
    }

private:
    ParentType* parent_;

};

class Child : public Base<Parent> {
};