Sign in to follow this  

dont know when to use abstract base class or not?

This topic is 2386 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i dont understand when to use an abtract base class vs not?

for example


class Person
{
private:
int idNum;
string lastName;
string firstName;
public:
void setFields(int,string,string);
void outputData();
};

class customer : public person
{
private:
double balanceDue;
public:
void setBalDue(double);
void outputBalDue();
};


When/how would i decide wether or not this first class would be a good candidate for an "Abstract base class"

Share this post


Link to post
Share on other sites
Are you going to create instances of Person, if that is the case you can't make it abstract. Sometimes the derived classes are quite different from each other and doesn't share any data members, so making the base class abstract makes sense.

Share this post


Link to post
Share on other sites
[code]
#include <iostream>
using namespace std;

#include <stdlib.h>
#include <time.h>

class CWeapon
{
protected:
std::string m_strName;
int m_iDamage;
public:
CWeapon::CWeapon( std::string Name, int iDamage) : m_strName(Name), m_iDamage(iDamage) { }
CWeapon::CWeapon() : m_strName(NULL), m_iDamage(0){}; // no weapon atm
int GetDamage() { return m_iDamage; }
std::string GetWeaponName() { return m_strName; }
virtual void DisplayWeaponInfo();
virtual void Attack( int iNumTimeToAttack , int iOption )=0;
};

void CWeapon::DisplayWeaponInfo()
{
std::cout << m_strName.c_str() << std::endl;
std::cout << m_iDamage << std::endl;
}

class CShotgun : public CWeapon
{
protected:
float m_fReloadRatio;
int m_iAmmo;
int m_iGrenadeAmmo;
public:
CShotgun::CShotgun() : m_fReloadRatio(.5), m_iAmmo(10), m_iGrenadeAmmo(2) { };
// shotguns Attack 2 bullets at once
virtual void Attack( int iNumTimeToAttack, int Option );
float GetReloadRatio() { return m_fReloadRatio; }
virtual void DisplayWeaponInfo();
int GetAmmo() { return m_iAmmo; }
int GetSecondaryAmmo() { return m_iGrenadeAmmo; }

};

void CShotgun::Attack( int iNumTimeToAttack, int iOption )
{
if( iOption == 1 ) {
m_iAmmo -= (iNumTimeToAttack * 2);
} else {
m_iGrenadeAmmo -= (iNumTimeToAttack * 1 );
}
}

void CShotgun::DisplayWeaponInfo()
{
std::cout << m_strName.c_str() << std::endl;
std::cout << m_fReloadRatio << std::endl;
std::cout << m_iAmmo << std::endl;
std::cout << m_iDamage << std::endl;
std::cout << m_iGrenadeAmmo << std::endl;
}

class CRifle : public CWeapon
{
protected:
float m_fReloadRatio;
int m_iAmmo;
bool m_bIsZoomed;
public:
CRifle::CRifle()
{
m_fReloadRatio = 1.25;
m_iAmmo = 7;
m_bIsZoomed = 0;
}
// shotguns Attack 2 bullets at once
virtual void Attack( int iNumTimeToAttack, int Option )
{
--m_iAmmo;
}
virtual void DisplayWeaponInfo();
int GetAmmo() { return m_iAmmo; }
float GetReloadRatio() { return m_fReloadRatio; }
bool isZoomed() { return m_bIsZoomed; }

};

void CRifle::DisplayWeaponInfo()
{
std::cout << m_strName.c_str() << std::endl;
std::cout << m_fReloadRatio << std::endl;
std::cout << m_iAmmo << std::endl;
std::cout << m_iDamage << std::endl;
std::cout << m_bIsZoomed << std::endl;
}

class CMonster
{
private:
std::string m_strName;
int m_iHealth;
int m_iLives;
float m_fHpRegenRatio;
CWeapon *m_CWeapon;
public:
CMonster::CMonster()
{
m_strName = "Michael";
m_iHealth = 100;
m_iLives = 5;
m_fHpRegenRatio = .25;
m_CWeapon = NULL;
}
std::string GetMonsterName() { return m_strName; }
int GetMonsterHealth() { return m_iHealth; }
int GetMonsterLives() { return m_iLives; }
float GetMonsterHpRegenRatio() { return m_fHpRegenRatio; }
void DisplayMonsterInfo();
void AttackSelf( int iNumTimes, int iOption );
void Attack( int iNumTimes, int iOption);
void ObtainRandomWeapon();
};

void CMonster::DisplayMonsterInfo()
{
std::cout << m_strName.c_str() << std::endl;
std::cout << m_iHealth << std::endl;
std::cout << m_iLives << std::endl;
std::cout << m_fHpRegenRatio << std::endl;
if( m_CWeapon ) {
m_CWeapon->DisplayWeaponInfo();
}
else {
std::cout << "No Weapon is being used at the moment" << std::endl;
}
}

void CMonster::AttackSelf( int iNumTimes, int iOption)
{
for(int i = 0; i < iNumTimes; i++ ) {
m_CWeapon->Attack( iNumTimes, iOption );
m_iHealth -= m_CWeapon->GetDamage();
}
}

void CMonster::Attack( int iNumTimes, int iOption )
{
m_CWeapon->Attack( iNumTimes, iOption );
}

void CMonster::ObtainRandomWeapon()
{
/* initialize random seed: */
srand ( time(NULL) );

/* generate secret number: */
int iRandomNum = rand() % 2 + 1; // generate random number from 1-2

if(iRandomNum == 1)
// init CWeapon into a shotgun
m_CWeapon = new CShotgun();
else
// init rifle
m_CWeapon = new CRifle();
}

int main()
{
std::cout << "Just now entering inside of main" << std::endl << std::endl;

std::cout << "Initializing local struct without blocks" << std::endl;
CMonster firstMonster;

std::cout << "//////////////////////////////////////" << std::endl;
std::cout << "Call void void CMonster::DisplayerMonsterInfo()" << std::endl;
firstMonster.DisplayMonsterInfo();
std::cout << "//////////////////////////////////////" << std::endl;

// run around aimlessly

// now pick up a random weapon
std::cout << "//////////////////////////////////////" << std::endl;
std::cout << "Call void void CMonster::ObtainRandomWeapon()" << std::endl;
firstMonster.ObtainRandomWeapon();
std::cout << "//////////////////////////////////////" << std::endl;


std::cout << "//////////////////////////////////////" << std::endl;
std::cout << "Call void void CMonster::AttackSelf( int iNumTimes )" << std::endl;
firstMonster.AttackSelf( 2, 1 );
std::cout << "//////////////////////////////////////" << std::endl;

std::cout << "//////////////////////////////////////" << std::endl;
std::cout << "Call void void CMonster::AttackGrenade( int iNumTimes )" << std::endl;
firstMonster.Attack( 1, 2 );
std::cout << "//////////////////////////////////////" << std::endl;

std::cout << "//////////////////////////////////////" << std::endl;
std::cout << "Call void void CMonster::DisplayerMonsterInfo()" << std::endl;
firstMonster.DisplayMonsterInfo();
std::cout << "//////////////////////////////////////" << std::endl;

getchar();
getchar();
std::cout << "Now exiting main" << std::endl;
return 0;
}
[/code]

When a monster is created he has no weapon
When he obtains a random weapon it will randomly allocate a weapon(either a rifle or shotgun) on the heap and assign its address to m_CWeapon.
When i compile and run the compiler throws an assertion about m_strName(NULL); How do i fix this? The weapon is not known at compile time until the weapon has been randomly picked up. My question is..... How do i use the rifle an shotgun constructors to pass a string to the base class?

for example



[code]
CRifle::CRifle() : <---- using init list i want to pass m_strName("Rifle) and m_iDamage(10) to CWeapon's constructor
{
m_fReloadRatio = 1.25;
m_iAmmo = 7;
m_bIsZoomed = 0;
}[/code]

Share this post


Link to post
Share on other sites
You can call the CWeapon constructor from the init list like this
[code]CRifle()
: CWeapon("Rifle", 10)
{
m_fReloadRatio = 1.25;
m_iAmmo = 7;
m_bIsZoomed = 0;
}[/code]


I noticed you called srand from inside ObtainRandomWeapon(). A problem with this is if you have many monsters that obtain a weapon in the same second they will all get the same weapon. It is recommended to only call srand once for for the whole program so a good place is at the start of main.

Share this post


Link to post
Share on other sites

This topic is 2386 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this