I've got error "redefinition of class Book". Thats my code:
Book.cpp
#include "Book.h"
using namespace std;
class Book {
string author, title;
public:
Book()
{
cout<<"Book()"<<endl;
author = "-";
title = "-";
}
Book(const string& autor, const string& tytul)
{
cout<<"Book(const string& autor, const string& tytul)"<<endl;
author = autor;
title = tytul;
}
Book(string&& autor, string&& tytul)
{
cout<<"Book(Book&& autor, Book&& tytul)"<<endl;
author=autor;
title=tytul;
}
Book(const Book& other)
:author(other.author),title(other.title)
{
cout<<"Book(const Book& other)"<<endl;
}
string GetAuthor()
{
return author;
}
string GetTitle()
{
return title;
}
void SetAuthor(const string &autor)
{
cout<<"Setter ze stalymi l-ref"<<endl;
author=autor;
}
void SetTitle(const string &tytul)
{
cout<<"Setter ze stalymi l-ref"<<endl;
title=tytul;
}
void SetAuthor(string &&autor)
{
cout<<"Setter r-ref"<<endl;
author=autor;
}
void SetTitle(string &&tytul)
{
cout<<"Setter r-ref"<<endl;
title=tytul;
}
//OPERATORY
Book& operator=(const Book& right)
{
cout<<"Book& operator=(const Book& right)"<<endl;
Book tmp = right;
swap(author,tmp.author);
swap(title,tmp.title);
return *this;
}
Book& operator=(Book&& right)
{
cout<<"Book& operator=(Book&& right)"<<endl;
swap(author,right.author);
swap(title,right.title);
return *this;
}
};
Book.h
#include <string>
using namespace std;
class Book {
string author, title;
public:
Book();
Book(const string& autor, const string& tytul);
Book(string&& autor, string&& tytul);
Book(const Book& other);
string GetAuthor();
string GetTitle();
void SetAuthor(const string &autor);
void SetTitle(const string &tytul);
void SetAuthor(string &&autor);
void SetTitle(string &&tytul);
//OPERATORY
Book& operator=(const Book& right);
Book& operator=(Book&& right);
};
SOLUTIONS: after time, I can see few problems:
Never add using namespace std; in header files (namespace in header files)
cpp file should define methods from header file
declare class in header file and implement in cpp file
class template thats how class should looks like
when you want to define method from header file do this in proper way: ClassName::method_type method_name (){...}
The preprocessor which handles header files and the #include directive basically copy-pastes the header file into the place of the #include directive.
That means the compiler will see this in your source file:
class Book { ... };
class Book { ... };
You can't define a class multiple times like this.
Instead only define the class in the header file (and remember to add header include guards), and then the source file defines (implements) the functions only.
So beyond adding include guards, keep the header file as it is. Then change the source file to something similar to this:
#include "Book.h"
Book::Book()
{
cout<<"Book()"<<endl;
author = "-";
title = "-";
}
// ...
std::string Book::GetAuthor()
{
return author;
}
// ... And so on, doing the same with all other functions
Related
I managed to fix the error two different ways but I honestly don't know why it works. Can someone here please provide some clarification?
As is, the following code gives me the following errors
Error LNK2005 "public: __thiscall Person::Person(class std::basic_istream<char,struct std::char_traits<char> > &)" (??0Person##QAE#AAV?$basic_istream#DU?$char_traits#D#std###std###Z) already defined in Person_Functions.obj
Error LNK1169 one or more multiply defined symbols found
Program:
//**************
//Person_Class.h
//**************
#ifndef PERSON_CLASS_H
#define PERSON_CLASS_H
#include <iostream>
#include <string>
using namespace std;
struct Person {
string name;
string address;
string getName() const { return name; }
string getAddress() const { return address; }
Person() = default;
Person(string n, string a) : name(n), address(a) {}
Person(istream& is);
};
ostream& print(ostream&, const Person&);
istream& read(istream&, Person&);
Person::Person(istream& is) { read(is, *this); }
#endif
//********************
//Person_Functions.cpp
//********************
#include "Person_Class.h"
istream& read(istream& is, Person& p) {
is >> p.name >> p.address;
return is;
}
ostream& print(ostream& os, const Person& p) {
os << p.getName() << " " << p.getAddress();
return os;
}
If I write the header like this instead, the errors go away
//**************
//Person_Class.h
//**************
#ifndef PERSON_CLASS_H
#define PERSON_CLASS_H
#include <iostream>
#include <string>
using namespace std;
//This seems like a "duct tape" fix, feels messy and unorganized.
struct Person;
istream& read(istream&, Person&);
struct Person {
string name;
string address;
string getName() const { return name; }
string getAddress() const { return address; }
Person() = default;
Person(string n, string a) : name(n), address(a) {}
Person(istream& is) { read(is, *this); }
//Defining istream constructor in the class definition fixes the issue
//but as you can see above, this forces me to declare read above the struct
//which means I have to then declare the struct above read
};
ostream& print(ostream&, const Person&);
#endif
//This uses the same Person_Functions.cpp as before
The other solution I found is to instead define the istream constructor inside Person_Functions.cpp
I am really confused about why the first version doesn't work. Is there a preferred way to handle this and can someone provide some clarification here on the differences?
Sorry for the long post. I wasn't sure how much detail to include. Thanks for taking the time to teach me!
I have most of this working I am struggling with syntax errors on the employee.h
here are all 3 of the headers
Address.h
#pragma once
#include <string>
using namespace std;
class Address
{
public:
explicit Address();
explicit Address(const string& city, const string& state,
const string& street, const string& zip);
const string& getCity() const;
const string& getState() const;
const string& getStreet() const;
const string& getZip() const;
void printAddress() const;
private:
string street;
string city;
string state;
string zip;
};
Address::Address() :
city("Beverly Hills,"),
state("CA,"),
street("99999 Sunset Boulevard,"),
zip("99999")
{ }
Address::Address(const string& city, const string& state,
const string& street, const string& zip) :
city(city), state(state), street(street), zip(zip)
{ }
const string& Address::getCity() const
{
return city;
}
const string& Address::getState() const
{
return state;
}
const string& Address::getStreet() const
{
return street;
}
const string& Address::getZip() const
{
return zip;
}
void Address::printAddress() const
{
std::cout << street << city << state << zip << endl;
};
Name.h
#include <string>
using namespace std;
class Name
{
public:
explicit Name();
explicit Name(const string& firstName, const string& middleName, const string& lastName);
const string& getFirstLast() const;
void printName() const;
private:
string firstName;
string middleName;
string lastName;
Name::Name() :
firstName("John"),
middleName("H."),
lastName("Doe")
{}
Name::Name(const string& firstName, const string& middleName, const string& lastName) :
firstName(firstName), lastName(lastName)
{ }
const string& Name::getFirstLast() const
{
return name;
}
void Name::printName() const
{
std::cout << firstName << middleName << lastName << endl;
}
};
Employee.H
This is where I am getting most of my errors.
#include <iostream>
#include <string>
#include "Name.h"
#include "Address.h"
using namespace std;
class Employee
{
public:
explicit Employee();
explicit Employee(const Name& name, const Address& address, const string& ssn);
const string& getName() const;
const string& getSSN() const;
const string& getAddress() const;
void printEmployee() const;
private:
Name name;
Address address;
string ssn;
};
Employee::Employee() :
name("John H. Doe"),
address("99999 Sunset Boulevard", "Beverly Hills", "CA", "99999"),
SSN("999-99-9999")
{}
Employee::Employee(const Name& name, const Address& address, const std::string& ssn) :
name(name), address(address), ssn(ssn)
{ }
const string& Employee::getName() const
{
return printName;
}
const string& Employee::getSSN() const
{
return ssn;
}
const string& Employee::getAddress() const
{
return address
}
void Employee::printEmployee() const
{
cout << Name.printName() << Address.printAddress() << ssn << std::endl;
}
Here are the instructions for the assignment
Name Header file (Name.h) will have:
A default constructor. Remember that the default constructor for Name has the following initial values: Name to "John H. Doe".
A constructor with 3 parameters: one for First name, one for Middle Name, and One for last Name.
3 private string instance variables for :First Name, Middle Name, and a last Name.
getFirstLast() function: it returns the first and middle name and last name in order
printName() function: it prints the first, middle, and last name.
Address Header File (Address.h) will have:
A default constructor. Remember that the default constructor for Address has the following initial values: Address to "99999 Sunset Boulevard" , "Beverly Hills", "CA", "99999"
4 private string instance variables for :Street, City, State, Zip
A constructor with 4 parameters: one for street, one for city, one for state, one for zip.
getCity(): it returns the City
getState(): It returns the State
getStreet(): It returns the street
getZip(): it returns the zip
printAddress(): it prints the Street, City, State, and Zip.
Employee Header File (Employee.h) will have:
3 private instance variables: One for Name (Use the Header Name from above), One for The Address (Use the Address Header from above), a string variable for the SSN.
a default constructor which initializes the SSN to "999-99-9999", Name to "John H. Doe", Address to "99999 Sunset Boulevard" , "Beverly Hills", "CA", "99999"
a constructor with 3 parameters: One for Name, one for Address, a string for SSN.
getName() function: it returns the Name of the Employee
getAddress() function : it returns the address of the Employee.
getSSN() function: it returns the SSN as a string
printEmployee() function:
print the name: Make sure you use the printName() function from Name.h
print the address: Make sure you use the printAddress() function from Address.h
prints the SSN.
Employee (Employee.cpp) class will have:
In the void main() function you would declare:
a Name n;
an Address A;
and an Employee e;
and print e using the printEmployee().
Also you need to declare:
A Name n1: Your Name
an Address a1: your own address
string ssn1: 987-65-4321
An employee e1 which has a name n1, and address A1, and ssn1.
Print e1 using printEmployee().
I tried to create a complete example for you.
You should put declarations in header *.h files.
Implementations go into the *.cpp files.
Address.h
#pragma once
#include <string>
class Address
{
public:
explicit Address();
explicit Address(const std::string& city, const std::string& state,
const std::string& street, const std::string& zip);
const std::string& getCity() const;
const std::string& getState() const;
const std::string& getStreet() const;
const std::string& getZip() const;
void printAddress() const;
private:
std::string street;
std::string city;
std::string state;
std::string zip;
};
Address.cpp
#include "Address.h"
#include <iostream>
// Default Constructor
Address::Address() :
city("Beverly Hills"),
state("CA"),
street("99999 Sunset Boulevard"),
zip("99999")
{ }
Address::Address(const std::string& city, const std::string& state,
const std::string& street, const std::string& zip) :
city(city), state(state), street(street), zip(zip)
{ }
const std::string& Address::getCity() const
{
return city;
}
const std::string& Address::getState() const
{
return state;
}
const std::string& Address::getStreet() const
{
return street;
}
const std::string& Address::getZip() const
{
return zip;
}
void Address::printAddress() const
{
// removed the endl here !
std::cout << "Address: " << street << ", " << city << ", "
<< state << ", " << zip;
};
Name.h
#pragma once
#include <string>
class Name
{
public:
explicit Name(const std::string& firstName, const std::string& lastName);
void printName() const;
private:
std::string firstName;
std::string lastName;
};
Name.cpp
#include "Name.h"
#include <iostream>
Name::Name(const std::string& firstName, const std::string& lastName) :
firstName(firstName), lastName(lastName)
{ }
void Name::printName() const
{
std::cout << "Name: " << lastName << ", " << firstName;
}
Employee.h
#pragma once
#include <string>
#include "Name.h"
#include "Address.h"
class Employee
{
public:
explicit Employee(const Name& name, const Address& address, const std::string& ssn);
void printEmployee() const;
private:
Name name;
Address address;
std::string ssn;
};
Employee.cpp
#include "Employee.h"
#include <iostream>
Employee::Employee(const Name& name, const Address& address, const std::string& ssn) :
name(name), address(address), ssn(ssn)
{ }
void Employee::printEmployee() const
{
std::cout << "Employee: ";
name.printName();
std::cout << ", ";
address.printAddress();
std::cout << ", ssn: " << ssn << std::endl;
}
Main.cpp
#include <iostream>
#include <string>
#include "Employee.h"
int main(int argc, char* argv[]) {
Address address("Cologne", "NRW", "Domplatz 1", "D-50668");
Name name("John", "Jones");
Employee employee(name, address, "123-abc-456");
employee.printEmployee();
return 0;
}
That was fun! :-)
EDIT:
I think I need to add a little explanation:
If you want to use a function or method from one cpp file in another cpp file you should seperate declaration and implementation. Actually you should always do this. Put declaration in the *.h file and implementation in *.cpp file. In the cpp file where you want to use the function include the header file where the function is declared. Then compile all cpp files to object files. And then link all the objects files together.
For example look in Employee.cpp file. There I use the print method from the Address class. Now look at the includes of the Employee.cpp file. There you see I included Employee.h which in turn includes Address.h. Including is actually just inserting the content of one file in the other. So now we have included the declaration of the Address class and methods in the Employee cpp file so it can be called from there.
Another Update
I tested the code I posted yesterday. It works fine. The problem starts because you want to change the printEmployee() method like this:
void Employee::printEmployee() const
{
cout << Name.printName() << Address.printAddress() << ssn << std::endl;
}
This will only work when the printName() and printAddress() methods do not print but rather return a string. In that case software developers often name the method ToString() or similiar. But we will leave the name as it is because we stick to the assignment of your professor.
You must change the declaration of the methods in the header files to return a string. And then you must also change the implementation in the cpp files to return a string. Here you go (not complete source code, only the changes) :
Address.h
class Address
{
public:
// .....
std::string& printAddress() const;
// .....
};
Address.cpp
// Add this new include to the others at the top of the file:
#include <sstream>
// ......
std::string& Address::printAddress() const
{
std::stringstream ss;
ss << "Address: " << street << ", " << city << ", "
<< state << ", " << zip;
return ss.str();
}
Name.h
class Name
{
public:
// .....
std::string& printName() const;
// .....
};
Name.cpp
// Add this new include to the others at the top of the file:
#include <sstream>
// ......
std::string& Name::printName() const
{
std::stringstream ss;
ss << "Name: " << lastName << ", " << firstName;
return ss.str();
}
Now you can use them in the Employee class like you wanted:
Employee.cpp
void Employee::printEmployee() const
{
std::cout << Name.printName() << Address.printAddress() << ssn << std::endl;
}
Final Edit
After I read the details of the assignment you posted, I think my first solution was good. Your Professor clearly says the printAddress() and printName() methods should print not return a string. So maybe you should consider using the code from my first solution.
I have 3 c++ files, instrument.h, percussion.h, and instrumentApp.cpp. Instrument.h is the base class and percussion.h inherits it. Percussion objects are defined and implemented in the instrumentApp.cpp class. Whenever I run instrumentApp.cpp, I get the segmentation fault error.
I have managed to trace the cause of the error to the overloaded << operator function in percussion.h where I am calling a method of the base class instrument.h. For some reason, my code is unable to call methods of the base class and I don't know why. Can you please help me?
Here is the instrument.h class
#ifndef INSTRUMENT_H
#define INSTRUMENT_H
class Instrument{
private:
std::string name;
std::string sound;
std::string lowRange;
std::string highRange;
public:
Instrument(std::string name, std::string sound, std::string lowRange, std::string highRange){
this->name = name;
this->sound = sound;
this->lowRange = lowRange;
this->highRange = highRange;
}
std::string getName() const{
return this->name;
}
std::string play()const {
return this->sound;
}
std::string getLowRange() const{
return this->lowRange;
}
std::string getHighRange() const{
return this->highRange;
}
bool isWind();
bool isWoodWind();
bool isBrass();
bool isKeyboard();
bool isPercussion();
bool isStrings();
friend std::ostream &operator <<(std::ostream &os, const Instrument &instrument){
}
};
#endif
Here is the percussion.h class
#ifndef PERCUSSION_H
#define PERCUSSION_H
#include "instrument.h"
class Percussion : public Instrument{
private:
bool struck;
public:
Percussion(std::string name, std::string sound, std::string lowRange, std::string highRange, bool struck) : Instrument(name,sound,lowRange,highRange){
this->struck=struck;
}
bool isStrucked() const {
return this->struck;
}
bool isPercussion() {
return true;
}
std::string getType() const{
if(this->struck){
return "struck";
}
else{
return "";
}
}
friend std::ostream &operator <<(std::ostream &os, Percussion &percussion){
//The error stems from this line of code
//Apparently, the getName() method in the base class isn't called
os<<percussion.getName();
}
};
#endif
Here is the implementation file instrumentApp.cpp
#include <iostream>
#include <string>
#include <sstream>
#include <cstdlib>
#include "instrument.h"
#include "percussion.h"
#include "strings.h"
using namespace std;
int main() {
Percussion timpani("timpani", "boom", "D2", "A2", true);
cout << timpani << endl;
Percussion harp("harp", "pling", "Cb1", "F#7", false);
cout << harp << endl;
return 0;
}
The problem here is that I wasn't returning the os object when I overloaded the << operator.
The fix is as follows in the percussion.h file
friend std::ostream &operator <<(std::ostream &os, Percussion &percussion){
os<<percussion.getName();
return os;
}
I got two classes, one named Person that I checked is working (I can create objects of that class so the problem should not be here).
I then have another class called Family with composition from Person:
Family.h
#include "Person.h"
class Family
{
public:
Family();
void printFamily();
private:
Person dad_();
Person mum_();
Person son_();
Person daughter_();
};
Family.cpp
#include "Family.h"
Family::Family()
{
}
void printFamily()
{
dad_.printAll();
mum_.printAll();
son_.printAll();
daughter_.printAll();
//printAll() is a function in the Person class that worked when
//I tested it earlier with only the person class
}
But when i try to compile this I get an error:
left of '.printAll' must have class/struct/union
'son_' : undeclared identifier
This error goes for all the .printAll() calls in family.cpp.
I can't see why this wouldn't work, so I hope you can.
Edit1:
Ok i changed
void printFamily()
to
void Family::printFamily()
That removes one error, but i still get
left of '.printAll' must have class/struct/union
Edit2
Ah my bad with the Person calls i changed them to
Person dad_;
and the same with the rest.
Seems like their might be an error with my Person class so i will post that also
Person.h
#include <string>
using namespace std;
class Person
{
public:
Person( const string & = "000000-0000", const string & = "N", const string & = "",const string & = "N");
~Person();
void setFirstName(const string &);
void setMiddleName(const string &);
void setLastName(const string &);
void getData(string &,string &,string &,string &);
static int getNumberOfPersons();
void printPartially() const;
void printAll() const;
bool checkForSameName(const Person &);
private:
string firstName_;
string middleName_;
string lastName_;
string socialSecNumber_;
static int numberOfPersons_;
};
Person.cpp
#include "Person.h"
#include <iostream>
int Person::numberOfPersons_ = 0;
Person::Person( const string &sNumber, const string &firstName, const string &middleName,const string &lastName )
:firstName_(firstName),middleName_(middleName),lastName_(lastName),socialSecNumber_(sNumber)
{
numberOfPersons_ ++;
}
Person::~Person()
{
numberOfPersons_--;
}
void Person::setFirstName(const string &firstName)
{ firstName_ = firstName; }
void Person::setMiddleName(const string &middleName)
{ middleName_ = middleName; }
void Person::setLastName(const string &lastName)
{lastName_ = lastName;}
void Person::getData(string &fName,string &mName,string &lName,string &sNumber)
{
fName = firstName_;
mName = middleName_;
lName = lastName_;
sNumber = socialSecNumber_;
}
int Person::getNumberOfPersons()
{
return numberOfPersons_;
}
void Person::printPartially() const
{
cout <<"Navn: "<<firstName_<<" "<<middleName_<<" "<<lastName_<<endl;
cout <<"Født: ";
for (int i = 0;i<6;i++)
{
cout <<socialSecNumber_.at(i);
}
}
void Person::printAll() const
{
cout <<"Navn: "<<firstName_<<" "<<middleName_<<" "<<lastName_<<endl;
cout <<"Personnr: "<<socialSecNumber_<<endl;
}
bool Person::checkForSameName(const Person &p)
{
if (p.firstName_ == firstName_ && p.middleName_ ==middleName_ && p.lastName_ == lastName_)
return true;
else
return false;
}
Now i am getting some new errors:
error C2011: 'Person' : 'class' type redefinition
see declaration of 'Person'
'Family::dad_' uses undefined class 'Person'
The "dad" error applies to the whole family
You have a few syntax issues.
First, you're declaring each of what are supposed to be member variables as functions which return Person. They should look like (note, no parens):
Person dad_;
Person mum_;
Person son_;
Person daughter_;
You're also missing the scoping on your definition of printFamily:
void Family::printFamily() {
...
}
Without the preceding Family::, C++ thinks you're defining a free function, and doesn't know to look inside the Family class for the declarations of dad_, mum_, etc.
Additionally, at least with the code you've shown, there's no way to initialize the people in your class. The Family constructor should take arguments to define the people, or you should have setters which allow defining them later. Right now, you'll get 4 identical people, set up however the default person constructor builds them.
I would normally prefer the constructor method, but I have other design reservations about your code to begin with (e.g. Does a family always contain mum, dad, brother, sister?) and that's not really what this question is about.
The line:
Person dad_();
says that dad_ is a function that returns a Person, not an object. Did you mean that? Similarly for others.
Try
Person dad_;
Family.h
#include "Person.h"
class Family
{
public:
Family();
void printFamily();
private:
Person dad_;
Person mum_;
Person son_;
Person daughter_;
};
Family.cpp
#include "Family.h"
Family::Family()
{
}
void Family::printFamily()
{
dad_.printAll();
mum_.printAll();
son_.printAll();
daughter_.printAll();
//printAll() is a function in the Person class that worked when
//I tested it earlier with only the person class
}
The out of line definition of a member function needs to include the class name:
void Family::printFamily()
{
//...
Surprisingly, you already got this right for the constructor but then immediately forgot...
Second, your private class members are functions, not data members (which is odd), but if that's deliberate, you need to call them:
dad_().printAll();
// ^^^
I am currently learning about classes and am having a problem in my class implementation file.
In my class header/specification file Book.h , I have the public member function setPages.
#ifndef BOOK_H
#define BOOK_H
#include <string>
#include "Author.h"
#include "Publisher.h"
class Book
{
private:
std::string _title;
std::string _edition;
int _pages;
int _copyrightYear;
Author _author;
Publisher _publisher;
public:
Book (std::string title, Author author, Publisher publisher)
{_title = title; _author = author; _publisher = publisher;}
void setPages (int pages);
void setCopyYear (int copyrightYear);
void setEdition (std::string edition);
std::string getTitle () const;
std::string getEditon () const;
int getPages () const;
int getCopyYear () const;
Author getAuthor () const;
Publisher getPublisher () const;
};
#endif
In my Book.cpp implementation file I have
#include <string>
#include "Author.h"
#include "Publisher.h"
#include "Book.h"
void Book::setPages (int pages)
{
_pages = pages;
}
I keep getting the error that Book is not a classname or namespace but I don't see what I've done wrong. I included my Book header file and checked to make sure everything was spelled correctly in the class. I've done the same thing in my other classes and it is working so I don't see why this isn't.
Any help appreciated thanks.
Here is Publisher.h and Author.h
#ifndef PUBLISHER_H
#define PUBLISHER_H
class Publisher
{
private:
std::string _name;
std::string _address;
std::string _phoneNumber;
public:
Publisher (std::string& name)
{_name=name;}
void setAddress (std::string address);
void setNumber (std::string phoneNumber);
std::string getAddress () const;
std::string getNumber () const;
bool operator==(std::string name)
{
if (_name == name)
return true;
else
return false;
};
#endif
and Author.H
#ifndef AUTHOR_H
#define AUTHOR_H
class Author
{
private:
std::string _name;
int _numberOfBooks;
public:
Author(std::string& name)
{_name = name;}
void setNumOfBooks (int numberOfBooks);
int getNoOfBooks () const;
bool operator==(std::string _name)
{
if (this->_name == _name)
return true;
else
return false;
}
};
#endif
Until #ahenderson decides to turn his comments into an answer:
bool operator==(std::string name) in "Publisher.h" is missing a brace in your example. is that actually in your code or a copy and paste error?
bool operator==(std::string name)
{
if (_name == name)
return true;
else
return false;
Oops, no brace here!
Suggestion: Simplify your operator== method:
The expression _name == name will already return true or false. No need to put it into an if clause that returns true or false.
Try this:
bool operator==(const std::string& name)
{
return (_name == name);
}
In the above example, the expression is evaluated and the result is returned, directly.
Also, you may run into compiler issues if your variables begin with an underscore, '_'. Change your naming convention so this issue doesn't raise its ugly head. Two common practices are to append a suffix, name_, or prefixing with something like m_name.