簡體   English   中英

C ++中的協變虛函數

[英]covariant virtual function in C++

我嘗試了以下程序,但編譯器顯示錯誤。

#include <iostream>
class Base
{
    public:
        virtual Base& fun() const 
        {
            std::cout<<"fun() in Base\n";
            return *this;
        }
};
class Derived : public Base
{
    public:
         Derived& fun() const
        {
            std::cout<<"fun() in Derived\n";
            return *this;
        }
};
int main()
{
    Base* p=new Derived();
    p->fun();
    delete p;
    return 0;
}

編譯器錯誤:

[Error] invalid initialization of reference of type 'Base&' from expression of type 'const Base'
[Error] invalid initialization of reference of type 'Derived&' from expression of type 'const Derived'

為什么我會收到這些錯誤?
但是當我在兩個類中編寫以下函數程序時工作正常。

return (Base&)*this;      // write this line in Base class function
return (Derived&)*this    // write this line in Derived class function

上述2個陳述的含義是什么?
請幫我。

解:

在你fun成員函數中(例如,對於Base::funDerived::fun ),你必須刪除const限定符:

virtual Base& fun() 
{
  std::cout<<"fun() in Base\n";
  return *this;
}

或者將const引用返回給Base類對象。

virtual const Base& fun() const
{
  std::cout<<"fun() in Base\n";
  return *this;
}

現場演示

此外,您必須至少為您的Base類定義一個虛擬析構函數,以確保以正確的順序激發析構函數。

說明:

根據標准§9.3.2 this指針[class.this]

在非靜態(9.3)成員函數的主體中,關鍵字this是一個prvalue表達式,其值是調用該函數的對象的地址。 所述類型的this在一個的成員函數class XX* 如果成員函數聲明為const的類型, thisconst X*如果成員函數聲明為volatile的類型, thisvolatile X* ,如果成員函數聲明為const volatile的類型, thisconst volatile X* [注意: 因此在const成員函數中,調用函數的對象是通過const訪問路徑訪問的。 - 結束說明]

因此,解釋上面的內容,在const成員函數中thisconst因此將其作為非const引用返回會丟棄其const限定符,因此編譯器會正確地抱怨。

const關鍵字in

virtual Base& fun() const 

...使this成一個指向const的方法內的對象。 問題是你正在嘗試使用

return *this;

...並從返回Base&的方法返回它,從而刪除const

要么你需要刪除const在你的宣言,使this不是指向一個const對象,或者您需要聲明返回方法const Base&

當您在變量聲明中或在函數的返回類型上編寫const時,它意味着“此值是只讀的,因此不允許任何人更改它”。 當你在函數聲明中的一個參數上寫const時,它意味着“這個函數不會改變這個值”。 當你在成員函數(方法)聲明的末尾寫const時,它意味着“這個成員函數不會改變它被調用的對象”。

編譯器的一個工作是確保遵守這些const聲明。 特別是,編譯器不允許您執行以下任何操作。

  • 更改已聲明為const的變量的值。
  • 如果參數聲明為const ,則將參數的值更改為const
  • 通過一個已經聲明為一個變量的值const到一個函數,通過引用或指針,因為這不是聲明為參數const
  • 在已聲明為const的變量上調用沒有最終const聲明的成員函數。

第三個限制的原因是,如果聲明了一個函數而沒有在其中一個參數上使用const聲明,那么編譯器將不會阻止它更改相應參數的值。 如果你可以將const變量傳遞給這樣的函數,那么編譯器將無法保證其值不會改變。 因此,編譯器不會讓你傳入一個const變量。

第四個限制的原因是,如果在結尾處聲明了沒有 const聲明的成員函數,則編譯器不會阻止它更改調用它的對象的值。 如果你可以在const對象上調用這樣的函數,那么編譯器將無法保證其值不會改變。

因此,如果您編寫的函數不會更改其參數之一(通過引用參數或指針參數)引用的值,那么最好將const添加到聲明中。 這樣,就可以調用函數,通過引用或指針傳入const變量。 同樣,如果你的成員函數沒有改變調用它的對象的值,那么最好在聲明的末尾添加const

但是在您的特定示例中,您已將const聲明放在成員函數的末尾,該成員函數返回對調用它的對象的引用,但沒有在返回的引用上使用const聲明。 這意味着可以在const對象上調用此成員函數,將結果分配給非const變量,然后通過該變量更改其值。 這打破了const規則。

為了使這項工作,你有三個選擇。

  • 使函數返回值而不是引用。
  • 使函數返回一個const引用(即,在函數聲明的開頭添加單詞const )。
  • const聲明的末尾刪除const聲明。

暫無
暫無

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

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