C ++ Полиморфизм и новое ключевое слово - PullRequest
0 голосов
/ 18 февраля 2012

Есть ли способ выделить память в зависимости от типа переданного указателя?

Вот моя проблема: у меня есть классы 'bouncyball' и 'hero', оба унаследованные от 'Actor'. Чтобы добавить надувной мяч, я звоню:

_actors.push_back(new Bouncyball());

Для героя это будет:

_actors.push_back(new Hero());

Поскольку _actors является вектором указателей Actor, он работает из-за полиморфизма. Но я хочу написать общий метод для добавления новых актеров на мою сцену:

unsigned Scene::addActor(Actor * actor){
    this->_actors.push_back(new [something]);
}

Поскольку параметр может быть любой производной от Actor, я не знаю, для чего выделять память ... Я могу обойти это с помощью оператора case, но что если я получу другие Actors позже?

Ответы [ 3 ]

3 голосов
/ 18 февраля 2012

Что не так с этим:

unsigned Scene::addActor(Actor * actor){
    this->_actors.push_back(actor);
    //what do you want to return? why not make return type as void?
}

Разве это не actor, который вы хотите добавить к _actors?

И вы можете назвать addActor() как:

scene.addActor(new Bouncyball());
scene.addActor(new Hero());

Убедитесь, что вы объявили деструктор Actor как virtual, так как наиболее вероятно вы захотите удалить объекты производного класса через указатель базового типа (который является Actor).

2 голосов
/ 18 февраля 2012

Решение Наваза хорошо, но альтернативой является функция-член шаблона:

template<typename T>
unsigned Scene::addActor()
{
   _actors.push_back(new T());
}

А потом в коде клиента:

scene.addActor<Hero>();

Стоит отметить, что функция-член шаблона должна быть реализована в заголовке или файле, включаемом в заголовок (например, .inl). Если вы реализуете это непосредственно в теле класса, вы не должны писать Scene :: перед addActor ().

Одним из преимуществ этого метода является то, что клиенты не вызывают новый. Обычно это «плохо», если код вызывает новый, но не вызывает удаление, и в этом случае удаление, вероятно, будет вызвано классом Scene позже. Это также создает критическую точку, если для повышения производительности необходимо использовать собственный распределитель.

0 голосов
/ 18 февраля 2012

Почему бы не создать pv класс Clonable:

template <typename T>
struct Clonable {
    virtual smart_ptr<T> clone() const = 0;
}

для smart_ptr, являющегося std::shared_ptr, std::unique_ptr, boost::shared_ptr и т. Д. Смысл в том, чтобы пересчитать указатель, чтобы избежатьиспользование руководства delete с, за исключением случаев написания пользовательского Deleter.

Затем определите Actor как:

 class Actor : ..., public Clonable<Actor> {
 ...
 public:
     ...
     virtual smart_ptr<T> clone() const { return 0; }
     ...
 ...
}

Затем для T : public Actor,

scene.addActor((T()).clone());

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...