创建对象指针列表

时间:2015-10-05 01:39:53

标签: c++ list pointers

我正在尝试创建一个对象指针的列表(它是对象的私有成员)......

所以我编写的程序是两组“英雄”之间的模拟。每个英雄都有特殊的力量,物理属性等......以及目标列表。目标列表是指向Hero的指针列表。当我调用构造函数创建一个Hero时,除了目标列表之外,所有信息都是用随机值初始化的。到目前为止,我已经创建了Hero's,team 1和team 2的两个列表。我正在尝试在团队1中创建一个指针列表,指向团队2中的Heros地址,反之亦然。 main()中的for循环系列是我的最佳解决方案,但函数Hero :: setTarget“pushes_back”多次第一个Hero的地址。任何建议都将不胜感激。

这里我到目前为止除了Powers.h和Powers.cpp文件......

EDITED:删除了嵌套for循环,但我仍然将相同的地址传递到我的列表....

    #include <iostream>
    #include <list>
    #include <random>
    #include <ctime>

    #include "Hero1.h"
    #include "Powers.h"

    using namespace std;

    int main()
    {
 ///random number generator
    default_random_engine generator(time(NULL));
    uniform_int_distribution<int> numHero(1,10);

///lists of hero's, pointers to a hero, list iterators
    list<Hero> team1;
    list<Hero> team2;
    Hero * hptr1;
    Hero * hptr2;
    list<Hero>::iterator hitr1;
    list<Hero>::iterator hitr2;

/// team 1 is created
    int a =  numHero(generator);
    for(int x=0; x<a; x++)
    {
    hptr1 = new Hero();
    team1.push_back(*hptr1);
    }

/// team 2 is created
    int b = numHero(generator);
    for(int x=0;x<b;x++)
    {
    hptr2 = new Hero();
    team2.push_back(*hptr2);
    }

for(hitr2=team2.begin();hitr2!=team2.end();hitr2++)
{
        hptr1->setTarget(hptr2);
}

for(hitr1=team1.begin();hitr1!=team1.end();hitr1++)
{
    hptr2->setTarget(hptr1);
}

 ///printing results for list of targets
 int w =1;
 cout<<"target address "<<w<<endl;
        hitr1=team1.begin();
        hptr1->displayTarget();

英雄是我的Hero.h

#ifndef HERO1_H_INCLUDED
#define HERO1_H_INCLUDED

#include <iostream>
#include <random>
#include <ctime>
#include <list>

#include "Powers.h"


using namespace std;

class Power;

class Hero
{
public:

    Hero();
   // ~Hero();

    void setID();
    void setLoc();
    void setPhy();
    void setPowers();
    void setEquip();
    void setTarget(Hero *h);

    int getID(){return id;}
    int getLoc(int x);
    int getPhy(int x);

    void displayHero();
    void displayTarget();
    void displayPowers();


private:
    int id;
    int location[3];
    int physical [4];
    Power * powPtr;
    Power * equipPtr;
    Hero * targetPtr;
    list<Power> powers;
    list<Power> equipment;
    list<Hero*> target;
    list<Power>::iterator equipItr;
    list<Power>::iterator powItr;
    list<Hero*>::iterator targetItr;

};

My Hero.cpp

#include "Hero1.h"

default_random_engine generator(time(NULL));
uniform_int_distribution<int> distribution(100000,200000);
normal_distribution<double> disto(50,10);
uniform_int_distribution<int> randPow(1,3);

Hero::Hero()
{
    setLoc();
    setID();
    setPhy();
    setPowers();
    setEquip();
}

void Hero::setLoc()
{
    location[0] = 1;
    location[1] = 2;
    location[2] = 3;
}

void Hero::setID()
{
    int a = distribution(generator);
    id = a;
}

void Hero::setPhy()
{
    double a = disto(generator);
    double b = disto(generator);
    double c = disto(generator);
    double d = disto(generator);

    physical[0] = a;
    physical[1] = b;
    physical[2] = c;
    physical[3] = d;

}

void Hero::setPowers()
{
    int a = randPow(generator);
    for(int x=0;x<a;x++)
    {
    powPtr = new Power(getPhy(3));
    powers.push_back(*powPtr);


    }
}


void Hero::setEquip()
{
    int a = randPow(generator);
    for(int x=0;x<a;x++)
    {
    equipPtr = new Power(getPhy(3));
    powers.push_back(*equipPtr);
    }

}
void Hero::setTarget(Hero *h)
{

    target.push_back(h);

}

void Hero::displayTarget()
{
    int x =1;
    for(targetItr=target.begin();targetItr!=target.end();targetItr++)
    {
        cout<<&targetPtr<<endl;
        x++;
    }
    cout<<x<<endl;

}

int Hero::getLoc(int x)
{
    int p;
    p = location[x];
    return p;
}

int Hero::getPhy(int x)
{
    int p;
    p = physical[x];
    return p;
}
void Hero::displayPowers()
{
    cout<<"Number of powers = "<<powers.size()<<endl<<endl;
    for(powItr=powers.begin();powItr!=powers.end();powItr++)
    {
        powPtr->displayEffect();
    }
}

void Hero::displayHero()
{
    cout<<"Id :\t\t\t\t\t"<<id
        <<"\nLocation:\t\t\t\t"<<location[0]<<","<<location[1]<<","<<location[2]
        <<"\nPhysical attributes:\tstrength\t"<<physical[0]<<"\n\t\t\tendurance\t"<<physical[1]
        <<"\n\t\t\tagility\t\t"<<physical[2]<<"\n\t\t\tspeed\t\t"<<physical[3]<<endl<<endl;

        displayPowers();
}

4 个答案:

答案 0 :(得分:1)

我在您的代码中看到了几个不同的问题,但让我们从您询问的问题开始......

你的setTarget调用每次都在做同样的事情,因为它们是用循环中根本没有更新的指针调用的。这是一个问题,可以通过在函数顶部声明所有变量来实现。比它们的目的更长的变量容易受到这样的错误(或者被重用于多个目的,然后使代码更难理解和维护)。因此,我强烈建议将局部变量确定为确切需要的位置。

例如:

/// lists of heroes
    list<Hero> team1;
    list<Hero> team2;

/// team 1 is created
    int a = numHero(generator);
    for(int x=0; x<a; x++)
    {
        Hero * hptr1 = new Hero();
        team1.push_back(*hptr1);
    }

/// team 2 is created
    int b = numHero(generator);
    for(int x=0;x<b;x++)
    {
        Hero * hptr2 = new Hero();
        team2.push_back(*hptr2);
    }

for(list<Hero>::iterator hitr2=team2.begin();hitr2!=team2.end();hitr2++)
{

    for(list<Hero>::iterator hitr1=team1.begin();hitr1!=team1.end();hitr1++)
    {
        hptr1->setTarget(hptr2);
    }
}

for(list<Hero>::iterator hitr1=team1.begin();hitr1!=team1.end();hitr1++)
{
    for(list<Hero>::iterator hitr2=team2.begin();hitr2!=team2.end();hitr2++)
    {
        hptr2->setTarget(hptr1);
    }
}

如果你这样做,那么你可能会遇到编译错误,因为调用hptr1hptr2setTarget不存在。而这正是你想要的 - 编译器会引起你的注意。

那么这些循环可以修正为:

for(list<Hero>::iterator hitr2=team2.begin();hitr2!=team2.end();hitr2++)
{

    for(list<Hero>::iterator hitr1=team1.begin();hitr1!=team1.end();hitr1++)
    {
        Hero& target = *hitr2;
        hitr1->setTarget(&target);
    }
}

接下来,对于第二个问题:填写列表时你会泄漏内存:

Hero * hptr1 = new Hero();
team1.push_back(*hptr1);

这将动态分配一个英雄,然后它的值复制到另一个在列表中创建的Hero中 - 因为这是push_backlist<Hero>类似的方式。然后,指向动态分配的指针将被丢弃(或在您最初发布的代码中重复使用),因此没有任何东西可以解除分配该内存。

你真正想做的更像是:

team1.push_back(Hero());

答案 1 :(得分:0)

我认为我所说的更值得作为评论然后回答这个问题,但StackOverflow的奇怪规则不允许我发表评论。也就是说,我认为你应该重命名&#34; setTarget&#34; to&#34; addTarget&#34;,as&#34; setTarget&#34;意味着变量只有一个值,每次调用它时都会被覆盖,而&#34; addTarget&#34;更好地传达您将目标添加到列表中。

此外,您应该考虑将std::for_each与lambda函数一起使用,而不是使用显式循环。我怀疑它会在性能或正确性方面产生明显的差异,但它会使你的程序更具可读性,了解STL函数将帮助你提高编程技巧。

答案 2 :(得分:0)

我同意@TheUndeadFish的言论。

此外,我还添加了以下观察结果:

list<Hero> team1;
list<Hero> team2;

不建议保留“Hero”对象列表,而是建议保留指向“Hero”对象的指针列表

list<Hero*> team1;
list<Hero*> team2;

以上建议的方法很有用,因为team1 heros保留了team2 heros的列表,反之亦然,因此这有助于访问每个英雄的更新信息,因为指针/引用有助于访问对象数据的动态变化。

此外,for循环在原始代码中没有hptr1和hptr2的初始化。它可以按如下方式完成:

///lists of hero's, pointers to a hero, list iterators
    list<Hero*> team1;                    <-- change done here
    list<Hero*> team2;                    <-- change done here
    Hero * hptr1;
    Hero * hptr2;
    list<Hero*>::iterator hitr1;          <-- change done here
    list<Hero*>::iterator hitr2;          <-- change done here

/// team 1 is created
    int a =  numHero(generator);
    for(int x=0; x<a; x++)
    {
    hptr1 = new Hero();
    team1.push_back(hptr1);               <-- change done here
    }

/// team 2 is created
    int b = numHero(generator);
    for(int x=0;x<b;x++)
    {
    hptr2 = new Hero();
    team2.push_back(hptr2);               <-- change done here
    }

for(hitr2=team2.begin();hitr2!=team2.end();hitr2++)
{
    hptr2 = *hitr2;                        <-- change done here
    for(hitr1=team1.begin();hitr1!=team1.end();hitr1++)
    {
        hptr1 = *hitr1;                    <-- change done here
        hptr1->setTarget(hptr2);
    }
}

for(hitr1=team1.begin();hitr1!=team1.end();hitr1++)
{
    hptr1 = *hitr1;                        <-- change done here
    for(hitr2=team2.begin();hitr2!=team2.end();hitr2++)
    {
    hptr2 = *hitr2;                        <-- change done here
    hptr2->setTarget(hptr1);
    }
}

答案 3 :(得分:0)

以下原始程序的代码部分也需要修改:

void Hero::displayTarget()
{
    int x = 0;                                  <-- change done here (not important)
    for (targetItr=target.begin(); targetItr!=target.end(); targetItr++)
    {
        cout << *targetItr << endl;              <-- change done here
        x++;
    }
    cout<<x<<endl;
}

注意:

  1. Hero类中的targetPtr成员未在原始代码中初始化。
  2. 在displayTarget()中,始终打印targetPtr,但每次迭代targetItr都不会更新。
  3. 此外,更改main()中的显示代码:

    cout<<"target addresses in team 1"<<endl;
            hitr1=team1.begin();
            hptr1 = *hitr1;                        <-- change done here
            cout<<"address of team 1 pointer "<<hptr1<<endl;
            hptr1->displayTarget();
            cout<<endl<<"-------------"<<endl;
            cout<<"target addresses in team 2"<<endl;
            hitr2=team2.begin();
            hptr2 = *hitr2;                        <-- change done here
            cout<<"addreass of team 2 pointer "<<hptr2<<endl;
            hptr2->displayTarget();
    

    希望这会对你有所帮助。一切都好。