繁体   English   中英

禁止使用返回非常量引用的方法覆盖返回常量引用的虚方法

[英]Disallowing overriding virtual method returning const reference with a method returning non-const reference

以下代码编译:

struct Ret {};

struct A
{
    virtual const Ret& fun() = 0; 
};

struct B : public A
{
    Ret& fun() override
    {
        static Ret ret;
        return ret;
    }
};

int main()
{
    B b;
}

如何在编译时禁止重写方法返回引用与返回类型的不同 const 说明符?

提前致谢。

以下所有标准参考均指N4659:2017 年 3 月后 Kona 工作草案/C++17 DIS


派生函数的返回类型需要与它覆盖的函数的返回类型协变,反之则不然

[class.virtual]/7 [extract,强调我的]管理:

覆盖函数的返回类型应与覆盖函数的返回类型相同或与函数的类协变 如果函数D​::​f覆盖函数B​::​f ,则如果函数满足以下条件,则函数的返回类型是协变的:

  • [...]
  • (7.3) 指针或引用都具有相同的 cv 限定并且D​::​f的返回类型中的类类型具有与B​::​f的返回类型中的类类型相同或更少的cv 限定B​::​f

使得以下程序格式良好

struct Ret {};

struct A {
    virtual const Ret& fun() = 0;
};

struct B : public A {
    Ret& fun() override { /* ... */ }
};

int main() {}

我们可能会注意到,底层B对象的A::fun接口的多态使用将强制接口返回类型的常量性,而以下程序是格式错误的:

struct Ret {};

struct A {
    virtual Ret& fun() = 0;
};

struct B : public A {
    const Ret& fun() override { /* ... */ }
};

int main() { }

它带有以下指导性编译器错误消息(Clang)

 error: return type of virtual function 'fun' is not covariant with the return type of the function it overrides

这个要求是很自然的,因为我们可能会注意到,如果接口A允许多态调用非常量Ret&返回fun()即使派生对象将重载实现为返回一个const Ret& ,那么我们将有办法修改const对象(通过多态),这是未定义的行为。


有一些自然的解决方法(例如,用Curiosly Recurring Template Pattern替换动态多态,并在 into-base 注入派生类型上进行常量断言),但这些似乎都可以解决XY 问题,并且可能实现只会增加复杂性的模式代码没有任何明显的增益。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM