Differing return type for virtual functions

一曲冷凌霜 提交于 2019-12-18 05:47:05

问题


A virtual function's return type should be the same type that is in base class, or covariant. But why do we have this restriction?


回答1:


Because of the nonsense that would ensue:

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?
}

It isn't sensible to have a derived class return something completely unrelated.




回答2:


Because how would the code that's using the return value cope with all sorts of unrelated types coming back? 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?



回答3:


According to C++ Standard:

The return type of an overriding function shall be either identical to the return type of the overridden func- tion or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:

1) both are pointers to classes or references to classes

2) the class in the return type of B::f is the same class as the class in the return type of D::f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D::f

3) both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.




回答4:


The answer is very similar to the one given for "Why can't I assign a vector<Apple*> to a vector<Fruit*>?" on Bjarne Stroustrup's FAQ.

The ability to modify the return type would lead to a hole in the type safety of the language (see the answer from @GManNickG for a specific example) when dealing with polymorphic types.

There is one fairly common situation when affecting the return type would be ideal: when returning a polymorphic pointer from a virtual method of a base type. For example,

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

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

Here we lost the type information that Child knows about it's parent_ member. This leads to lots of casting, even though the type was at one point well defined. We can solve this using the Curiously Recurring Template Parameter (CRTP) idiom,

template<class ParentType>
class Base {
public:
    virtual ParentType* parent()
    {
        return parent_;
    }

private:
    ParentType* parent_;

};

class Child : public Base<Parent> {
};


来源:https://stackoverflow.com/questions/4826356/differing-return-type-for-virtual-functions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!