You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

派生类重写函数修改返回值常量性为何未触发编译错误?

问题

基类中声明了返回const Widget&的纯虚函数,但派生类DerivedAgain重写该函数时,将返回类型改为Widget&(去掉了const修饰),且使用override关键字,代码却能正常编译通过。这是否符合C++标准,还是编译器存在错误?

复现代码如下:

struct Widget
{
    int x = 42;
};

struct Base
{
    virtual const Widget & GetWidget() = 0;
};

struct Derived : public Base
{
    virtual const Widget & GetWidget() override
    {
        return m_widget;
    }
private:
    Widget m_widget;
};

struct DerivedAgain : public Derived
{
    virtual /* missing "const"*/ Widget & GetWidget() override // Shouldn't compile?
    {
        return m_widgetAgain;
    }
private:
    Widget m_widgetAgain;
};

void main()
{
    DerivedAgain thing;

    thing.GetWidget().x = 666; // Shouldn't be allowed?
}

操作:编译上述源文件
预期结果:触发编译错误
实际结果:编译成功

Build started at 11:33 AM...
1>------ Build started: Project: Test, Configuration: Debug Win32 ------
1>Test.cpp
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
========== Build completed at 11:33 AM and took 00.301 seconds ==========
解答

这完全符合C标准的规定,并非编译器错误。核心原因是**C允许虚函数重写时使用协变返回类型**,具体到引用类型的规则是:如果基类虚函数返回const T&,派生类重写时可以返回T&——因为T&可以安全地隐式转换为const T&,满足协变返回类型的要求。

当通过基类指针或引用调用GetWidget时,得到的是const Widget&,无法修改成员;但直接通过DerivedAgain对象调用时,调用的是派生类的版本,返回的是Widget&,自然允许修改x的值,这是合法的。

override关键字在这里能正常通过,因为编译器认可这种返回类型的协变关系,判定该函数确实是对基类虚函数的重写。

内容的提问来源于stack exchange,提问作者GeoRanger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:15:03