I am trying to create a class called "enemyManager", that well, manages the enemies in my game (deployment, memory deletion, etc.).
Well, for the function that adds an "enemy" class to the manager, I'm having difficulty trying to create a copy of "refEnemy", then putting that copy into an array that manages the enemy data.
Here is the function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Add an enemy to the manager
void enemyManager::addEnemy(enemy *refEnemy, int instances) {
if ((instances < 1) || (_numEnemies >= EM_MAX_NUM_ENEMIES)) // Just to makesure we don't add any extra stuff
return;
int tempVerticesArray[64][2];
for (int i = 0; i < instances; i++) {
enemies[_curAvailableSlot]->enemyPtr = refEnemy; // <-- Issue is right here
enemies[_curAvailableSlot]->ptrClearedFromMem = false;
_curAvailableSlot++;
_numEnemies++;
}
}
All I know is that I'm putting the address of "refEnemy" into "enemyPtr" right now which is what I don't want. I want it to copy all the data from "refEnemy" to "enemyPtr".
struct Base {
virtual ~Base() {}
int x;
int y;
};
struct Derived : Base {
int z;
};
void copy_it( Base* b )
{
Base* copy_of_it = new Base( b );
}
int main()
{
Derived* d = new Derived;
copy_it( d );
}
copy_it does what is called "slicing" -- an instance of Derived has two "layers" -- the bottom-most layer is the data members of Base and the topmost layer is the data members of Derived. When copy_it is called, it makes a copy not of the two-layer cake, but only of the bottom-most layer. This is the problem with polymorphism. To solve that problem -- to have copy_it make a complete copy of what is passed to it -- you have to write a virtual clone() method that derived instances must override.
So what would I want to include in my virtual clone() method?
And wouldn't that example code (if compiled and ran) create a memory leak?
EDIT:
I forgot to mention that the "enemy" class contains pointers to a lot of other classes (like "sprite", "sound", etc). So would I want the clone function/method to return clones of these other classes?
struct Base {
virtual ~Base() {}
virtual Base* clone() const { returnnew Base( *this ); }
int x;
int y;
};
struct Derived : Base {
virtual Derived* clone() const { returnnew Derived( *this ); }
int z;
};
void copy_it( Base* b )
{
Base* copy_of_it = b->clone();
// use copy_of_it ...
delete copy_of_it;
}
int main()
{
Derived* d = new Derived;
copy_it( d );
}
Whether you want to implement a deep copy or a shallow copy is up to your design. If the enemy class owns the pointers, then probably yes, you'll want a deep copy. If sprite and sound are also base classes, you'll need a clone method on them too. If they are not polymorphic, then you don't need the clone() method.
The clone() pattern exists solely to get around the slicing issue that results from casting a pointer up to a base class type and then attempting to copy the entire object through the base class pointer.
class enemy : public sprite {
public:
staticint sNextEnemyID;
bool invul;
int speed;
int damage;
int pointValue;
private:
int _enemyID;
int _curHealth;
int _maxHealth;
bool _isAlive;
bool _hitNoiseAdded;
bool _deathNoiseAdded;
bool _deathSpriteAdded;
sound *_hitNoise;
sound *_deathNoise;
sprite *_deathSprite;
int _deathSpriteOffsetX;
int _deathSpriteOffsetY;
int _deathSpriteTimer;
bool _deathRoutineStarted;
};
Sprite and Sound are base classes, but as you can see, "enemy" is derived from "sprite".
I'm also using The DarkGDK game library, and each time I create a new sprite, it calls a DarkGDK function where it loads an image file into memory and then creates a sprite for it. Both of the base classes don't contain any pointers.
In the "enemy" class deconstructer, it uses the "delete" keyword.
Ex:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// Enemy class destructor
// cleans up some of the stuff for us
enemy::~enemy() {
// Delete the hit noise
if (_hitNoiseAdded)
delete _hitNoise;
// Delete the death noise
if (_deathNoiseAdded)
delete _deathNoise;
// Delete the death Sprite
if (_deathSpriteAdded)
delete _deathSprite;
}
Okay, sorry for both double-posting and necro-posting.
I got my "clone()" method written for both my "sprite" and "enemy" class, but I'm running into a little bit of a problem.
I'm getting these compiler errors:
1 2 3 4 5
error C2143: syntax error : missing ';' before '*'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
error C2556: 'int *enemy::clone(void)' : overloaded function differs only by return type from 'enemy *enemy::clone(void)' see declaration of 'enemy::clone'
error C2371: 'enemy::clone' : redefinition; different basic types see declaration of 'enemy::clone'
I think it has something to do with my function declarations and definitions.
For "sprite" class: (<- This works weel by itself.)
makes Derived a concrete class since Derived's frobnicate() is an override of Base's pure virtual method. It's perfectly ok for the derived class therefore to return a pointer to its type instead of the base type.
@Ne555
The reason why I derived "enemy" from "sprite" is that the original class for "enemy" contained many similar things that "sprite" had, so why not just derive it. Lot of work saved.