The programm below is about polymorphism. It just changes the status of a door between open and closed. My problem is that i can't switch the status in my class "Open" to closed since the class "Close" is below my class "Open".
How can i forward declare the class "Close" that it will work properly? (since a normal forward declaration like 'class Close;' doesnt seem to work)
class Status;
class Door {
private:
Status* currentStatus;
public:
void setStatus(Status*);
void opendoor();
void closedoor();
};
class Status {
public:
virtual void opendoor(Door* s)=0;
virtual void closedoor(Door* s) = 0;
};
class Open : public Status {
public:
void opendoor(Door* s) {
return;
}
void closedoor(Door* s){
s->setStatus( new Close() ); //Error here
return;
}
};
class Close : public Status {
public:
void opendoor(Door* s) {
s->setStatus( new Open() );
return;
}
void closedoor(Door* s){
return;
}
};
void Door::opendoor() {
currentStatus->opendoor(this);
return;
}
void Door::closedoor(){
currentStatus->closedoor(this);
return;
}
void Door::setStatus(Status* x) {
delete currentStatus;
currentStatus = x;
return;
}
The easiest would be to separate the class from the implementation: first declare all the classes. Then only the implementation of the member functions.
class Status;
class Door {
...
};
class Status {
...
};
class Open : public Status {
public:
void opendoor(Door* s) override;
void closedoor(Door* s) override;
};
class Close : public Status {
public:
void opendoor(Door* s) override;
void closedoor(Door* s) override;
};
...
void Open::closedoor(Door* s){
s->setStatus( new Close() ); //no more error here
return;
}
Define the member function that needs the full definition of Close after the full implementation of Close. For example,
void Open::closedoor(Door* s)
should be defined outside your class, after class Close. That's because in the line
s->setStatus( new Close() )
the compiler needs to know the full definition of Close, as it tries to constructs an object of type Close.
Related
As the title says I have the following "base" class that user can extend:
class BaseScene
{
private:
bool sceneloop = false;
public:
virtual void Start();
virtual void EventHandler(SDL_Event event);
virtual void Update();
virtual void Draw();
void _toggleLoopMode() { sceneloop = !sceneloop; }
bool _sceneloop() { return sceneloop; }
};
My problem is I can't know what name, the user, choose for his classes so how I can call a known method (like Start or EventHandler) from my main class inside an unknown class?
An example of a class that is unknown to me but well-known to the user can be:
class SomeFunnyRandomName : public BaseScene
{
public:
void Start();
void Eventhandler(SDL_Event event);
void Update();
void Draw();
};
So form the main class I need to call Start() inside "SomeFunnyRandomName" without:
SomeFunnyRandomName sfrn = new SomeFunnyRandomName();
If you can include the code it will be very helpful (but not required).
You take a reference or pointer to BaseScene, and call the methods on that. The caller passes an instance of their derived class.
class UsesScene {
BaseScene & scene;
public:
UsesScene(BaseScene & scene) : scene(scene) {}
void doStuff() { scene.Start(); scene.Update(); }
/*... etc*/
};
int main() {
SomeFunnyRandomName scene;
UsesScene usesScene(scene);
usesScene.doStuff();
}
Here I am trying to pass the instance of ATMMachine using "this" keyword to the HasCard class and trying to call any method of ATMMachine from HasClass using that instance. But I am not able to call any of the methods of ATMMachine.
For example unable to call machine->insertCard();
Could someone please help me to find out where the problem is?
Is there any better approach in CPP to communicate between classes?
class ATMState{
virtual void insertCard() = 0;
virtual void ejectCard() = 0;
virtual void insertPin(int pinNumber) = 0;
virtual void withdrawCash(int amount) = 0;
};
class ATMMachine;
class HasCard: public ATMState {
private:
ATMMachine* machine;
public:
HasCard(ATMMachine* _machine) {
machine = _machine;
machine->insertCard();
}
void insertCard() {
}
void ejectCard() {
}
void insertPin(int pinNumber) {
}
void withdrawCash(int amount) {
}
};
class ATMMachine{
public:
int balance;
ATMState* currentState;
ATMState* hasCard;
ATMState* noCard;
ATMState* hasPin;
ATMState* noCash;
ATMMachine() {
hasCard = new HasCard(this);
// noCard = new NoCard();
// noCash = new NoCash();
// hasPin = new HasPin();
currentState = hasCard;
}
void insertCard() {
cout<<"Card has been inserted" <<endl;
}
void ejectCard() {
}
void insertPin(int pinNumber) {
}
void withdrawCash(int amount) {
}
};
But I am not able to call any of the methods of ATMMachine. with the forward declaration class ATMMachine; you only tell that this class exists, but the compiler does not know anything of its member functions until the full class definition is reached.
That's why you get an error like this:
invalid use of incomplete type 'class ATMMachine'
machine->insertCard();
note: forward declaration of 'class ATMMachine'
class ATMMachine;
If you have this kind of cross dependencies you need to split the declaration of the member functions, constructors, or destructors and their definitions.
class ATMState {
virtual void insertCard() = 0;
virtual void ejectCard() = 0;
virtual void insertPin(int pinNumber) = 0;
virtual void withdrawCash(int amount) = 0;
};
class ATMMachine;
class HasCard : public ATMState {
private:
ATMMachine *machine;
public:
// only declare the constructor here
HasCard(ATMMachine *_machine);
void insertCard() {}
void ejectCard() {}
void insertPin(int pinNumber) {}
void withdrawCash(int amount) {}
};
class ATMMachine {
public:
int balance;
ATMState *currentState;
ATMState *hasCard;
ATMState *noCard;
ATMState *hasPin;
ATMState *noCash;
ATMMachine() {
hasCard = new HasCard(this);
// noCard = new NoCard();
// noCash = new NoCash();
// hasPin = new HasPin();
currentState = hasCard;
}
void insertCard() { cout << "Card has been inserted" << endl; }
void ejectCard() {}
void insertPin(int pinNumber) {}
void withdrawCash(int amount) {}
};
// move the definition of the HasCard constructor after the declaration of ATMMachine
HasCard::HasCard(ATMMachine *_machine){
machine = _machine;
machine->insertCard();
}
Is there any better approach in CPP to communicate between classes? Having the need to do something like that is often an indication that you should restructure your code. There are various ways how to solve such issues each with their pros and cons. But that's something to ask on codereview.
Having trouble with inheritance. I do not know what is wrong with the script..
in main
int main(){
Repository repo("dogs.txt");
FileAdoptionList* a = new CSVDoglist{}; / here is the error
Controller ctrl(repo, dogValidator{}, a);
UI ui(ctrl);
ui.startUI();
delete a;
}
CSVDoglist.h
class CSVDoglist : public FileAdoptionList
{
public:
void writeToFile();
void displayAdoptionlist() const;
};
FileAdoptionList.h
class FileAdoptionList : public AdoptionList
{
protected:
std::string filename;
public:
FileAdoptionList();
virtual ~FileAdoptionList() {}
void setFilename(const std::string& filename);
virtual void writeToFile() = 0;
virtual void displayAdoptionList() const = 0;
};
AdoptionList.h
class AdoptionList
{
protected:
std::vector<Dog> storage;
public:
AdoptionList();
// Adds a dog to the playlist.
void add(const Dog& dog);
// Checks if the adoptionlist is empty.
bool isEmpty();
virtual ~AdoptionList() {}
};
ERRORS:
object of abstract class type "CSVDoglist" is not allowed:
'CSVDoglist': cannot instantiate abstract class Adoptig Dogs
I have read more topics about this problem but I didn't found the solution.
Can someone help me? Thanks
It seems you have a typo.
A function named displayAdoptionlist (contains small l) is declared in CSVDoglist, but the pure virtual function displayAdoptionList (contains large L) isn't overrided in CSVDoglist.
I get the following compilation error here. Why can't the derived class access another derived class method. Although the method is public. I am confused here. Please help.
/export/home/joshis1/Dropbox/Design_Patterns_UML/ObserverPattern/ObserverPatternProgram-build-desktop-Qt_4_8_4_in_PATH__System__Release/../ObserverPatternProgram/UpdateReceiver.h:43:
error: no matching function for call to
‘IPublisher::registerObserver(UpdateReceiver* const)’
I have a publisher class - Interface -
class ISubscriber;
/** Interface **/
class IPublisher
{
public:
virtual void registerObserver(ISubscriber *observer) = 0;
virtual void unregisterObserver(ISubscriber &observer) = 0;
virtual void notifyObserver() = 0;
virtual void setBaudRate(int newBaudRate) = 0;
virtual void setAspectRatio(int newAspectRatio) = 0;
virtual void setVolumeLevel(int newVolume) = 0;
};
//////////////////////////////////////
class ISubscriber;
class UpdateManager: public IPublisher
{
private:
QList<ISubscriber *> subscribers;
int m_baudRate;
int m_aspectRatio;
int m_volumeLevel;
public:
UpdateManager()
{
qDebug()<<"Update Manager --- Server/Subject Initialized";
subscribers.clear();
}
virtual void registerObserver(ISubscriber *observer)
{
subscribers.append(observer);
}
virtual void unregisterObserver(ISubscriber *observer)
{
int index = subscribers.indexOf(observer);
subscribers.removeAt(index);
qWarning()<<"Removed the subscriber Index = "<<index;
}
virtual void setBaudRate(int newBaudRate)
{
m_baudRate = newBaudRate;
notifyObserver();
}
virtual void setAspectRatio(int newAspectRatio)
{
m_aspectRatio = newAspectRatio;
notifyObserver();
}
virtual void setVolumeLevel(int newVolume)
{
m_volumeLevel = newVolume;
notifyObserver();
}
virtual void notifyObserver()
{
#if 0
foreach( ISubscriber observer, subscribers )
{
observer.update(m_baudRate,m_aspectRatio,m_volumeLevel);
}
#endif
}
};
///////////////////
I have the observer --
/** Subscriber Interface **/
class ISubsrciber
{
public:
virtual void update(int baudRate, int AspectRatio, int VolumeLevel) = 0;
};
class UpdateManager;
class ISubsrciber;
#include "IPublisher.h"
class UpdateReceiver: public ISubsrciber
{
private:
int m_baudRate;
int m_aspectRatio;
int m_volumeLevel;
int m_receiverNumber;
public:
// static int updateReceiverTracker;
/** Update Interface of the client **/
void update(int baudRate, int AspectRatio, int VolumeLevel)
{
m_baudRate = baudRate;
m_aspectRatio = AspectRatio;
m_volumeLevel = VolumeLevel;
qDebug()<<"The following client number : "<< m_receiverNumber<< " got the update ";
qDebug()<<"The baudRate is "<<baudRate;
qDebug()<<"The AspectRatio is"<<AspectRatio;
qDebug()<<"The VolumeLevel is"<<VolumeLevel;
}
/** Constructor -- and registers with the Server or Publisher or UpdateManager **/
UpdateReceiver(IPublisher *updateManager)
{
//m_receiverNumber = UpdateReceiver::updateReceiverTracker++;
updateManager->registerObserver(this);
}
};
Regarding the error message you have - you don't have a method (at least in this question) with the signature that your code is apparently looking for. You have:
virtual void registerObserver(ISubscriber *observer)
{
subscribers.append(observer);
}
Your first file describes an ISubscriber but your second file inherits from an ISubsrciber (sic).
You have a typo in your file. Change to ISubscriber and you should have better luck!
here updateManager->registerObserver(this); you are sending it object of UpdateReceiver while it requires ISubscriber.
class
class UpdateReceiver: public ISubsrciber // wrong
class UpdateReceiver: public UpdateManager // right
should inherit UpdateManager not ISubsrciber?
Well I do see a few problems along your solution. Firstly you do have different forward declarations for the type ISubscriber as I stated in my earlier comment. Which results in your program not compiling.
These two wont match for sure.
virtual void registerObserver(ISubscriber *observer) {...}
class UpdateReceiver: public ISubsrciber {...}
^^^^
Secondly your notifyObserver implementation does need some rethinking as well. But since you kind of commented that code out, I'll leave this one up to you. Just remember that you're holding pointers to ISubscriber in your subscriber list when you're trying to iterate/loop over it.
Also the definition of unregisterObserver does not match your declaration.
virtual void unregisterObserver(ISubscriber &observer) = 0;
virtual void unregisterObserver(ISubscriber *observer) {...}
BUT
I would consider some major refactorings for your code. In my opinion you should not mix up the Interface of the Observerpattern with your application logic.
I think your solution should look similar to this. It's not complete and does not use your QT classes tho but you should get the idea. See the demo for a runnable solution.
class ISubscriber {
public:
virtual void update() = 0;
};
class Publisher {
std::vector<ISubscriber*> m_observerList;
public:
virtual void registerSubscriber(ISubscriber& observer);
virtual void unregisterSubscriber(ISubscriber& observer);
virtual void notifySubscribers();
};
class UpdateManager : public Publisher {
int m_baudRate;
int m_aspectRatio;
int m_volumeLevel;
public:
virtual void setBaudRate(int newBaudRate);
virtual void setAspectRatio(int newAspectRatio);
virtual void setVolumeLevel(int newVolume);
int getBaudRate() const;
int getAspectRatio() const;
int getVolumeLevel() const;
};
class UpdateReceiver : public ISubscriber {
UpdateManager& m_manager;
public:
UpdateReceiver(UpdateManager& manager) : m_manager(manager) {
m_manager.registerSubscriber(*this);
}
virtual void update() {
// Process the new values
m_manager.getBaudRate();
m_manager.getAspectRatio();
m_manager.getVolumeLevel();
}
};
DEMO
There is a nice state machine tutorial called UML Tutorial: Finite State Machines by Robert C. Martin. But I can't compile the sample code it provides. I got *FsmTest.cpp(46) : error C2664: 'SetState' : cannot convert parameter 1 from 'class UnlockedState *' to 'class TurnstileState '
Please, help. Thanks.
class Turnstile
{
public:
virtual void Lock();
virtual void Unlock();
virtual void Thankyou();
virtual void Alarm();
};
class TurnstileFSM;
class LockedState;
class UnlockedState;
class TurnstileState
{
public:
virtual void Coin(TurnstileFSM*) = 0;
virtual void Pass(TurnstileFSM*) = 0;
protected:
static LockedState lockedState;
static UnlockedState unlockedState;
};
class TurnstileFSM : public Turnstile
{
public:
void SetState(TurnstileState* s) {itsState = s;}
void Coin() {itsState->Coin(this);}
void Pass() {itsState->Pass(this);}
private:
TurnstileState *itsState;
};
class LockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t)
{
t->SetState(&unlockedState);
t->Unlock();
}
virtual void Pass(TurnstileFSM* t)
{
t->Alarm();
}
};
class UnlockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t)
{
t->Thankyou();
}
virtual void Pass(TurnstileFSM* t)
{
t->SetState(&lockedState);
t->Lock();
}
};
LockedState TurnstileState::lockedState;
UnlockedState TurnstileState::unlockedState;
The problem is that when you try to call SetState() inside of LockedState::Coin(), the class UnlockedState is an incomplete type: it has been declared but not defined. In order to fix it, you'll need to move the definition of of Coin() to after that of UnlockedState:
class LockedState : public TurnstileState
{
public:
virtual void Coin(TurnstileFSM* t);
...
};
class UnlockedState : public TurnstileState
{
...
};
void LockedState::Coin(TurnstileFSM* t)
{
...
}
Most likely this is because it does not know UnlockedState is a subclass of TurnstileState yet. Remove the function from inside the class to the end of the file:
class TurnstileFSM {
void SetState(TurnstileState* s);
};
void TurnstileFSM::SetState(TurnstileState* s) {itsState = s;}
In the example, the generated code should include the tscontext.h, and the TurnStyle class is derived from the context, which should be declared in *tscontext.h" as class TurnStyleContext.
In my case the generated code looks like this:
#include "tscontext.h" // the header file name for the context class"
// Forward Declarations
class TurnStyle;
//----------------------------------------------
// TurnStyleState: The base state class
//----------------------------------------------
class TurnStyleState
{
public:
virtual const char* StateName() const = 0;
virtual void Coin( TurnStyle& );
virtual void Pass( TurnStyle& );
};
//----------------------------------------------
// State: Unlocked
//----------------------------------------------
class TurnStyleUnlockedState : public TurnStyleState
{
public:
virtual const char* StateName() const
{ return "Unlocked"; }
virtual void Pass( TurnStyle& );
virtual void Coin( TurnStyle& );
};
//----------------------------------------------
// State: Locked
//----------------------------------------------
class TurnStyleLockedState : public TurnStyleState
{
public:
virtual const char* StateName() const
{ return "Locked"; }
virtual void Coin( TurnStyle& );
virtual void Pass( TurnStyle& );
};
//----------------------------------------------
// TurnStyle: The Finite State Machine class
//----------------------------------------------
class TurnStyle: public TurnStyleContext
{
public:
// Static State variables
static TurnStyleUnlockedState Unlocked;
static TurnStyleLockedState Locked;
TurnStyle(); // default Constructor
// Event functions
virtual void Coin() { itsState->Coin( *this ); }
virtual void Pass() { itsState->Pass( *this ); }
// State Accessor functions
void SetState( TurnStyleState& theState ) { itsState = &theState; }
TurnStyleState& GetState() const { return *itsState; }
const char* GetCurrentStateName() const { return itsState->StateName(); }
const char* GetVersion() const;
private:
TurnStyleState* itsState;
};
with the state machine defined this way:
Context TurnStyleContext // the name of the context class
FSMName TurnStyle // the name of the FSM to create
Initial Locked // the name of the initial state
// for C++ output
pragma Header tscontext.h" // the header file name for the context class, note the necessary "
{
Locked
{
Coin Unlocked Unlock
Pass Locked Alarm
}
Unlocked <BeforeUnlocked >AfterUnlocked
{
Coin Unlocked Thankyou
Pass Locked Lock
}
}
The context implements FSMError, Thankyou, Lock, Alarm, Unlock, BeforeUnlocked, AfterUnlocked