将指针复制到包含表的对象时遇到问题...保留了一些信息(字符串,例如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;
}

最佳答案

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)为索引使用无符号数据类型(例如std::size_t)。与您的问题无关,但值得考虑。

关于c++ - 用表复制指向对象的指针,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27446820/

10-11 23:12
查看更多