c++ - 试图读取充满对象的 vector 的访问冲突

标签 c++ vector clone copy-constructor

edit: I made some changes and updated the code in this post based on the comments of Kyle and Dieter, so I fixed my Clone()function and added a assignment-operator to fulfil the rule of three. While this fixes were for sure badly needed, the same error prevails. Maybe my assignment operator is wrong?

我正在使用我在网上找到的库 jsonplus 来完成一个更大的项目。 我需要将 CJsonArray 类的对象保存在一个 vector 中。 CJsonArray 没有复制构造函数,但有一个指针属性,所以我尝试自己制作一个(我第一次制作复制构造函数,我是 c++ 的新手)。

这里是 CJsonArray 的相关部分:

cjsonarray.h

    class CJsonArray : public CJsonValue
    {
    private:
      std::vector <CJsonValue*> members;
    public:
        LIB_PRE CJsonArray();
        LIB_PRE CJsonArray(const CJsonArray * value);
        LIB_PRE CJsonArray(const CJsonArray &); //the added copy constructor
        LIB_PRE CJsonArray& operator=(const CJsonArray&);
        LIB_PRE ~CJsonArray();

cjsonarray.cpp

 CJsonArray::CJsonArray(const CJsonArray& ori) : members(ori.members.size()) {
        for (std::size_t i = 0; i < ori.members.size()-1; ++i)
            members[i] =ori.members[i]->Clone();
    }
CJsonArray& CJsonArray::operator=(const CJsonArray& ori){
    for (std::size_t i = 0; i < ori.members.size() - 1; ++i){
        this->members[i] = ori.members[i]->Clone();
    }   
    return *this;
}

此外,我必须在 CJsonValue 中实现一个 clone() 函数,它是一个抽象类和从它派生的类。以下是相关的代码片段:

cjson值.h

enum CJsonValueType
{
  JV_STRING,
  JV_NUMBER,
  JV_OBJECT,
  JV_ARRAY,
  JV_NULL,
  JV_BOOL
};

class CJsonValue
{
private:
  CJsonValueType type;
public:
  LIB_PRE CJsonValue();
  LIB_PRE virtual ~CJsonValue();
  LIB_PRE CJsonValue(CJsonValueType type);
  LIB_PRE virtual CJsonValue * Clone(); //the added Clone-Function
  LIB_PRE virtual jstring ToString() const = 0;
  LIB_PRE CJsonValueType GetType() const;
  LIB_PRE virtual void Clear(){};
};

cjson值.cpp

    CJsonValue * CJsonValue::Clone(){
    return NULL;
}

派生类的例子,cjsonvaluenumber.h

    class CJsonValueNumber : public CJsonValue
{
private:
  int value;
public:
  LIB_PRE CJsonValueNumber(int value);
  LIB_PRE CJsonValueNumber(const CJsonValueNumber * value);
  LIB_PRE CJsonValue * Clone();
  LIB_PRE jstring ToString() const;
  LIB_PRE void GetValue(int & number) const;
};

cjsonvaluenumber.cpp

CJsonValue * CJsonValueNumber::Clone(){
    return new CJsonValueNumber(*this);
}

产生错误的 main.cpp:

 CJsonArray array1;
 CJsonArray array2;
 CJsonArray array3;
 CJsonArray array4;
 CJsonArray array5;

 array1.AddMember("test1");
 array2.AddMember("test1");
 array3.AddMember("test1");
 array4.AddMember("test1");
 array5.AddMember("test1");

 arrays.push_back(array1);
 arrays.push_back(array2);
 arrays.push_back(array3);
 arrays.push_back(array4);
 arrays.push_back(array5);

 std::string str = arrays[0].ToString();

错误:

Unhandled exception at 0x026574BD in Message.exe: 0xC0000005: Access violation reading location 0x00000000.

调试信息: 在第一个 push_back 上,第一个条目的成员已经损坏。 在我实现 Copy-Constructor 之前程序已经在第二次或第三次推回时崩溃了,我猜是因为 vectore 必须重新分配他的条目并且找不到它们?难过的是,我第一次不得不处理这个问题。

所以我的问题是:我是否做错了复制构造函数?还是我完全走错了路,这与它无关?

我查看了许多其他处理类似问题的 Stackoverflow 问题,并尝试遵循那里的建议,但我想我在这个过程中做错了什么。

如果我需要提供其他信息,请告诉我。

预先感谢您的帮助!

最佳答案

CJsonValue::Clone() 方法需要是虚拟的。如果 CJsonArray 对象存储了 CJsonValue 对象的集合(与 CJsonValueNumber 或其他方式相反),则编译器无法知道 CJsonValueNumber 想要覆盖 Clone() 方法(如果它不是虚拟的)。

这会导致 CJsonValue::Clone() 总是被调用而不是 CJsonValueNumber::Clone()。此时您的数组中有 NULL 引用,这可能会导致您在 0x00000000 处发生访问冲突(NULL 定义为 0,或者0x00000000)。

因为 CJsonValue 无论如何都是一个抽象类(CJsonValue::ToString() 方法是虚空的),我会制作 CJsonValue::Clone() virtual void 也是。这将保证必须通过继承类来实现 Clone 方法。

总而言之,将 CJsonValue::Clone() 的声明更改为:

LIB_PRE virtual CJsonValue * Clone() = 0;

关于c++ - 试图读取充满对象的 vector 的访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30650017/

相关文章:

git - git 中的 pull 和 clone 有什么区别?

Django 克隆模型对象与基于类的 createview

c++ - 如何同时使用 2 个套接字 PF_INET 和 PF_PACKET?

github - 如何在 Atom 文本编辑器中克隆所有分支而不仅仅是掌握

java - 通过 JNI 在 C++ 中进行图形操作

database - KD-Trees 和缺失值(向量比较)

c++ - 迭代二维 STL vector c++

html - SVG 图像显示我无法删除的细边框

C++ 中缀到逻辑条件的前缀转换

c++ - stringstream初始化错误