error: No matching function for call to class object - c++

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)
{
// ...
}

Related

Construct two classes that has attributes and can use methods of each other

I'd like to know is it possible that two classes has attributes and can use methods of each other. For example, there're a class STUDENT and a class COURSE, a STUDENT have a list of joined courses and a COURSE have list of participants(students). I tried this:
in STUDENT.h
#include <iostream>
#include <vector>
// #include "COURSE.h"
class COURSE;
class STUDENT {
string name;
std::vector<COURSE*> listCourses;
public:
STUDENT(){};
addCourse(COURSE* &course){
listCourses.push_back(course);
course.addStudent(this);
}
string getName(){
return this->name;
}
void showCourses(){
for(COURSE* course : listCourses)
std::cout << course->getName() << std::endl;
}
};
in COURSE.h
#include <iostream>
#include <vector>
// #include "STUDENT.h"
class STUDENT;
class COURSE {
string name;
std::vector<STUDENT*> listStudents;
public:
COURSE(){}
addStudent(STUDENT* &student){
listStudents.push_back(student);
student.addCourse(this);
}
string getName(){
return this->name;
}
void showStudent(){
for(STUDENT* student : listCourses)
std::cout << student->getName() << std::endl;
}
};
If I include two classes each other, it said errors. If I just include one, just one class worked, other class has problem.
Can anyone help me to fix it and I wonder that is it necessary to use some design patterns or data structures to solve this.
Thank you
Yes, what you are attempting is possible, but not in the way you are attempting it. You need to separate your method declarations and definitions.
Also, you have a flaw in your add... methods that will lead to endless recursion as soon as a Student is added to a Course or vice versa. You need to detect when the two are already linked together so that you can avoid the loop.
Try something more like this:
Student.h
#ifndef StudentH
#define StudentH
#include <vector>
#include <string>
class Course;
class Student {
std::string name;
std::vector<Course*> listCourses;
public:
Student() = default;
~Student();
std::string getName() const;
void addCourse(Course* course);
void removeCourse(Course* course);
void showCourses() const;
};
#endif
Student.cpp
#include "Student.h"
#include "Course.h"
#include <iostream>
#include <algorithm>
Student::~Student() {
for(Course* course : listCourses) {
course->removeStudent(this);
}
}
std::string Student::getName() const {
return name;
}
void Student::addCourse(Course* course) {
if (std::find(listCourses.begin(), listCourses.end(), course) == listCourses.end()) {
listCourses.push_back(course);
course->addStudent(this);
}
}
void Student::removeCourse(Course* course) {
auto iter = std::find(listCourses.begin(), listCourses.end(), course);
if (iter != listCourses.end()) {
listCourses.erase(iter);
course->removeStudent(this);
}
}
void Student::showCourses() const {
for(Course* course : listCourses) {
std::cout << course->getName() << std::endl;
}
}
Course.h
#ifndef CourseH
#define CourseH
#include <vector>
#include <string>
class Student;
class Course {
std::string name;
std::vector<Student*> listStudents;
public:
Course() = default;
~Course();
std::string getName() const;
void addStudent(Student* student);
void removeStudent(Student* student);
void showStudents() const;
};
#endif
Course.cpp
#include "Course.h"
#include "Student.h"
#include <iostream>
#include <algorithm>
Course::~Course() {
for(Student* student : listStudents) {
student->removeCourse(this);
}
}
std::string Course::getName() const {
return name;
}
void Course::addStudent(Student* student) {
if (std::find(listStudents.begin(), listStudents.end(), student) == listStudents.end()) {
listStudents.push_back(student);
student->addCourse(this);
}
}
void Course::removeStudent(Student* student) {
auto iter = std::find(listStudents.begin(), listStudents.end(), student);
if (iter != listStudents.end()) {
listStudents.erase(iter);
student->removeCourse(this);
}
}
void Course::showStudents() const {
for(Student* student : listStudents) {
std::cout << student->getName() << std::endl;
}
}

How to get the name of an Object

I am coding a little RPG(Role Playing Game)
Here is the situation: I created an object Personnage.
In my classes, I created a method atttaquer. But I would like that after calling my method attaquer it writes something like this: Goliath attaque David . But to that, I need to grab the name of the Object. Because the player may want to edit the name of Object (The personage name) before playing.
There is my code:
Personnage.h
#ifndef Personnage_h
#define Personnage_h
#include <string>
#include "Arme.h"
class Personnage{
//methods
public:
Personnage();
Personnage(std::string nomArme, int degatsArme);
Personnage(int vie, int mana);
// ~Personnage();
void recevoirDegats(int nbDegats);
void attaquer(Personnage &cible);
private:
// Attributs
int m_vie;
int m_magie;
std::string m_nom;
};
#endif
My Personnage.cpp code:
#include "Personnage.h"
#include <string>
#include <iostream>
void Personnage::recevoirDegats(int nbDegats){
m_vie -= nbDegats;
if (m_vie < 0) {
m_vie = 0;
}
}
void Personnage::attaquer(Personnage &cible){
cible.recevoirDegats(m_arme.getDegats());
// if David attacks Goliath I want to write std::cout << David << "attaque "<< Goliath << endl; but I do not know how to grab the name of the object after it's creation
}
There is my main.cpp
#include <iostream>
#include <string>
#include "Personnage.h"
//#include "Personnage.cpp"
#include <ctime>
using namespace std;
int main()
{
Personnage David, Goliath, Atangana("Ak47", 35);
Goliath.attaquer(David);
return 0;
}
If you want to give your objects names, it cannot be the variable names. They are only meant for the compiler and they are fixed. So you need to create a class that can have a name:
class NamedObject
{
private:
std::string m_name;
public:
const std::string& getName() const
{
return m_name;
}
void setName(const std::string& name)
{
m_name = name;
}
}
And if you want your classes to have a name, the easiest way would be to derive from it:
class Personnage : NamedObject {
Then you can say:
Personnage player1, player2;
player1.setName("David");
player2.setName("Goliath");
Alternatively, you can get those string from user input.
And if you need to address one by name:
std::cout << player1.getName() << " please make your move." << std::endl;

Can't set member data when nested in a class

I'm having this issue on another program, but I tried to simplify it with this one. I cannot set the weapon name through p.getWeaopn().setName("sword"); It works fine when I simply set it through its own object, but when I try to access the setter through player it doesn't set anything.
#include <iostream>
#include <string>
#include "Player.h"
#include "Weapon.h"
using namespace std;
int main()
{
Player p; // Player contains only a Weapon weapon;
Weapon w; // Weapon only contains a string name;
//w.setName("sword"); // this changes the name of the weapon
p.setWeapon(w);
p.weapon.setName("sword"); // this also changes the name
p.getWeapon().setName("sword"); // this is not setting the name. Why?
// checking if weapon has a name
if (p.getWeapon().getName().empty())
{
cout << "Weapon name is empty!" << endl;
}
else
{
cout << "Weapon name is " << p.getWeapon().getName() << endl;
}
}
Weapon.h
#pragma once
#include <string>
using namespace std;
class Weapon
{
private:
string name;
public:
string getName();
void setName(string);
};
Weapon.cpp
#include "Weapon.h"
string Weapon::getName()
{
return name;
}
void Weapon::setName(string n)
{
name = n;
}
Player.h
#pragma once
#include "Weapon.h"
class Player
{
private:
Weapon weapon;
public:
Weapon getWeapon();
void setWeapon(Weapon);
};
Player.cpp
#include "Player.h"
Weapon Player::getWeapon()
{
return weapon;
}
void Player::setWeapon(Weapon w)
{
weapon = w;
}
Weapon Player::getWeapon()
You return a copy and not a reference of the weapon, so any change to the copy does not affect the original.
For return a reference, use & operator:
Weapon& Player::getWeapon()
{
return this->weapon;
}
Player::getWeapon() returns a copy of the weapon every time instead of a reference to the weapon. Changing the name in the copy changes nothing in the original.

C++ composition circular dependency

I'm trying to learn C++ and currently I'm trying to know how to implement an object composition in this language.
I have a Character class which is inherited by a Hero and a Monster class.
A Character has a NormalAbility and a SpecialAbility.
I've made the NormalAbility and SpecialAbility classes and both are inheriting an Ability superclass.
My problem is that when I put the #include "Character.h" in Ability.h the normalAbility and specialAbility variables in Character.h don't get recognized as their respected classes. Errors such as "syntax error : identifier string" shows in the headers of both Ability inherited classes
Here's my code:
Character.h
#pragma once
#include <string>
#include "NormalAbility.h"
#include "SpecialAbility.h"
using namespace std;
class Character
{
public:
Character(string name, string type, int hp, NormalAbility na,
SpecialAbility sa);
bool isDead();
void damage(int amt);
void heal(int amt);
void attack(Character* c, int amt);
private:
string name;
string type;
int hp;
int maxHp;
NormalAbility* normalAblity;
SpecialAbility* specialAbility;
}
Character.cpp
#include "Character.h"
#include <iostream>
Character::Character(string name, string type, int hp, NormalAbility* na,
SpecialAbility* sa)
{
this->name = name;
this->type = type;
this->maxHp = hp;
this->hp = hp;
normalAbility = na;
specialAbility = sa;
}
bool Character::isDead(){
return hp <= 0;
}
void Character::damage(int amt){
if (hp > 0){
hp -= amt;
}
else{
hp = 0;
}
}
void Character::heal(int amt){
if (hp + amt > maxHp){
hp = maxHp;
}
else{
hp += amt;
}
}
void Character::attack(Character* c, int amt){
c->damage(amt);
}
Hero.h
#pragma once
#include "Character.h"
#include <string>
using namespace std;
class Hero :
public Character
{
public:
Hero(string name, int hp);
}
Hero.cpp
#include "Hero.h"
#include <iostream>
Hero::Hero(string name, int hp)
: Character(name, "Hero", hp)
{
}
Ability.h
#pragma once
#include <string>
#include "Character.h"
using namespace std;
class Ability
{
public:
Ability(string name, string type, Character* owner);
void levelUp();
private:
string name;
string type;
int level;
Character* owner;
}
Ability.cpp
#include "Ability.h"
Ability::Ability(string name, string type, Character* owner)
{
this->name = name;
this->type = type;
this->owner = owner;
level = 1;
}
void Ability::levelUp(){
level++;
}
NormalAbility.h
#pragma once
#include "Ability.h"
#include <string>
using namespace std;
class NormalAbility :
public Ability
{
public:
NormalAbility(string name);
}
NormalAbility.cpp
#pragma once
#include "NormalAbility.h"
#include <string>
using namespace std;
NormalAbility::NormalAbility(string name) : Ability(name, "Normal")
{
//some codes
}
This way you avoid the circular include of the .h files, because you're including it in the .cpp, and in the .h you're saying that, "Character exists but don't care about his definition right now"
Ability.h
#pragma once
#include <string>
class Character;
using namespace std;
class Ability
{
public:
Ability(string name, string type, Character* owner);
void levelUp();
private:
string name;
string type;
int level;
Character* owner;
}
Ability.cpp
#include "Ability.h"
#include "Character.h"
Ability::Ability(string name, string type, Character* owner)
{
this->name = name;
this->type = type;
this->owner = owner;
level = 1;
}
void Ability::levelUp(){
level++;
}

C++ OOP - Losing data

I have a few simple classes and I can't get them to work.
TL;DR I have a "Player" instance, after I set some data to the instance, I can get it back. If I push the instance to std::vector Players; if I have Players.at(0).getName() it returns "". The data is not there! Is gone. (Debugging the application I see "_name" set in "vPlayer" and in "Players" I see an element, with "_name" = "")
Here is the code:
//Player.h
#ifndef PLAYER_H
#define PLAYER_H
#include <iostream>
class Player
{
public:
Player();
Player(const Player &Player);
Player& operator=(const Player &Player);
std::string getName();
bool setName(const std::string &name);
bool nameValid(const std::string &name);
private:
std::string _name;
};
#endif
//Player.cpp
#include "Player.h"
#include <iostream>
#include <string>
using namespace std;
Player::Player()
{
}
Player::Player(const Player &Player)
{
}
Player& Player::operator=(const Player &Player) {
return *this;
}
std::string Player::getName()
{
return this->_name;
}
bool Player::setName(const std::string &name)
{
if ( ! this->nameValid(name) )
{
return false;
}
this->_name = name;
return true;
}
bool Player::nameValid(const std::string &name)
{
return name.empty() == false;
}
//Map.h
#ifndef MAP_H
#define MAP_H
#define MAP_X 40
#define MAP_Y 40
#include "Player.h"
#include "Point.h"
#include <vector>
class Map
{
public:
Map();
bool movePlayer(Player &Player, Point &Point);
std::vector<Player> getPlayers();
private:
};
#endif //MAP_H
//Map.cpp
#include "Map.h"
#include "Player.h"
#include "Point.h"
#include <iostream>
#include <string>
using namespace std;
Map::Map()
{
}
bool Map::movePlayer(Player &Player, Point &Point)
{
return true;
}
std::vector<Player> Map::getPlayers()
{
Player vPlayer;
vPlayer.setName(std::string("test"));
std::vector<Player> Players;
Players.push_back(vPlayer);
return Players;
}
in main:
std::vector<Player> Players = vMap.getPlayers();
cout<<"Test:"<<Players.at(0).getName()<<endl;
You define the class's copy constructor and copy assignment operator to do nothing. How do you expect the copy in the vector to have same data as the instance you put into the vector?
Your class can be perfectly fine with the default, compiler-generated copy constructor and copy assignment operator, so just remove your declarations and definitions for them and everything will work.
Your vector will contain copies of the elements you add to it. These copies will be added using Player::Player(const Player&) constructor.
This constructor (in your implementation) doesn't set any value for the name.
Solutions:
set the name in the copied object:
Player::Player(const Player &Player)
: _name(Player._name)
{
}
(The same is true for your assignment operator)
Remove the copy and assignment functionality and rely on the default. Because the name is a std::string, it will get a copy of the source player name by default.