为什么我不能将返回类型与void *协变?

时间:2015-06-05 06:03:52

标签: c++ covariance return-type

为什么以下代码是协方差错误?不是T *void *协变......?

struct Base { virtual void *foo(); };
struct Derived : Base { int *foo(); };
海湾合作委员会说:

invalid covariant return type for 'virtual int* Derived::foo()'

3 个答案:

答案 0 :(得分:7)

[class.virtual] / p7,强调我的:

  

覆盖函数的返回类型应与...相同   被覆盖函数的返回类型或协变与   功能的类。如果函数D::f覆盖函数   B::f,函数的返回类型是协变的   满足以下标准:

     
      
  • 都指向的指针,两者都是的左值引用,或者两者都是类的右值引用 [脚注省略]
  •   
  • [...]
  •   

来自D&E的第294-5页:

  

考虑到替代方案后,我们决定允许   覆盖B* D*B&覆盖D&其中B是{   D的可访问基础。此外,还可以添加const或   减去任何安全的地方。我们决定不放宽规则   允许技术上可行的转换,例如D到可访问的转换   基数BDX D有转化,int*到   void*doubleint等我们感受到的好处   通过覆盖允许这样的转换不会超过   实施成本和混淆用户的可能性。

答案 1 :(得分:1)

不允许使用void*T*之间的协方差,因为:

<强> 1。缺乏一致性。

目前的协方差方法很容易理解,也不会引起混淆 想象一下void*类型的协方差是允许的。对于1阶段的推导是好的,但它会产生混乱。 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_的第3层次结构中,用户会感到困惑,即使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*`

这会增加混乱。

答案 2 :(得分:0)

协变返回类型功能是指派生类为重写函数提供更具体/更窄的返回类型。派生类返回类型被称为协变。

int *不是void *类型,而像这样的东西确实描述了协变返回类型:

struct Base {
  virtual void *foo();
  virtual Base* func();
};
struct Derived : Base {
//  int *foo();
  Derived* func(); //COVARIANT RETURN TYPE
};