Объект с абстрактным членом (без указателей) - PullRequest
1 голос
/ 12 сентября 2011

У меня есть следующий класс,

class Simulation {
public:
  btDefaultCollisionConfiguration collisionConfiguration;
  btBroadphaseInterface broadphase;
  btSequentialImpulseConstraintSolver solver;
  btDynamicsWorld dynamicsWorld;

  Simulation() {
    broadphase = btCollisionDispatcher(&collisionConfiguration);
  }
}

, и когда я компилирую, я получаю эту ошибку

cannot declare field ‘Simulation::broadphase’ to be of abstract type ‘btBroadphaseInterface’

Теперь я думаю, что знаю, что сделал неправильно.Если это скомпилировано, то в тот момент, когда я вызову конструктор, выделенная память будет выделена для виртуального класса и не будет содержать подкласс (btCollisionDispatcher).Я знаю, как решить эту проблему с помощью указателей, но я слышал от людей, что вам следует избегать указателей в C ++, и я подумал, что попробую.Я до сих пор добился успеха, но я не знаю, что здесь делать.

Ответы [ 3 ]

2 голосов
/ 12 сентября 2011

Да, вы можете иметь только указатели или ссылки на абстрактные классы, потому что вы не можете создать экземпляр абстрактного класса, потому что, по определению, он имеет «неполное» определение (не следует понимать буквально). Это просто интерфейс.

Если вы хотите избежать указателей, вы можете использовать ссылки, например:

class Simulation {
public:
  btDefaultCollisionConfiguration collisionConfiguration;
  btBroadphaseInterface& broadphase;
  btSequentialImpulseConstraintSolver solver;
  btDynamicsWorld dynamicsWorld;

  Simulation() : broadphase(someFunctionThatReturnsAbtBroadphaseInterfaceReference()) {

  }
}

Или умные указатели, например:

// header for shared_ptr
#include <memory>

class Simulation {
public:
  btDefaultCollisionConfiguration collisionConfiguration;
  shared_ptr<btBroadphaseInterface> broadphase;
  btSequentialImpulseConstraintSolver solver;
  btDynamicsWorld dynamicsWorld;

  Simulation() : broadphase(someFunctionThatReturnsAbtBroadphaseInterfacePointerOrSmartPointer()) {

  }
}
0 голосов
/ 13 сентября 2011

Нет абсолютно никаких проблем с использованием указателей.

По крайней мере, когда вы используете некоторые библиотеки, вы должны стараться делать вещи так, как они о них думают.

Лучший способделай то, что на самом деле имеешь в виду, используя их.

Не беспокойся о них.

0 голосов
/ 12 сентября 2011

Поскольку в своей реализации класса вы уже исправляете тип, почему бы просто не сохранить переменную фактического типа, который будет использоваться?

class Simulation {
public:
  btDefaultCollisionConfiguration collisionConfiguration;
  btCollisionDispatcher broadphase;

  Simulation() : broadphase(&collisionConfiguration) {
  }
};

Обратите внимание, что приведенный выше код верен, но может быть подвержен ошибкам, поскольку один член зависит от инициализации другого члена, поэтому не переупорядочивайте объявления в классе.

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

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