This question already has an answer here:
What exactly is One Definition Rule in C++?
(1 answer)
Closed 4 years ago.
I am working on a program that simulates a game of GoFish. I have a weird error that is making it difficult to make any progress. I get the following error when building "error: redefinition of 'Player'." I have looked at various websites regarding the error, but it seems as if all of the code includes the cpp in the header and the header in the cpp. However, mine does not.
Here is the .cpp file:
#include "player.h"
Player::Player(){
myName = "";
}
Player::Player(string name) {
myName = name;
}
string Player::getName() const {
return myName;
}
I have excluded the methods which aren't giving errors.
Additionally, here is the .h file:
#ifndef UNTITLED3_PLAYER_H
#define UNTITLED3_PLAYER_H
#include <iostream>
#include <string>
#include <vector>
#include "card.h"
using namespace std;
class Player
{
public:
Player();
Player(string name) {
myName = name;
}
string getName() const {
return myName;
}
void addCard(Card c); //adds a card to the hand
void bookCards(Card c1, Card c2);
bool checkHandForBook(Card &c1, Card &c2);
bool rankInHand(Card c) const;
Card chooseCardFromHand() const;
bool cardInHand(Card c) const;
Card removeCardFromHand(Card c);
string showHand() const;
string showBooks() const;
int getHandSize() const;
int getBookSize() const;
private:
vector <Card> myHand;
vector <Card> myBook;
string myName;
};
#endif
The only two function which are getting redefinition errors are the constructor and getName. What could be causing this?
You've included the entire constructor and getName() function in the header and in the .cpp file. They should only exist in one or the other.
Related
This question already has answers here:
How do I write setters and getters for an array? (c++)
(3 answers)
Closed 3 years ago.
I'm trying to represent a Course with Students. The Students have information about their first and last names, age... And the Courses have a name and an array of 3 Students.
I'm getting an error when I try to define the getters and setters for the array.
Error (active) E0415 no suitable constructor exists to convert from "Student [3]" to "Student"
Error (active) E0137 expression must be a modifiable lvalue
Course.h
#pragma once
#include "Student.h"
#include "Teacher.h"
class Course
{
private:
string name;
Student students[3];
Teacher teacher;
public:
Course();
~Course();
void setName(string name);
string getName();
void setStudents(Student students[3]);
[3] Student getStudents();
};
Course.cpp
#include <iostream>
#include "Course.h"
#include "Student.h"
#include "Teacher.h"
using namespace std;
Course::Course() {}
Course::~Course()
{
}
void Course::setName(string name)
{
this->name = name;
}
string Course::getName()
{
return this->name;
}
void Course::setStudents(Student students[3])
{
/*for (int i = 0; i < 3; i++) {
this->students[i] = students[i];
}*/
//This way the set works
this->students = students;
}
[3]Student Course::getStudents()
{
return this->students;
}
I expect the output of the get to be the array of students.
A C style array cannot be copied, cannot be automatically assigned, and cannot be returned from a function.
Thankfully, the C++ standard library provides a thin wrapper class over C style arrays which implement all these operations. It’s called std::array and it can be used exactly like you’re trying to use C-style arrays.
#pragma once
#include "Student.h"
#include "Teacher.h"
#include <array>
class Course
{
private:
string name;
std::array<Student, 3> students;
Teacher teacher;
public:
Course();
~Course();
void setName(string name);
string getName();
void setStudents(std::array<Student, 3> students);
std::array<Student, 3> getStudents();
};
My first ever c++ program and i cant seem to figure out why it says that my 'object' was not declared in the scope. I've included the header files, i've prototyped my functions. i'm used to coding in java and the separation is pretty confusing to me.
The aim of the program is simple: create a class: Semester.
Semester: will have ID, name, credit, marks.
provide get/set methods to input and output from kb
Main
#include <iostream>
#include <stdio.h>
#include "Semester.h"
using namespace std;
int main()
{
Semester s1;
cout << "Please enter ID" << endl;
cin >> sl.setid();
cout << "ID: " << s1.getid();
}
cpp
#include <stdio.h>
#include <iostream>
#include "Semester.h"
using namespace std;
Semester::Semester(){
}
//setters
void Semester::setid(string t_id) {id = t_id;}
void Semester::setunit(string t_name) {unit_name = t_name;}
void Semester::setcredit(int t_credit){credit = t_credit;}
void Semester::setmark(int t_marks) {marks = t_marks;}
//getters
string Semester::getid() {return id;}
string Semester::getunit() {return unit_name;}
int Semester::getcredit() {return credit;}
int Semester::getmark() {return marks;}
header
#ifndef SEMESTER_H
#define SEMESTER_H
#include <stdio.h>
#include <iostream>
class Semester{
private: //variables
std::string id;
std:: string unit_name;
int credit, marks;
public:
Semester(); //constructor
//setters
void setid(std::string id);
void setunit(std::string name);
void setcredit(int credit);
void setmark(int marks);
//getters
std::string getid();
std::string getunit();
int getcredit();
int getmark();
};
#endif // SEMESTER_H
The following line is incorrect.
cin >> sl.setid();
Problems with that line:
You are calling a function that expects an argument with no arguments.
The return type of setid() is void. That cannot be used as the RHS of the stream extraction function.
What you need is:
std::string id;
cin >> id;
s1.setid(id);
Suggestion for improvement: Make all the get functions const member functions.
//getters
std::string getid() const;
std::string getunit() const;
int getcredit() const;
int getmark() const;
Make sure to update the .cpp file accordingly.
I'm trying to simply use a vector within one of my classes. When trying to access the vector it tells me that it's undefined (but I've defined it in my header).
I have two classes, Person and Dog. A person can own one or more dogs so I want to add each dog a person owns into an array. This should be real simple so this problem is really starting to get to me. Here's some code:
The class Person.cpp:
#include "Person.h"
#include "stdafx.h"
#include <iostream>
using namespace std;
Person::Person(string name, string address, int age)
:name(name),
address(address),
age(age)
{}
int Person::getAge(){
return age;
}
std::string Person::getDogInfo(int index){
}
void Person::addDog(string dogName, string breed){
dogCollection.push_back(Dog(dogName, breed));
}
std::vector<Dog> getDogs(){
return dogCollection; //dogCollection undefined error here
}
And here's Person.h:
#ifndef Person_H
#define Person_H
#include <vector>
#include "Dog.h"
using namespace std;
class Person{
public:
Person(string name, string address, int age);
string getName(){return name};
string getAddress(){return address};
void addDog(string dogName, string breed);
string getDogInfo(int index);
std::vector<Dog> getDogs();
int getAge();
private:
string name;
string address;
int age;
std::vector<Dog> dogCollection;
};
#endif
If you want to have a look at my dog classes I'll paste them as well:
Dog.cpp:
#include "stdafx.h"
#include <iostream>
#include "dog.h"
Dog::Dog(string dogName, string breed)
:dogName(dogName),
breed(breed){}
std::string Dog::Dog.getDogName(){
return dogName;
}
std::string Dog::Dog.getBreed(){
return breed;
}
and Dog.h:
#ifndef Dog_H
#define Dog_H
#include <iostream>
using namespace std;
class Dog{
public:
Dog(std::string dogName, std::string breed);
std::string getDogName();
std::string getBreed();
private:
std::string dogName;
std::string breed;
};
#endif
Also, I just want to add that this is no homework. I'm used to java and I'm only trying to learn some C++ since I need it for future work.
EDIT: Updated the code
std::vector<Dog> dogCollection; // here im defining dogCollection, no error here!
There actually is an problem here - class Dog isn't known to the compiler at this point.
You can solve this by either including Dog.h before Person.h in Person.cpp, or better add an #include "Dog.h" at the top of Person.h.
This is incorrect (and unrequired):
dogCollection = new std::vector<Dog>; // Remove this line.
as dogCollection is not a std::vector<Dog>*.
This is also incorrect:
void Person::addDog(string dogName, string breed){
Dog *newDog = new Dog(dogName, breed);
dogCollection.push_back(newDog);
}
as dogCollection contains Dog instances, not Dog*. Change to:
void Person::addDog(string dogName, string breed){
dogCollection.push_back(Dog(dogName, breed));
}
There is a problem with all of constructors:
Person::Person(string name, string address, int age){
name=name;
address=address;
age=age;
}
This is assigning the argument name to itself: it is not assigning to the member name. Same for address and age and similarly for the constructors of the other classes. Use initializer list:
Person::Person(string name, string address, int age) :
name(name),
address(address),
age(age)
{}
This method does not return a std::string:
string Person::getDogInfo(int index){
}
EDIT:
Missing class qualifier:
std::vector<Dog> getDogs(){
return dogCollection; //dogCollection undefined error here
}
means this is just a free function, with no association to class Person and therefore no access to dogCollection.
Change to:
std::vector<Dog> Person::getDogs(){
return dogCollection;
}
There are several problems with your code, and most of the other answers have pointed them out - mostly regarding the use of new when it should not be used. (Are you a C# programmer, moving to C++?)
However, there are problems with the #include directives as well. As #Bo mentioned, since Person uses Dog, you should include that header in Person.h. But Person also uses vector so that header should be included there as well. So Person.h should start with...
#include <vector>
#include "Dog.h"
Then in Person.cpp you don't have to include those files.
As a general rule (you can learn about "forward declaration" later), any types referenced in a header should be #included in that header.
Why gcc cannot compile successful of the codes below?
Can the constructor be defined out of the class?
#include <string>
using std::string;
class Person{
public:
Person(const string &a, const string &b);
private:
string name, address;
};
Person::Person(const string &a, const string &b){
name(a);
address(b);
}
Thanks!
Because neither name nor address are callable. You probably meant to put them into a member-initializer-list.
Person::Person(const string &a, const string &b)
: name(a), address(b)
{
}
Your syntax is wrong:
Person::Person(const string &a, const string &b) : name(a), address(b) {}
You just wrote it wrong. It should be:
Person::Person(const string &a, const string &b) : name(a), address(b) { }
In principle, and very much in practice, too, you can and should define member functions outside the class definition to decouple the code base and reduce compile times.
This is called separation of implementation and declaration. It is actually a good idea to keep your implementations separately, in a cc or cpp file.
Thus, in your header:
//Person.h
#ifndef PERSON_H // <---- include header guards in your headers
#define PERSON_H
#include <string>
//using std::string; <--- you should remove this line, you don't want to import namespaces
// in your header file, or else they are imported in all
// files including this header
class Person{
public:
Person(const std::string &a, const std::string &b);
private:
std::string name, address; // qualify your names in the header
};
#endif
and your implementation file:
//Person.cpp
#include "Person.h"
using namespace std; // <---- if you wish, import the std namespace in your global namespace
// in the implementation file
Person::Person(const string &a, const string &b):
name(a), // <---- correct syntax of initializer lists
address(b)
{
}
I've these 2 files, but the interface (and the compiler) give me this error, can you help me find what is wrong?Is really strange... should I define all body of my methods in the .cpp file?
//GameMatch.h
#pragma once
#include "Player.h"
namespace Core
{
class GameMatch
{
private:
const static unsigned int MAX_PLAYERS=20;
unsigned int m_HumanControlled;
Score* m_LastDeclaredScore;
Score* m_LastScore;
unsigned int m_MaxPlayers;
Player* m_Players[MAX_PLAYERS];
unsigned int m_PlayerTurn;
inline void NextTurn() { m_PlayerTurn=(m_PlayerTurn+1U)%m_MaxPlayers; }
public:
GameMatch(void);
~GameMatch(void);
void RemovePlayer(Player* _player);
inline Player* getPlayingPlayer() { return m_Players[m_PlayerTurn]; }
};
}
and
//Player.h
#pragma once
#include "IController.h"
#include "GameMatch.h"
#include <string>
#include <Windows.h>
using namespace Core::Controller;
using namespace std;
namespace Core
{
class Player
{
private:
IController* m_Controller;
unsigned int m_Lives;
GameMatch* m_GameMatch;
string m_Name;
bool m_TurnDone;
public:
inline void Die()
{
m_Lives-=1U;
if (m_Lives<1) m_GameMatch->RemovePlayer(this);//m_GameMatch is the first error
}
inline const string& getName() { return m_Name; }
inline bool IsPlayerTurn() { return (m_GameMatch->getPlayingPlayer()==this); }//m_GameMatch is the second error
virtual void Play()=0;
inline Player(GameMatch* _gameMatch,const char* name,unsigned int lives=3)
{
m_GameMatch=_gameMatch;
m_Name=name;
m_Lives=lives;
}
inline void WaitTurn() { while(!IsPlayerTurn()) Sleep(1); }
virtual ~Player()
{
delete m_Controller;
}
};
}
But as you can see, m_GameMatch is a pointer, so I don't understand why this error, maybe for "recursive inclusion" of header files...
UPDATE 1:
//GameMatch.h
#pragma once
#include "Score.h"
#include "Player.h"
namespace Core
{
class GameMatch
{
private:
const static unsigned int MAX_PLAYERS=20;
unsigned int m_HumanControlled;
Score* m_LastDeclaredScore;
Score* m_LastScore;
unsigned int m_MaxPlayers;
Player* m_Players[MAX_PLAYERS];
unsigned int m_PlayerTurn;
inline void NextTurn();
public:
GameMatch(void);
~GameMatch(void);
void RemovePlayer(Player* _player);
inline Player* getPlayingPlayer();
};
}
and
//Player.h
#pragma once
#include "IController.h"
#include "GameMatch.h"
#include <string>
#include <Windows.h>
using namespace Core::Controller;
using namespace std;
namespace Core
{
class Player
{
private:
IController* m_Controller;
unsigned int m_Lives;
GameMatch* m_GameMatch;
string m_Name;
bool m_TurnDone;
public:
inline void Die();
inline const string& getName();
inline bool IsPlayerTurn();
virtual void Play()=0;
inline Player(GameMatch* _gameMatch,const char* name,unsigned int lives=3);
inline void WaitTurn();
virtual ~Player();
};
}
These are the 2 headers now, however it's still not working, if I don't include Player.h and forward declare a class in this way inside GameMatch.h:
class Player;
It works, however what if I want use some Player methods?I should re-forward declare everything... isn't this what header files are done for? I can include an header file in a lot of places... why can't I do it in this case?
SOLUTION:
The answer is from Alf P. Steinbach on chat:
yes, and the answer you got seems to be correct. the cyclic header dependency is a problem. there might be other problems also, but the cyclic dependency is a big one.
you don't need a full definition of a class in order to use T*.
so the usual breaking of the cycle is to just forward-declare a class, like
class Player;
that tells the compiler that Player is a class, so you can use Player* and Player&, and even declare member functions that return Player (although you can't define such a function until Player class is fully defined)
well as a concrete example, all that's needed for the Core::GameMatch class definition is a forward declaration of class Player.
then in implementation file you can include "player.h".
if it's needed for GameMatch implementation.
if you draw the files as little boxes and draw arrows to show includes, you'll see that that gets rid of the cyclic dependency
This said, he explain that the answer I got is the correct one so I'll mark OJ's
You should definitely avoid the cyclic header include.
Break the content of your functions out into .cpp files instead of putting everything in header files. Also, rather than #include things every time, just forward declare instead.
If you remove the cyclic include, your code will most likely work.