0

我正在尝试将派生类存储在没有对象切片的向量中。我一天中的大部分时间都在努力寻找,但还没有弄清楚如何让它发挥作用。我读过的解决方案建议存储指向派生对象而不是实际对象的指针。我无法让它工作,但我想以这样的方式将这些对象添加到向量中,这将导致对象在向量超出范围之前超出范围。所以,我认为这种解决方案无论如何都行不通。另一种解决方案建议使基类抽象,但这也不起作用。我读到了关于覆盖赋值运算符和复制构造函数的内容,但我认为它们最终没有做任何不同于普通赋值运算符和 noraml 复制构造函数的事情。我也用虚拟赋值运算符尝试过,但没有成功。以下是我一直在使用的示例。“vec.emplace_back(&derivedEvent);” main 方法中的语句导致将基类添加到向量中。紧接着,对象超出范围,向量不再包含派生事件的数据。我对编程还是很陌生,所以我尝试过的任何事情都可能做错了。

#include <string>
#include <vector>
////////////////////////////////////////////////////////////////////////////////
class CBaseEvent {
protected:
    CBaseEvent(){}
    std::string m_strBeginning;
    std::string m_strEnd;
public:
    CBaseEvent(std::string strBeginning, std::string strEnd)
    : m_strBeginning(strBeginning), m_strEnd(strEnd){}
};
////////////////////////////////////////////////////////////////////////////////
class CDerivedEvent : public CBaseEvent {
private:
    CDerivedEvent(){}
    std::string m_strMiddle;
public:
    CDerivedEvent(
        std::string strBeginning,
        std::string strMiddle,
        std::string strEnd)
        : CBaseEvent(strBeginning, strEnd),
        m_strMiddle(strMiddle){}
};
////////////////////////////////////////////////////////////////////////////////
int main() {
    std::vector<std::shared_ptr<CBaseEvent>> vec;
    if (true) {
        CDerivedEvent derivedEvent = CDerivedEvent("1", "2", "3");
        vec.emplace_back(&derivedEvent);
    }
    return 0; //CRASH: possible corruption of the heap
}
4

2 回答 2

1

您正在堆栈中和 if 语句的范围内创建对象,一旦超出该范围,该对象将不再存在,并且当 share_ptr 被超出主函数范围的向量破坏时程序将崩溃,因为它会尝试销毁不再存在的对象。

这:

 if (true) {
        CDerivedEvent derivedEvent = CDerivedEvent("1", "2", "3");
        vec.emplace_back(&derivedEvent);
    }

应该:

 if (true) {
        CDerivedEvent* derivedEvent = new CDerivedEvent("1", "2", "3");
        vec.emplace_back(derivedEvent);
    }

它应该可以按您的预期工作,但正如 Jhon Purdy 在下面的评论中所说,这会更合适:

int main()
{
    std::vector<std::unique_ptr<CBaseEvent> > vec;

    vec.push_back(std::unique_ptr<CBaseEvent>(new CDerivedEvent("1", "2", "3")));

    return 0; 
}
于 2013-07-14T21:43:11.483 回答
1

我喜欢

std::vector<std::unique_ptr<CBaseEvent> > vec;

AngelCastillo 使用了很多方法,但它只有一件事是错误的。

std::unique_ptr<CBaseEvent>(new CDerivedEvent(blah))将导致CDerivedEvent通过 type 的指针删除 type 的对象CBaseEvent*。由于CBaseEvent没有虚拟析构函数(它甚至不是多态的),这是未定义的行为。

这可以通过以下任一方式解决

  • 添加虚拟析构函数或
  • using std::shared_ptr,它在删除器内部保留类型信息。

    std::vector<std::shared_ptr<CBaseEvent> > vec;
    vec.push_back(std::make_shared<CDerivedEvent>(whatever));
    
于 2013-07-14T22:24:33.573 回答