当调用基类的指针时,赋值运算符不会重载吗?

发布于 2024-09-24 03:09:00 字数 608 浏览 2 评论 0原文

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

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

谢谢!

I have encountered the following problem which proved to me that I know far too little about the workings of C++.

I use a base class with pure virtual functions

class Base
    ...

and a derived classes of type

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

Both have assignment operators implemented. Among other things, the assignment operator for Derived copies the data in f1. In my code, I create two new instances of class Derived

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

If I now call the assignment operator

*d1 = *d2;

the assignment operator of Derived is not called, and the data in f1 is not copied! It only works if I do

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

Can someone explain why the assignment operators are not overloaded?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

生生漫 2024-10-01 03:09:00

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

#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&运算符=(A&a) { cout << “B”<<结束; }B&运算符=(B&a) { cout << “B”<<结束; } 在上面的例子中,它将不再打印 B

It's hard to say without seeing the relevant code. Here's an example that works:

#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;
}

This will print B when run.

Things that you might be doing wrong:

  1. You might have forgotten to make operator= virtual in the base class.
  2. You might have given the child's class operator= as signature that's more restrictive than that of the parent's operator=, so you're not actually overriding the parent's definition. For example if you change B& operator=(A& a) { cout << "B" << endl; } to B& operator=(B& a) { cout << "B" << endl; } in the example above, it will no longer print B.
丑丑阿 2024-10-01 03:09:00

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

I have some alternate perspective on the accepted answer. This is basically More Effetive C++ Item 33. So even though the accepted solution works, I think it is important to bring out the dangers involved in making assignment operator virtual!

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.
}
墨离汐 2024-10-01 03:09:00

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

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

For virtual to work you need the same signature. So if your operator= works on a const Derived& parameter in your Derived class that doesn't match the one that is working on a const Base& parameter in your base class.

This means that you can accomplish polymorphism but you need to have an operator=(const Base&) in your derived class to do so.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文