C++中的对象数组

An Array of Objects in C++

本文关键字:数组 对象 C++      更新时间:2023-10-16

我有一个名为Actor的类,以及一个名为Beast的类。我想在每个ActorBeast对象中拥有一个包含所有BeastActor对象的数组。假设我有两个Actorsa1a2,以及两个Beastsb1b2a1中会有一个数组包含对a1a2b1b2的引用。同样的数组将位于 a2b1b2 中。

我将如何制作这个数组?

您可以有两个静态类成员、两个向量,并将每个实例添加到构造函数中的此向量中。

class Animal {
    private:
        static std::vector<Animal*> animal_list;
    public:
        Animal() { animal_list.push_back(this); }
        void print_them() { 
            for (auto iter = animal_list.begin(); 
                    iter != animal_list.end(); 
                    iter++) {
                std::cout << *iter << std::endl;
            }
        }
};
std::vector<Animal*> Animal::animal_list;
int main() {
    Animal a1, b1; 
    a1.print_them();
    return 0;
}

当然,处理被破坏的实例、管理所有权和线程安全是一些进一步的考虑因素。

这里有几个条件可以将Actor s和Beast s保存在同一个"数组"中。它们必须共享一个公共基类型,并且数组必须是指针数组。

最重要的是,您可能应该使用向量而不是数组。

一种模式是基类中的静态向量,派生类可以在构造或销毁时在向量中添加和删除自身:

class Base
{
protected:
    void Add( Base* in )
    {
        m_Vec.push_back(this);
    }
    void Remove( Base* in )
    {
        m_Vec.erase(find(m_Vec.begin(), m_Vec.end(), this));
    }
private:
    static vector<Base*> m_Vec;
};
class Actor : public Base
{
public:
    Actor()
    {
        Add( this );
    }
    ~Actor()
    {
        Remove( this );
    }
};
class Beast : public Base
{
        // do as in Actor
};

您有两个问题需要解决:

  • 首先,从您的帖子来看,您似乎想在同一数组中存储不同类型的(Actor和Beast)。仅当两种类型都派生自同一基类时,才能执行此操作,在这种情况下,数组必须是指向基类元素的指针数组。(旁注:仅基于您命名类的方式,Beast 可能会从 Acter 派生,在这种情况下,您的数组可以包含 Actor* 元素。
  • 您可能遇到的第二个问题是类型递归。您希望Actor引用野兽,而Beasts引用Actor。如果不先声明 Beast,就无法完全声明 Actor 类,但由于 Beast 也引用 Actor,因此您也不能先声明 Beast。在C++中,您可以通过"前向声明"类来解决此类递归。前向声明一个类告诉编译器该类将在稍后声明,但现在它应该只接受它作为一个有效的类。在前向声明和完整声明之间,您将能够使用指向类的指针(并且仅在不取消引用的情况下),但只能使用指针,因为编译器还不知道类的大小或成员。正向声明这两个类很简单:

    类演员;类野兽;

不过,请注意,如果您不将两个类存储在单独的数组中,而是使用基类实现我的第一点中的解决方案,那么您还应该将公共数组存储在基类中,并且无需转发声明 Actor 和 Beast。