I see multiple examples on how to add two variables of the same class, but I can't find examples on how to add variables of different classes with overloading.
We haven't worked with templates yet if it is relevant to my problem, but I am assuming we are not allowed to use it.
I want to add class book to class person with the + operator.
ex. Person p; Book b; p+b;//adds a book like it would if it were using a function like p.addBook(b);
class Person
{
private:
B * b;
string sName;
int numOfBook;
int maxNumOfBooks;
maxNumOfBooks is the max that person is allowed to carry
public:
Person();
Person(const Person&);
~Person();
const Person operator = (const Person &)
void addBook(const Book &); //adds a book to a Person
Person operator+(Person );
Book getBook(){return b[numOfBook];}//returns index of book
};
Person::Person()
{
numOfBook = 0;
maxNumOfBooks = 10;
b = new B[maxNumOfBooks];
for(int x=0;x<maxNumOfBooks;x++)
{
sets name to "". I did overload this.
b[x] = "";
}
}
Person::Person(const Person& p)
{
numOfBook = p.numOfBook;
maxNumOfBooks = p.maxNumOfBooks;
b = new B[maxNumOfBooks];
for(int x=0;x<maxNumOfBooks;x++)
{
b[x] = p.b[x];
}
}
Person::~Person()
{
delete [] b;
}
void Person::addBook()
{
replaces "" if numOfBooks < maxNumOfBooks;
Did code this.
}
Person Person::operator+(Person obj)
{
not entirely sure what to do here. but I am assuming it must look something like this.
Spell a;
++numOfBook;
a=this->getBook(numOfBook);
obj.addBook(a);
return *this;
}
const Person Person::operator = (const Person & obj)
{
delete [] b;
numOfBook = p.numOfBook;
maxNumOfBooks = p.maxNumOfBooks;
b = new B[maxNumOfBooks];
for(int x=0;x<maxNumOfBooks;x++)
{
b[x] = p.b[x];
}
return *this;
}
class Book
{
private:
string name;
int price;
public:
void setP();
int getP();
};
int main()
{
Person s;
Book bk("Story", 18);
s+bk;
I want to add a book at Person, but it should also make use of the addBook() function.
}
When you overload the + operator, you return a new instance of the return type (often this is overloaded for arithmetic type where the two inputs and output are the same type, but that's not at all necessary).
You just need to figure out what the operator is supposed to do.
In this case, the + operator should add a book to a copy of the person object called on (i.e. return a new instance and not modify the origional).
Person Person::operator + (const Book& b){
Person tmp(*this); //create a copy of this Person to modify
tmp.addBook(b); //modify this new copy and not the original
return tmp; //return the modified copy
}
whereas the += operator will modify the current object and return a reference
Person& Person::operator += (const Book& b){
addBook(b);
return *this;
}
If you already have += defined you can change your + operator to:
Person Person::operator + (const Book& b){
return Person(*this) += b;
}
Note:
Person P;
Book B;
P + B; // P is not modified;
Is not equivalant to:
Person P;
Book B;
P.addBook(B); // P is modified
However the following is.
Person P;
Book B;
P += B; // P is modified
As well as
Person P;
Book B;
P = P + B; // P is modified because it is assigned (P + B)
Related
While in assignment operator overloading why we return a reference to the object and why it can't return a const-reference? For example, in this case:
MyClass& MyClass::operator=(const MyClass &rhs) {
... // Do the assignment
return *this;
}
Why we can't return a constant reference like:
const MyClass& MyClass::operator=(const MyClass &rhs) {
... // Do the assignment operation!
return *this; // Return a reference to myself.
}
You can, but the users of MyClass may be surprised.
Usually, references can be taken to assignments (and less often, assignments can be assigned again). This is slightly confusing to word correctly, so here's what it looks like:
int a = 4;
int &r = a = 5;
(a = 6) = 7;
This also disallows calling member functions that modify the arguments of the function, for example:
#include <iostream>
struct C
{
int value;
const C &operator=(int v){value = v; return *this;}
};
void assign_value(C &ref)
{
ref %= 4;
}
int main(void)
{
C test;
assign_value(test = 5);
std::cout << c.value << '\n';
}
I've created an object and a Repository for it.
When I try inserting the object into the Repository (with the insert function i've created) I get compile error.
The Class I'm trying to insert into Repository
class Payment{
private:
int day;
int amount;
char *type;
public:
Payment();
Payment(int day, int amount, char *type);
Payment(const Payment &p);
~Payment();
//getters
int getDay()const;
int getAmount()const;
char* getType()const;
//setters
void setDay(int day);
void setAmount(int amount);
void setType(char* type);
//operator
Payment& operator=(const Payment& other);
friend ostream& operator<<(ostream &os,const Payment &obj);
};
//copy constructor
Payment::Payment(const Payment & p){
this->day = p.day;
this->amount = p.amount;
if(this->type!=NULL)
delete[] this->type;
this->type = new char[strlen(p.type)+1];
strcpy_s(this->type, strlen(p.type) + 1, p.type);
}
//assignment operator
Payment& Payment::operator=(const Payment &other) {
this->day = other.day;
this->amount = other.amount;
this->type = new char[strlen(other.type) + 1];
strcpy_s(this->type, strlen(other.type) + 1, other.type);
return *this;
}
//destructor
Payment::~Payment(){
this->day = 0;
this->amount = 0;
if (this->type != NULL) {
delete[]this -> type;
this->type = NULL;
}
}
//Repository header
class Repository{
private:
vector<Payment> list;
public:
Repository();
int getLength();
void insert(const Payment& obj);
void remove(int position);
};
//Repository cpp
Repository::Repository(){
this->list.reserve(10);
}
//return the size of the list
int Repository::getLength() {
return this->list.size();
}
//add payment to list
void Repository::insert(const Payment &obj) {
this->list.emplace_back(obj);
}
//remove payment from list
void Repository::remove(int position) {
this->list.erase(this->list.begin() + position);
}
In main function I have
char c[] = "some characters";
Payment pay = Payment(7,9,c);
Repository rep = Repository();
rep.insert(pay);
When I run the program I get the error "
Expression: _CrtlsValidHeapPointer(block) "
Since std::vector will make copies, a std::vector<Payment> requires that Payment has correct copy semantics. Your copy constructor and assignment operator are not implemented correctly. The assignment operator causes memory leaks, since you failed to delete [] the existing memory.
The easiest solution is to drop using the char *type; member and simply use std::string type;. Then the Payment class would have the correct copy semantics automatically.
Given that, the corrections to your Payment class is below:
#include <algorithm>
//...
Payment::Payment() : day(0), amount(0), type(nullptr) {}
Payment::Payment(const Payment & p) : day(p.day), amount(p.amount), type(nullptr)
{
if ( p.type )
{
type = new char[strlen(p.type) + 1];
strcpy_s(this->type, strlen(p.type) + 1, p.type);
}
}
// Use the copy/swap idiom
Payment& Payment::operator=(const Payment &other)
{
Payment temp(other); // make a temporary copy
// swap out contents of temporary with this object
std::swap(temp.day, day);
std::swap(temp.amount, amount);
std::swap(temp.type, type);
return *this;
} // when this brace has been reached, the temp copy dies off with the old data
Payment::~Payment()
{
delete [] type;
}
The above uses the copy/swap idiom within the assignment operator. The copy constructor uses a member initialization list.
The destructor need not check for a null pointer, since deleting a nullptr is perfectly valid.
Now adding to a std::vector is working well, without any runtime error (using the code #PaulMcKenzie posted). I've also found an example of code that's working, where only the assignment operator is kinda different.
Converted to my code would be (and it's working either):
Payment& Payment::operator=(const Payment &other) {
if (this != &other) {
this->setDay(other.day);
this->setAmount(other.amount);
this->setType(other.type);
}
return *this;
}
Thanks for the help! Now it's working perfectly! I didn't get to study very much from <algorithm> library, so I'll have to take a closer look. Wish you the best luck! ^_^
How to implement the comparison function in this case?
void remove(const Object1 &object1) {
for(auto &object2 : objectVector) {
if(object1 == object2) {
/*....... */
}
}
}
You are asking 2 questions:
How can objects be made comparable:
By implementing operator== for the class. Be sure you override operator != then too.
As a member function:
bool Object1::operator ==(const Object1 &b) const
{
// return true if *this equals b;
}
Or as a free function:
bool operator ==(const Object1 &a, const Object1 &b)
How can objects with a given value be removed from a vector:
The easiest way is to use std::remove:
objectVector.erase(std::remove(objectVector.begin(), objectVector.end(), object1), objectVector.end());
You can remove objects also while iterating through the vector, but you have to keep in mind that the vector iterator is invalidated then. You may not further iterate on the vector then.
An object of your class can contain different types and number of members so let's say that you have a class A:
class A{
int x,
float y;
char* z;
};
And you have two instances:
A a1;
A a2;
To compare:
if(a1 == a2) // compile-time error
;// DoSomeThing
Above you get the error because the compiler doesn't know which fields will be compared against each other. The solution is to overload the equals operator "==" to work on objects of your class.
class Student{
public:
Student(std::string, int age);
std::string getName()const;
int getAge()const;
bool operator == (const Student&);
private:
std::string name;
int age;
};
Student::Student(std::string str, int x) :
name(str), age(x){
}
bool Student::operator == (const Student& rhs){
return age == rhs.age;
}
std::string Student::getName()const{
return name;
}
int Student::getAge()const{
return age;
}
int main(){
Student a("Alpha", 77);
Student b("Beta", 49);
if(a == b)
std::cout << a.getName() << " is the same age as " <<
b.getName() << std::endl;
cout << endl << endl;
return 0;
}
Now the compiler knows how to compare objects of your class and know what the equals operator compares on your ojects members.
if object is a class you can override the operator == in the class as a friend function, or you can implement your own function bool isEqual(Object1 o1, Object1 o2) { if(something) return true; return false; }
I have implementated a class for an arbitrary model as the following
class model_lincommands : public QAbstractTableModel
{
Q_OBJECT
...
private:
QList<lin_display_role> datalist_display_roles_;
QList<LIN_FRAME> datalist_frames_;
QList<LIN_CMD> datalist_commands_;
};
Furthermore, I have one custom struct/class, called LIN_FRAME, which is defined separately.
My goal is now depending on the typed cast to overload the =-operator and realize a handy copy function for datalist_frames_, which is from type QList<LIN_FRAME>.
In the model_lincommands, I have tried the following:
inline QList<LIN_FRAME> operator= (QList<LIN_FRAME> const& rhs)
{
return this->datalist_frames_;
}
and then calling this by
QList<LIN_FRAME> tframe = *model;
whereas *model is a pointer to the instantiated model_lincommands class.
However, this is not working at all. Can you help me out what is the wrong point here?
Your operator overloading is incorrect. Try datalist_frames_ = rhs; return *this; instead of return this->datalist_frames_; Edited
Have a look at this:
// Operator overloading in C++
//assignment operator overloading
#include<iostream>
using namespace std;
class Employee
{
private:
int idNum;
double salary;
public:
Employee ( ) {
idNum = 0, salary = 0.0;
}
void setValues (int a, int b);
void operator= (Employee &emp );
};
void Employee::setValues ( int idN , int sal )
{
salary = sal; idNum = idN;
}
void Employee::operator = (Employee &emp) // Assignment operator overloading function
{
salary = emp.salary;
}
int main ( )
{
Employee emp1;
emp1.setValues(10,33);
Employee emp2;
emp2 = emp1; // emp2 is calling object using assignment operator
}
you can define your operator function inside the class, as you wish...
I have a class:
class Person{
public:
Person();
~Person();
string name;
int* age;
};
int main()
{
Person* personOne = new Person;
personOne->name = "Foo";
personOne->age = new int(10);
return 0;
}
How do I create another object of Person that copies all of personOne data? The age pointer needs to be pointing to a new int so whenever the age changes in personOne or personTwo, it doesn't affect each other.
There are two posibilites:
copy constructor + assignment operator
clone method
Code:
class Person{
public:
Person();
~Person();
Person (const Person& other) : name(other.name), age(new int(*(other.age)))
{
}
Person& operator = (const Person& other)
{
name = other.name;
delete age; //in case it was already allocated
age = new int(*(other.age))
return *this;
}
//alternatively
Person clone()
{
Person p;
p.name = name;
p.age = new int(age);
return p;
}
string name;
int* age;
};
Answer these before going forward:
do you really need an int pointer?
are you aware of smart pointers?
do you free all memory you allocate?
do you initialize all members in the constructor?