C++ 为什么可以';我有与void*协变的返回类型吗?
为什么下面的代码是协方差错误?C++ 为什么可以';我有与void*协变的返回类型吗?,c++,covariance,return-type,C++,Covariance,Return Type,为什么下面的代码是协方差错误?t*是否与void*共变 struct Base { virtual void *foo(); }; struct Derived : Base { int *foo(); }; GCC表示: invalid covariant return type for 'virtual int* Derived::foo()' [class.virtual]/p7,重点: 重写函数的返回类型应与 重写函数的返回类型或与 函数的类。如果函数D::f重写函数 B::f,如果
t*
是否与void*
共变
struct Base { virtual void *foo(); };
struct Derived : Base { int *foo(); };
GCC表示:
invalid covariant return type for 'virtual int* Derived::foo()'
[class.virtual]/p7,重点: 重写函数的返回类型应与 重写函数的返回类型或与 函数的类。如果函数
D::f
重写函数
B::f
,如果函数的返回类型
满足以下标准:
- 两者都是指向类的指针,都是对类的左值引用,或者都是对类的右值引用。[脚注省略]
- [……]
摘自以下第294-5页: 在考虑了一些替代方案后,我们决定允许 用a
D*
覆盖aB*
,用aD&
覆盖aB&
,其中B
是
D
的可访问基础。此外,还可以添加或
在安全的地方减去。我们决定不放宽规定,以避免发生意外
允许技术上可行的转换,例如将D
转换为可访问的
基本B
,aD
到X
,其中D
有一个转换,int*
到
void*
,double
到int
等。我们认为
允许通过重写进行此类转换不会超过
实施成本和可能让用户感到困惑
协变返回类型特性是当派生类为重写函数提供更具体/更窄的返回类型时。派生类返回类型称为协变 int*不是void*类型,而类似这样的东西确实描述了协变返回类型:
struct Base {
virtual void *foo();
virtual Base* func();
};
struct Derived : Base {
// int *foo();
Derived* func(); //COVARIANT RETURN TYPE
};
void*
和T*
之间的协方差是不允许的,因为:
1。缺乏一致性
当前的协方差方法很难理解,也不会造成混淆。想象一下,允许使用
void*
类型的协方差。对于一个阶段的推导是好的,但它会造成混乱。e、 g:
struct void_ { virtual void* foo (); };
struct int_ : void_ { virtual int* foo (); };
struct double_ : int_ { virtual double* foo (); }; // int* to double* or void* to double*
在struct double
的第三层次结构中,用户会感到困惑,即使double*
到int*
是不可能的,为什么代码仍在编译?只有在检查最顶层的类void
之后,才知道这是因为double*
到void*
是“协变的”。编译器也是如此:-)
2。参考文献发布
对于类,可以返回B&
/D*
/DD*
。但是同样的事情在void&
中是不可能的,因此int&
等等
3。协方差的混合
如果允许使用void*
,则也允许无意中使用以下命令
struct void_ { virtual void* foo (); };
struct Base : void_ { virtual Base* foo (); };
struct Derived : Base { virtual int* foo (); }; // Look at `int*`
这是一个混乱。如果你能解释这个设计背后的“为什么”,那么Mehrdad将是一个很好的例子。@ Dead增加了一个D&E引用。当我用C++中的名字空间的协方差和限制来看待这个问题时,我可以识别java对象和包后面的推理。你解释“协方差”的定义,OP问“为什么”。.