Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么可以';我有与void*协变的返回类型吗?_C++_Covariance_Return Type - Fatal编程技术网

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*
覆盖a
B*
,用a
D&
覆盖a
B&
,其中
B
D
的可访问基础。此外,还可以添加或 在安全的地方减去。我们决定不放宽规定,以避免发生意外 允许技术上可行的转换,例如将
D
转换为可访问的 基本
B
,a
D
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问“为什么”。.