[英]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::fun
和Derived::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 X
是X*
。 如果成員函數聲明為const
的類型,this
是const X*
,如果成員函數聲明為volatile
的類型,this
是volatile X*
,如果成員函數聲明為const volatile
的類型,this
是const volatile X*
。 [注意: 因此在const
成員函數中,調用函數的對象是通過const
訪問路徑訪問的。 - 結束說明]
因此,解釋上面的內容,在const
成員函數中this
是const
因此將其作為非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.