2012-01-14 93 views
0

我不是一个非常有经验的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() compliles但在运行时崩溃。

+0

您正在创建*指针数组*和努力在里面存储* objects *。这绝对不行,它通常不应该编译。还有其他错误。我真的看不到这是如何编译的。 – Jon 2012-01-14 02:05:44

+0

这是你的真实代码吗?因为那真的不应该编译('T [0]'如果'T'是一个类型是没有意义的。如果使用'objectList',那么它仍然不能编译,因为'objectList [0]'是键入'T *',而'object'类型为'T&') – Grizzly 2012-01-14 02:08:13

+0

T是一个类。这只是伪代码,我试图从几个分散的地方提取样本。 – 2012-01-14 02:09:36

回答

1

对于你的问题最简单的答案是,你必须正确声明你的容器你必须为你的类定义一个合适的assigment操作符。从你的例子尽可能密切合作:

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引用其中强调,我们要复制原始对象,不以任何方式改变它。

而且笔记仔细是arrayFromElsewhere [0] .action()不是一样objInstance.action(),因为你已经做了一个副本 - 行动()被在不同的上下文中调用,不管有多相似。

虽然很明显你已经浓缩了,但是这样做的原因并不那么明显 - 例如指定你想要维护一个回调对象数组会更好地满足“需要”这个能力。像你这样使用“T”也是一个糟糕的选择,因为这往往意味着大多数有经验的C++程序员都会使用模板。

最有可能导致您的“不明原因”崩溃的事情是赋值运算符;如果你没有定义一个,编译器会自动生成一个作为按位副本的工具 - 几乎可以肯定地是而不是如果你的类不是简单数据类型(POD)的集合,你想要什么。

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

而且,当然,使用标准容器而不是您的示例中隐含的简单数组机制将是个不错的主意。在这种情况下,由于容器和算法的假设,你应该也可以定义一个默认的ctor,一个虚拟的dtor和一个copy。

如果,事实上,你想创建对象的副本,但希望,相反,在一个阵列中调用对象,但是从动作(),那么你就需要一个数组的指针来代替。再次紧密合作,以你原来的例子:

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修饰在这种情况下,因为我不知道,如果行动()是一个const方法 - 有了这样的名字我假设不...

注意仔细号(地址 - 的)运营商正在使用的任务。

还要注意通过使用pointer-to运算符来调用action()方法的新语法。

最后注意,使用指针的标准集装箱是充满了内存泄漏的危险,但通常不作为危险的,因为使用裸阵列: -/

+0

谢谢你的回答,你似乎明白我正在尝试做什么。我认为你对自动赋值运算符是正确的,正如成功的编译和可怕的崩溃所证明的那样。尝试使用抽象类也有一些麻烦,但我已经完成了排序。 – 2012-01-14 07:22:07

0

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

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

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

现在我在等待一个C++高手一个解释,为什么你的代码编译,我真的很好奇。

+0

编辑该问题以修复我声明objectList = NULL的方式。这不是真正的代码,只是一个快速示例。 – 2012-01-14 02:15:05

+0

不改变任何相关。你声明的指针(用作数组)是'objectList',所以在分配之后,'objectList =(T *)malloc(8 * sizeof(T));','objectList = new T [8];' ,你设置'objectList [0] = object;'。 – 2012-01-14 02:30:42

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(); 
} 

这并不真正使一个很大的意义,但是,你通常会在函数之外的其他地方定义你的数组。

相关问题