【问题标题】:Using a(n empty) base class to enable storing different objects in the same container使用一个(n 空)基类来启用在同一个容器中存储不同的对象
【发布时间】:2012-10-16 20:57:30
【问题描述】:

假设我有两个完全不同的对象,Sprite 和 PhysicsData。

我编写了一个空基类和一个容器类,可以将对象推送到容器或从容器中移除。

我创建了两个这样的容器来存储两个不同的对象 - Sprite 和 PhysicsData。 (不同的对象不在同一个类中)

class base
{
};

class ContainerManager
{
public:
    std::vector<base*> list;
    void Push(base *object);
    void Remove(base *object);
};

class PhysicsData : public base
{
    void applyGravity();
};

class Sprite : public base
{
    void Draw();
};

ContainerManager SpriteContainer;
ContainerManager PhysicsDataContainer;

Sprite aSprite;
SpriteContainer.Push(&aSprite);

PhysicsData SomeData;
PhysicsDataContainer.Push(&SomeData);

这是应该下注的方式吗?

【问题讨论】:

  • 它会给你任何错误还是什么?
  • 不要只使用pre 作为代码。通过在其前面放置 4 个空格来格式化它。
  • 我才刚开始接触 c++,很好奇。
  • 我不明白。您定义了一个公共基础,因此您可以(大概)在同一个容器中压缩不同的对象。但是随后您制作了两个容器并将它们分开存放。是什么赋予了?为什么不只拥有两个不同类型的容器?
  • 一个std::vector不管是什么类型的接口都是一样的,那么ContainerManager给你买了什么?

标签: c++ containers


【解决方案1】:

不是一种 C++ 方式。您应该使用模板。

如您所知,STL(您在使用 std:: 命名空间前缀时调用它)实际上是标准模板库 :)。许多模板类已经存在,例如推送/删除操作见std::list&lt;T&gt;

你可以这样使用它:

std::list<Sprite> SpriteContainer;
std::list<PhysicsData> PhysicsDataContainer;

等等。

There 是一本关于 C++ 模板的很棒的指南,如果您仍然想编写自己的类以获得更多功能。
there 是对std::list 的引用,(我认为我不需要为你解释std::vector 的用法)如果问题是你真正想做的事情。

【讨论】:

  • 该类的函数还处理其他事情,例如在传递给它的对象中调用函数。
  • 我明白了,那你还是需要使用模板。只需点击链接并仔细阅读指南。这不是 C++ 中最琐碎的事情。
  • @andrew 这也可以使用模板。将模板视为(在您的情况下)键入模板类时尚不知道的类型 T 的占位符;但是您仍然可以在“未知”类型 T 上调用函数(比如说T::foo()。只要确保在实例化具体类时这些函数确实存在。例如在说ContainerManager&lt;Sprite&gt; 时,被调用的函数,这里是foo(),必须存在于Sprite
【解决方案2】:

您在 C++ 中使用模板,但仍在为普通容器使用通用基类而烦恼??

template <class T>
class Container{
  private:
    vector<T> list;
  public:
    void Push(T data);
    T Pop();
};

【讨论】:

  • C++ 中的 pop 函数通常不应该返回它删除的值,因为如果它返回了,那么在 T 的复制构造函数的情况下它不可能提供强大的异常保证可以扔。也就是说,从 C++11 开始,复制构造函数可以抛出的任何类型都可能 ought 具有 nothrow move 构造函数,因此只要您只使用最近编写且行为良好的类型,问题就会消失。
【解决方案3】:

如果您将单个虚函数放入基类,如果您在同一个容器中混合不同类型,您将能够使用dynamic_cast 取回正确的指针。虚拟析构函数是一个好主意,因为如果对象是动态分配的,您可以删除它,而不必将其转换回原始指针。

如果您要在单个容器中混合类型,我agree with dreamzor 认为模板类会更好。这就是所有标准容器的实现方式。

【讨论】:

    【解决方案4】:

    这看起来像是技术上正确的代码,但您没有进行任何类型检查。如您所见,PhysicsData 显示在您的 SpriteContainer 中。你可能不想要这个。

    将 PhysicsData 排除在 SpriteContainer 之外的方法不止一种。一种方法是使用模板。使用模板,您可以在编译时声明容器应该使用哪种类型的基础对象。

    另一种方法是从您的 ContainerManager 继承两种类型的 ContainerManager,一种称为 PhysicsContainerManager,另一种称为 SpriteContainerManager。这两个子类可以进行类型检查以验证传递的对象实际上是 SpriteContainer 还是 PhisicsData。此链接显示了如何在 c++ 中进行类型检查 C++ equivalent of instanceof

    谢谢 何塞

    【讨论】:

    • SomeData 实际上并不意味着要进入 SpriteContainer。我的错。感谢您指出这一点!
    猜你喜欢
    • 2012-08-05
    • 1970-01-01
    • 2022-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    相关资源
    最近更新 更多