Yes. The types of returned data may be different if they are covariant . The C ++ standard describes this as follows (Β§10.3 / 5):
The return type of an overriding function must either be identical to the return type of an overridden function, or covariant with function classes. If the function D::f overrides the function B::f , the return type of the functions is covariant if they satisfy the following criteria:
- both are pointers to classes or class references 98)
- the class of the return type
B::f is the same class as the class of the return type D::f or, is the unambiguous direct or indirect base class of the class in the return type D::f and is available in D - both pointers or references have the same cv qualification, and the class type in the return type
D::f has the same cv qualification as or less cv-qualification than the class type in the return type B::f .
Footnote 98 indicates that "multilevel pointers to classes or references to multilevel pointers to classes are not permitted."
In short, if D is a subtype of B , then the return type of the function in D must be a subtype of the return type of the function in B The most common example is when return types themselves are based on D and B , but they do not have to be. Consider this where we have two separate type hierarchies:
struct Base { }; struct Derived: public Base { }; struct B { virtual Base* func() { return new Base; } virtual ~B() { } }; struct D: public B { Derived* func() { return new Derived; } }; int main() { B* b = new D; Base* base = b->func(); delete base; delete b; }
The reason for this is that any func caller expects a Base pointer. Any Base pointer will do. So, if D::func promises always returns a Derived pointer, then it will always satisfy the contract set by the ancestor class, because any Derived pointer can be implicitly converted to a Base pointer. This way, subscribers will always get what they expect.
In addition to the fact that the type of the return value may vary, some languages ββalso allow you to change the types of parameters of the override function. When they do this, they usually have to be contravariant. That is, if B::f accepts a Derived* , then D::f will be allowed to accept Base* . Descendants are allowed to be free in what they will accept, and more strict in what they return. C ++ does not allow contravariance of the parametric type. If you change the types of parameters, C ++ considers this a completely new function, so you start to overload and hide. For more on this topic, see Covariance and contravariance (computer science) on Wikipedia.
Rob Kennedy Jan 12 2018-11-11T00: 00Z
source share