標題的問題同樣可以是:為什麼賦值運算子operator=()不能使用虛函式。
有一篇文章說得比較好,連線在此:為什麼c++賦值運算子過載函式不能被繼承?,推測過程如下:
class a1
int operator+(int a)
};class b1 : public a1
};int main()
vc
error c2679: binary '=' : no operator defined which takes a right-hand operand of type 'const int' (or there is no acceptable conversion)
明顯是找不到定義,但很明顯這份**的意圖就是讓派生類物件使用基類繼承下來的賦值運算子來返回乙個整數。但是卻找不到形如const int operator=(const int )的函式定義。
這份**比較有幫助就是在於,一般的=都是把自身的型別轉化為自身的引用。但是這個=確實以int為引數,類型別的引用為返回的操作符。因此能看出問題,所以羅列線索(線索**鏈結文章原文):
1,每乙個類物件例項在建立的時候,如果使用者沒有定義「賦值運算子過載函式」,那麼,編譯器會自動生成乙個隱含和預設的「賦值運算子過載函式」。所以,b1的實際上的宣告應該類似於下面這種情況:
class a1
int operator+(int a)
};class b1 : public a1
};2,c++標準規定:如果派生類中宣告的成員與基類的成員同名,那麼,基類的成員會被覆蓋,哪怕基類的成員與派生類的成員的資料型別和引數個數都完全不同。顯然,b1中的賦值運算子函式名operator =和基類a1中的operator =同名,所以,a1中的賦值運算子函式int operator=(int a);被b1中的隱含的賦值運算子函式b1& operator =(const b1& robj);所覆蓋。 a1中的int operator=(int a);函式無法被b1物件訪問。
3,程式中語句v = 2實際上相當於v.operator =(2);,但是a1中的int operator=(int a);已經被覆蓋,無法訪問。而b1中預設的b1& operator =(const b1& robj);函式又與引數2的整數型別不相符,無法呼叫。
4,為了確認b1中預設的b1& operator =(const b1& robj);函式的存在性,可以用以下**驗證:
b1 b;
b1 v;
v = b; // ok, 相當於呼叫v.operator =(b);
5,所以,「賦值運算子過載函式」不是不能被派生類繼承,而是被派生類的預設「賦值運算子過載函式」給覆蓋了。
這就是c++賦值運算子過載函式不能被派生類繼承的真實原因!
這裡面呢,我發現了一點我覺得有問題的地方,就在於第2條「如果派生類中宣告的成員與基類的成員同名,那麼,基類的成員會被覆蓋」,只有虛函式才有這種覆蓋的特性,如果是非虛函式的話,還是以物件的引用或者指標的型別決定了operator=()使用基類還是派生類的。因此,在文章的例子中出現的問題並不在於a1的方法是否被覆蓋,而是由於「b1中預設的b1& operator =(const b1& robj);函式又與引數2的整數型別不相符,無法呼叫」。這就回答了原標題的問題:「為什麼賦值運算子不能被繼承」,如果本例的計算流程變一下,型別匹配之後也許會發現是可以被繼承的。
這之後,再回到自己提的問題「為什麼賦值運算子operator=()不能使用虛函式」。
假設基類中的operator=()為虛函式,同樣舉個例子:
derivedclass a;//派生類某物件a
derivedclass b;//派生類某物件b
baseclass &c = a;//基類某指標、或者引用都行c
baseclass &d = b;//基類某指標、或者引用都行d
a = b;//呼叫a.operator=(const derivedclass & b)
如果b中忘記自己定義的賦值操作符了,那麼編譯器會給我們生成預設的操作符,在a的拷貝過程中,將會採用此預設的operator=(),即淺拷貝賦值的方法逐成員呼叫=(注:派生類成員),這對非動態管理的派生類沒有問題,但是對於有字串或new操作的派生類來說卻是不行的。但是呢,如果由使用者自己重新定義了虛賦值操作符,那麼通過正確的改寫是可以正確地實現賦值。
反觀如果不用虛函式,使用基類的賦值操作符來進行逐成員賦值(注:基類成員改變、派生類成員不變)同樣會產生問題。所以結論和之前的一樣,不是不行,而是需要結合具體的情況去正確地實現。
C 運算子過載賦值運算子
自定義類的賦值運算子過載函式的作用與內建賦值運算子的作用類似,但是要要注意的是,它與拷貝建構函式與析構函式一樣,要注意深拷貝淺拷貝的問題,在沒有深拷貝淺拷貝的情況下,如果沒有指定預設的賦值運算子過載函式,那麼系統將會自動提供乙個賦值運算子過載函式。賦值運算子過載函式的定義與其它運算子過載函式的定義是...
賦值運算子過載函式
問題 給出如下cmystring的宣告,要求為該型別新增賦值運算子函式。class cmystring 當面試官要求應聘者定義乙個複製運算子函式時,他會關注如下幾點 是否把返回值的型別宣告為該型別的引用,並在函式結束前返回例項自身 即 this 的引用?只有返回乙個引用,才可以允許連續賦值。否則如果...
C 賦值運算子過載
c 賦值運算子過載,為什麼要返回引用?查了許多資料,基本有兩種說法 一 c c 賦值運算子的本意為 返回左值的引用 左值 賦值號左面的變數而非其值 可用以下程式段測試 int a,b 3,c 2 a b c cout 對於x y x,y均為物件時 若不返回左值的引用,將會生成臨時物件。如果不處理x ...