2014-12-05 82 views
2

我遇到了复制构造函数的问题......我假设有一个基本的答案,我错过了一些显而易见的东西 - 也许我正在做一些完全错误的事情 - 但我一直无法弄清楚。父类/子类的C++复制构造函数问题

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

下面是一个伪代码示例,如果这能帮助:

// 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对象的指针)。

+0

您将需要一个拷贝从基构造,与签名'JDI_Item :: JDI_Item(常量ItemRev&)'东西。这个构造函数不是默认为你生成的,因为它很少有意义。 – cdhowie 2014-12-05 23:31:31

+0

首先,'JDI_Item'-ctor是越野车。如果发生任何异常,它会泄漏。为什么你总是有'std :: vector'指针指向'JDI_ItemRev'?为什么他们不直接在向量中,或者至少由智能指针管理? (在第一种情况下,隐式定义应该起作用。)对“Item”也可以这么说。 – Deduplicator 2014-12-05 23:31:57

回答

1

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

但是,如果您想这样做,最简单的方法是在基类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<>dynamic_cast<>来获得派生类的接口。

... ...但是

推导往往似乎是一个轻松取胜,但结果往往并非如此。只有派生类确实是基类的类型时才应该使用继承。通常人们在派生类很像基类时选择继承,或者基类共享很多特性。这不是使用继承的时候。现在是使用封装的时候了。

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

另一方面,你可能会发现这个链接有趣。

Presentation on inheritance as an implementation detail