试图将对象存储在数组中,然后如何调用该对象的方法?

时间:2012-01-14 02:00:32

标签: c++

我不是一个非常有经验的c ++编码器,这让我很难过。我将一个对象(在别处创建)传递给一个函数,我希望能够将该对象存储在某个数组中,然后运行该数组来调用该对象上的函数。这是一些伪代码:

void AddObject(T& object) {
  object.action(); // this works

  T* objectList = NULL;
  // T gets allocated (not shown here) ...
  T[0] = object;
  T[0].action(); // this doesn't work
}

我知道对象正确传递,因为第一次调用object.action()会做到它应该做的事情。但是当我将对象存储在数组中时,尝试调用action()会导致严重崩溃。

可能我的问题是我只是修改了。和*,直到编译完成,T[0].action()编译但在运行时崩溃。

3 个答案:

答案 0 :(得分:1)

您问题的最简单答案是,您必须正确声明容器,您必须为您的班级定义适当的分配运算符。尽可能密切地与您的示例一起工作:

typedef class MyActionableClass T;
T* getGlobalPointer();

void AddInstance(T const& objInstance)
{
    T* arrayFromElsewhere = getGlobalPointer();

//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **objects**
//whose first element we don't mind losing

//**copy** the instance we've received
    arrayFromElsewhere[0] = objInstance;

//now invoke the action() method on our **copy**
    arrayFromElsewhere[0].action();

}

请注意 const reference 的签名更改,强调我们将复制原始对象,而不是以任何方式更改它。

同样请注意:arrayFromElsewhere [0] .action()相同,因为你已经制作了副本 - action()是在不同的环境中被调用,无论多么相似。

虽然很明显你已经凝聚了,但凝结使得这样做的原因不太明显 - 例如,指定你想维护一个回调对象数组会为“需要”这个功能提供更好的理由。像你一样使用“T”也是一个糟糕的选择,因为这往往意味着模板使用给大多数有经验的C ++程序员。

最有可能导致“无法解释”崩溃的事情是任务操作员;如果你没有定义一个,编译器会自动生成一个作为按位复制的文件 - 几乎可以肯定你想要的东西,如果你的类不是简单数据类型(POD)的集合。

为了在任何复杂的类上正常工作,您可能需要定义深层副本或使用引用计数;在C ++中,让编译器为你创建任何ctor,dtor或赋值几乎总是一个糟糕的选择。

当然,使用标准容器而不是您的示例所暗示的简单数组机制是个好主意。在这种情况下,由于容器和算法的假设,您可能还应该定义默认的ctor,虚拟dtor和copy ctor。

事实上,如果想要创建对象的副本,而是希望在原始对象上调用action()一个数组,那么你需要一个指针数组。再次与原始示例密切合作:

typedef class MyActionableClass T;
T** getGlobalPointer();

void AddInstance(T& objInstance)
{
    T** arrayFromElsewhere = getGlobalPointer();

//ok, now at this point we have a reference to an object instance
//and a pointer which we assume is at the base of an array of T **pointers**
//whose first element we don't mind losing

//**reference** the instance we've received by saving its address
    arrayFromElsewhere[0] = &objInstance;

//now invoke the action() method on **the original instance**
    arrayFromElsewhere[0]->action();

}

请注意,arrayFromElsewhere现在是一个指向对象的指针的数组,而不是实际对象的数组。

请注意,我在这种情况下删除了const修饰符,因为我不知道action()是否是一个const方法 - 具有类似我假设的名称...

请仔细注意分配中使用的&符号(地址)运算符。

还要注意使用指针运算符调用action()方法的新语法。

最后要注意的是,使用标准的指针容器充满了内存泄漏危险,但通常几乎与使用裸阵列一样危险: - /

答案 1 :(得分:0)

我很惊讶它编译。您声明了一个指向objectList的8个指针的T数组。然后指定T[0] = object;。这不是你想要的,你想要的是

之一
T objectList[8];
objectList[0] = object;
objectList[0].action();

T *objectList[8];
objectList[0] = &object;
objectList[0]->action();

现在我正在等待C ++专家解释你的代码编译的原因,我真的很好奇。

答案 2 :(得分:0)

您可以将对象放入动态或静态数组中:

#include <vector> // dynamic
#include <array>  // static

void AddObject(T const & t)
{
    std::array<T, 12> arr;
    std::vector<T>      v;

    arr[0] = t;
    v.push_back(t);

    arr[0].action();
      v[0].action();
}

但这并没有多大意义;你通常会在函数之外的其他地方定义你的数组。