【问题标题】:C++ copy constructor issue with parent/child classes父/子类的 C++ 复制构造函数问题
【发布时间】:2014-12-05 23:29:19
【问题描述】:

我遇到了复制构造函数的问题...我认为对此有一个基本的答案,但我遗漏了一些明显的东西-也许我做错了-但我无法想办法。

基本上,我有一个父类和子类。父类包含指向(不同)基类对象的指针向量。子类希望存储指向从该基对象派生的对象的指针。

这是一个伪代码示例,如果有帮助的话:

// Base classes
class ItemRev {
  ...
}

class Item {

protected:

vector<ItemRev *> m_revPtrVec;

}


Item::Item(const Item &inputItemObj)
{
  // Copy contents of the input object's item rev pointer vector
  vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revPtrVec).begin();
  while (vecIter != (inputItemObj.m_revPtrVec).end()) {
    (this->m_revPtrVec).push_back(new ItemRev(**vecIter));
  }
}

=========

// Derived classes
class JDI_ItemRev : public ItemRev {
  ...
}

class JDI_Item : public Item {

...

}

JDI_Item::JDI_Item(const JDI_Item &itemObj)
{
  // Copy contents of the input object's item rev pointer vector
  vector<ItemRev *>::const_iterator vecIter = (inputItemObj.m_revObjPtVec).begin();

  // The below does not work!
  while (vecIter != (inputItemObj.m_revObjPtVec).end()) {
    m_revObjPtVec.push_back(new JDI_ItemRev(**vecIter));
  }
}

上述问题出在JDI_Item复制构造函数中的push_back()调用中。

鉴于此设置,子类的复制构造函数应该是什么样的?我什至需要一个子类复制构造函数吗?我假设我做到了,因为复制构造函数正在创建新对象,而父复制构造函数将在派生类中创建不是我想要的类型的新对象(即,父对象存储指向 ItemRev 对象的指针,而子对象应存储指向派生的JDI_ItemRev 对象的指针)。

【问题讨论】:

  • 你需要一个从基础复制的构造函数,带有签名JDI_Item::JDI_Item(const ItemRev &amp;)的东西。默认情况下不会为您生成此构造函数,因为它很少有意义。
  • 首先,JDI_Item-ctor 有问题。如果抛出任何异常,它就会泄漏。为什么你有一个std::vector 指向JDI_ItemRev 的指针?为什么它们不直接在向量中,或者至少由智能指针管理? (在第一种情况下,隐式定义应该有效。)Item 也可以这样说。

标签: c++ pointers constructor


【解决方案1】:

正如 cmets 中提到的,可能有一种更简洁的方式来表达这个问题(即你的类结构需要一些工作)。

但是,如果您想这样做,最简单的实现方法是在 ItemRev 的基类中使用虚拟 clone() 方法,并在派生类中定义它的覆盖。

例如:

class ItemRev {

  virtual ItemRev* clone() const = 0;
};

class JDI_ItemRev : public ItemRev {

  ItemRev* clone() const override 
  {
    // do your actual cloning here, using the copy constructor
    return new ItemRev(*this);
  }
};

现在,每当您在任何从ItemRev 派生的类上调用clone() 时,都会返回一个ItemRev*,但它将指向一个完全构造的派生类。您当然可以使用static_cast&lt;&gt;dynamic_cast&lt;&gt; 访问派生类的接口。

...然而...

推导通常看起来很容易获胜,但事实往往并非如此。仅当派生类确实是基类的一个类型时,才应使用继承。当派生类很像基类,或者基类共享许多特征时,人们通常会选择继承。现在不是使用继承的时候。是时候使用封装了。

一般来说,继承是邪恶的。

另一方面,您可能会觉得这个链接很有趣。

Presentation on inheritance as an implementation detail

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 2013-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-29
    相关资源
    最近更新 更多