Issues with inheritance and polymorphism - c++

I'm currently learning inheritance and polymorphism in C++, and am coming across this issue when trying to create a child of a parent class that inherits and defines a virtual function.
The goal is for HumanPlayer to be a child of Player, and to create its own implementation of insertion() (a function that inserts an input into a tic-tac-toe board, once complete), however, I have run into a few errors that I can't seem to get by. I'm getting a dwarf error saying
There's an undefined reference to 'vtable for Player'. In function Player::Player() and Player::~Player().
As well as another dwarf error saying
Undefined reference to 'typeinfo for Player'.
Any help with this would be greatly appreciated.
Player.cpp:
#include <iostream>
#include <string>
#include "Player.h"
Player::Player() {
name = "Zoe";
myState = 0;
isWon = false;
}
Player.h
#ifndef PLAYER_H
#define PLAYER_H
class Player {
Player();
protected:
std::string name;
int myState;
bool isWon;
public:
virtual void insertion();
};
#endif
HumanPlayer.h :
#ifndef HUMANPLAYER_H
#define HUMANPLAYER_H
#include "Player.h"
class HumanPlayer : public Player {
public:
HumanPlayer();
void insertion();
protected:
std::string Name1;
std::string Name2;
int humanCheck=0;
std::string getName();
int toInsert;
};
#endif
HumanPlayer.cpp
#include <iostream>
#include <string>
#include "Player.h"
#include "HumanPlayer.h"
HumanPlayer::HumanPlayer() {
if(humanCheck == 0) {
std::cout<<"Player One type your name";
scanf("%s", Name1);
std::cout<<"Player Two type your name";
scanf("%s", Name2);
humanCheck++;
}
}
void HumanPlayer::insertion() {
if(humanCheck % 2 ==0) {
std::cout<<Name2<<"'s turn, please enter an integer between 1 and 7";
scanf("%i", &toInsert);
} else {
std::cout<<Name1<<"'s turn, please enter an integer between 1 and 7";
scanf("%i", &toInsert);
}
humanCheck++;
}

Related

Getting class type redefinition and a few other errors

I'm creating a student data management console application for a project. I created a class called Student which is storing all the data that a student needs to have, and it also has all the getters and setters associated with it. Here is how all my files are laid out:
Student.h
#include <iostream>
#include <string>
using namespace std;
class Student {
private:
string name;
string id;
string email;
int presentation;
int essay1;
int essay2;
int project;
public:
//constructor
//Student();
//setters
void set_name(string);
void set_id(string);
void set_email(string);
void set_presentation(int);
void set_essay1(int);
void set_essay2(int);
void set_project(int);
//getters
string get_name();
string get_id();
string get_email();
int get_presentation();
int get_essay1();
int get_essay2();
int get_project();
};
Student.cpp
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;
//constructor definition
/*
Student::Student(void) {
cout << "Student created" << endl;
}
*/
//setter definition
void Student::set_name(string s) {
name = s;
}
void Student::set_id(string s) {
id = s;
}
void Student::set_email(string s) {
email = s;
}
void Student::set_presentation(int a) {
presentation = a;
}
void Student::set_essay1(int a) {
essay1 = a;
}
void Student::set_essay2(int a) {
essay2 = a;
}
void Student::set_project(int a) {
project = a;
}
//getter definition
string Student::get_name() {
return name;
}
string Student::get_id() {
return id;
}
string Student::get_email() {
return email;
}
int Student::get_presentation() {
return presentation;
}
int Student::get_essay1() {
return essay1;
}
int Student::get_essay2() {
return essay2;
}
int Student::get_project() {
return project;
}
Main.cpp
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;
int main() {
cout << "Hello World!" << endl;
Student student1;
Student student2;
Student student3;
student1.set_name("John");
student2.set_name("Bob");
student3.set_name("Carl");
return 0;
}
When I try to run my program, I get, amongst others, the following errors:
Error 1 error C2011: 'Student' : 'class' type redefinition
Error 2 error C2079: 'student1' uses undefined class 'Student'
Error 5 error C2228: left of '.set_name' must have class/struct/union
Error 9 error C2027: use of undefined type 'Student'
How can I go about fixing this issue?
I'm quite sure this is an error caused by the fact that student.h is included twice in a certain .cpp file. Thus you need to use so-called header guards to make sure the file is only included once in every .cpp file:
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
#include <string>
using namespace std;
class Student {
/* ... */
};
#endif
The idea behind this is that an #include is a preprocessor directive that results in the argument file being copied into the file where the #include was issued. Hence, if files A and B include Student.h, and file C includes both files A and B, then the declaration of class Student is going to end up duplicated. Hence the error. The above macros make sure that this doesn't happen.
Edit as per the question author's comment:
#pragma once is the same as #ifndef .. #define #endif but non-standard .
See #pragma once vs include guards? for reference.
I had the same error. I just clean and rebuild the solution and error resolved.

Debugging C++ compiler error

I'm still a noobie in c++ so I am not to skilled in debugging yet. Just trying to figure out how to fix this compilation error.
CruiseShip.cpp:11: error: expected ā€˜)ā€™ before ā€˜nā€™
CruiseShip.cpp
#include "CruiseShip.h"
#include "Ship.h"
#include <iostream>
using namespace std;
Ship s;
int passengers;
CruiseShip(string n, string y, int p) : Ship(n,y)
{
passengers=p;
}
void print()
{
cout<<"Name: "<<s.getName()<<"\nMaximum passengers:"<<passengers<<endl;
cout<<"-------------------------"<<endl;
}
CruiseShip.h
#ifndef CRUISESHIP_H
#define CRUISESHIP_H
#include "Ship.h"
#include <string>
using namespace std;
//class Ship;
class CruiseShip:public Ship{
private:
int passengers;
Ship::Ship s;
public:
CruiseShip(string, string, int);
virtual void print();
};
#endif
Ship.h
#ifndef SHIP_H
#define SHIP_H
#include <string>
using namespace std;
class Ship{
private:
string name;
string built;
public:
Ship();
Ship(string, string);
string getName();
string getBuilt();
virtual void print();
};
#endif
You have 3 errors:
1 and 2. You don't declare print and CruiseShip (The constructor) as part of the class CruiseShip when you define them. You need to:
CruiseShip::CruiseShip(string n, string y, int p) : Ship(n,y) {
virtual void CruiseShip::print() {
3, you dont have a namespace Ship so this is unnecessary:
Ship::Ship s; // This only needs to be Ship s <- NameSpace::ObjectType nameOfObject;
After this it will compile http://ideone.com/wJ6mPO. It will not link however, because you have undefined references to all of the functions you have yet to define.

error: No matching function for call to class object

Each time I've attempted to build my project, I receive the same error:
>error: no matching function for call to 'Agent::Agent()'
>note: candidates are: Agent::Agent(std::string, room*)
>note: Agent::Agent(const Agent&)
Initially I assumed that I was feeding the wrong values, but even after seemingly correcting, I still get the same error.
main
#include <iostream>
#include <string>
#include <sstream>
#include "room.h"
#include "Thing.h"
//#include "Agent.h"
//#include "Grue.h"
//#include "Player.h"
using namespace std;
int main()
{
srand(time(NULL));
room *entrance = new room("Entrance","A wide open entrance...", 100);
room *hallway = new room("Hallway","A long hallway...", 50);
room *ballroom = new room("Ballroom","A huge ballroom...", 200);
room *garden = new room("Garden","A lush garden...", 150);
entrance->link("south", hallway);
hallway->link("north", entrance);
hallway->link("east", ballroom);
ballroom->link("west", hallway);
ballroom->link("east", garden);
hallway->printLinked();
while(true)
{
for(int i = 0; i < agents.size(); i++)
{
bool ok = agents[i]->act();
if(!ok)
{
cout << "Game quits." << endl;
return 0;
}
}
}
Player *josh = new Player("Josh", entrance);
Player *tracy = new Player("Tracy", entrance);
game.addAgent(josh);
game.addAgent(tracy);
cout << "Welcome!" << endl;
// the step() function in the Game class will eventually
// return false, when a player chooses to quit;
// this tiny "while" loop keeps asking the game.step()
// function if it is false or true; the effect is
// that the step() function is called repeatedly
// until it returns false
while(game.step());
return 0;
}
Thing header
#ifndef THING_H
#define THING_H
#include <iostream>
#include <string>
#include "room.h"
class room;
class Thing
{
private:
std::string name, desc;
protected:
room* cur_room;
public:
Thing(std::string _name, std::string _desc);
std::string getName();
std::string getDesc();
int getSize();
};
#endif // THING_H
Thing cpp
#include "Thing.h"
Thing::Thing(std::string _name, std::string _desc)
{
name = _name;
desc = _desc;
cur_room = NULL;
}
std::string Thing::getName()
{
return name;
}
std::string Thing::getDesc()
{
return desc;
}
int Thing::getSize()
{
return size;
}
Agent header
#ifndef AGENT_H
#define AGENT_H
#include "Thing.h"
#include <iostream>
#include <string>
#include "room.h"
class Agent : public Thing
{
protected:
//bool walk(std::string exit);
room *cur_room;
std::string name;
public:
Agent(std::string _name, room *_cur_room);
void get_curroom();
virtual bool act() = 0;
std::string getName() { return name; }
};
#endif // AGENT_H
Agent cpp
#include "Agent.h"
Agent::Agent(std::string _name, room *_cur_room)
{
name = _name;
room = _cur_room;
}
bool Agent::walk(std::string exit)
{
return 0;
}
bool Agent::act()
{
return 0;
}
void Agent::get_curroom()
{
return cur_room;
}
Player header
#ifndef PLAYER_H
#define PLAYER_H
#include <iostream>
#include <string>
#include "Agent.h"
#include "room.h"
class room;
class Player : public Agent
{
private:
std::string name;
protected:
public:
Player(std::string _name, room *starting_room);
bool Act();
};
#endif // PLAYER_H
Player cpp
#include "Player.h"
Player::Player(std::string _name, room *starting_room)
{
name = _name;
cur_room = starting_room;
}
bool Player::Act()
{
std::cout << "Where do you want to go? (or 'quit')" << std::endl;
}
I'm honestly stumped on where to go next. Any help is greatly appreciated!
In your inheritance chain of Player<-Agent<-Thing, you aren't passing the constructor parameters up to the parent. So, you need to change the Player constructor to:
Player::Player(std::string _name, room *starting_room)
:Agent(_name, starting_room)
{
name = _name;
cur_room = starting_room;
}
And you need to change the Agent constructor to:
Agent::Agent(std::string _name, room *_cur_room)
:Thing(_name, "")
{
name = _name;
room = _cur_room;
}
The parts I added after the colons are called initialization lists. One use of these is to call the constructor of the parent class. In C++, you have to call the parent class's constructor by name, since there is no keyword to reference the parent class generally.
The problem is that in the constructor of Player you don't call the constructor of the base class Agent and the latter doesn't have the default constructor. To fix it call the Agent's constructor (or add the default constructor):
Player::Player(std::string _name, room *starting_room)
: Agent(_name, starting_room)
{
// ...
}

C++ Class object as argument in other class function

I have a C++ project in Visual Studio 2015.
GameManager.h and Input.h both give me a syntax error: identifier 'Player'. This happens because I want to give an object of type 'Player' as an argument to functions in these two Header files and their appropriate C++ Files.
How do I fix that? For further information I have provided my code.
main.cpp:
#include "GameManager.h"
#include "Input.h"
#include "Player"
#include <iostream>
#include <string>
using namespace std;
const int maxPlayerCnt = 10;
static Player p1, p2, morePlayers[maxPlayerCnt];
int main()
{
GameManager game;
game.Game(p1, p2, morePlayers);
return 0;
}
It creates an object of type GameManager and 3 objects of type Player.
GameManager.h:
#include "Player.h"
class GameManager
{
public:
void Game(Player p1, Player p2, Player morePlayers[]);
};
GameManager.cpp:
#include "GameManager.h"
void GameManager::Game(Player p1, Player p2, Player morePlayers[])
{
int playerCnt = 0;
Input input;
input.getPlayerDetails(playerCnt, p2);
input.getMorePlayerDetails(playerCnt, morePlayers);
}
It creates an object of type Input to use further functions and will get more code, once I figure this problem out. And then calls to functions with specific arguments it gets from main.cpp
Input.h:
#pragma once
#include "Player.h"
#include <iostream>
#include <string>
using namespace std;
class Input
{
public:
Input();
void getPlayerDetails(int &playerNum, Player p);
void getMorePlayerDetails(int &playerNum, Player p[]);
};
It includes everything Input.cpp needs and initializes the funcitons
Input.cpp:
#include "Input.h"
void Input::getPlayerDetails(int &playerNum, Player p)
{
playerNum++;
string currentName;
char currentSymbol;
cout << "Player " << playerNum << ", what is your name?\n";
cin >> currentName;
p.setName(currentName);
cout << currentName << " what is your symbol?\n";
cin >> currentSymbol;
p.setSymbol(currentSymbol);
}
void Input::getMorePlayerDetails(int &playerNum, Player p[])
{
int plNum = playerNum;
if (playerNum >= 12)
cout << "You can't get another player!\n";
else
{
//getPlayerDetails(p[playerNum - 2], (plNum - 2));
}
}
It for now has all the functions needed and both get an object of type Player. And the second function is not quite done now. But that is not important.
Player.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Player
{
private:
string _name;
char _symbol;
public:
Player();
void getName();
void setName(string name);
void setSymbol(char symbol);
};
Player.cpp:
#include "Player.h"
Player::Player()
{
}
void Player::getName()
{
cout << "I have no name!\n";
}
void Player::setName(string name)
{
_name = name;
}
void Player::setSymbol(char symbol)
{
_symbol = symbol;
}
If you can help me, I would be pleased to see your response.

Qt 4 C++ Getting an error when using 3 classes that use each other, error: field `m_Employer' has incomplete type

I'm in desperate need of help and direction. Been trying to get this to compile, but battling due to the fact that there are 3 classes and not hundreds on how the includes/forward declarations should work here.
The error is marked in person.h.
In addition to the error, there is a warning I've marked in main.cpp.
This is a console app.
Thank you in advance.
person.h
#ifndef PERSON_H
#define PERSON_H
#include <QString>
class Employer;
class Person
{
public:
Person(QString name);
QString toString() const;
void setPosition(Employer newE, Position newP);
Position getPosition() const;
private:
QString m_Name;
bool m_Employed;
Position m_Position;
Employer m_Employer; //--> ERROR: field `m_Employer' has incomplete type.
};
#endif // PERSON_H
person.cpp
#include "employer.h"
#include "position.h"
#include "person.h"
Person::Person(QString name) : m_Name(name), m_Employed(false), m_Position(""), m_Employer("")
{
}
void Person::setPosition(Employer newE, Position newP)
{
m_Position = newP;
m_Employed = true;
m_Employer = newE;
}
Position Person::getPosition()const
{
return (m_Employed ? m_Position : Position("Professional nose-picker"));
}
QString Person::toString()const
{
return m_Name + ", Employed: " + (m_Employed ? "Yes" : "No") + ", Position: " + getPosition().toString();
}
employer.h
#ifndef EMPLOYER_H
#define EMPLOYER_H
#include <QString>
//class Position;
//class Person;
class Employer
{
public:
Employer(QString name, QString market = "");
void hire(Person &newHire, Position pos);
QString toString() const;
private:
QString m_Name;
QString m_Market;
};
#endif // EMPLOYER_H
employer.cpp
#include "employer.h"
#include "person.h"
#include "position.h"
Employer::Employer(QString name, QString market) : m_Name(name), m_Market(market)
{
}
QString Employer::toString()const
{
return m_Name + (m_Market != "" ? ", Market: " + m_Market : "");
}
void Employer::hire(Person &newHire, Position pos)
{
newHire.setPosition(*this, pos);
}
position.h
#ifndef POSITION_H
#define POSITION_H
#include <QString>
class Position
{
public:
Position(QString name, QString desc = "");
QString toString() const;
private:
QString m_Name;
QString m_Desc;
};
#endif // POSITION_H
position.cpp
#include "position.h"
Position::Position(QString name, QString desc)
:m_Name(name), m_Desc(desc)
{}
QString Position::toString()const
{
return m_Name + (m_Desc != "" ? ", Description: " + m_Desc : "");
}
main.cpp
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include "position.h"
#include "person.h" //--WARNING -> In file included from main.cpp:4:
#include "employer.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream cout(stdout);
Person bob("Bob");
Employer devCo("Dev Co");
cout << bob.toString() << endl;
bob.setPosition(is, Position("Developer", "Software Eng"));
cout << bob.toString() << endl;
cout << devCo.toString() << endl;
return a.exec();
}
The Person class needs to know all about Employer and so needs Employer.h included in it rather than the class forward declaration.
In this case the person needs to know the size of the Employee class as you have an Employee stored inside the class.
If you wanted to decouple the classes and just use a forward declaration then Person would have to contain a pointer (raw or smart) to the employer.
You need to take a look at things to consider when using forward declaration. By using forward declaration, you not only break dependencies, but also speed up the compilation by not having to include lots of headers.
The solution for your specific problem is like this :
#ifndef PERSON_H
#define PERSON_H
#include <QString>
class Employer;
class Person
{
public:
Person(QString name);
QString toString() const;
void setPosition(Employer &newE, Position newP);
Position getPosition() const;
private:
QString m_Name;
bool m_Employed;
Position m_Position;
Employer *m_Employer;
};
#endif // PERSON_H
Thanks Guys! I ended up moving #include "employer.h" and
include "position.h" to the person.h and from the person.cpp.
And then fixed a few other errors that then came up.
Looks like I'm battling with when and where to use includes or forward directives. Need to read up on it some more.
I like where you guys are going with the pointer idea.