[SOLVED] Polymorphism

Started by
6 comments, last by Zahlman 16 years, 5 months ago
Hi all. Well i'm having some problems with polymorphism. Within my main function i'm creating a CEnemy* which contains a CBubble. I'm then trying to access the Initialise function of my new objecct. I want to access the initialise function associated with my CBubble class, but keep getting Initialise for my CEnemy class.
CEnemy* pEnemy = new CBubble();
pEnemy->Initialise(10,0.0f);


I'm sure i'm doing something stupid, but I can't think what :P I've included my header files below. Thanks for any help :) bubble.h
// Local Includes
#include "enemy.h"

// Types

// Constants

// Prototypes

class CBubble : public CEnemy
{
     // Member Functions
public:
	CBubble();
	virtual ~CBubble();

	virtual bool Initialise(int _iStartHp, float _fLifeTime);
	virtual void Process(float _fDeltaTick);
	virtual void Draw();

protected:

private:

     // Member Variables
public:

protected:

private:

};


enemy.h
// Local Includes
#include "entity.h"
// Types

// Constants

// Prototypes

class CEnemy : public CEntity
{
     // Member Functions
public:
	CEnemy();
	virtual ~CEnemy();

	virtual bool Initialise(int _iStartHp, float _fLifeTime, const int _kiSpriteID, const int _kiMaskID, float _fX, float _fY);
	virtual void Process(float _fDeltaTick);
	virtual void Draw();

	void DeductHp(const int _iDeductHp);
	int GetHp();

	bool IsDead();
	bool IsAtPathEnd();

	void SetLifeTime(float _fLifeTime);
	float GetLifeTime();

	void MoveAlongPath();

protected:

private:

     // Member Variables
public:

protected:

private:
	int m_iHp;
	int m_iMoveSpeed;
	//int m_iLifeModifier;
	float m_fLifeTime;
	bool m_bDead;

};


entity.h

// Library Includes

// Local Includes

// Types

// Constants

// Prototypes
class CSprite;

class CEntity
{
     // Member Functions
public:
	CEntity();
	virtual ~CEntity();
	
	virtual bool Initialise(const int _kiSpriteID, const int _kiMaskID);

	virtual void Draw();
	virtual void Process(float _fDeltaTick);

	void SetX(float _fX);
	void SetY(float _fY);
	
	float GetX() const;
	float GetY() const;

	float GetHeight() const;
	float GetWidth() const;

protected:

private:
	CEntity(const CEntity& _kr);
	CEntity& operator= (const CEntity& _kr);

     // Member Variables
public:

protected:
	CSprite* m_pSprite;

	float m_fX;
	float m_fY;

private:

};


[Edited by - MightyNinja on October 27, 2007 8:01:05 PM]
Advertisement
I think I understand your problem:

Since you declared pEnemy as a CEnemy*, the compiler will address it as a CEnemy instance. Polymorphism should be taken the other way around: Since every CBubble is a CEneny, but not every CEneny is a CBubble, then you should either declare pEnemy as a CBubble, so as to access the member fuctions associated with that particular class, or leave it as it is, but cast it to CBubble when invoking its initialize function, like this:

CEnemy* pEnemy = new CBubble();
(CBubble)pEnemy->Initialize(10.0f);

I'd recommend you to do it the first way, since you can do

pBubbleEnemy->CEnemyMemberFuction();

but you cannot do

pEnemy->CBubbleMemberFunction();

I hope this helps you out!!! don't forget to rate me!!
Tsuki wo miru tabi omoidase!
AHHhhhhh! Thankyou very much! :P No idea why I was thinking that way hehe. :D
CEnemy::Initialise and CBubble::Initialise have differing parameters. In order for a function in a derived class to be dynamically called instead of a function in the base class, they must have the same return type, name and parameters.

If you want to keep using the specialised CBubble::Initialise function for CBubbles, you can declare your pointer as a CBubble* when you create the object, so that the Initialise() call statically binds to CBubble::Initialise. This isn't really polymorphism, however. You can then convert it to a CEnemy* for storage in a vector or something, and access it like you would any other CEnemy*.

A better way to deal with this would involve altering your design, but I'm a little too hazy now to think of it, sorry.

Edit: Another look made me aware of something else. CEnemy::Initialise has a bunch of parameters. What this effectively means is that every CEnemy needs those parameters in order to Initialise. As CBubble is also a CEnemy, it should also need those parameters, no? Yet they aren't in the parameter list for CBubble::Initialise. If a CBubble doesn't need all of these parameters, you should rethink whether CBubble should really derive from CEnemy. If it does need them, then use them in CBubble::Initialise!
Using a post-construction initialization function instead of a constructor or factory function is often a sign of an incorrect design. This means that your design could be simplified and indirectly eliminate all problems related to initialization. Why do you need that Initialise function?
You definately need to change your design, because right now you don't understand very well how object construction or inheritance or polymorphism or overloading works. You should not rush into fleshing out your classes before you have some understanding of the basics. Keep in mind though that, as scjohnno said, inheritance defines an "is-a" relationship. If type B is derived from type A, it means that B is-an A, and it must support all the operations and properties A supports.

And FighterNinja, your remarks were incorrect as well. If the OP's code was correct, then he would be able to call a CBubble method using a CEnemy* pointer. That's the point of polymorphism. I would suggest you avoid advising others before you have the matters cleared up for yourself first.
Thanks for the replies. I went back and completely re-wrote my classes removing the initalise function. I do understand the concepts, it's just putting them into a semi-large project which stuffed me up (designing the classes before hand didn't help me hehe).

Anyhoo thanks for the comments, and it's all working now :)
Quote:Original post by Fighterguard
I think I understand your problem:

Since you declared pEnemy as a CEnemy*, the compiler will address it as a CEnemy instance. Polymorphism should be taken the other way around: Since every CBubble is a CEneny, but not every CEneny is a CBubble, then you should either declare pEnemy as a CBubble, so as to access the member fuctions associated with that particular class, or leave it as it is, but cast it to CBubble


Wrong, and completely missing the point of polymorphism, which is specifically to avoid having to make this cast.

Quote:Original post by scjohnno
CEnemy::Initialise and CBubble::Initialise have differing parameters. In order for a function in a derived class to be dynamically called instead of a function in the base class, they must have the same return type, name and parameters.


Correct, but likely still missing the mark.

Quote:Original post by ToohrVyk
Using a post-construction initialization function instead of a constructor or factory function is often a sign of an incorrect design. This means that your design could be simplified and indirectly eliminate all problems related to initialization. Why do you need that Initialise function?


Quote:Original post by mikeman
You definately need to change your design, because right now you don't understand very well how object construction or inheritance or polymorphism or overloading works. You should not rush into fleshing out your classes before you have some understanding of the basics. Keep in mind though that, as scjohnno said, inheritance defines an "is-a" relationship. If type B is derived from type A, it means that B is-an A, and it must support all the operations and properties A supports.


Yep.

In C++, we construct objects using a constructor.

OP: Try reading this.

This topic is closed to new replies.

Advertisement