2016-10-05 57 views
19

下面的代码编译和运行,并且没有警告是由两种或GCC铛发出:我可以在覆盖虚拟函数的返回类型中丢失“const”吗?

#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

是有意义的,因为如果需要,您可以简单地重新应用调用方的常量。当然,你不能自动退回,所以相反的情况不会是这样。 – xaxxon

+0

@xaxxon:是的,我真的很惊讶它的工作原理(从来没有想过它!)......尤其是因为CLion不幸在那里发生了错误。为此,我在跟踪器上提出了一个错误。 –

+1

有趣的是,我发现它在DR1250中也被固定以允许不完整的类型:http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1250 – marcinj

回答

18

这在class.virtual规定,在最新的草案(n4606),我们看到:

10.3节7/压倒一切的函数的返回类型应与覆盖函数 或协变的返回类型与函数的类相同。如果D::f覆盖了一个功能B::f,返回类型的功能 是协变,如果它们满足以下条件的函数:

  • 两者都是类型指针,两者都是对类左值的引用,或两者都是rvalue引用类
  • B::f返回类型的类是相同的类中的D::f返回类型的类,或者是一个明确的和可访问的直接或间接的基类的类中的D::f
  • 返回类型
  • 指针或引用都具有相同的cv资格,并且返回类型D::f中的类别类别与返回类型B::f中的类别类型具有相同或更低的cv资格。

具体而言,最后一个点地址这里正是如此:它是可以接受的压倒一切类型失去const和/或volatile限定符(它不能但是,增益它们)。


注:如通过上文提到@george,第8段/用于防止这种不完整的类类型的工作,但是这是since fixed

相关问题