复制具有该类成员对象的类的赋值实现。(c ++)

时间:2015-03-20 14:49:30

标签: c++

我是一名新的计算科学专业的学生,​​在c ++方面经验不足。我一直在谷歌搜索几个小时,并没有遇到一个解决方案(说实话,我甚至找不到一个好的搜索声明)。基本上我在这里要学习的是如何为以下情况实现复制操作符:

#include <string>
#include <vector>
class foo
{
    foo* parentObject;
    std::vector<foo*> childObjects;
    char a;
    int *b;
public:
    foo(char a, int* b) : a(a), b(b) {};
    foo();
    foo& operator =(const foo& other)
    {
        a = other.a;
        b = new int(*other.b);
        //parentobject???
        //pretty sure i can figure childObjects if i can manageparentObject,
        //but just in case there are some special stuff wanted to include.
        return *this;
    }
    friend void getElements(std::string fpath);
};

为了更深入,我想从格式化的文本文件中读取类似树状层次结构(类似于XML)的相同类型的对象,并且只在内存中读取对象的一个​​实例(让假设这是getElements所做的事情,其余的是指向这些对象的指针(我们可以将其视为快捷方式的工作方式)。那是因为,我认为这将是最有效的方法,因为可能有很多对象,请纠正我,如果我错了。

但我也想跟踪结构,所以我决定采用这种父/子设计(再次可能是一个糟糕的选择,随时启发我)。由于我使用的读取方法(从父级到子级),即使我能找到初始化parentObject的方法,我也不能简单地初始化childObjects。因此我不能使用'new constructor()'赋值(或者我可以,但我只是不知道我可以)。

如果我需要()复制操作符背后的原因不清楚,因为我没有初始化parentObject或childObjects,我需要稍后在阅读文本文档时分配它们(它真的感觉我不应该需要一个,但我想我会这样做。)。

我的实际代码真的难以阅读;因为这是一个只是为了在c ++上变得更好的项目,我没有重视编码风格)而且它更长,所以我创建了一个更简单的版本。我非常感谢任何评论,所以请随意写一篇。

编辑:我甚至无法正确复制粘贴(b的初始化)。 编辑:清除。

2 个答案:

答案 0 :(得分:2)

如果有一个具有成员变量的对象来定义对象树,则复制构造函数或复制赋值运算符将不足以处理所有情况。你可能想:

  1. 仅复制树中节点的内容(ab)。
  2. 复制一层父母和孩子。
  3. 复制N层父母和子女。
  4. 复制N1层父母和N2层儿童。
  5. 复制整棵树。
  6. 上面的

    (1)可以由复制构造函数或复制赋值运算符处理。对于其他人来说,最好让extern函数遍历树并复制树的右边部分。

答案 1 :(得分:0)

您遇到了XML节点自身复制的逻辑问题。实际上没有明确和直观的方法来复制作为树的一部分的XML节点。 C ++中的经验法则是:如果operator没有直观的行为,请将其命名为命名函数。在您的情况下,我会创建一个foo& assign_from_content(foo&)函数,它的作用类似于复制赋值,而static foo construct_from_content(foo&)就像一个复制构造函数,只复制内容。

现在如何处理复制构造函数和复制赋值运算符? delete他们。而是使用移动构造和移动分配。

foo& operator =(const foo& other)=delete;
foo& operator =(foo&& other) noexcept=delete;
{
    disconnect_from_tree();

    a = other.a;
    delete b;
    b = other.b;
    other.b = null;

    take_place_in_tree(other);       
    return *this;
}

//These are untested, they probably don't compile and have logical errors
void disconnect_from_tree() noexcept {
    if (parentObject) {
        auto it = std::find(parentObject->childObjects.begin(), 
                            parentObject->childObjects.end(), 
                            this);
        if(it != parentObject->childObjects.end())
            parentObject->childObjects.erase(it);
    }
    for(foo* child : childObjects)
        child->parentObject = nullptr;
    childObjects.clear();
}

//These are untested, they probably don't compile and have logical errors
void take_place_in_tree(foo& other) noexcept {
    childObjects = std::move(other.childObjects);
    parentObject = other.parentObject;     
    other.disconnect_from_tree();
    for(foo* child : childObjects)
        child->parentObject = this;  
    if (parentObject) {
        auto it = std::find(parentObject->childObjects.begin(), 
                            parentObject->childObjects.end(), 
                            this);
        if(it != parentObject->childObjects.end())
            parentObject->childObjects.erase(it);
        parentObject->childObjects.push_back(this);
    }
}