C++ C++;虚常数函数

C++ C++;虚常数函数,c++,C++,给出以下代码片段 class Base { public: virtual void eval() const { std::cout<<"Base Const Eval\n"; } }; class Derived:public Base { public: void eval() { std::cout<<"Derived Non-Const Eval\n"; } }; int mai

给出以下代码片段

class Base
{
public:
    virtual void eval() const
    {
        std::cout<<"Base Const Eval\n";
    }
};

class Derived:public Base
{
public:
    void eval()
    {
        std::cout<<"Derived Non-Const Eval\n";
    }
};

int main()
{

    Derived d;
    Base* pB=&d;

    pB->eval(); //This will call the Base eval()

    return 0;
}
类基
{
公众:
虚拟void eval()常量
{

std::cout这是因为一个声明为常量,另一个声明为非常量。一个函数被另一个隐藏。派生中的函数隐藏在基中,因为它们具有相同的名称,而不是相同的函数

Base::eval() const;
Derived::eval(); //No const.

我的编译器在这里给出了一个警告,你的编译器呢?

在你的
派生的
类中,eval的原型与
Base
中的虚拟函数的原型不匹配。因此它不会覆盖虚拟函数

Base::eval() const;
Derived::eval(); //No const.

如果为
派生::eval()
添加常量,则应获得虚拟行为。

常量是函数签名的一部分。为了重写函数,重写必须与基本版本具有完全相同的签名-在这种情况下,它没有

考虑到调用代码不需要知道任何关于
派生的
-它是在
上调用
常量
函数。您不会期望该调用在一个可能改变类内容的非常量函数中结束

$10.3/2-“如果是虚拟会员功能 vf在基类和 派生类派生、直接派生或直接派生的类 间接地从基地,一个成员 具有相同名称的函数vf, 参数类型列表(8.3.5), cv资格认证和REF资格认证(或 缺少与Base::vf相同的 声明,然后派生::vf也是 虚拟的(无论是否如此) 声明)并且它覆盖111 Base::vf。“

111)具有相同名称但 不同的参数列表(第13条) 因为虚拟函数不是 必须是虚拟的,而不是虚拟的 重写。使用虚拟 声明中的说明符 覆盖功能是合法的,但是 冗余(语义为空)。 访问控制(第11条)不适用 在确定覆盖时考虑

另一方面,请注意,它没有讨论访问规范。因此,被重写函数的基类和派生类访问规范可能不同


这意味着派生::eval不会覆盖Base::eval,因为它们的简历资格不同。

您可以在脑海中翻译:

virtual void Base::eval() const;
void Derived::eval() ;


通过检查第二个与第一个签名的匹配程度。在C++0x中,使用
base\u check
override
关键字在编译时可以检测到这种情况:

属性上的[[base_check]]属性 类/结构表示任何隐式 压倒一切将导致 编译器错误。必须删除任何重写 显式标记为 [[override]]属性

最有可能(不太清楚语法):


好奇:什么编译器?什么警告选项?如果你打开警告,大多数编译器都会。
class Derived [[base_check]] : public Base {

    virtual void eval [[override]] () {
        ....
    }
};