simple c++ polymorphism question

Hi all, I have a simple C++ OOP question regarding a problem I’ve run into.

I have a Particle class, and ParticleManager class which handles a list of Particles. Then I want to extend these two classes for different types of particles (e.g. Ball and BallManager).

My problem is when I call BallManager balls.update(); it doesn’t seem to run the Ball::update function but only the Particle::update();

  
  
class Particle {  
	friend class ParticleManager;  
	  
protected:  
	...some vars  
  
	void update();  
  
public:	  
	Particle(...);  
	~Particle();  
  
};  
  
  
class ParticleManager : public ofxThread {  
  
protected:  
	...some vars  
	  
public:  
	list<Particle*> particles;  
  
	~ParticleManager();  
	void init(...);  
	void add(...);  
	void update();  
	void render();  
};  
  
  
  
/********************* Particle ***********************/  
  
Particle::Particle(...) {  
	...init code  
}  
  
  
Particle::~Particle() {  
}  
  
  
void Particle::update() {  
}  
  
   
   
 /********************* Particle Manager ***********************/  
void ParticleManager::init(...) {  
	...  
}  
  
ParticleManager::~ParticleManager() {  
}  
  
  
void ParticleManager::add(...) {  
	particles.push_back(new Particle(...);  
	if(particles.size() >= maxCount) {  
		particles.pop_front();  
		// I probably need to delete the particle as well  
	}  
  
	printf("PARTICLE add %i \n", particles.size());  
}  
  
void ParticleManager::update() {  
	printf("PARTICLE update %i \n", particles.size());  
	for (list<Particle*>::iterator it = particles.begin(); it != particles.end(); it++) {  
		Particle* particle = *it;  
		particle->update();  
	}  
}  
  
void ParticleManager::render() {  
	for (list<Particle*>::iterator it = particles.begin(); it != particles.end(); it++) {  
		Particle* particle = *it;  
		image.draw(particle->x - particle->visible_radius, particle->y - particle->visible_radius, particle->visible_size, particle->visible_size);  
	}  
}  
  

and

  
  
class Ball : public Particle {  
	friend class BallManager;  
	  
protected:  
	...some more vars and functions  
	void update();  
	  
public:  
	Ball(...);  
	  
};  
  
  
class BallManager : public ParticleManager {  
	  
public:  
	~BallManager();  
	  
	void update();  
	void add(...);  
};  
  
  
Ball::Ball(...) : Particle(...) {  
	... custom init code  
}  
  
  
void Ball::update() {  
	printf("Ball update  \n");  
	.... custom ball update WHICH IS NOT BEING CALLED  
}        
  
BallManager::~BallManager() {  
}  
  
  
void BallManager::add(...) {  
	ParticleManager::add(...);  
	... custom add code  
}  
  
  
  
void BallManager::update() {  
	ParticleManager::update();  
	... custom manager code which is being called   
  
}  
  
  
  

maybe its because i’m a bit tired :stuck_out_tongue: but I can’t see what I need to do for the ParticleManager::update() inside BallManager::update() to loop through all the particles but treat them as Balls instead of Particles…

Hey memo,

you need to put the keyword “virtual” in front of all your functions in your header file, otherwise the compiler will not generate indivudual functions for each subclass.
As in:

  
  
class Particle {  
   friend class ParticleManager;  
     
protected:  
   ...some vars  
  
   virtual void update();  
  
public:     
   Particle(...);  
   ~Particle();  
  
};   
  

More info can be found here:

http://www.codersource.net/cpp-virtual-functions.html

Hope this helps!

Hi fiezi, yea its true I forgot that! I put in the virtual keyword for all the functions in my Particle and ParticleManager classes, unfortunately it did not solve the mystery of the missing balls.
For all my balls Particle::update is being called (which dumps to the console), but not Ball:update();

I think its because ultimately ParticleManager::update() gets called for BallManager, which does

  
 for (list<Particle*>::iterator it = particles.begin(); it != particles.end(); it++) {   
      Particle* particle = *it;   
      particle->update();   
   }   

so it cycles through all balls seeing them as simple Particles and using the wrong update function. Is that correct? how can I get around this?

Can you check if you are actually creating Balls in your Ballmanager->add() function? And if that function gets called?

Hi fiezi, yea it is, here is my console with a printf in each function:

  
ParticleManager::add now with 1 particles   
BallManager::add   
ParticleManager::add now with 2 particles   
BallManager::add   
ParticleManager::add now with 3 particles   
BallManager::add   
ParticleManager::add now with 4 particles   
BallManager::add   
ParticleManager::add now with 5 particles   
BallManager::add   
ParticleManager::add now with 6 particles   
BallManager::add   
ParticleManager::add now with 7 particles   
BallManager::add   
ParticleManager::add now with 8 particles   
BallManager::add   
ParticleManager::add now with 9 particles   
BallManager::add   
ParticleManager::add now with 9 particles   
BallManager::add   
BallManager::update() with 9 particles   
ParticleManager::update() with 9 particles   
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
ParticleManager::render() with 9 particles   
  
BallManager::update() with 9 particles   
ParticleManager::update() with 9 particles   
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
Particle::update()    
ParticleManager::render() with 9 particles   
  
  
  

okay, it seems like you are calling the ParticleManager::add() everytime you want to call your BallManager::add() code.
That means that you are not creating a new Ball with something like:

Particle* myBall=new Ball;
particles.push_back(myBall);

you can check for the creation of a Ball by using a printf in the Ball Constructor, just to make sure.

I suggest not calling the “super” functions (sorry for the java slang)
Like this:

  
  
BallManager::add(){  
  
//ParticleManager::add();  <-- don't do this!  
  
Particle* myBall=new Ball;  //<-- here you actually generate a ball   
  
particles.push_back(myBall);  
}  
  

doh! you’re completely right. there isn’t a single ‘new Ball()’ in the whole code :stuck_out_tongue:

In case anyone else stumbles upon this code, there’s a memory leak in addToList :oops:
It should be:

  
void ParticleManager::addToList(Particle* particle) {  
	particles.push_back(particle);  
	if(particles.size() > maxCount) {   // if we reached max number  
		Particle *firstParticle = particles.front(); // get ref to first in list  
		if(firstParticle) {	// if its not null (it exists)  
			particles.pop_front();   // remove from list  
			delete firstParticle;    // and delete it from memory  
		}  
	}  
	particle->setManager(this);  
//	printf("ParticleManager::addToList %i particles \n", particle  

s.size());
}

Hey hey,

i’m glad i could help. Just as a sidenote, it’s perfectly fine to have “empty” functions in your base class that you then just fill in in your derived classes. I think it’s even some sort of pattern to have your base classes be all virtual or something, and then just do the implementations of your functions in the derived classes…
I think the “add” function made complete sense and helps prevent memory leaks :wink: