C++虚函数返回类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4665117/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ virtual function return type
提问by Bob
Is it possible for an inherited class to implement a virtual function with a different return type (not using a template as return)?
继承的类是否可以实现具有不同返回类型的虚函数(不使用模板作为返回)?
回答by templatetypedef
In some cases, yes, it is legal for a derived class to override a virtual function using a different return type as long as the return type is covariantwith the original return type. For example, consider the following:
在某些情况下,是的,只要返回类型与原始返回类型协变,派生类使用不同的返回类型覆盖虚函数是合法的。例如,请考虑以下情况:
class Base {
public:
virtual ~Base() {}
virtual Base* clone() const = 0;
};
class Derived: public Base {
public:
virtual Derived* clone() const {
return new Derived(*this);
}
};
Here, Base
defines a pure virtual function called clone
that returns a Base *
. In the derived implementation, this virtual function is overridden using a return type of Derived *
. Although the return type is not the same as in the base, this is perfectly safe because any time you would write
在这里,Base
定义了一个纯虚函数clone
,它返回一个Base *
. 在派生实现中,此虚函数使用返回类型Derived *
. 尽管返回类型与基类中的不同,但这是完全安全的,因为任何时候您都可以编写
Base* ptr = /* ... */
Base* clone = ptr->clone();
The call to clone()
will always return a pointer to a Base
object, since even if it returns a Derived*
, this pointer is implicitly convertible to a Base*
and the operation is well-defined.
对 的调用clone()
将始终返回一个指向Base
对象的指针,因为即使它返回 a Derived*
,该指针也可以隐式转换为 aBase*
并且操作是明确定义的。
More generally, a function's return type is never considered part of its signature. You can override a member function with any return type as long as the return type is covariant.
更一般地说,函数的返回类型永远不会被视为其签名的一部分。只要返回类型是协变的,您就可以使用任何返回类型覆盖成员函数。
回答by Rob Kennedy
Yes. The return types are allowed to be different as long as they are covariant. The C++ standard describes it like this (§10.3/5):
是的。返回类型可以不同,只要它们是协变的。C++ 标准是这样描述的(第 10.3/5 节):
The return type of an overriding function shall be either identical to the return type of the overridden function or covariantwith the classes of the functions. If a function
D::f
overrides a functionB::f
, the return type of the functions are covariant if the satisfy the following criteria:
- both are pointers to classes or references to classes98)
- the class in the return type of
B::f
is the same class as the class in the return type ofD::f
or, is an unambiguous direct or indirect base class of the class in the return type ofD::f
and is accessible inD
- 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 ofB::f
.
覆盖函数的返回类型应与覆盖函数的返回类型相同或与函数的类协变。如果一个函数
D::f
覆盖一个函数B::f
,如果满足以下条件,函数的返回类型是协变的:
- 两者都是指向类的指针或对类的引用98)
- 返回类型中
B::f
的类与D::f
或返回类型中的类相同,是返回类型中的类的明确直接或间接基类,D::f
并且可以在D
- 指针或引用都具有相同的 cv 限定,并且 的返回类型中的类类型
D::f
具有与的返回类型中的类类型相同或更少的 cv 限定B::f
。
Footnote 98 points out that "multi-level pointers to classes or references to multi-level pointers to classes are not allowed."
脚注 98 指出“不允许使用指向类的多级指针或对指向类的多级指针的引用”。
In short, if D
is a subtype of B
, then the return type of the function in D
needs to be a subtype of the return type of the function in B
. The most common example is when the return types are themselves based on D
and B
, but they don't have to be. Consider this, where we two separate type hierarchies:
简而言之,如果D
是 的子B
类型,则函数in的返回类型D
需要是函数in的返回类型的子类型B
。最常见的例子是当返回类型本身基于D
and 时B
,但它们不一定是。考虑一下,我们有两个不同的类型层次结构:
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 this works is because any caller of func
is expecting a Base
pointer. Any Base
pointer will do. So, if D::func
promises to always return a Derived
pointer, then it will always satisfy the contract laid out by the ancestor class because any Derived
pointer can be implicitly converted to a Base
pointer. Thus, callers will always get what they expect.
这样做的原因是因为任何调用者都func
在期待一个Base
指针。任何Base
指针都可以。因此,如果D::func
承诺始终返回一个Derived
指针,那么它将始终满足祖先类制定的契约,因为任何Derived
指针都可以隐式转换为Base
指针。因此,呼叫者将始终得到他们所期望的。
In addition to allowing the return type to vary, some languages allow the parameter typesof the overriding function to vary, too. When they do that, they usually need to be contravariant. That is, if B::f
accepts a Derived*
, then D::f
would be allowed to accept a Base*
. Descendants are allowed to be looserin what they'll accept, and stricterin what they return. C++ does not allow parameter-type contravariance. If you change the parameter types, C++ considers it a brand new function, so you start getting into overloading and hiding. For more on this topic, see Covariance and contravariance (computer science)in Wikipedia.
除了允许返回类型变化之外,一些语言还允许覆盖函数的参数类型变化。当他们这样做时,他们通常需要逆变。也就是说,如果B::f
接受 a Derived*
,则将D::f
允许接受 a Base*
。后代被允许在他们接受的方面更宽松,在他们返回的方面更严格。C++ 不允许参数类型逆变。如果您更改参数类型,C++ 会将其视为一个全新的函数,因此您会开始重载和隐藏。有关此主题的更多信息,请参阅Wikipedia 中的协方差和逆变(计算机科学)。
回答by Nikolai Fetissov
A derived class implementation of the virtual function can have a Covariant Return Type.
虚函数的派生类实现可以具有协变返回类型。