views:

95

answers:

4

Hi. Im working on an assignment for one of my classes. Simply I have a GumballMachine class and a bunch of State classes that change the state of the GumballMachine.

Here is the offending code:

class GumballMachine;

class State {
public:
 virtual void insertQuarter() const = 0;
 virtual void ejectQuarter() const = 0;
 virtual void turnCrank() const = 0;
 virtual void dispense() const = 0; 

protected:
 GumballMachine *GBM;
};

class NoQuarterState : public State {
public: 
 NoQuarterState (GumballMachine *GBM) {
  this->GBM = GBM;  
 }

 void insertQuarter() const {
  cout << "You inserted a quarter\n";  
  **this->GBM->QuarterInserted();** // <--- C2027 error on MSDN  
 }
};

Now further below I have defined my GumballMachine class as:

class GumballMachine {
public:
 GumballMachine(int numOfGB) {
  this->noQuarterState = new NoQuarterState(this);
  this->soldOutState = new SoldOutState(this);
  this->hasQuarterState = new HasQuarterState(this);
  this->soldState = new SoldState(this);
  this->winnerState = new WinnerState(this);
  this->count = numOfGB;
  if (0 < numOfGB) {
   this->state = this->noQuarterState;
  }
  else {
   this->state = this->soldOutState;
  }  
 }

        ... more code ...

 void QuarterInserted() {
  this->state = this->hasQuarterState;
 }

 ... more code ...

protected:
 int count;
 NoQuarterState *noQuarterState;
 SoldOutState *soldOutState;
 HasQuarterState *hasQuarterState;
 SoldState *soldState;
 WinnerState *winnerState;
 State *state;
};

Visual Studios was throwing a C2259 and C2027 error but after looking at MSDN I feel like I am doing it right. Maybe I am just tired, but I can't seem to find the error/see what I did wrong.

Much thanks to any help. :D

+4  A: 

You cannot access any members of GumballMachine before you define the class, so you'll have to either split your file into several files, each containing one class, or define your NoQuarterState::insertQuarter method after the definition of the GumballMachine class:

class NoQuarterState : public State {
  public: 
    NoQuarterState (GumballMachine *GBM) {
       this->GBM = GBM;  
    }

    void insertQuarter() const; // Declaration only
};

class GumballMachine {
  public:
    ...
};

void NoQuarterState::insertQuarter() const {
  cout << "You inserted a quarter\n";  
  this->GBM->QuarterInserted(); // Works now bec. comp. has seen the def.
}
Manuel
Hmmmm.... Even though I reference it up by just putting class GumballMachine; ?
Chris
That's just the class *declaration*, the compiler needs to see the whole thing (the *definition*) in order to compile any code that accesses members of the class (otherwise it has no way to know if those members actually exist or if they have the signature/type required)
Manuel
Everything with the classes seems to compile but now I get linker errors when I try to create a class by using GumballMachine *GBM = new GumballMachine(5). I get the LNK2001 unresolved externals on all the definitions of the functions I created outside of the class. The MSDN page for LNK2001 is overwhelming. Might you know what is going on now?
Chris
Are you putting the member function definitions in the same namespace where the class is defined?
Manuel
I am. My teacher said I could just use one file for the assignment.
Chris
The following compiles and links fine: http://codepad.org/TxDY5e4B. See what's different in your example.
Manuel
Mine looks to be the same/similar as yours does. I really have no idea. I posted my code on codepad and when I submit it it gives me errors about the VTable. http://codepad.org/vyUHZHZe
Chris
OMG. NM. I see what I did wrong and it was a silly error. I was looking for something else.
Chris
Actually I lied. I don't see what is wrong. :(
Chris
+1  A: 

GumballMachine class is missing a semicolon after its definition.

erelender
Maybe you see something I don't but I see (think I see) that I have put in the semicolons.
Chris
class GumballMachibne{ //members, methods vs. }; that last semicolon is missing.
erelender
@erelender: I think that Chris has got that right. The semi colon is on the last line of the code snippet in the question.
quamrana
A: 

class GumballMachine; declares the class. If you wish to dereference a pointer to an object of the class, you must first define the class. This is usually done in header files. In the class definition must declare all of it's member functions and variables, but you may define those functions wherever you like.

JonM
+1  A: 

Chris, you need to adopt a more standard approach of splitting declarations into header files and definitions into module files.

class State needs to be in something like State.h and things like the definition of NoQuarterState::insertQuarter() needs to be in State.cpp.

When that is done you will know which .cpp files need to #include other header files to make them compile.

You are right to have class GumballMachine; before the declaration of class State since both State and NoQuarterState need to know that name.

quamrana