Error with const member in class - c++

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.

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;

E0349 Error while Extending istream to support a Person class

I tried with and without #include <iostream> #include <string> or even using namespace std and nothing changed. The parameters must be references. When trying to run the code I receive the following error: E0349 no operator ">>" matches these operands in line 9.
#include <iostream>
#include <string>
#include "Person.h"
#include <cstdio>
using namespace std;
//Extending istream to support the Person class
std::istream & operator>>(std::istream & is, Person & p) {
is >> p.getName() >> p.getAge();
return is;
}
//Extending ostream to support the Person class
std::ostream & operator<<(std::ostream & os, Person & p) {
os << "[" << p.getName()<<"," << p.getAge()<<"]";
}
int main() {
Person *pOne = new Person();
cout << "Person1's name is: " << pOne->getName() << endl;
cin >> *pOne;
getchar(); //Just to leave the console window open
return 0;
}
Code from Person.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Person
{
private:
string name;
short age;
public:
Person();
virtual ~Person();
Person(string, short);
string getName();
short getAge();
};
And here the code from Person.cpp:
#include "Person.h"
#include <iostream>
#include <string>
using namespace std;
Person::Person()
:name("[Unassigned Name]"), age(0)
{
cout << "Hello from Person::Person" << endl;
}
Person::~Person()
{
cout << "Goodbye from Person::~Person" << endl;
}
Person::Person(string name, short age)
:name(name), age(age)
{
cout << "Hello from Person::Person" << endl;
}
string Person::getName()
{
return this->name;
}
short Person::getAge()
{
return this->age;
}
The first >> in line 9 right after is is underlined red. I'm using Visual Studio 2017 Community.
The problem is that operator>> needs something it can alter. The return value of a function like getName is not such a thing.
Here's how you normally do this which is to make operator>> a friend function so that it can directly access the internals of the Person class.
class Person
{
// make operator>> a friend function
friend std::istream & operator>>(std::istream & is, Person & p);
private:
string name;
short age;
public:
Person(string, short);
string getName();
short getAge();
};
//Extending istream to support the Person class
std::istream & operator>>(std::istream & is, Person & p) {
is >> p.name >> p.age;
return is;
}
Not the only way though. Here's another approach that doesn't need to make anything a friend function. It uses temporary variables and then makes and assigns a Person object from those temporary variables.
//Extending istream to support the Person class
std::istream & operator>>(std::istream & is, Person & p) {
string name;
short age;
is >> name >> age;
p = Person(name, age);
return is;
}

Error creating a class object

I am having a problem creating a simple class object. I created a small program to simulate the problem. I have a class "Person" with data members string name, string eye_color, and int pets. When I call Person new_person("Bob", "Blue", 3), my debugger shows this as the new_person's value:
{name=""eye_color=""pets=-858993460}
I'm looking at previous projects where I had no problems with this and am not spotting anything...What am I missing?
person.h
#include <iostream>
#include <string>
class Person
{
public:
Person(std::string name, std::string eye_color, int pets);
~Person();
std::string name;
std::string eye_color;
int pets;
};
person.cpp
#include "person.h"
Person::Person(std::string name, std::string eye_color, int pets)
{
this->name;
this->eye_color;
this->pets;
}
Person::~Person(){}
city.h
#include "person.h"
class City
{
public:
City();
~City();
void addPerson();
};
city.cpp
#include "city.h"
City::City(){}
City::~City(){}
void City::addPerson(){
Person new_person("Bob", "Blue", 3);
}
main.cpp
#include "city.h"
int main(){
City myCity;
myCity.addPerson();
}
It doesn't look like you are actually assigning the values in the Person class so that is why you are getting random values for those data members.
It should be:
Person::Person(std::string name, std::string eye_color, int pets)
{
this->name = name;
this->eye_color = eye_color;
this->pets = pets;
}

Defining << operator at a base class

I'm trying to define the << operator for a base class, so I can later print the identifier of each object easily.
I have tried an SSCCE, but I don't really know where the problem is, since I'm printing a direction and not the content. I don't know if the problem appears by printing the vector position, or by printing the std::string(char[]).
main.cpp:
#include "City.h"
#include <vector>
#include <iostream>
int main() {
std::vector<Location*> locations;
locations.push_back(new City("TEST"));
for(unsigned int it = 0; it<locations.size(); it++){
std::cout << locations[it] << std::endl;
}
return 0;
}
Location.h:
#include <cstring>
#include <string>
class Location {
public:
Location(const std::string id);
friend std::ostream& operator<<(std::ostream& os, Location& loc);
std::string GetId();
private:
// Name/identifier of the location
char ID[5];
};
Location.cpp:
#include "Location.h"
Location::Location(const std::string id){
memset(this->ID, 0, 5);
strncpy(this->ID, id.c_str(), 5); // I have it as a char[5] at a larger app
}
std::string Location::GetId(){
return std::string(this->ID);
}
std::ostream& operator<<(std::ostream& os, Location& loc){
os << loc.GetId();
return os;
}
City.h:
#include "Location.h"
class City: public Location{
public:
City(std::string id);
};
City.cpp:
#include "City.h"
City::City(const std::string id) : Location(id){
}
Any idea?