State Machines, Sub-Classes, and Function Pointers - c++

I'm having trouble implementing a state machine for class. I keep getting the errors:
state.cpp:5: error: have0 was not declared in this scope
state.cpp:10: error: redefinition of State* Have0State::process(std::string)
state.h:18: error: virtual State* Have0State::process(std::string) previously defined here
I'm trying to get the Have0State to work before I continue onto the rest of the machine, hence the sparse code.
state.h:
#ifndef STATE_H
#define STATE_H
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <iostream>
class State{
public:
State(){};
virtual State* process(std::string input) = 0;
};
class Have0State: public State {
public:
Have0State():State(){};
virtual State* process(std::string input);
}have0;
#endif
state.cpp:
#include "state.h"
using namespace std;
State *currentState = &have0;
State* Have0State::process(string input){
if(input == "quarter"){
cout << "cool" << endl;
}
return &have0;
}
int main(int argc, char** argv) {
string input;
//get input
cin >> input;
while (input != "exit") {
currentState = currentState->process(input);
//get input
cin >> input;
}
return 0;
};
I've tried defining the process function as Have0State::State::process(string input) but that didn't work either. Any clarification on how function pointers are supposed to work, especially in the context of subclass member functions, I would greatly appreciate it.
EDIT: Also, what exactly is the have0 declaration at the end of the Have0State class declaration in the state.h file? It doesn't have an explicitly stated type; is it implied that it is of type Have0State??

There aren't any function pointers in your example. Also, like Marciej, I am able to compile (and run) this code.
But, since you asked, the 'have0' declaration simply declares an instance of the class. A class definition can be followed by 0 or more of these declarations (as well as initializers):
class Thing {...} one, another, many[3] = { Thing(1), Thing(2), Thing(3) };
the same as for any other type:
int counter = 0, flag = 0x80, limit = 500;
The possibility of this optional declarator list is why class, struct, union, and enum definitions must be followed with a semi-colon (to terminate the list).
But, as Karthik said, defining a variable in a header will cause "duplicate definition" errors at link time, if the header is included in more than one .cpp file. IMO it's fine though to use this technique to define and declare private objects in a .cpp file (rather than a .h file).

Related

'Cashier' was not declared in this scope

I have this piece of code
#ifndef STATION_H
#define STATION_H
#include <vector>
#include "Dispenser.h"
#include "Cashier.h"
//class Cashier;
class Station
{
private:
int price;
int dispenser_count;
int cashier_count;
std::vector<Dispenser> dispensers;
std::vector<Cashier> cashiers;
public:
Station(int, int, int);
int GetPrice() const { return price; }
Dispenser *LookForUnoccupiedDispenser(int &id);
Dispenser *GetDispenserByID(int id);
Cashier *LookForUnoccupiedCashier();
};
#endif // STATION_H
When I have the class Cashier line commented, the compiler fails with a 'Cashier' was not declared in this scope error even though Cashier.h was included. Uncommenting it makes it possible to compile but I'm concerned that it shouldn't be happening.
Cashier.h
#ifndef CASHIER_H
#define CASHIER_H
#include "Station.h"
class Station;
class Cashier
{
private:
bool busy;
Station *at_station;
public:
Cashier(Station *employer);
bool IsBusy() const { return busy; }
};
#endif // CASHIER_H
How is it possible? It's clearly declared in the header file and as far as I know, #include does nothing more than pasting the content of a file into another one.
Thank you for the answers in advance!
Your station.h includes cachier.h. This is an example of cyclic dependency. Given that you only have a pointer to Station in Cachier I'd suggest removing the dependency of station.h and forward declare it.
An #include is literally nothing more than verbatim copy and paste of that file into the current compilation unit. The guards protect you from the effect of an infinite include cycle, but due to the guards one of the #includes does nothing, i.e. does NOT suck in the declaration (nor definition) of the respective class. This results in the error you get. In station.h the compiler has never seen any mention of the Cachier type when it sees the Station type.

a typo on page 252 of the book " a complete guide to c++"?

I'm reading the book "a complete guide to c++". I think there is a typo there on page 252. So I have three files as the following.
In file account.h,
// account.h
// Defining the class Account. class definition (methods prototypes) is usually put in the header file
// ---------------------------------------------------
#ifndef _ACCOUNT_ // if _ACCOUNT_ is not defined
#define _ACCOUNT_
#include <iostream>
#include <string>
using namespace std;
class Account
{
private:
string name;
unsigned long nr;
double balance;
public: //Public interface:
bool init( const string&, unsigned long, double);
void display();
};
#endif
// _ACCOUNT_
In file account.cpp,
// account.cpp
// Defines methods init() and display().
// ---------------------------------------------------
#include "account.h" // Class definition
#include <iostream>
#include <iomanip>
using namespace std;
// The method init() copies the given arguments
// into the private members of the class.
bool Account::init(const string& i_name,
unsigned long i_nr,
double i_balance)
{
if( i_name.size() < 1)
return false; // check data format to make sure it is valid
name = i_name;
nr = i_nr;
balance = i_balance;
return true;
}
// the method display() outputs private data.
void Account::display()
{
cout << fixed << setprecision(2)
<< "--------------------------------------\n"
<< "Account holder:" << name << '\n'
<< "Account number:" << nr << '\n'
<< "Account balance:" << balance << '\n'
<< "--------------------------------------\n"
<< endl;
}
And finally, in file account_t.cpp
// account_t.cpp
// Uses objects of class Account.
// ---------------------------------------------------
#include "account.h" // header file which contains class definition; (prototype for member functions)
int main()
{
Account current1, current2; // create two instances with name current1, current2
current1.init("Cheers, Mary", 1234567, -1200.99);
// have to call the init function to initialize a Account object; init function is public; members properties are private;
// that's why can not do current1.name = "nana" outside of the class definition
current1.display();
// current1.balance += 100; // Error: private member
current2 = current1;
current2.display();
current2.init("Jones, Tom", 3512347, 199.40);
current2.display();
Account& mtr = current1; // create a reference, which points to object current1
mtr.display();
return 0;
}
I do not think it's correct; because obviously there is no way to get access the init member methods and the display member methods, right? I hope this is not a naive question.
EDIT: I tried to run the main function in file account_t.cpp, and got the following output.
~$ g++ account_t.cpp
/tmp/ccSWLo5v.o: In function `main':
account_t.cpp:(.text+0x8c): undefined reference to `Account::init(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long, double)'
account_t.cpp:(.text+0xb6): undefined reference to `Account::display()'
account_t.cpp:(.text+0xd5): undefined reference to `Account::display()'
account_t.cpp:(.text+0x132): undefined reference to `Account::init(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned long, double)'
account_t.cpp:(.text+0x15c): undefined reference to `Account::display()'
account_t.cpp:(.text+0x176): undefined reference to `Account::display()'
collect2: error: ld returned 1 exit status
Any more comments are greatly appreciated.
There is no issue with what you are asking about. init and display are declared public in the definition of class Account and the file with the class definition is #includeed properly in the .cpp using these methods.
In order to use a function only its declaration is needed (which is in the class definition in the header which is included). The definition/implementation in the .cpp file is not needed to use the function.
Each .cpp is compiled individually (called a translation unit) and afterwards each use of a function (for which only the declaration might have been available) is linked to the correct definitions from the other translation units if necessary via the function's scope, name and signature. This is called the linking process.
An introductory book to C++ should explain how compilation and linking process work.
For g++, there is an easy way to compile all .cpp files individually as translation units and then directly link them together:
g++ account_t.cpp account.cpp
You always need to add all .cpp to the compiler invocation like that. (There are alternative ways, but this is the easiest one.)
However, as mentioned in the comments there are other issues with this program:
_ACCOUNT_ is a reserved identifier that one may not #define in a program. All identifiers starting with an underscore followed by a capital letter are reserved. Using them causes undefined behavior.
using namespace std; is bad, at the very least when used in a header file, see Why is "using namespace std;" considered bad practice?.
Classes have constructors. One should not write init methods in most cases. The constructor is responsible for constructing and initializing class instances. But no constructor is used in the code.
Money should never be stored in double, because arithmetic with double is imprecise. You should store the value in an integer type in dimensions of the smallest relevant unit of money (e.g. cents).
#include <iostream> is not needed in the header file. One should avoid adding #includes that are not needed.
init returns a boolean indicating successful initialization. But main never checks that value. If a function can fail with an error value, then you must check that error value returned by the function to make sure that continuing the rest of the program is safe.
Some of these points may be excusable as simplification for a beginner program, depending on how far the book got at this point (though 200+ pages should already cover a lot), but others aren't.
Example of constructor use doing the same thing:
class Account
{
private:
string name;
unsigned long nr;
double balance;
public: //Public interface:
Account(const string&, unsigned long, double);
void display();
};
Account::Account(const string& i_name,
unsigned long i_nr,
double i_balance)
: name(i_name), nr(i_nr), balance(i_balance)
{
}
int main()
{
Account current1("Cheers, Mary", 1234567, -1200.99);
// Create Account instance and initialize private members; constructor is public; members properties are private;
// that's why can not do current1.name = "nana" outside of the class definition
current1.display();
// current1.balance += 100; // Error: private member
Account current2 = current1; // Create second Account instance and copy private members from first one
current2.display();
current2 = Account("Jones, Tom", 3512347, 199.40); // Replace instance with a copy of a new one
current2.display();
Account& mtr = current1; // create a reference, which points to object current1
mtr.display();
return 0;
}
The i_name.size() < 1 check (which is weirdly written, why not i_name.size() == 0?) would be realized by throwing an exception from the constructor:
Account::Account(const string& i_name,
unsigned long i_nr,
double i_balance)
: name(i_name), nr(i_nr), balance(i_balance)
{
if(i_name.size() == 0) {
throw invalid_argument("Account does not accept empty names!");
}
}
This requires #include<stdexcept> and is a more advanced topic.

How to make it work, problem with 2 classes

i have problem with my small project. I have two classes in it.
Problem:
error: 'Display' was not declared in this scope
Display is a class. Here is code:
//main.cpp
#include <iostream>
#include "Display.h"
#include "Polynomial.h"
using namespace std;
int main()
{
Polynomial prr;
prr.show();
cout<<endl;
cout<<"Enter x= ";
int x;
cin>>x;
cout<<endl;
cout<<"value for x="<<x<<endl<<"y="<<prr.value(x);
Display aa; // this doesn't work
//abc.show();
return 0;
}
//Display.h
#ifndef DISPLAY_H
#define DISPLAY_H
class Display
{
std::vector <vector <char> > graph;
public:
Display(int a, int b);
//friend void lay(Polynomial abc,Display cba);
//void show();
};
#endif // DISPLAY_H
I was thinking that maybe vectors are doing problems. I tested it without vectors, but it didn't change anthing.
//Display.cpp
#include "Display.h"
#include <iostream>
using namespace std;
Display::Display(int a, int b)
{
//ctor
if(a%2==0)
a++;
if(b%2==0)
b++;
vector <char> help;
vector <char> mid;
for(int i=0; i<b; i++)
{
mid.push_back('-');
if(i==(b+1)/2)
help.push_back('|');
else
help.push_back(' ');
}
for(int i=0; i<a; i++)
{
if(i==(a+1)/2)
graph.push_back(mid);
else
graph.push_back(help);
}
}
Now it's Polynomial class it's working fine, but Display class no, and i don't know why.
//Polynomial.h
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <vector>
//class Display;
class Polynomial
{...}
#endif // POLYNOMIAL_H
//Polynomial.cpp
#include "Polynomial.h"
#include <iostream>
#include <windows.h>
#include <cmath>
using namespace std;
// constructors and methods here
// everything here working fine
Edit:
After few tries i am one step back,
Now in Display.h
i have error :
error: 'vector' does not name a type
So i included vector lib.
But it didn't help.
Error Number 1:
You defined a constructor with 2 parameters
Display(int a, int b);
But when you call
Display aa;
Compiler try to instantiate a Display object with a default constructor, that you disabled defining a custom costructor;
you have 2 possibilities:
Adding a default constructor like
Display() = default;
or
Display() { /* do whatever you want to init with default parameter */}
Instantiate your variable using the constructor you defined
Display aa{0,0};
Error number 2:
std::vector < std::vector <char> > graph;
You declared vector<char> instead of std::vector<char>
See a Live Example
One reason is that your Display class has no default constructor, considering you're creating object like Display aa; . A default constructor is the constructor that has no arguments. Default constructors are provided implicitly by compiler as synthesized default constructor only if you don't provide any constructors to your class. If you provide your own constructors to your class, you must also explicitly provide a default constructor. So in your case, you should actually create Display object like this Display aa(argument, argument); by providing arguments. However, If you want to create object like Display aa; then add either Display () { } or Display() = default; in your Display.h file.
Considering you created object like the way I described but still getting an error, another reason could be that you're not compiling the source file that contains the Display (int,int); constructor definition (not just declaration as you did in your header file) along with the source file that contains the main function. If you did that but still getting an error in compilation, then I would assume it is a compiler issue and try adding a forward declaration class Display; which should compile the code. But the definition of Display has to be within the visible range of main function otherwise a forward declaration would do nothing.
In any case, you have to make sure the definition of your class is within the visible range of the main function that creates the class object. A class type with only declaration without a definition is called incomplete type and you cannot create an object of incomplete type. So the declaration of your Display (int,int); constructor in the Display.h is not enough. You also need a definition of that within the visible range of main function. You can either do that in the same file as main, same file as header, or a separate source file (which is the best practice) that has the complete definition of Display class, its data members, and member functions. However, you must make sure to compile that source file along with the source file containing main.

Error request for member getName which is of non-class type 'char'

I'm trying to make a program involving files assign2.cpp, Player.h, Player.cpp, Team.h, Team.cpp which reads data from a txt file on player info (like hits, atBat, position, name and number) and displays it out into assign2.cpp. assign2.cpp is what contains int main() and is suppose to contain very little code because relies on the other files to do the work.
The error:
request for member getName which is of non-class type ‘char’...
Please help, I've been trying to find the issue and can never do so. The compilation failure :
In file included from Team.cpp:1:0:
Team.h:34:11: warning: extra tokens at end of #endif directive [enabled by default]
Team.cpp: In constructor ‘Team::Team()’:
Team.cpp:15:5: warning: unused variable ‘numPlayers’ [-Wunused-variable]
Team.cpp: In member function ‘void Team::sortByName()’:
Team.cpp:49:56: error: request for member ‘getName’ in ‘((Team*)this
-> Team::playerObject[(j + -1)]’, which is of non-class type ‘char’
Team.cpp:49:74: error: request for member ‘getName’ in ‘bucket’, which is of non-class type ‘int’
Team.cpp: In member function ‘void Team::print()’:
Team.cpp:63:18: error: request for member ‘print’ in ‘((Team*)this)- >Team::playerObject[i]’, which is of non-class type ‘char’
make: *** [Team.o] Error 1
Team.h
#ifndef TEAM_H
#define TEAM_H
#include "Player.h"
class Team
{
private:
char playerObject[40];
int numPlayers; // specifies the number of Player objects
// actually stored in the array
void readPlayerData();
void sortByName();
public:
Team();
Team(char*);
void print();
};
#endif / *Team.h* /
Team.cpp
#include "Team.h"
#include <cstring>
#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <cstdlib>
using namespace std;
Team::Team()
{
strcpy (playerObject,"");
int numPlayers = 0;
}
Team::Team(char* newPlayerObject)
{
strncpy(playerObject, newPlayerObject, 40);
readPlayerData();
}
void Team::readPlayerData()
{
ifstream inFile;
inFile.open("gamestats.txt");
if (!inFile){
cout << "Error, couldn't open file";
exit(1);
}
inFile.read((char*) this, sizeof(Team));
inFile.close();
}
void Team::sortByName()
{
int i, j;
int bucket;
for (i = 1; i < numPlayers; i++)
{
bucket = playerObject[i];
for (j = i; (j > 0) && (strcmp(playerObject[j-1].getName(), bucket.getName()) > 0); j--)
playerObject[j] = playerObject[j-1];
playerObject[j] = bucket;
}
}
Player.h (incase anyone needs it)
#ifndef PLAYER_H
#define PLAYER_H
class Player
{
// Data members and method prototypes for the Player class go here
private:
int number;
char name[26];
char position[3];
int hits;
int atBats;
double battingAverage;
public:
Player();
Player(int, char*, char*, int, int);
char* getName();
char* getPosition();
int getNumber();
int getHits();
int getAtBats();
double getBattingAverage();
void print();
void setAtBats(int);
void setHits(int);
};
#endif
I'm very stuck, Thanks in advance.
In the Team constructor on this line
playerObject = newPlayerObject;
you're trying to assign a value of type char* to a member of type char[40], which doesn't work, since they are two different types. In any case, you probably would need to copy the data from the input instead of just trying to hold the pointer internally. Something like
strncpy(playerObject, newPlayerObject, 40);
Generally, you will always be able to assign a char[N] to a char*, but not the other way around, but that's just because C++ will automatically convert the char[N] to a char*, they are still different types.
Your declaration is:
char playerObject[40];
And your constructor reads:
Team::Team(char* newPlayerObject)
{
playerObject = newPlayerObject;
The error message you referenced in the title of this question obviously comes from here, and it is self explanatory. An array and a pointer are two completely different, incompatible types, when it comes to this kind of an assignment.
What you need to do depends entirely on what you expect to happen, and what your specifications are.
A) You could be trying to initialize the array from the character pointer, in which case you'll probably want to use strcpy(). Of course, you have to make sure that the string, including the null byte terminator, does not exceed 40 bytes, otherwise this will be undefined behavior.
Incidently, this is what you did in your default constructor:
Team::Team()
{
strcpy (playerObject,"");
}
B) Or, your playerObject class member should, perhaps, be a char * instead, and should be either assigned, just like that, or perhaps strdup()ed. In which case your default constructor will probably need to do the same.
Whichever one is the right answer for you depends entirely on your requirements, that you will have to figure out yourself.

C++ Hunter/Prey "C2027 undefined type" compilation error

I've been getting weird compile errors all over the place in a simple hunter/prey simulation (mostly because the professor hasn't explained the syntax for inherited classes and virtual functions very well) and I'm completely stuck on one issue. In this program, "Creatures" (an abstract class with "Hunter" and "Prey" children) walk around a "Grid" class in a Move(), Breed(), Die() cycle.
I'm getting the following errors: "C2027: use of undefined type 'Creature'" and "C2227: left of '->face' must point to class/struct/union/generic type" at the line specified in below (all my code's in the header because several students were getting unresolved externals in another project and the professor told us to just put it all in the headers). Let me know if I need to post more code.
I've gotten several other errors that I couldn't explain before this that seemed to be solved through a seemingly random combination of adding/removing included headers and pre-declaring classes, but an actual explanation of what's going wrong would be much appreciated so I'm not just flailing in the dark until it works. I understand the concept of what we're trying to do and even how to go about it for the most part, but as I mentioned, we didn't spend any time on the syntax of how to properly set up multiple files so that everyone works smoothly so any detailed explanation of how this should be done would be greatly appreciated.
Grid.h
#ifndef GRID_H
#define GRID_H
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include "Constants.h"
#include "creature.h"
using namespace std;
class Creature;
class Grid
{
public:
Creature* grid[MAX_X][MAX_Y];
Grid() //Initalizes the grid and spawns random creatures
{
for(int i = 0; i < MAX_X; i++)
for(int j = 0; j < MAX_Y; j++)
grid[i][j] = NULL;
}
void Move() //Tells each creature on the grid to move
{
//Call creature.Move() on each cell (if not NULL)
}
void Breed() //Tells each creature to breed (if it can)
{
//Call creature.Breed() on each cell (if not NULL)
}
void Kill() //Tells each creature to die (if it's old)
{
//Call creature.Die() on each cell (if not NULL)
}
char** Snapshot() //Creates a char array "snapshot" of the board
{
//Produces a 2D char array of the grid for display
}
Creature* Get(Coords here) //Returns a pointer to the object at the specified position
{
return grid[here.x][here.y];
}
char Occupant(Coords here) //Returns the character of the specified position
{
if(!Get(here))
return FACE_EMPTY;
Creature* temp = Get(here);
return temp->face; //*** ERRORS APPEAR HERE ***
}
void Clear(Coords here) //Deletes the object at the specified position
{
if(Get(here))
delete Get(here);
grid[here.x][here.y] = NULL;
}
};
#endif // GRID_H
creature.h
#ifndef CREATURE_H
#define CREATURE_H
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include "Constants.h"
#include "coords.h"
#include "grid.h"
using namespace std;
class Grid;
class Creature
{
public:
Grid* theGrid;
Coords position;
int stepBreed;
int stepHunger;
char face;
Creature(Grid* _grid, Coords _position, char _face) //Constructor
{
theGrid = _grid;
position = _position;
face = _face;
stepBreed = stepHunger = 0;
}
virtual Coords Move() = 0; //Allows the child to define it's own movement
virtual Coords Breed() = 0; //Allows the child to define it's own breeding
virtual bool Starve() = 0; //Allows the child to starve of its own accord
};
#endif // CREATURE_H
Your use of class Creature at the top of the file seems to indicate that you don't have access to the complete definition of Creature in this file. That makes it impossible for the compiler to do the -> operation on it - it doesn't know what the members of that class are! You need to have a complete definition of Creature in the same translation unit as this code. That is, Creature needs to be a complete type if you want to use it in this way.
Edit: Thanks for posting creature.h. Your problem (as mentioned in the comments below) is that you have a circular dependency problem. creature.h includes grid.h and vice versa. You'll need to break one of those links to get things working properly. In this case, removing #include "grid.h" from creature.h should do the trick - no code in creature.h depends on Grid being a complete type.