Is it possible to have an array of different objects that come from the same base class?
I'm trying to design a weapons class for a game. This is some of the code I have come up with to fit my needs:
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();
};
And then I would like to define a weapons array like so:
//Weapon variables
const int totalWeapons = 2;
int currentWeapon = 1;
weapon weapons[totalWeapons];
I would like element [0] to represent the machineGun class and element [1] to represent the flamer class. Am I going about this problem the correct way? Should I refactor this in some way? How do I achieve an array that holds these two different weapons?
The idea is so when I call weapons[0].fire();
I get a machineGun class and when I call weapons[1].fire();
I get flamer fire.
Edit: Thanks for helping guys. I'm having a few problems with using "weapons[0] = new machineGun;". I get an error "cannot allocate an array of constant size 0" when I try to run this code.
Has anyone got any insight into why this isn't working? My updated code looks something like this:
//Weapon variables
const int totalWeapons = 2;
int currentWeapon = 1;
weapon weapons[totalWeapons];
weapons[0] = new machineGun;
weapons[1] = new flamer;
But I get lots of errors:
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
I have taken another different approach and gotten some different errors. I'm still pretty unsure how this is all meant to glue together.
//Weapon variables
const int totalWeapons = 2;
int currentWeapon = 1;
weapon weapons[totalWeapons] = {new machineGun, new flamer};
With errors:
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'
The answer ended up being something like this:
//Weapon variables
const int totalWeapons = 2;
int currentWeapon = 1;
weapon *weapons[totalWeapons] = {new machineGun, new flamer};
Thanks everyone who helped me get my head around this!
#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;
}
As noted by Ross, your array has to be of type weapon* to allow you to downcast specialized weapon types.
So,
weapon* weapons[totalWeapons];
weapons[0] = new machineGun;
Also as noted, as you're creating these dynamically, you'll want to make sure that you clean them up later or you're going to run into memory leaks
fire()
needs to be virtual - that way, if you call it, the proper implementation will be called.
Declare it as
virtual void fire();
You then just assign objects of the appropriate type, for example weapon[0] = new flamer();
- be sure to delete it when you're done, or before reassigning another object on the same slot.
Other than that, your approach is exactly how polymorphism should be implemented. (Of course, you could consider a different storage than a C-style array, or be sure that you implement proper bounds checking, but that's beyond the scope of your question).
(Side note: If you have virtual functions, you also need to add a virtual destructor.)
Not entirely accurate. I would use pointers, otherwise you will have the slicing effect. That is, the memory that is allocated for each area in that array is only enough memory for a weapon. If machinegun or flamer have extra attributes, they will be "missing" from what is held in the array, because there is not enough memory. If you use pointers and dynamically allocate each weapon in the array, you have no slicing problem. So your declaration for the array would be weapon* weapons[total weapons];
and when you declare each element of the array, weapons[numweapon]=new flamer(params);
Don't forget the destructor and don't forget to delete dynamically allocated variables.
精彩评论