【问题标题】:Are assignment operators not overloaded, when called upon pointers of a base class?当调用基类的指针时,赋值运算符是否没有重载?
【发布时间】:2011-04-13 11:53:08
【问题描述】:

我遇到了以下问题,这向我证明我对 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);

谁能解释为什么赋值运算符没有重载?

谢谢!

【问题讨论】:

  • 你没有虚拟基类;如果Base 是一个虚拟基类,Derived 将被声明为class Derived : public virtual Base。你的基类可能有虚函数。
  • 我认为您混淆了重载和覆盖。

标签: c++ operator-overloading assignment-operator


【解决方案1】:

我对接受的答案有一些不同的看法。这基本上是 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.
}

【讨论】:

    【解决方案2】:

    要让虚拟机工作,您需要相同的签名。因此,如果您的 operator= 在您的 Derived 类中使用的 const Derived&amp; 参数与在您的基类中使用 const Base&amp; 参数的参数不匹配。

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

    【讨论】:

    • 是否允许同时拥有运算符 operator=(const Derived&) 和 operator=(const Base&) ?
    【解决方案3】:

    不看相关代码很难说。这是一个有效的示例:

    #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&amp; operator=(A&amp; a) { cout &lt;&lt; "B" &lt;&lt; endl; } 更改为B&amp; operator=(B&amp; a) { cout &lt;&lt; "B" &lt;&lt; endl; },它将不再打印B

    【讨论】:

      猜你喜欢
      • 2020-08-17
      • 2013-04-29
      • 1970-01-01
      • 2014-05-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多