尝试将对象存储在数组中,但如何调用该对象的方法?
Trying to store an object in an array but then how to call that object's methods?
我不是一个经验丰富的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()
会编译,但在运行时崩溃。
问题的最简单答案是必须正确声明容器,必须为类定义适当的赋值运算符。从你的例子中尽可能紧密地工作:
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,这强调我们将复制原始对象,而不是以任何方式更改它。
此外,请注意arrayFromOtherwhere[0].action()与objInstance.action()不同,因为您已经复制了一个副本--action()在不同的上下文中被调用,无论多么相似。
虽然很明显您已经进行了压缩,但压缩使这样做的原因变得不那么明显——例如,指定要维护一个回调对象数组将为"需要"此功能提供更好的理由。像您那样使用"T"也是一个糟糕的选择,因为对于大多数有经验的C++程序员来说,这往往意味着模板的使用。
最有可能导致你"无法解释"的崩溃的是分配运算符;如果您不定义一个,编译器将自动生成一个可以作为逐位副本的副本——几乎可以肯定的是,如果您的类不是简单数据类型(POD)的集合,则不是您想要的。
为了在任何复杂的类上正常工作,您可能需要定义一个深度副本或使用引用计数;在C++中,让编译器为您创建任何ctor、dtor或赋值几乎总是一个糟糕的选择。
当然,最好使用标准容器,而不是示例中所暗示的简单数组机制。在这种情况下,由于容器和算法所做的假设,您可能还应该定义一个默认的ctor、一个虚拟dtor和一个复制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();
}
请注意,arrayFromOtherwhere现在是指向对象的指针数组,而不是实际对象数组。
注意,在这种情况下,我删除了const修饰符,因为我不知道action()是否是const方法——我假设它的名称不是…
请仔细记下分配中使用的"与"和(地址)运算符。
还要注意使用指针到运算符调用action()方法的新语法。
最后要注意的是,使用指针的标准容器充满了内存泄漏的危险,但通常情况下,不会像使用裸数组那样危险:-/
我很惊讶它能编译。您声明了一个数组objectList
,它包含指向T
的8个指针。然后分配T[0] = object;
。这不是你想要的,你想要的是
T objectList[8];
objectList[0] = object;
objectList[0].action();
或
T *objectList[8];
objectList[0] = &object;
objectList[0]->action();
现在我正在等待一位C++专家来解释为什么要编译你的代码,我真的很好奇。
您可以将对象放入动态或静态数组:
#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();
}
不过,这并没有多大意义;您通常会在函数之外的其他地方定义数组。
- 对RValue对象调用的LValue ref限定成员函数
- 检查哪个对象调用了另一个对象的对象方法
- 在 C++ 的 Switch Case 中创建对象后对对象调用方法
- 从 Base 引用对象调用派生类的成员
- 为什么为未删除的对象调用析构函数?
- Qt c++不会为所有对象调用move_slot.为什么?
- 使用在堆栈上创建的对象调用虚拟函数
- 使用基类对象调用Dervied Class函数
- C++:允许临时对象调用非常量成员函数的设计理念是什么?
- 从类中的对象调用类中的函数的最佳方法
- 派生对象调用的 Base 方法的模板推导
- 如何使用单个对象调用具有相同名称的两个类函数
- 是否可以从另一个类对象调用一个类函数而不继承第一个类
- 如果类没有任何成员变量,则通过临时对象调用类的成员函数的开销是多少?
- 如何对动态数组中的某些对象调用析构函数
- 如何从列表中存储的对象调用成员函数
- 从线程内的对象调用静态方法
- 从成员对象调用方法
- 当包含它的对象调用其析构函数时,unique_ptr是否未分配
- 从对象调用成员对象,错误:引用非常量值的初始值必须是左值