重写方法时,不会出现针对非 POD 类型的“const”指针的编译器警告

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

Adr*_*ica 5

您观察到的行为符合标准。从这个 C++17 标准草案#

\n
\n

13.3 虚函数 \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 [class.virtual]

\n

\xe2\x80\xa6
\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

\n
\n

因此,在第二种情况下,满足上述所有三个标准。请注意,8.3 是正确的,因为返回的指针不是 cv 限定的 \xe2\x80\x93 ,它const指的是指向的对象,而不是指针本身。如果您将基类函数声明为,virtual S* const f();那么您拥有的派生类版本将不再有效。此外,派生类函数中的返回类型比基类函数中的 cv 限定更少;交换基类virtual S* f();和派生类的定义const S* f() override;也会使其无效。

\n

但是,在您的第一个代码片段中,函数的返回类型不符合8.1 标准(int不是类);因此,为了成为有效的重写,其返回类型必须与基类版本的返回类型相同。

\n
\n

#最新的在线草稿中的文本没有显着变化。

\n