2

我遇到了以下问题,这向我证明我对 C++ 的工作原理知之甚少。

我使用带有纯虚函数的基类

class Base
    ...

和类型的派生类

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

两者都实现了赋值运算符。除其他外,Derived 的赋值运算符复制 f1 中的数据。在我的代码中,我创建了 Derived 类的两个新实例

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

如果我现在调用赋值运算符

*d1 = *d2;

不调用Derived的赋值运算符,不复制f1中的数据!只有当我这样做时它才有效

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

有人可以解释为什么赋值运算符没有重载吗?

谢谢!

4

3 回答 3

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=在基类中设置 virtual 了。
  2. 您可能已将孩子的班级operator=作为签名,该签名比父母的班级更具限制性operator=,因此您实际上并没有覆盖父母的定义。例如,如果您在上面的示例中更改B& operator=(A& a) { cout << "B" << endl; }B& operator=(B& a) { cout << "B" << endl; },它将不再打印B.
于 2010-09-16T23:35:29.220 回答
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.
}
于 2010-09-17T04:28:04.457 回答
1

为了使虚拟工作,您需要相同的签名。因此,如果您operator=在类中处理的const Derived&参数与在基类中处理参数的参数Derived不匹配。const Base&

这意味着您可以实现多态性,但您需要operator=(const Base&)在派生类中有一个才能做到这一点。

于 2010-09-16T23:29:25.303 回答