2010-09-16 121 views
2

我遇到了以下問題,這證明我對C++的工作知之甚少。當基類的指針被調用時,賦值運算符是否被重載?

我使用基類與純虛函數

class Base 
    ... 

和類型

class Derived : public Base{ 
private: 
    Foo* f1; 
... 

兩者的派生類具有賦值運算符來實現。除其他外,Derived的賦值運算符會複製f1中的數據。在我的代碼,我創建類的兩個新實例派生

Base* d1 = new Derived(); 
Base* d2 = new Derived(); 

如果我現在請賦值運算符

*d1 = *d2; 

的衍生賦值運算符不叫,而在F1中的數據不會被複制!它只適用於我,如果我做

*dynamic_cast<Derived*>(d1) = *dynamic_cast<Derived*>(d2); 

有人可以解釋爲什麼賦值運算符沒有超載嗎?

謝謝!

+1

您沒有虛擬基類;如果'Base'是一個虛擬基類,'Derived'將被聲明爲'class Derived:public virtual Base'。你的基類可能有虛函數。 – 2010-09-16 23:32:23

+0

我認爲你很容易混淆超載和覆蓋。 – fredoverflow 2010-09-17 08:53:46

回答

4

很難說,沒有看到相關的代碼。下面是一個可用的示例:

#include <iostream> 

using namespace std; 

class A { 
    public: 
    virtual A& operator=(A& a) {} 
}; 

class B : public A { 
    public: 
    B& operator=(A& a) { cout << "B" << endl; } 
}; 

int main() { 
    A* foo = new B(); 
    A* bar = new B(); 
    *foo = *bar; 
    return 0; 
} 

運行時將打印B

事情,你可能會做錯了:

  1. 您可能忘記,使operator=虛基類。
  2. 您可能已將孩子的operator=作爲比父母的operator=限制性更強的簽名,因此實際上並未覆蓋父母的定義。例如,如果在上面的示例中將B& operator=(A& a) { cout << "B" << endl; }更改爲B& operator=(B& a) { cout << "B" << endl; },則將不再打印B
1

對於虛擬工作,您需要相同的簽名。因此,如果operator=在您的Derived類中的const Derived&參數上工作,該參數與您的基類中參數const Base&的參數不匹配。

這意味着你可以完成多態性,但是你需要在你的派生類中有一個operator=(const Base&)這樣做。

+0

是否允許運算符operator =(const Derived&) 和operator =(const Base&)? – Hans 2010-09-17 09:15:41

+0

@Hans:沒關係。 – 2010-09-17 13:36:46

3

我對接受的答案有一些不同的觀點。這基本上是More Effetive C++第33項。因此,儘管接受的解決方案有效,但我認爲重要的是指出讓分配操作員虛擬化的危險!

class Animal { 
public: 
    virtual Animal& operator=(const Animal& rhs); 
}; 

class Lizard: public Animal { 
public: 
    virtual Lizard& operator=(const Animal& rhs); 
}; 

class Chicken: public Animal { 
public: 
    virtual Chicken& operator=(const Animal& rhs); 
}; 

int main(){ 
    Lizard l; 
    Chicken c; 

    Animal *pL = &l; 
    Animal *pC = &c; 

    *pL = *pC;    // assigns chicken to a lizard. 
} 
相關問題