如何使用指针向量为类创建复制函数?

时间:2017-06-29 17:27:54

标签: c++

我有一个类Somec,带有指向项目的向量。向量中的每个项都来自另一个类类型Myitem

我想为Somec制作一个复制功能,但我遇到了一些问题。

另外,我有Myitem的复制功能,我是否必须在Somec的复制功能中使用它?

到目前为止我尝试过:

class Somec {
    string Name;
    std::vector<Myitem*> Items;

public:
    Somec(const Somec& somec); // my copy function
};

/// this the clas to my item :
class Myitem {
    Itemk itemk;
public:
    // ... some fuction 
};

// now I want to make a copy function for Somec

Somec::Somec(const Somec& somec) {
    int size = somec.Items.size();
    this->Items = new (vector*) (size); // i get an error here
    this->Name = somec.Name;
    for(int i = 0; i < size; i++) {
        *Items.at(i) = *somec.Items.at(i);
    }
}

更新:我像Remy Lebeau告诉我的那样制作了复制功能,但是当我尝试测试此功能时,代码停止工作。这就是我测试它的方式:

class Somec {
    string Name;
    std::vector<Myitem*> Items;

public:    
    Somec(const Somec& somec); // my copy function
};

Somec::Somec(const Somec& somec) { // new copy function for somec
    int size = somec.Items.size();
    this->Name = somec.Name;
    for(int i = 0; i < size; i++) {
        Items.push_back(new Myitem(*somec.Items[i]));
    }
}

// create item function
void Somec::createitem(char* name, const int& Time, const int& level) {
    try{
        Myitem* ORitem=new Myitem(name, Time, level);
        Somec::Items.push_back(ORitem);        
    }
    catch(MemoryProblemException& error) {
        throw SomecMemoryProblemException();
    }
}

std::vector<Myitem*> Somec::getAllItems() const {
    return Items;
}

/// this the class to my item :
class Myitem {
    Itemk itemk;
public:
    // ... some fuction 
};

// my copy function to MYitem 
Myitem::Myitem(const Myitem& item){
    Myitem* currie = Myitem::clone_item();
    curritem->item = itemCopy(item.item);
    if (!curritem->item) {
        throw itemMemoryProblemException();
        return;
    }
}

void testCopy() {
    Somec somec("name1")
    somec.createitem((char*) "item1", 30, 1, 2);
    Somec temp(somec);
    int x=0;
    if ( std::equal(somec.getAllItems().begin() + 1, somec.getAllItems().end(), somec.getAllItems().begin()) ) {
        x++;
    }
    ASSERT_TRUE(x==1);
}

我的问题是什么?我的意思是,我做了复制功能,我认为这是真的。但为什么代码停止工作?我是以正确的方式测试这个吗?

我的createitem功能,实际上我100%肯定。

我只是想在Somec中添加项目并检查这是否正确。我了解到在C ++中,我们需要一个复制构造函数,所以我写了一个,并考虑测试它,因为这是我第一次做它。

2 个答案:

答案 0 :(得分:1)

如果要将其他实例的向量中的元素复制到复制构造函数中当前实例的向量,则只需执行此操作

class Somec {
    string Name;
    std::vector<Myitem> Items;
public:
    Somec(const Somec& somec); // my copy function
};

即。制作值的向量而不是指针。

如果由于某种原因你必须使用指针,因为可能删除了复制构造函数或类似的东西。然后仍然使用这种方法,但只是不复制复制构造函数中的内容,让它们构造然后分配它们

Somec(const Somec& somec) {
    this->Items.resize(somec.Items.resize());
    for (std::size_t i = 0; i < somec.Items.size(); ++i) {
        this->Items[i] = somec.Items[i];
    }
    // or simply
    this->Items = somec.Items;
}

答案 1 :(得分:0)

默认的编译器生成的复制构造函数已经完全您的复制构造函数手动执行的操作。所以它是冗余代码。

但是,假设Somec拥有项目,那么您需要定义自定义复制构造函数,并且需要分配 Myitem个对象并复制现有数据进入他们,例如:

Somec::Somec(const Somec& somec) {
    this->Name = somec.Name;
    std::size_t size = somec.Items.size();
    this->Items.reserve(size);
    for(std::size_t i = 0; i < size; i++) {
        Items.push_back(new Myitem(*somec.Items[i]));
    }
}

您还必须在覆盖operator=中执行类似的操作。您可以使用复制构造函数来帮助您:

Somec& Somec::operator=(const Somec& somec) {
    if (&somec != this) { 
        Somec temp(somec);
        std::swap(this->Name, temp.Name);
        std::swap(this->Items, temp.Items);
    }
    return *this;
}

当然,请确保释放析构函数中的拥有项:

Somec::~Somec() {
    std::size_t size = somec.Items.size();
    for(std::size_t i = 0; i < size; i++) {
        delete Items[i];
    }
}

有关为何需要此三重奏的详细信息,请参阅Rule of Three