EDIT:
I'm using namespace std
I'm using VS10
Room is a separate class
I've included the memory header in all necessary files
The original error was an Intellisense error I was getting before building. After building, I got a buttload more:
[The original Intellisense error before building] declaration is incompatible with "std::tr1::shared_ptr<< error-type >> Option::getRoom()
'std::tr1::shared_ptr<_Ty> Option::getRoom(void)' : overloaded function differs only by return type from 'std::tr1::shared_ptr Option::getRoom(void)'
'Option::getRoom' : redefinition; different basic types
'Option::getRoom' uses undefined class 'std::tr1::shared_ptr'
These are related to this piece of code in Option.cpp:
shared_ptr<Room> Option::getRoom(){
shared_ptr<Room> room(new Room);
return room;
}
The corresponding code in Option.hpp:
public:
virtual shared_ptr<Room> getRoom();
Error 'RoomOption::getRoom': overriding virtual function return type differs and is not covariant from 'Option::getRoom'
[IntelliSense] return type is not identical to nor covariant with return type "std::tr1::shared_ptr<< error-type >>" of overridden virtual function function "Option::getRoom"
This is related to this piece of code in RoomOption.hpp, a subclass of Option:
public:
shared_ptr<Room> getRoom();
Here's all the code from the two classes I'm having trouble with:
Option.h:
#pragma once
#include "Room.h"
#include <memory>
using namespace std;
class Option
{
protected:
int id;
char* text;
public:
Option(void);
Option(int, char*);
virtual ~Option(void);
char* getText();
int getID();
virtual shared_ptr<Room> getRoom();
};
Option.cpp:
#include "Option.h"
#include "Room.h"
#include <memory>
using namespace std;
Option::Option(void)
{
}
Option::Option(int newID, char* newText){
id = newID;
text = newText;
}
Option::~Option(void)
{
}
char* Option::getText(){
return text;
}
int Option::getID(){
return id;
}
shared_ptr<Room> Option::getRoom(){
shared_ptr<Room> room(new Room());
return room;
//note that this function will never be used. I'd prefer to
//pass back a null pointer but I couldn't do that either.
}
RoomOption.h:
#pragma once
#include "Option.h"
#include "Room.h"
#include <memory>
using namespace std;
class RoomOption :
public Option
{
private:
shared_ptr<Room> room;
public:
RoomOption(void);
RoomOption(int, char*, shared_ptr<Room>);
~RoomOption(void);
void setRoom(shared_ptr<Room>);
shared_ptr<Room> getRoom();
};
RoomOption.cpp:
#include "RoomOption.h"
#include "Room.h"
#include <memory>
using namespace std;
RoomOption::RoomOption(void)
{
}
RoomOption::RoomOption(int newID, char* newText, shared_ptr<Room> newRoom)
{
id = newID;
strcpy(text, newText);
room = newRoom;
}
RoomOption::~RoomOption(void)
{
}
void RoomOption::setRoom(shared_ptr<Room> newRoom){
room = newRoom;
}
shared_ptr<Room> RoomOption::getRoom(){
return room;
}
This code compiles without error at /W4 /WX with VS 2010:
#include <memory>
struct Room {};
class Option {
public:
std::shared_ptr<Room> getRoom();
};
std::shared_ptr<Room> Option::getRoom(){
std::shared_ptr<Room> room(new Room());
return room;
}
int main() {
Option opt;
std::shared_ptr<Room> room = opt.getRoom();
return 0;
}
What are you doing differently?
Is Room declared at the point where it's used in the getRoom() call in Option.hpp?
Have you tried removing the () from new Room() in case you're somehow getting hit by the most vexing parse, possibly in other code we can't see??
Related
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.
can sombody explain to me why my code will not work, and how to fix it thanks :)
I keep recieving this error :
no 'int burrito::setName()' member function declared in class 'burrito'
My goal is to call a function from a different class file
My main.cpp :
#include <iostream>
#include "burrito.h"
using namespace std;
int main()
{
burrito a;
a.setName("Ammar T.");
return 0;
}
My class header (burrito.h)
#ifndef BURRITO_H
#define BURRITO_H
class burrito
{
public:
burrito();
};
#endif // BURRITO_H
My class file (burrito.cpp):
#include "burrito.h"
#include <iostream>
using namespace std;
burrito::setName()
{
public:
void setName(string x){
name = x;
};
burrito::getName(){
string getName(){
return name;
};
}
burrito::variables(string name){
string name;
};
private:
string name;
};
Your code is a mess. You need to write function prototypes in the header file and function definitions in the cpp file. You are missing some basic coding structures. See below and learn this pattern of coding:
This code should work and enjoy burritos !
main():
#include <iostream>
#include "Header.h"
int main()
{
burrito a;
a.setName("Ammar T.");
std::cout << a.getName() << "\n";
getchar();
return 0;
}
CPP file:
#include "Header.h"
#include <string>
void burrito::setName(std::string x) { this->name = x; }
std::string burrito::getName() { return this->name; }
Header file:
#include <string>
class burrito
{
private:
std::string name;
public:
void setName(std::string);
std::string getName();
//variables(string name) {string name;} // What do you mean by this??
};
Your poor little burrito is confused. Confused burritos can't help much.
You may want your burrito declaration as:
class Burrito
{
public:
Burrito();
void set_name(const std::string& new_name);
std::string get_name() const;
private:
std::string name;
};
The methods could be defined in the source file as:
void
Burrito::set_name(const std::string& new_name)
{
name = new_name;
}
std::string
Burrito::get_name() const
{
return name;
}
The header file only has a constructor for the class. The member functions
setName(string) and getName()
are not declared in the header file and that is why you get the error.
Also, you need to specify the return type for functions.
One way to do this would be
//Header
//burrito.h
class burrito{
private:
string burrito_name;
public:
burrito();
string getName();
void setName(string);
}
//burrito.cpp
#include "burrito.h"
#include <iostream>
using namespace std;
string burrito::getName()
{
return burrito_name;
}
void burrito::setName(string bname)
{
bname =burrito_name;
}
This is a simple example for class in C++,
Save this in burrito.cpp file then compile and run it:
#include <iostream>
#include <string>
using namespace std;
class burrito {
public:
void setName(string s);
string getName();
private:
string name;
};
void burrito::setName(string s) {
name = s;
}
string burrito::getName() {
return name;
}
int main() {
burrito a;
a.setName("Ammar T.");
std::cout << a.getName() << "\n";
return 0;
}
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)
{
// ...
}
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++;
}
I've got a third party library named person.lib and its header person.h. This is my actual project structure and it compiles and runs perfectly.
Actual Structure:
main.cpp
#include <iostream>
#include <time.h>
#include <ctype.h>
#include <string>
#include "person.h"
using namespace person;
using namespace std;
class Client : public Person
{
public:
Client();
void onMessage(const char * const);
private:
void gen_random(char*, const int);
};
Client::Client() {
char str[11];
gen_random(str, 10);
this->setName(str);
}
void Client::onMessage(const char * const message) throw(Exception &)
{
cout << message << endl;
}
void Client::gen_random(char *s, const int len) {
//THIS FUNCTION GENERATES A RANDOM NAME WITH SPECIFIED LENGTH FOR THE CLIENT
}
int main()
{
try
{
Person *p = new Client;
p->sayHello();
}
catch(Exception &e)
{
cout << e.what() << endl;
return 1;
}
return 0;
}
I want to refactor my code by dividing the declaration of my Client class from its definition and create client.h and client.cpp. PAY ATTENTION: sayHello() and onMessage(const * char const) are functions of the person library.
Refactored Structure:
main.cpp
#include <iostream>
#include "client.h"
using namespace person;
using namespace std;
int main()
{
try
{
Person *p = new Client;
p->sayHello();
}
catch(Exception &e)
{
cout << e.what() << endl;
return 1;
}
return 0;
}
client.cpp
#include "client.h"
using namespace person;
using namespace std;
Client::Client() {
char str[11];
gen_random(str, 10);
this->setName(str);
}
void Client::onMessage(const char * const message) throw(Exception &)
{
cout << message << endl;
}
void Client::gen_random(char *s, const int len) {
//THIS FUNCTION GENERATES A RANDOM NAME WITH SPECIFIED LENGTH FOR THE CLIENT
}
client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <time.h>
#include <ctype.h>
#include <string>
#include "person.h"
class Client : public Person
{
public:
Client();
void onMessage(const char * const);
private:
void gen_random(char*, const int);
};
#endif
As you can see, I've simply created a client.h in which there's the inclusion of the base class person.h, then I've created client.cpp in which there's the inclusion of client.h and the definitions of its functions. Now, the compilation gives me these errors:
error C2504: 'Person': base class undefined client.h 7 1 Test
error C2440: 'inizialization': unable to convert from 'Client *' to 'person::impl::Person *' main.cpp 15 1 Test
error C2504: 'Person': base class undefined client.h 7 1 Test
error C2039: 'setName': is not a member of 'Client' client.cpp 8 1 Test
error C3861: 'sendMessage': identifier not found client.cpp 34 1 Test
It's a merely cut© refactoring but it doesn't work and I really don't understand WHY! What's the solution and why it gives me these errors? Is there something about C++ structure that I'm missing?
Here's a dog-n-bird implementation (ruff ruff, cheep cheep)
cLawyer is defined and implemented in main.cpp, while cPerson and cClient are defined in their own header files, implemented in their own cpp file.
A better approach would store the name of the class. Then, one wouldn't need to overload the speak method - one could simply set the className in each derived copy. But that would have provided in my estimates, a less useful example for you.
main.cpp
#include <cstdio>
#include "cClient.h"
class cLawyer : public cPerson
{
public:
cLawyer() : cPerson() {}
~cLawyer() {}
void talk(char *sayWhat){printf("cLawyer says: '%s'\n", sayWhat);}
};
int main()
{
cPerson newPerson;
cClient newClient;
cLawyer newLawyer;
newPerson.talk("Hello world!");
newClient.talk("Hello world!");
newLawyer.talk("Hello $$$");
return 0;
}
cPerson.h
#ifndef cPerson_h_
#define cPerson_h_
class cPerson
{
public:
cPerson();
virtual ~cPerson();
virtual void talk(char *sayWhat);
protected:
private:
};
#endif // cPerson_h_
cPerson.cpp
#include "cPerson.h"
#include <cstdio>
cPerson::cPerson()
{
//ctor
}
cPerson::~cPerson()
{
//dtor
}
void cPerson::talk(char *sayWhat)
{
printf("cPerson says: '%s'\n",sayWhat);
}
cClient.h
#ifndef cClient_h_
#define cClient_h_
#include "cPerson.h"
class cClient : public cPerson
{
public:
cClient();
virtual ~cClient();
void talk(char *sayWhat);
protected:
private:
};
#endif // cClient_h_
cClient.cpp
#include "cClient.h"
#include <cstdio>
cClient::cClient()
{
//ctor
}
cClient::~cClient()
{
//dtor
}
Output
cPerson says: 'Hello world!'
cClient says: 'Hello world!'
cLawyer says: 'Hello $$$'
Suggestions noted above:
//In the cPerson class, a var
char *m_className;
//In the cPerson::cPerson constructer, set the var
m_className = "cPerson";
//Re-jig the cPerson::speak method
void cPerson::speak(char *sayWhat)
{
printf("%s says: '%s'\n", m_className, sayWhat);
}
// EDIT: *** remove the speak methods from the cClient and cLawyer classes ***
//Initialize the clas name apporpriately in derived classes
//cClient::cClient
m_className = "cClient";
//Initialize the clas name apporpriately in derived classes
//cLaywer::cLaywer
m_className = "cLawyer";
You are declaring the class Client twice - once in the .h file and once in .cpp. You only need to declare it in the .h file.
You also need to put the using namespace person; to the .h file.
If class Person is in namcespace person, use the person::Person to access it.
The client.cpp must contain definitions only!
I think for the linker the class Client defined in client.h and class Client defined in client.cpp are different classes, thus it cannot find the implementation of Client::Client(). I purpose to remove the declaration of class Client from the client.cpp and leave there only definitions of functions:
// client.cpp
#include <time.h>
#include <ctype.h>
#include <string>
#include "client.h"
using namespace std;
Client::Client()
{
//DO STUFF
}
void Client::onMessage(const char * const message)
{
//DO STUFF
}
void Client::gen_random(char *s, const int len) {
//DO STUFF
}