簡體   English   中英

禁止使用返回非常量引用的方法覆蓋返回常量引用的虛方法

[英]Disallowing overriding virtual method returning const reference with a method returning non-const reference

以下代碼編譯:

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 [extract,強調我的]管理:

覆蓋函數的返回類型應與覆蓋函數的返回類型相同或與函數的類協變 如果函數D​::​f覆蓋函數B​::​f ,則如果函數滿足以下條件,則函數的返回類型是協變的:

  • [...]
  • (7.3) 指針或引用都具有相同的 cv 限定並且D​::​f的返回類型中的類類型具有與B​::​f的返回類型中的類類型相同或更少的cv 限定B​::​f

使得以下程序格式良好

struct Ret {};

struct A {
    virtual const Ret& fun() = 0;
};

struct B : public A {
    Ret& fun() override { /* ... */ }
};

int main() {}

我們可能會注意到,底層B對象的A::fun接口的多態使用將強制接口返回類型的常量性,而以下程序是格式錯誤的:

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允許多態調用非常量Ret&返回fun()即使派生對象將重載實現為返回一個const Ret& ,那么我們將有辦法修改const對象(通過多態),這是未定義的行為。


有一些自然的解決方法(例如,用Curiosly Recurring Template Pattern替換動態多態,並在 into-base 注入派生類型上進行常量斷言),但這些似乎都可以解決XY 問題,並且可能實現只會增加復雜性的模式代碼沒有任何明顯的增益。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM