I have some problem with overloading += operator
I want to add a item to vector (getAuthorList) with += operator
How can I do it in main ?
Code snippet (header file) :
class Author {
public:
Author(std::string firstName, std::string lastname, std::string affiliation);
std::string getFirstName();
std::string getLastName();
std::string getAffiliation();
void setFirstName(std::string);
void setLastName(std::string);
void setAffiliation(std::string);
void printFullName();
friend std::ostream& operator<<(std::ostream& output, const Author& author);
private:
std::string firstName;
std::string lastname;
std::string affiliation;
};
class Publication {
public :
Publication(std::string tiltle, Date publishDate, std::string publisher);
vector<Author> getAuthorList();
Author& operator+=(Author);
private:
vector<Author> authorList;
};
You can overload += operator like this
void operator+=(Author);
Change the operator return type to void as you are storing it in Publication class so it does not make any sense to return The same author from this operator.
you can write the operator definition like this
void Publication::operator+=(Author auth){
this->authorList.push_back(auth);
}
here is the working example:
#include <string>
#include <vector>
#include <iostream>
class Author {
public:
Author(const std::string& name):
Name(name){
}
const std::string& getName() const{
return Name;
}
private:
std::string Name;
};
class Publication {
public :
Publication(){
}
void operator+=(Author);
void getAuthorList(){
for (const auto& author: authorList){
std::cout << author.getName() << std::endl;
}
}
private:
std::vector<Author> authorList;
};
void Publication::operator+=(Author auth){
this->authorList.push_back(auth);
}
int main(){
Publication pub;
Author auth("Alice");
pub += auth;
Author auth2("Mark");
pub += auth2;
pub.getAuthorList();
}
Note: I just tried to make simple.
You could use the std::vector method called push_back inside the implementation block of your overloaded operator.
Related
I've done the Harvard CS50 Course and worked with python a fair bit. I'm now doing a C++ course (Microsoft's) and the learning exercise has me creating a few classes. The exercise specifically tasks me to instantiate a few objects in main and return some values;
#include <iostream>
#include "School.h"
int main()
{
Student student1("Joe", "Bloggs", 31, "123 Fake Street", "London");
Student student2("Fred", "Adams", 24, "95 Something Avenue", "Manchester");
Student student3("John", "Doe", 90, "44a Old Man Lane", "Kettering");
Course course1("Introduction to Psychology");
course1.addStudent(student1);
course1.addStudent(student2);
course1.addStudent(student3);
Teacher teacher1("Helen", "Professorson", 48, "15 Teacher Way", "Kent");
course1.addTeacher(teacher1);
std::cout << course1.getCourseName() << std::endl;
teacher1.GradeStudent();
}
I'm using a header file and cpp file to define the classes, School.h:
#pragma once
#include <string>
class Person
{
public:
// Constructors and Destructors
Person();
Person(std::string, std::string); // First and Last Name
Person(std::string, std::string, int, std::string, std::string, std::string); // fName, lName, Age, Address, City, Phone
~Person();
// Member functions
std::string getFirstName();
void setFirstName(std::string);
std::string getLastName();
void setLastName(std::string);
int getAge();
void setAge(int);
std::string getAddress();
void setAddress(std::string);
std::string getCity();
void setCity(std::string);
std::string getPhone();
void setPhone(std::string);
private:
std::string _fName;
std::string _lName;
int _age;
std::string _address;
std::string _city;
std::string _phone;
};
class Student : public Person
{
public:
// Constructors and Destructors
// Member Functions
void SitInClass();
};
class Teacher : public Person
{
public:
// Member Functions
void SitInClass();
void GradeStudent();
};
class Course
{
public:
// Constructors and Desctructors
Course();
Course(std::string); // course name
~Course();
// Member functions
void addStudent(Student);
void addTeacher(Teacher);
// Getters and Setters
std::string getCourseName();
void setCourseName(std::string);
private:
// Member variables
std::string _courseName;
Student _students[30];
Teacher _teacher;
};
School.cpp:
#include "School.h"
#include <iostream>
#include <string>
// Constructors
Person::Person()
{
std::string _fName{};
std::string _lName{};
int _age{};
std::string _address{};
std::string _city{};
std::string _phone{};
}
Person::Person(std::string fName, std::string lName)
{
std::string _fName{ fName };
std::string _lName{ lName };
int _age{};
std::string _address{};
std::string _city{};
std::string _phone{};
}
Person::Person(std::string fName, std::string lName, int age, std::string address, std::string city, std::string phone)
{
std::string _fName{ fName };
std::string _lName{ lName };
int _age{ age };
std::string _address{ address };
std::string _city{ city };
std::string _phone{ phone };
}
// Destructor
Person::~Person()
{
}
std::string Person::getFirstName()
{
return this->_fName;
}
void Person::setFirstName(std::string fName)
{
this->_fName = fName;
}
std::string Person::getLastName()
{
return this->_lName;
}
void Person::setLastName(std::string lName)
{
this->_lName = lName;
}
int Person::getAge()
{
return this->_age;
}
void Person::setAge(int age)
{
this->_age = age;
}
std::string Person::getAddress()
{
return this->_address;
}
void Person::setAddress(std::string address)
{
this->_address = address;
}
std::string Person::getCity()
{
return this->_city;
}
void Person::setCity(std::string city)
{
this->_city = city;
}
std::string Person::getPhone()
{
return this->_phone;
}
void Person::setPhone(std::string phone)
{
this->_phone = phone;
}
void Student::SitInClass()
{
std::cout << "Sitting in main theater" << std::endl;
}
void Teacher::SitInClass()
{
std::cout << "Sitting at front of class" << std::endl;
}
void Teacher::GradeStudent()
{
std::cout << "Student Graded" << std::endl;
}
Course::Course()
{
Student* _students;
Teacher* _teacher;
std::string _name{};
}
Course::Course(std::string name)
{
Student* _students[30];
Teacher* _teacher;
std::string _name{ name };
}
Course::~Course()
{
}
void Course::addStudent(Student student)
{
// TODO: Loop through _students and insert new student in
}
void Course::addTeacher(Teacher teacher)
{
this->_teacher = &teacher;
}
std::string Course::getCourseName()
{
return this->_name;
}
void Course::setCourseName(std::string name)
{
this->_name = name;
}
I actually haven't been taught inheritance yet, but since both Student and Teacher needed the same variables (name, age, address etc.) I decided it'd be sensible.
Having a few problems though:
My instantiations of Student and Teacher in main.cpp aren't correct. I think because they are inheriting from Person(?). How do I create a constructor within these derived classes? I googled this but the solutions didn't seem to work.
The Course Class requires an array of Students. Do I have to specify a size of the array in the header file? It seems silly that I've specified 30 in both the header file and the cpp file, but VSstudio complains if I don't.
I'm using strings here. I have previously learned from a different course about char* and memory regarding strings. How many chars are assigned to all of these string class variables? If I instantiate a Students with name "Joe" and then want to later change his name to "Joseph" using student1.SetFirstName, is that going to cause segmentation faults?
Thanks, I figured it out mostly...
I needed to create constructors in Student and Teacher with the same input variables as the Person class, and then call the Person constructor in the Student consturctor:
Student::Student()
{
}
Student::Student(std::string fName, std::string lName)
: Person(fName, lName)
{
}
Student::Student(std::string fName, std::string lName, int age, std::string address, std::string city, std::string phone)
: Person(fName, lName, age, address, city, phone)
{
}
You do not need to specify array size in the constructor:
Header file looks like this:
class Course
{
...
private:
// Member variables
std::string _name;
Student* _students[30];
Teacher* _teacher;
};
And the constructor looks like this:
Course::Course()
: _students{ 0 }, _teacher{ 0 }, _name{}
{
}
To initialise every array item to 0.
Not so sure on still...
I have a class named Demo and in that class I have overloaded the Text() method for setting and getting it's private variable called text.
#ifndef DEMO_H
#define DEMO_H
#include <string>
#include <iostream>
using namespace std;
class Demo {
string text;
public:
Demo() {};
Demo(string newText) : text(newText) {};
void Text(string updatedText);
string Text();
};
#endif // !DEMO_H
void Demo::Text(string updatedText) {
text = updatedText;
}
string Demo::Text() {
return text;
}
Then in another class, I have used the method in following way-
#include "Demo.h"
int main()
{
Demo d;
d.Text("test");
cout << d.Text() << endl;
return 0;
}
This works fine. However, I want to set the parameter of the method with "=" operator. So rather than
d.Text("test");
I want to do
d.Text = "test";
Is it possible to achieve in C++ and if so then how. I was thinking of operator overloading but I couldn't achieve the goal. Can anyone please suggest.
The closest you can get in c++ to express property like getter / setter functions similar as in c# is to provide class member functions like these:
class Demo {
string text;
public:
void Text(const string& updatedText) { text = updatedText; }
const string& Text() const { return text; }
};
That idiom is used a lot in the c++ standard library like here.
I want to do
d.Text = "test";
What you can do is
class Demo {
public:
string& Text() { return text; }
};
and
d.Text() = "test";
but that totally defeats the concept of encapsulation of data.
The right way to proceed is overloading the assignment '=' operator and use as below.
class Demo {
string text;
public:
Demo() {};
Demo(string newText) : text(newText) {};
**void operator =(const string& val) { text = val; }**
void Text(string updatedText);
string Text();
};
int main()
{
Demo d;
//d.Text("test");
d = "hello world";
cout << d.Text() << endl;
return 0;
}
You could define your Text property as an object T. T could then overload some common property operations ( haven't figured out how a common getter call like Object o; o.set(d.Text); would be implemented yet ) :
#include <iostream>
using namespace std;
class T {
string _text;
public:
void operator =(const string& t) { _text = t; }
friend ostream& operator<<(ostream& os, const T& obj)
{
cout << obj._text;
return os;
}
};
class Demo {
public:
T Text;
};
int main()
{
Demo d;
d.Text = "test";
cout << d.Text << endl;
}
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I would like to make this programm show the "Gianna" "Maria" and "M" strings on the screen but I can't. There's no error so I guess there's something wrong with my programm. Any suggestions what could fix my programm?
#include <iostream>
#include <string>
using namespace std;
class name
{
string fName, mName, sName;
public:
name (string fName, string mName, string sName){};
void setFName (string fName);
void setMName (string mName);
void setSName (string sName);
string getFName() const {return fName;}
string getSName() const {return sName;}
string getMName() const {return mName;}
friend ostream & operator <<(ostream &, const name &);
};
ostream& operator<<(ostream& os, const name& n) {
return os << n.fName << " " << n.sName<< " " << n.mName;
}
int main ()
{
name myName ("Gianna", "Maria", "M");
cout<<myName.getFName()<<" "<<myName.getMName()<<" "<<myName.getSName()<<endl;
return 0;
}
Your constructor:
name (string fName, string mName, string sName){};
doesn't do anything. You need to use the parameters to initialise your member variables.
name (string f, string m, string s)
: fName(f), mName(m), sName(s) {}
You forgot to initialize daya members of the class in the constructor.
Define the constructor the following way
name( const string &fName, const string &mName, const string &sName )
: fName( fName ), mName( mName ), sName( sName )
{
}
Correspondingly these member functions should be defined like
void setFName ( const string &fName)
{
this->fName = fName;
}
void setMName (const string &mName)
{
this->mName = mName;
}
void setSName (const string &sName)
{
this->sName = sName;
}
There is no need to make the operator << as a friend function of the class. It can be defined like
ostream& operator <<( ostream& os, const name& n ) {
return os << n.getFName() << " " << n.getMName() << " " << n.getSName();
}
Your constructor must assign the parameters you pass to the member variables, that doesn't happen automatically.
name (string fName, string mName, string sName) : fName(fName), mName(mName), sName(sName) {};
For your constructor, you have the three strings as your parameters but you aren't setting the member variables to their values. You can use an initializer list on the constructor like this...
name (string f, string m, string s)
: fName(f), mName(m), sName(s) // member(parameter) format
{
}
...or you can implement the setter stubs you have...
void setFName(string name) { this->fName = name;}
... and use them inside of your constructor like...
name (string fName, string mName, string sName) {
setFName(fName);
//...
}
Basically the parameters passed in the constructor are getting lost since you are not assigning it to the class vars..
Do something like:
name (string f, string m, string s) : fName(f), mName(m), sName(s){....};
try this. You forgot to implement Constructor of the class
#include <iostream>
#include <string.h>
using namespace std;
class name
{
string sFName, sMName, sSName;
public:
name (string FName, string MName, string SName);
void Display();
void setFName (string fName);
void setMName (string mName);
void setSName (string sName);
string getFName() const {return sFName;}
string getSName() const {return sSName;}
string getMName() const {return sMName;}
};
name::name(string FName, string MName, string SName )
{
sFName = FName;
sMName = MName;
sSName = SName;
}
void name::setFName(string fName)
{
sFName = fName;
}
void name::setMName(string mName)
{
sMName = mName;
}
void name::setSName(string sName)
{
sSName = sName;
}
void name::Display()
{
cout<< sFName<< endl;
cout<< sMName<< endl;
cout<< sSName<< endl;
}
int main ()
{
name myName ("Gianna", "Maria", "M");
myName.Display();
return 0;
}
I am planning to use json c++ at https://github.com/nlohmann/json#examples . After reading its simple examples, I still have no idea how to use it with my own object? For example, I have a class
class Student
{
public:
Student(int id, string const& name)
: m_id(id), m_name(name)
{}
private:
int m_id;
string m_name;
};
How to use json to read and write (deserialize and serialize) a Student object?
this is another way to do the conversion from json to custom class, that actually fits the best practices defined in the official repo from nlohmann here
https://github.com/nlohmann/json#arbitrary-types-conversions
h:
#ifndef STUDENT_H
#define STUDENT_H
#include<string>
#include "json.hpp"
class Student
{
public:
Student();
Student(int id, const std::string &name);
int getId() const;
void setId(int newId);
std::string getName() const;
void setName(const std::string &newName);
private:
int m_id;
std::string m_name;
};
//json serialization
inline void to_json(nlohmann::json &j, const Student &s)
{
j["id"] = s.getId();
j["name"] = s.getName();
}
inline void from_json(const nlohmann::json &j, Student &s)
{
s.setId((j.at("id").get<int>()));
s.setName(j.at("name").get<std::string>());
}
#endif // STUDENT_H
cpp:
#include "Student.h"
#include<string>
Student::Student() : Student(0, "")
{
}
Student::Student(int id, const std::string &name) : m_id{id}, m_name{name}
{
}
int Student::getId() const
{
return this->m_id;
}
void Student::setId(int newId)
{
m_id = newId;
}
std::string Student::getName() const
{
return this->m_name;
}
void Student::setName(const std::string &newName)
{
this->m_name = newName;
}
example:
Student s{0, "x"};
nlohmann::json studentJson = s;
std::cout << "Student from object: " << s.getId() << std::endl;
std::cout << "Student from json: " << studentJson.at("id").get<int>() << std::endl;
//String
std::string jSt = studentJson.dump(); //{"id":0,"name":"x"}
Student s2 = studentJson;
Student s3 = nlohmann::json::parse(jSt);
This library doesnt seems to have any interaction with a class for serialization and deserialization.
But you can implement it yourself with a constructor and a getter.
using json = nlohmann::json;
class Student
{
public:
Student(int id, string const& name)
: m_id(id), m_name(name)
{}
Student(json data)
: m_id(data["id"]), m_name(data["name"])
{}
json getJson()
{
json student;
student["id"] = m_id;
student["name"] = m_name;
return student;
}
private:
int m_id;
string m_name;
};
I'm trying to use a vector for derived class Employee but I got en error:
class Company : public Employee, public TesterEmployee, public DeveloperEmployee {
private:
std::vector<Employee*> _table;
public:
friend std::vector<Employee*>& operator+=(const Employee* emp) {
_table.push_back(emp->clone());
return *this;
}
};
The error is:
error: 'std::vector<Employee*>& operator+=(const Employee*)' must have an argument of class or enumerated type
+= is a binary operator. The function
friend std::vector<Employee*>& operator+=(const Employee* emp) {
_table.push_back(emp->clone());
return *this;
}
defines a non-member function that can take only one argument. Hence, it cannot be used in an expression like:
a += b;
What you need is:
Company& operator+=(const Employee* emp) {
_table.push_back(emp->clone());
return *this;
}
In response to the other question about the same code (that you deleted https://stackoverflow.com/questions/30717107/operator-overloading-in-my-class-with-error):
Q and the problem :
error: invalid operands of types 'Company*' and 'DeveloperEmployee*' to binary 'operator+'|
What does it mean?
It means you're trying to write Java/C# code in C++. Don't do that.
In particular you're abusing OOP for the sake of OOP. A Company is-not-a Employee (see Liskov), and company + employee doesn't make sense.
Lose the new.
Lose the base class.
Probably lose the clone based dynamic value semantics.
Finally, your problem is, you're using operator+= which you didn't overload.
Live On Coliru
#include <vector>
#include <iostream>
struct Employee {
int getID() const { return _id; }
private:
int _id = generate_id();
static int generate_id() {
static int next = 0;
return ++next;
}
};
struct DeveloperEmployee : Employee {
DeveloperEmployee(std::string const& descr, std::string const& project)
: _description(descr), _project(project) { }
private:
std::string _description;
std::string _project;
friend std::ostream& operator<<(std::ostream& os, DeveloperEmployee const& de) {
return os << "id:" << de.getID() << " descr:'" << de._description << "' project:'" << de._project << "'";
}
};
class Company {
private:
std::vector<Employee> _table;
std::string _des;
public:
Company &operator+=(const Employee &emp) {
_table.push_back(emp);
return *this;
}
void setDescription(std::string des) { _des = des; }
};
int main() {
Company company;
DeveloperEmployee a("description", "project");
int id = a.getID();
std::cout << a << std::endl; // Developer ID = 2, project = hw5
company += a;
}