【问题标题】:How to call derived assignment operator from base class?如何从基类调用派生赋值运算符?
【发布时间】:2016-07-10 21:46:32
【问题描述】:

给定一个指向抽象基类A* 的指针,我想复制或分配它(作为基类)并调用派生的复制构造函数或赋值运算符。我知道复制构造函数不能是虚拟的,所以大概复制构造函数不是这样做的选项,但赋值运算符是。不过,它似乎不起作用:打印以下代码

assigned a
x!
destroyed b
destroyed b

分配 b 失败。

#include <iostream>
using namespace std;

class A
{
public:
    virtual void x()=0;
    virtual ~A() {}
    virtual A& operator=(const A& other) { cout << "assigned a" << endl; return *this;}
};

class B : public A
{
public:
    virtual B& operator=(const B& other)  { cout << "assigned b" << endl; return *this;}
    virtual void x() { cout << "x!" << endl; }
    virtual ~B() { cout << "destroyed b" << endl; }
};

int main() 
{ 
    A* a = new B(); 
    A* aa = new B(); 
    *aa=*a; 
    aa->x(); 
    delete a; 
    delete aa; 
    return 0;
}

如何做到这一点?

编辑这个问题在下面得到了正确的回答,但它是错误的问题。我不应该尝试重写赋值运算符,因为我不希望 A 的子类将 分配给另一个。对于更简单的答案(希望),请参阅C++ elegantly clone derived class by calling base class

【问题讨论】:

  • 这并不重要,但问题是关于虚拟基类,而代码没有。
  • 我认为您的意思是 abstract 基类,而不是“虚拟”(这是完全不同的东西)。基类的抽象性与您的问题无关。

标签: c++ inheritance assignment-operator


【解决方案1】:

问题在于您的B::operator= 没有覆盖 A 中的那个。改成

virtual A& operator=(const A& other)  { cout << "assigned b" << endl; return *this;}

它会起作用的。此外,在覆盖成员函数时尝试使用 override 关键字(需要 C++11)。如果您不覆盖,代码将无法编译。在你的情况下,它会抓住你的错误

错误:“virtual B& B::operator=(const B&)”标记为“覆盖”,但没有覆盖

PS:你可能在想covariant return types。为了让它工作,你的函数的签名必须是相同的,除了返回类型。例如,这将起作用:

virtual B& operator=(const A& other)  { cout << "assigned b" << endl; return *this;}

【讨论】:

  • 好的,但是如果B::operator= 不能保证const A&amp; otherB 的一个实例,它如何访问B 独有的字段?
  • @SideshowBob 你可以测试dynamic_cast 的结果,看看other 是否真的是B。但这也应该让你思考你的设计是否合理。
  • 这很难的事实确实让我质疑我的设计。最终,我需要在不知道该类到底是什么的情况下从基类指针中深度复制一个类。在封装的原则下,这不是一个疯狂的要求,对吧?
  • @SideshowBob 一种解决方案是通过不同的函数使用double dispatching,称为assign
  • 这意味着给所有派生类一个assign 函数(或clone 在我的情况下会完成这项工作),当只有一个派生类需要除默认值之外的任何东西时。有没有办法说find the derived class assignment operator (which will be virtual if not default) and use it
猜你喜欢
  • 2013-03-03
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
  • 2020-02-16
  • 1970-01-01
  • 2012-02-10
  • 2021-07-31
相关资源
最近更新 更多