c++ - 不允许用返回非常量引用的方法覆盖返回常量引用的虚方法
问题描述
以下代码编译:
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 [摘录,强调我的] 管理:
覆盖函数的返回类型应与被覆盖函数的返回类型相同或与函数的类协变。如果函数
D::f
覆盖函数B::f
,则函数的返回类型如果满足以下条件,则它们是协变的:
- [...]
- (7.3) 指针或引用都具有相同的 cv 限定,并且 的返回类型中的类类型具有与 的返回类型中的类类型
D::f
相同或更少的cv 限定B::f
。
使得下面的程序是格式良好的
struct Ret {};
struct A {
virtual const Ret& fun() = 0;
};
struct B : public A {
Ret& fun() override { /* ... */ }
};
int main() {}
我们可能会注意到,A::fun
底层B
对象接口的多态使用将强制接口返回类型的常量性,而以下程序格式错误:
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
允许多态调用非 const Ret&
-return fun()
,即使派生对象实现重载作为返回 a const Ret&
,那么我们将有一种方法修改const
对象(通过多态),即未定义的行为。
有自然的变通方法(例如,用好奇的循环模板模式替换动态多态性和对 in -base 注入派生类型的 constness 断言),但可以说这些似乎都解决了 XY 问题,并且可能实现只会增加复杂性的模式代码没有任何明显的收获。
推荐阅读
- node.js - 在投资组合网站上创建 github 仪表板
- javascript - .setAttribute 在 for 循环中不起作用 - JavaScript
- django - Django - 表单数据不会保存到数据库
- node.js - app.post 正在工作,但 app.use 没有。快速节点
- javascript - 延迟 n 秒重试轮询服务
- r - R- 无效或过期的令牌
- here-api - 这里 api 请求错误 --- 无效的凭据
- amazon-web-services - 如何在单个 API 网关后面合并多个微服务?
- swift - 从pdf文件快速打开网址
- node.js - NodeJS 语法错误