Возможно ли иметь массив разных объектов, которые происходят из одного базового класса? - PullRequest
5 голосов
/ 08 декабря 2010

Я пытаюсь создать класс оружия для игры. Вот код, который я придумал, чтобы соответствовать моим потребностям:

class weapon {

 public:
  int fireRate;
  int bulletDamage;
  int range;
  ofImage sprite;
  ofImage bulletSprite;
  bullet bullets[50];
  int activeBullet;

 public:
  void fire();
};

class machineGun: public weapon {
 public: 
  void fire();
};

class flamer: public weapon {
 public: 
  void fire();
};

И тогда я бы хотел определить массив оружия следующим образом:

//Weapon variables
const int totalWeapons = 2;
int currentWeapon = 1;
weapon weapons[totalWeapons];

Я бы хотел, чтобы element [0] представлял класс machineGun, а element [1] представлял класс flamer. Правильно ли я решаю эту проблему? Должен ли я рефакторинг это каким-то образом? Как мне получить массив, содержащий эти два разных оружия?

Идея в том, что когда я звоню weapons[0].fire();, я получаю класс MachineGun, а когда я звоню weapons[1].fire();, я получаю огненный огонь.




Редактировать: Спасибо за помощь, ребята. У меня есть несколько проблем с использованием "arms [0] = new machineGun;". Я получаю сообщение об ошибке «не могу выделить массив постоянного размера 0» при попытке запустить этот код.

Кто-нибудь понял, почему это не работает? Мой обновленный код выглядит примерно так:

//Weapon variables
const int totalWeapons = 2;
int currentWeapon = 1;
weapon weapons[totalWeapons];
weapons[0] = new machineGun;
weapons[1] = new flamer;

Но я получаю много ошибок:

1>gameplay.cpp(49) : error C2466: cannot allocate an array of constant size 0
1>gameplay.cpp(49) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>gameplay.cpp(49) : error C2371: 'weapons' : redefinition; different basic types
1>        gameplay.cpp(48) : see declaration of 'weapons'
1>gameplay.cpp(49) : error C2440: 'initializing' : cannot convert from 'machineGun *' to 'int []'
1>        There are no conversions to array types, although there are conversions to references or pointers to arrays
1>gameplay.cpp(50) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>gameplay.cpp(50) : error C2369: 'weapons' : redefinition; different subscripts
1>        gameplay.cpp(48) : see declaration of 'weapons'
1>gameplay.cpp(50) : error C2440: 'initializing' : cannot convert from 'flamer *' to 'int [1]'
1>        There are no conversions to array types, although there are conversions to references or pointers to arrays




Я выбрал другой подход и получил несколько разных ошибок. Я все еще не совсем уверен, как все это склеить.

//Weapon variables
const int totalWeapons = 2;
int currentWeapon = 1;
weapon weapons[totalWeapons] = {new machineGun, new flamer};

С ошибками:

1>gameplay.cpp(48) : error C2275: 'machineGun' : illegal use of this type as an expression
1>        gameplay.h(36) : see declaration of 'machineGun'
1>gameplay.cpp(48) : error C2275: 'flamer' : illegal use of this type as an expression
1>        gameplay.h(41) : see declaration of 'flamer'




В итоге ответ был примерно таким:

//Weapon variables
const int totalWeapons = 2;
int currentWeapon = 1;
weapon *weapons[totalWeapons] = {new machineGun, new flamer};

Спасибо всем, кто помог мне разобраться с этим!

Ответы [ 4 ]

4 голосов
/ 08 декабря 2010
#include <iostream>

class weapon {

 public:
  int fireRate;
  int bulletDamage;
  int range;
  int activeBullet;

 public:
  virtual void fire(void) {std::cout << "machine " << '\n';}
  virtual ~weapon() {std::cout << "destructor is virtual" << '\n';}
};

class machineGun: public weapon {
 public: 
  void fire(void) {std::cout << "machine gun firing" << '\n';}
  ~machineGun(void) { std::cout << "machine gun destroyed" << '\n';}
};

class flamer: public weapon {
 public: 
  void fire(void) {std::cout << "flamer firing" << '\n';}
  ~flamer(void) {std::cout << "flamer destroyed" << '\n';}
};

int main(void)
{
    const int count = 2;
    weapon *weapons[count];

    machineGun *a = new machineGun();
    flamer     *b = new flamer();

    weapons[0] = a;
    weapons[1] = b;

    weapons[0]->fire();
    weapons[1]->fire();

    delete a;
    delete b;

}
2 голосов
/ 08 декабря 2010

Как отметил Росс, ваш массив должен быть типа оружия *, чтобы позволить вам сбивать специализированные типы оружия.

Итак,

weapon* weapons[totalWeapons];
weapons[0] = new machineGun;

Кроме того, как уже отмечалось, поскольку вы создаете их динамически, вы захотите убедиться, что вы очистите их позже или вы столкнетесь с утечками памяти

2 голосов
/ 08 декабря 2010

Не совсем точно. Я бы использовал указатели, иначе у вас будет эффект нарезки. То есть памяти, выделенной для каждой области в этом массиве, достаточно только для оружия. Если у пулемета или фламера есть дополнительные атрибуты, они будут «отсутствовать» в том, что содержится в массиве, потому что недостаточно памяти. Если вы используете указатели и динамически распределяете каждое оружие в массиве, у вас нет проблем с нарезкой. Поэтому ваше объявление для массива будет weapon* weapons[total weapons];, а когда вы объявляете каждый элемент массива, weapons[numweapon]=new flamer(params); Не забывайте деструктор и не забывайте удалять динамически размещенные переменные.

2 голосов
/ 08 декабря 2010

fire() должен быть виртуальным - таким образом, если вы его вызовите, будет вызвана правильная реализация.

Объявите его как

virtual void fire();

Затем вы просто назначаете объекты соответствующего типа, например weapon[0] = new flamer(); - обязательно удалите его, когда закончите, или перед переназначением другого объекта в том же слоте.

Кроме этого, ваш подходкак именно полиморфизм должен быть реализован.(Конечно, вы можете рассмотреть другое хранилище, чем массив в стиле C, или быть уверенным, что вы реализуете правильную проверку границ, но это выходит за рамки вашего вопроса).

(Примечание: если у вас естьвиртуальные функции, вам также нужно добавить виртуальный деструктор.)

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