使用表复制指向对象的指针

时间:2014-12-12 15:27:14

标签: c++ c++11 codeblocks

将指针复制到包含表的对象时出现问题...保留了一些信息(字符串,例如skillName),但表中包含新的随机数据。我试了好几件事,但我还是不知道怎么回事,怎么办......请帮帮我。 :)

编辑:我已经编辑了整个帖子,正如WhozCraig所建议的那样使它成为MCVE(至少我试过)。 现在一切都在这段代码中,所以你可以复制它并亲自看看。由于某些原因,问题现在在不同的位置,但它仍然是相同的......

#include <iostream>
#include <string>

using namespace std;

class Skill
{
protected:
    int const maxSkillLevel;
    short skillLevel;
    string skillName;

public:
    Skill(string skillName) : maxSkillLevel(5){
        skillLevel = 0;
        this->skillName = skillName;
    }

    virtual ~Skill(){}
    virtual int getMaxDmg(int i){ return 0; };

    void increaseSkillLevel(int);
    string getSkillName(){ return skillName; }
};


class OffensiveSkill : public Skill{
protected:
    int *maxDmg;

public:
    OffensiveSkill(string skillName, int maxDmg[]) : Skill(skillName){
        this->maxDmg = maxDmg;
    }

    ~OffensiveSkill(){}

    int getMaxDmg(int i){ return maxDmg[i]; }

};


class Role{
protected:
    string roleName;
    Skill **skills;

public:
    Role(string roleName){
        skills = new Skill*[3];
        this->roleName = roleName;
    }

    Role(Role* role){
        this->skills = role->getSkills();
        this->roleName = role->getRoleName();
    }

    Skill **getSkills(){ return skills; }
    string getRoleName(){ return roleName; }

    void setSkills(Skill* s1){ skills[0] = s1; }
};


class RoleGenerator{
protected:
    Role *role;
public:
    RoleGenerator(){
        role = new Role("assassin");

        int maxDmg[5] = { 30, 45, 60, 75, 90 };

        OffensiveSkill* assassinate = new OffensiveSkill("Assassinate", maxDmg);
        role->setSkills(assassinate);

        cout << "maxDmg in RoleGenerator " <<  role->getSkills()[0]->getMaxDmg(0) << endl;
    }

    Role *getRoles(){ return role; }
};


int main(){

    RoleGenerator* rg = new RoleGenerator();
    Role *role = rg->getRoles();

    cout << "maxDmg in main " << role->getSkills()[0]->getMaxDmg(0) << endl;

    Role *copied = new Role(role);

    //maxDmg here is different
    cout << "maxDmg in after copying " << role->getSkills()[0]->getMaxDmg(0) << endl;

    //but skill name is copied correctly
    cout << "skill name " <<  role->getSkills()[0]->getSkillName() << endl;
}

2 个答案:

答案 0 :(得分:1)

RoleGenerator:: RoleGenerator()

中的本地数组
int maxDmg[5] = { 30, 45, 60, 75, 90 };

正作为地址传递给:

OffensiveSkill* assassinate = new OffensiveSkill("Assassinate", maxDmg);

通过以下方式保存该地址:

this->maxDmg = maxDmg;

RoleGenerator:: RoleGenerator()返回后maxDmg不再有效。以后取消引用保存的地址会调用未定义的行为。

如果副本足够,那么通过将数组复制到简单的成员数组或向量中,一种方法就可以实现这一点。有多种方法可以做到这一点。使用向量的一个体面的任意长度解决方案将是这样的:

#include <vector>

class OffensiveSkill : public Skill {
protected:
    std::vector<int> maxDmg;

public:
    template<size_t N>
    OffensiveSkill(string skillName, int (&dmg)[N]) 
        : Skill(skillName)
        , maxDmg(dmg, dmg+N)
    {
    }

    int getMaxDmg(int i) const { return maxDmg[i]; }
};

仅此一项就可以作为现有构造函数和类定义的替代品。如果需要,您可以通过提供备用构造函数来提供额外的灵活性,例如允许开始和结束迭代器直接传递给maxDmg构造,int*size_t长度等等。

我建议您修改索引成员getMaxDmg(),以便(a)范围检查输入值,如果超出范围则抛出异常,并且(b)使用无符号数据类型(例如{{1你的索引。与你的问题无关,但值得考虑。

答案 1 :(得分:0)

这看起来很奇怪:

skills[0] = static_cast<OffensiveSkill*>(roleSkills[0]);

您需要包含更多代码。

但是,基于有限的信息,看起来你最好使用自定义的复制构造函数。编译器生成的复制构造函数不会为您执行深层复制。