此代码在g ++ 6.1下成功编译,但在clang 3.8中出错:
class C;
class Base {
public:
virtual const C *getC();
};
class Derived : public Base {
public:
virtual C *getC();
};
Run Code Online (Sandbox Code Playgroud)
clang的错误如下:
$ dev/compilers/linux-x86_64-2.12.2/clang3.8/bin/clang++ -Wall -c testcovariantreturn.cxx
testcovariantreturn.cxx:10:20: error: return type of virtual function 'getC' is not covariant with the return type of the function it overrides ('C' is incomplete)
Run Code Online (Sandbox Code Playgroud)
如果完全定义了C类而不是前向声明,则没有错误.我的理解是,当覆盖虚方法时,协变允许"较小"的cv限定(即,从返回类型中删除const).
clang是否正确/允许需要完整类型,如果是,为什么?怎么可以在这里改变C的定义呢?
这不是完全学术性的,在大型代码库中我不愿意添加不必要的包含,我们尝试将声明转发为标准实践.
Bar*_*rry 17
这是铿锵3.8 bug,特别是26297.来自[class.virtual],来自N4594的措辞:
重写函数的返回类型应与重写函数的返回类型相同或与函数类的协变相同.如果函数
D::f覆盖函数B::f,则函数的返回类型如果满足以下条件则是协变的:(7.1) - 两者都是指向类的指针,两者都是对类的左值引用,或者两者都是对类的右值引用
(7.2) -返回类型中的类与返回类型中B::f的类是同一个类D::f,或者是返回类型D::f
(7.3)中类的明确且可访问的直接或间接基类- 指针或引用都具有相同的类cv-qualification和返回类型中的类类型D::f具有相同的cv-qualification或者更少的cv-qualification,而不是返回类型中的类类型B::f.
具有B::f返回C const*并D::f返回C*匹配所有的这些要求(均未指针是CV-合格,和的类型D::f是CV-合格小于基准),因此其应该被允许.
完整性没有要求; C不需要完成检查这些标准.