ara*_*EST 7 c++ gcc clang compiler-warnings
一个示例,其中const
在派生类中不重写 POD 返回类型:
struct B1
{
virtual const int* f();
};
struct D1 : B1
{
int* f() override;
};
Run Code Online (Sandbox Code Playgroud)
Clang 和 GCC 等编译器发出警告:
“virtual int* D1::f()”的协变返回类型无效
当应用相同的场景但返回类型是某个结构/类时,不会引发警告:
struct S
{
};
struct B2
{
virtual const S* f();
};
struct D2 : B2
{
S* f() override;
};
Run Code Online (Sandbox Code Playgroud)
我在不同版本的 GCC 上编译了这个。当不使用声明时,在派生类中返回结构/类指针时,我预计会出现类似的警告const
。
您观察到的行为符合标准。从这个 C++17 标准草案#:
\n\n\n13.3 虚函数 \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 [class.virtual]
\n\xe2\x80\xa6
\n
\n 8 \xc2\xa0\xc2\xa0\xc2\xa0 重写函数的\n返回类型应与\n被重写函数的返回类型相同,\n或与该函数的类\n协变功能。如果函数D::f
重写函数B::f
,\n如果满足以下条件,函数的返回类型是协变的:
\n (8.1) \xc2\xa0\xc2\xa0\xe2\x80\x94 都是指向类的指针,两者都是对类的左值引用,或者都是对类的右值引用
\n (8.2) \xc2\xa0\xc2\xa0\xe2\x80\x94 返回类型中的类B::f
与\n 的返回类型D::f
, or 是返回类型中的类的明确且可访问的直接\或间接基类D::f
\n (8.3) \xc2\xa0\xc2\xa0\xe2\x80\x94 指针或引用都具有相同的\nncv 限定和返回类型中的类类型D::f
具有与 的返回类型中的类类型相同或更少的 cv 限定B::f
。
因此,在第二种情况下,满足上述所有三个标准。请注意,8.3 是正确的,因为返回的指针不是 cv 限定的 \xe2\x80\x93 ,它const
指的是指向的对象,而不是指针本身。如果您将基类函数声明为,virtual S* const f();
那么您拥有的派生类版本将不再有效。此外,派生类函数中的返回类型比基类函数中的 cv 限定更少;交换基类virtual S* f();
和派生类的定义const S* f() override;
也会使其无效。
但是,在您的第一个代码片段中,函数的返回类型不符合8.1 标准(int
不是类);因此,为了成为有效的重写,其返回类型必须与基类版本的返回类型相同。
#最新的在线草稿中的文本没有显着变化。
\n