How to pass a Class as Parameter

点点圈 提交于 2020-01-13 06:14:06

问题


In C++ is there a way to pass a type (e.g. a class) as parameter to a function?

Explanation why I need this: There is a abstract data class and a manager class. The manager class contains a list (or in this case a map) of objects of derived classes of data. I use unique_ptr for this as mentioned in the answer of this question.

class Data{}; // abstract

class Manager
{
    map<string, unique_ptr<Data>> List;
};

Now imagine I want to add a new data storage to the manager.

class Position : public Data
{
    int X;
    int Y;
}

How could I tell the manager to create a object of that type and refer an unique_ptr to it?

Manager manager;
manager.Add("position data", Position);

In this case I would need to pass the class Position to the add function of the manager class since I don't want to have to first create an instance and then send it to the manager.

And then, how could I add the object of that class to the List?

I am not sure if there is a way of doing that in C++. If that can't be done easily I would really like to see a workaround. Thanks a lot!


回答1:


You can use templates. In each type deriving from Data you will have to define a 'creator' function, which have the following prototype: Derived* create(). It will be called internally (you can also return a unique_ptr, but that would requires more memory).

Ex:

struct Position: public Data
{
    // ...
    static Position* create()
    {
        return new Position();
    }
};

The Add method will be:

template<typename D>
void Add(String str)
{
    List.insert(std::make_pair(str, std::unique_ptr<Data>(D::create())));
}

Then you use it like this:

Manager manager;
manager.Add<Position>("position data");

EDIT

You can also get rid of the create functions, by using this Add method:

template<typename D>
void Add(String str)
{
    List.insert(std::make_pair(str, std::unique_ptr<Data>(new D())));
}

Advantage: less code in data structure code.

Inconvenient: data structures have less control on how they're built.




回答2:


What about something like this:

class Manager
{
 public:
  template <typename T>
  void addData(const std::string& title)
  {
    List.insert(std::make_pair(title, std::unique_ptr<Data>(new T));
  }
 private:   
  map<string, unique_ptr<Data>> List;
};

then

Manager manager;
manager.addData<Position>("position data");



回答3:


Using unique_ptr means committing to working with dynamically allocated objects. (Not quite true: you could supply a custom deleter that doesn't call delete, but that becomes part of the type; this means you would be committing to working with non-dynamically allocated objects.)

void Manager::Add(String title, unique_ptr<Data> d) {
    List[title] = d;
}

Call it as:

Manager manager;
unique_ptr<Data> pos(new Position);
// Set it up
manager.Add("position data", pos);

Note: If you want to be able to do anything with your data objects, you probably want to declare at least one virtual function inside class Data.




回答4:


Define the function as following:

void Manager::Add(String title,Position pos){ /*snip*/ }

Then you can use the function as following:

Manager manager;
Position posData;
//setup the posData
manager.Add("position data",posData);


来源:https://stackoverflow.com/questions/13109356/how-to-pass-a-class-as-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!