Can the constructor be defined out of the class? - c++

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

Related

I'm newbie in c++, got unexpected error while <<operator Overloading. Could you tell me some advise?

While doing some code practice myself I got some Error
student.h file
#pragma once
class Student {
public:
Student() = default;
Student(int id, const char* name, int score);
Student(const Student& s);
Student(Student&& other);
Student& operator=(Student&& other);
virtual ~Student();
**friend std::ostream & operator<<(std::ostream & os, const Student & rhs);**
void print();
private:
int mId;
char* mName;
int mScore;
size_t mSize;
};
student.cpp file
#include "student.h"
#include <iostream>
#include <string>
... //bunch of constructors, override...
std::ostream & operator<<(std::ostream& os, const Student & rhs)
{
os << rhs.mId << rhs.mName << rhs.mScore ; // Compile Error: Cannot Access Student Member(rhs.mId, rhs.mName...)
return os;
}
The Error i got was i cannot access Student class member despite I declared it friend function in student.h
Strange to me, It compiled successfully if i declare #include<iostream> statement in student.cpp file like this
#include <iostream> //change position <iostream> and "student.h"
#include <string>
#include "student.h"
... //bunch of constructors, override...
std::ostream & operator<<(std::ostream& os, const Student & rhs)
{
os << rhs.mId << rhs.mName << rhs.mScore ; //Compile successfully
return os;
}
So, why #include statement sequences are matters? i thought #include statement just copy-paste to my cpp file.
And it also compiled successfully when i declare #include<iostream> to student.h,
so when i include some #include things the Best-case is declare it to header-file?
Could you give me some advise?
I compiled my program in Visual Studio 2019.
In student.h add an include for iosfwd:
#pragma once
#include <iosfwd>
class Student ...
This will ensure correct resolution of the std::ostream symbol and recognize the ostream operator you defined as the one you declared as a friend.
The iosfwd header contains forward declarations of the symbols in iostream header, and it is defined for exactly this scenario.
In C++ we must declare anything before using it.
So your problem is that you haven't declared std::ostream but you have used it in student.h.
An suitable solution is to #include <iostream> in the beginning of student.h, below #pragma once.
You can also put these before class Stduent:
namespace std
{
class ostream;
}
This is called forward declaration.

Redefintion Errors [duplicate]

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.

Error with const member in class

I have a class named Student with its Name and Address classes.
#ifndef ADDRESS_H
#define ADDRESS_H
//This is address class
#include <string>
class Address{
public:
Address(std::string street, std::string city, std::string state, std::string zip) :
street(street), city(city),state(state),zip(zip)
{}
std::string street,city,state,zip;
std::string aString;
aString=street+city+state+zip;
//private:
};
#endif
and the Name class is
#ifndef NAME_H
#define NAME_H
#include <iostream>
#include <string>
class Name {
friend std::ostream &operator <<(std::ostream &os, const Name &name) {
if(name.middle!="")
os << name.last << ", "<<name.middle<<" ," << name.first;
else
os<< name.last <<", "<<name.first;
return os;
}
public:
Name(std::string last, std::string middle, std::string first) : last(last), first(first),middle(middle) {}
private:
std::string last, first, middle;
};
#endif
And the Student class is like:
#ifndef PERSON_H
#define PERSON_H
#include <iostream>
#include <string>
#include "name.h"
#include "Address.h"
class Person {
friend std::ostream &operator <<(std::ostream &os, const Person &person);
public:
Person(const Name &name, int age, const Address &address);
Address address;
std::string adr=address.aString;
//private:
Name name;
int age;
};
#endif
Finally, to call them.
#include <iostream>
#include "student.h"
#include <string>
using namespace std;
Person::Person(const Name &name, int age, const Address &address) : name(name), age(age),address(address) {}
ostream &operator <<(ostream &os, const Person &person) {
os << person.name << " " << person.age<<person.adr;
return os;
}
#include <iostream>
#include "student.h"
using namespace std;
int main() {
Person p(Name("Doe","","Jane"), 21, Address("Park Ave","New York","NY","10002"));
Person p2(Name("Bane","IHateM","Jane"), 21, Address("Bay parkway","Brooklyn","NY","11223"));
cout << p<<endl;
cout<< p2<<endl;
return 0;
}
However, there are some errors during compilation.
(1) The following line is wrong based on complier, how to fix it please?
std::string adr=address.aString;
(2) In my address class, the compiler said that "string does not name a type Error", but following this Why am I getting string does not name a type Error? can't fix the problem, why is that?
Simple Solution
The simplest solution is to move your aString=street+city+state+zip; inside the Address constructor.
Do the same for your adr = ... statement (you'll still need a 'declaration' for std::string adr; within your class header).
To understand why what you wrote won't work, consider this:
When you write (within a class declaration, like in your header)
class myClass
{
int a = 5;
};
you assign a default value to the int a that you have declared - this is both declaration and (default) assignment.
When you write
class Address{
public:
Address(std::string street, std::string city, std::string state, std::string zip) :
street(street), city(city),state(state),zip(zip)
{}
std::string street,city,state,zip;
std::string aString;
aString=street+city+state+zip;
};
you're trying to give a default assignment to aString, but this is invalid code.
You could do this using
std::string aString = ...;
but not
std::string aString;
aString = ...;
because the last line is a 'statement' - something to be executed.

String class in stl c++ project

Is it possible to create String class with String.cpp and String.h in c++ stl project?
String.h
#include <string>
class String {
public:
static std::string Replace(const std::string& str, const std::string& oldValue, const std::string& newValue);
};
There are compilation errors unless the class is renamed to something else like Stringy
Instead of a class with only static members, you use a namespace in C++.
#include <string>
namespace String {
std::string Replace(const std::string& str, const std::string& oldValue, const std::string& newValue);
};
You need to remove the static from the class declaration and your posted code works just fine then.

Defining a vector within a custom class

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.