0

Quick question. I've got a bunch of inherited classes like so:

Object_____
  |       |
Actor    Item
  |
  |_______
Human  Animal

I also have a class called Room, defined like so:

class Room 
{
    Object * addObject (unsigned long _UID, string _name);
    map<int, Object *> objects; // A map containing the Objects within the room
}

What I'd like to do is make the function addObject() able to instantiate any type of the Object classes, something like Room.addObject(Object::Actor::Human), which would then add a Human Object to my list of Objects in the Room. They all have the same constructor arguments, if that helps. Is there any way to do this in C++?

4

2 回答 2

1

我认为您正在寻找的是 C++ 的工厂模式。虽然在 C++ 中实现工厂的方法有很多,但据我所知并没有标准。

我认为简单通常是最好的,所以这里是一个使用您的示例代码的非常简单的对象工厂的示例:

#include <memory>
#include <string>
#include <map>
using namespace std;

// Stub class definitions
class Object { public: Object() {} ~Object() {} };
class Actor : public Object { public: Actor() {} ~Actor() {} };
class Human : public Actor { public: Human() {} ~Human() {} };
class Animal : public Actor { public: Animal() {} ~Animal() {} };
class Item : public Object { public: Item() {} ~Item() {} };

class ObjectFactory
{
public:
    static shared_ptr<Object> create_object(string name);
};

shared_ptr<Object> ObjectFactory::create_object(string name)
{
    if (name == "Human")
        return shared_ptr<Object>(new Human());
    if (name == "Actor")
        return shared_ptr<Object>(new Actor());
    if (name == "Animal")
        return shared_ptr<Object>(new Animal());
    if (name == "Item")
        return shared_ptr<Object>(new Item());
    throw "unknown object type";
}

class Room 
{
public:
    shared_ptr<Object> addObject (unsigned long _UID, string _name);
    map<int, shared_ptr<Object>> objects; // A map containing the Objects within the room
};

shared_ptr<Object> Room::addObject(unsigned long _UID, string _name)
{
    shared_ptr<Object> object = ObjectFactory::create_object(_name);
    objects[_UID] = object; // not sure if this is what you intended to use _UID for...
    return object;
}

int main()
{
    Room room;
    room.addObject(1, "Actor");
    return 0;
}

请注意,这也可以使用Object *代替来完成shared_ptr<Object>,您只是没有自动引用计数/删除,并且必须自己跟踪对象(考虑到它们存储在地图中并不难)。

于 2013-10-21T05:21:11.970 回答
1
template<typename T> Object* addObject( ... ) {
  Object* myobject = new T(...);
  objects.insert({someint, myobject});
}

...
myroom.addObject<Human>(...);

您需要将地图从存储对象更改为存储指向对象的指针,并确定对象的所有者是什么,以便清理它们。(可能有助于使您的地图存储unique_ptrs 或shared_ptrs.

于 2013-10-21T04:17:02.907 回答