提问人:zzzbbx 提问时间:1/12/2011 最后编辑:templatetypedefzzzbbx 更新时间:4/20/2021 访问量:65390
C++ 虚函数返回类型
C++ virtual function return type
答:
是的。只要返回类型是协变的,就允许它们不同。C++ 标准是这样描述的(§10.3/5):
重写函数的返回类型应与被重写函数的返回类型相同,或与函数的类协变。如果一个函数覆盖一个函数,则函数的返回类型是协变的,如果满足以下条件:
D::f
B::f
- 两者都是指向类的指针或对类98 的引用)
- 返回类型 的类与返回类型 的 or 中的类是同一个类,是返回类型 的类的明确直接或间接基类,可在
B::f
D::f
D::f
D
- 两个指针或引用具有相同的 cv 限定,并且返回类型 中的类类型与返回类型 中的类类型具有相同的 cv 限定,或比返回类型中的类类型具有相同的 cv 限定。
D::f
B::f
脚注 98 指出,“不允许使用指向类的多级指针或指向类的多级指针。
简而言之,如果 是 的子类型,则 中的函数的返回类型必须是 中函数的返回类型的子类型。最常见的例子是返回类型本身基于 和 ,但不必如此。考虑一下,我们有两个单独的类型层次结构:D
B
D
B
D
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;
}
这样做的原因是,任何调用者都期望指针。任何指针都可以。因此,如果承诺始终返回指针,那么它将始终满足祖先类制定的约定,因为任何指针都可以隐式转换为指针。因此,来电者将始终得到他们所期望的。func
Base
Base
D::func
Derived
Derived
Base
除了允许返回类型发生变化外,某些语言还允许重写函数的参数类型发生变化。当他们这样做时,他们通常需要逆变。也就是说,如果接受 a ,则允许接受 .后代被允许在他们接受的东西上更宽松,在他们返回的东西上更严格。C++ 不允许参数类型的逆变。如果更改参数类型,C++ 会将其视为一个全新的函数,因此您开始进入重载和隐藏状态。有关此主题的更多信息,请参阅维基百科中的协方差和逆方差(计算机科学)。B::f
Derived*
D::f
Base*
评论
虚函数的派生类实现可以具有协变返回类型。
在某些情况下,是的,只要返回类型与原始返回类型协变,派生类使用不同的返回类型覆盖虚函数是合法的。例如,请考虑以下事项:
class Base {
public:
virtual ~Base() {}
virtual Base* clone() const = 0;
};
class Derived: public Base {
public:
virtual Derived* clone() const {
return new Derived(*this);
}
};
这里,定义了一个名为 的纯虚函数,该函数返回 .在派生实现中,使用返回类型 重写此虚函数。尽管返回类型与基数中的返回类型不同,但这是完全安全的,因为任何时候您都会写入Base
clone
Base *
Derived *
Base* ptr = /* ... */
Base* clone = ptr->clone();
对的调用将始终返回指向对象的指针,因为即使它返回 ,此指针也可以隐式转换为 a,并且操作是明确定义的。clone()
Base
Derived*
Base*
更一般地说,函数的返回类型永远不会被视为其签名的一部分。您可以使用任何返回类型覆盖成员函数,只要返回类型是协变的。
评论