以下代码编译并运行,gcc或clang不会发出警告:
#include <iostream>
struct Base {
virtual ~Base() = default;
virtual std::string const& get() = 0;
};
struct Derived: Base {
virtual std::string& get() override { return m; }
std::string m;
};
int main()
{
Derived d;
d.get() = "Hello, World";
Base& b = d;
std::cout << b.get() << "\n";
}
std::string&
是否与std::string const&
协变?
答案 0 :(得分:18)
是强>
这是在 class.virtual 中指定的,在我们看到的最新草稿(n4606)中:
§10.37/ 覆盖函数的返回类型应与被覆盖函数的返回类型相同 或协变与函数的类。如果函数
D::f
覆盖函数B::f
,则返回类型 如果它们满足以下标准,则函数是协变的:
- 都是指向类的指针,都是对类的左值引用,或者两者都是对类 111
的rvalue引用- 返回类型
B::f
中的类与返回类型D::f
中的类相同,或者是返回类中返回类型的明确且可访问的直接或间接基类类型D::f
- 指针或引用具有相同的cv限定,并且返回类型
D::f
中的类类型具有与返回类型{{中的类类型相同的cv-qualification或更少的cv-qualification 1}}。
具体来说,最后一点完全解决了这里的情况:覆盖类型可以丢失B::f
和/或const
限定符(但不能获得它们)。
注意:如上文@george所述,第8段/用于防止此操作使用不完整的类类型,但这是since fixed。