Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

Singleton

Started by Starfalcon2 6 replies 1.9k views
Original Post
Starfalcon2
Starfalcon2
I just got "Programming game AI by example" by Mat Buckland. His source is here I use his source to learn the singletion design pattern in the folder, buckland_AISource\Buckland_Chapter2-State Machines\WestWorld1 or WestWorldWithWoman The problem is that I write a source from scratch and end up to get an error, C2243. I couldn't find out how did I make the mistake. Here my sources: miner.h

#ifndef MINER_H
#define MINER_H

//#pragma once
#include "BaseEntity.h"
#include "State.h"
#include "Define.h"
#include "Miner_States.h"

class CState;


class CMiner :	public CBaseEntity
{
public:
	CMiner(int id);
	~CMiner(void);

	void Update();
	void ChangeState(CState<CMiner>* pNewState);
	void ChangeLocation(Location_Type location);
	Location_Type Location(void);

	bool PocketsFull(void);
	void IncreaseGold(void){m_iGoldCarried++;};
	int InBankValue(void){return m_iMoneyInBank;};

private:
	int m_iGoldCarried;
	int m_iMoneyInBank;
	int m_iThirst;
	int m_iFatigue;
	Location_Type m_eLocation;

	CState<CMiner>* m_pCurrentState;
};

#endif MINER_H

Miner.cpp

#include "Miner.h"
#include "State.h"
#include "Miner_States.h"
#include <assert.h>

//class CMiner;
class CState;

CMiner::CMiner(int id):CBaseEntity(id)
{
	m_eLocation = BANK;
	m_pCurrentState = CEnterMinerAndDig::Instance();
}

CMiner::~CMiner(void)
{
}

void CMiner::Update()
{
	m_iThirst++;

	if (m_pCurrentState)
		m_pCurrentState->Execute(this);
}

void CMiner::ChangeState(CState<CMiner>* pNewState)
{
	// make sure both states are valid
	assert(m_pCurrentState && pNewState);

	// call the exit method of the existing state
	m_pCurrentState->Exit(this);

	// change state to the new state
	m_pCurrentState = pNewState;

	// call the entry method of the new state
	m_pCurrentState->Enter(this);
}

void CMiner::ChangeLocation(Location_Type location)
{
	m_eLocation = location;
}

Location_Type CMiner::Location(void)
{
	return m_eLocation;
}

bool CMiner::PocketsFull(void)
{
	if (m_iGoldCarried > 5)
		return true;
	else
		return false;
}

state.h

#ifndef STATE_H
#define STATE_H

template <class entity_type>

class CState
{
public:	
	virtual ~CState(void){};

	// this will execute when the state is entered
	virtual void Enter(entity_type*) = 0;

	// this is called by the miner's update function each 

update step
	virtual void Execute(entity_type*) = 0;

	// this will execute when the state is exited
	virtual void Exit(entity_type*) = 0;
};

#endif STATE_H

Starfalcon2
Starfalcon2
Miner_States.cpp
#include "Miner_States.h"#include <iostream>using std::cout;using std::endl;// **************** CEnterMinerAndDig *****************CEnterMinerAndDig::CEnterMinerAndDig(){}CEnterMinerAndDig* CEnterMinerAndDig::Instance(void){	static CEnterMinerAndDig instance;	return &instance}void CEnterMinerAndDig::Enter(CMiner* pMiner){	if (pMiner->Location() != GOLDMINE)	{		cout << "Miner #" << pMiner->ID() << " enters the gold mine" << endl;		pMiner->ChangeLocation(GOLDMINE);	}}void CEnterMinerAndDig::Execute(CMiner* pMiner){	cout << "Miner# " << pMiner->ID() << "finds the gold, yay!" << endl;	pMiner->IncreaseGold();	if (pMiner->PocketsFull())		{		cout << "Miner# " << pMiner->ID() << "oh man, my pocket is so full! I have to go" << endl;		pMiner->ChangeState(CEnterBankAndDeposit::Instance());		}}void CEnterMinerAndDig::Exit(CMiner* pMiner){	cout << "Miner #" << pMiner->ID() << " leaves the gold mine" << endl;}
Starfalcon2
Starfalcon2
Miner_States.h
#ifndef Miner_States_H#define Miner_States_H//#pragma once#include "State.h"#include "Miner.h"#include "Define.h"//template <class entity_type>class CMiner;class CEnterMinerAndDig : CState<CMiner>{public:		//~CEnterMinerAndDig(void){};	// this is singleton	static CEnterMinerAndDig* Instance(void);	//virtual void Enter(<entity_type>* i){};	virtual void Enter(CMiner* pMiner);	virtual void Execute(CMiner* pMiner);	virtual void Exit(CMiner* pMiner);private:	CEnterMinerAndDig();	CEnterMinerAndDig(const CEnterMinerAndDig&);	CEnterMinerAndDig& operator=(const CEnterMinerAndDig&);};class CEnterBankAndDeposit : CState<CMiner>{public:		static CEnterBankAndDeposit* Instance(void);    	virtual void Enter(CMiner* pMiner);	virtual void Execute(CMiner* pMiner);	virtual void Exit(CMiner* pMiner);private:	CEnterBankAndDeposit();	CEnterBankAndDeposit(const CEnterBankAndDeposit&);	CEnterBankAndDeposit& operator=(const CEnterBankAndDeposit&);};#endif Miner_State_H

Starfalcon2
Starfalcon2
Anyways, my compiler told me my instance functions could not

accessible which is m_pCurrentState =

CEnterMinerAndDig::Instance();

I could not find out why it doesn't work alike in author's

source.
Steadtler
Steadtler
I cant seem to locate my copy of mat's book. Anyway.

Seems you left some code out, because ::instance is not declared anyway in the .h you posted, nor is "pCurrentState" appearing anywhere.
At any rate, may I suggest you make your inheritance public?

like replacing

class CEnterMinerAndDig : CState

by

class CEnterMinerAndDig : public CState

Good luck, I guess fup will be more familiar with the code ;)
WeirdoFu
WeirdoFu
There are a few things in your singleton that kind of confuses me. Why are you accessing a static variable that is declared inside a static method? I'm not certain whether there is a guard against that, but technically, it may work, though strange. Usually, a singleton class has a static pointer to itself that is checked and created (if needed) during run time.
BrianL
BrianL
If you look at the assembly for the static function/static object, it is almost exactly what you suggest WierdFu. The only difference is that the static memory is used instead of dynamically allocated memory.

Performance-wise, they are almost exactly the same. Both have a branch, which can hurt performance if used in inner loops. The static object locally declared does have one other penalty - it generally can't be inlined. This means you get a function calls worth of overhead whenever it is used.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.