【问题标题】:Pointers to a class within void function指向 void 函数中的类的指针
【发布时间】:2013-07-19 10:30:41
【问题描述】:

我正在学习类/继承/指针如何在 C++ 中工作并编写以下代码。

我有一个类 unit 声明如下:

class unit{
    public:
        int locationX,locationY;

        //genotype (does not change)
        float agility, build,size,stamina, aggression;
        //phenotype (changes based on genotype and stimuli)
        float speed, strength, hunger;
};

当我创建一个新实例以传递给一个 void 函数(分别如下)时,尚未分配内存。

实例

unit **units = 0;

虚函数原型

void initialize(grid *grids, unit **units /*, plant **plants, predator **predators */);

在 void 函数中使用一些参数分配内存:

void initialize(grid *grids, unit **units,plant **plants,predator **predators)
{
    units = new unit*[int(((grids->gridHeight)*(grids->gridWidth)*(grids->gridDivision))/20)];

    for(register int i = 0; i<int(((grids->gridHeight)*(grids->gridWidth)*(grids->gridDivision))/20); i++)
        {
        units[i] = new unit;
        units[i]->hunger = 5;
        units[i]->locationX = (rand()%((grids->gridWidth)-0));
        units[i]->locationY = (rand()%((grids->gridHeight)-0));
        //etc, etc
    }
}

但是,一旦我退出 void 函数,我刚刚存储的数据就会被删除。是不是指针声明和传入函数有问题(如下)?

initialize(&environment, units, plants, predators);

注意:我只有在 unit 类下声明的 units 变量有问题。 environment 变量很好。另外两个(plantspredators)和units类似,所以如果解决了,我可以解决其他的。

第二个说明:主要功能如下(相关部分):

int main()
{
    unit **units = 0; //<--- Important one
    plant **plants = 0;
    predator **predators = 0;
    grid environment(250,250,5); //Constructor for environment (don't mind this)
    initialize(&environment, units, plants, predators); //<-- Void function
    running = true;

    return 0;
}

感谢您提供的任何帮助/链接/说明。

【问题讨论】:

  • @Beta:感谢您的修复。现在可以使用了!

标签: c++ class pointers inheritance


【解决方案1】:

您将“units”作为堆栈中的“unit**”类型传递。当您为变量“units”分配新值时,您正在影响函数本地的变量。如果您希望调用代码更新其变量“单位”,则必须通过指针或引用传递它。

解决此问题的最简单方法是将函数签名更改为:

void initialize(grid *grids, unit **&units, etc.. );

这是将变量units作为对指向单元指针的指针的引用传递。

【讨论】:

  • “将变量单元作为对指向单元指针的指针的引用传递”:所以我认为您的意思也是unit ** &amp;units,而不是units * &amp;units :-)
  • 哎呀,是的!谢谢(原来是文本格式问题)
【解决方案2】:

在方法内初始化指针(或数组)A * a 是修改变量 a(在本例中为指针/数组)的特殊情况。修改方法中的变量可以通过传递指向它的指针或引用来完成。所以在你的变量已经是一个指针的情况下,这两个选项如下。

通过将指针传递给您的指针a

void init(A * *a)
{
    *a = new A(); // or "new A[n]" if "a" is an array
}

void main()
{
    A * a;
    init(&a);
}

或传递对您的指针的引用:

void init(A * &a)
{
    a = new A();  // or "new A[n]" if "a" is an array
}

void main()
{
    A * a;
    init(a);
}

因此,在您的情况下,aunit* 的数组(顺便说一下,我认为这是一个糟糕的设计,最好简单地使用 unit 的数组并将您从这个循环中拯救出来动态地分别分配所有单元),所以基本上aunit ** 类型,所以你的A 实际上是unit* 类型。使用第二种方法会导致:

void init(unit* * &units)

但正如我所说,最好直接使用 unit 的数组,而您的整个代码如下所示:

void initialize(unit * &units /* etc */)
{
    // note that I use unit instead of unit* here
    units = new unit[n];

    for(register int i = 0; i<n; i++)
    {
        // note that I remove the "new unit;" here
        // note that I use "." instead of "->"
        units[i].hunger = 5;
        units[i].locationX = (rand()%((grids->gridWidth)-0));
        units[i].locationY = (rand()%((grids->gridHeight)-0));
        //etc, etc
    }
}

void main()
{
    unit * units;
    initialize(units);
}

【讨论】:

    【解决方案3】:

    您将units 传递给函数按值。这意味着函数中的units 指针最初是调用代码中指针的副本。在函数中,您为本地 units 变量(即一些新创建的对象的地址)分配一个新值。然后当函数终止时,局部变量超出范围并且它指向的对象丢失。调用代码中的指针永远不会被修改,并且对此一无所知。

    改为通过引用传递:

    void initialize(grid *grids, unit ** &units)
    

    【讨论】:

    • 除了按预期工作外,还会节省一些开销
    猜你喜欢
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-06
    • 1970-01-01
    • 2016-11-23
    • 1970-01-01
    相关资源
    最近更新 更多