Operator Overloading (1)

→ majority of c++ operators can be overloaded

→ except: :: , :? , .* , . , sizeof

Example

main.cpp:

#include <iostream>
#include "Mystring.h"

using namespace std;

int main() {
	Mystring empty; // no-args constructor
	Mystring larry{"Larry"} // overloaded constructor
	Mystring stooge {larry}; // copy constructor

	empty.display();
	larry.display();
	stooge.display();

return 0;
}

Mystring.h:

#indef _MYSTRING_H_
#define _MYSTRING_H_

class Mystring
{
private:
	char *str; // pointer to char[] that holds a C-style string
public:
		Mystring();              // No-args constructor
		Mystring(const char *s); // Overloaded constructor
		Mystring(const Mystring &source); // Copy constructor
    ~Mystring();             // Destructor
		void display() const;
		int get_length() const; // getters
		const char *get_str() const;
};

#endif // _MYSTRING_H_

Mystring.cpp:

#include <cstring>
#include <iostream>
#include "Mystring.h"

// No-args construtor
Mystring::Mystring()
	: str{nullptr} {
	str = new char[1];
	*str = '\0';
}

// overloaded constructor
Mystring::Mystring(const char *s)
	:str {nullptr} {
		if (s==nullptr) {
			str = new char[1];
			*str = '\0';
	} else {
		str = new char[std::strlen(s)+1];
		std::strcpy(str,s)
	}
}

// Copy constructor
Mystring::Mystring(const Mystring &source)
	: str{nullptr} {
		str = new char[std::strlen(source.str) + 1];
		std::strcpy(str,source.str)
}

// Destructor
Mystring::~Mystring() {
	delete [] str;
}

// Display method
void Mystring::display() const {
	std::cout << str << ":" << get_length() << std::endl;
}

// length getter
int Mystring::get_length() const { return std::strlen(str); }

// string getter
const char *Mystring::get_str() const { return str; }

Overloading Copy assignment operator (deep copy)

Type &Type::operator=(const Type &rhs) // overloading the operator "="

Mystring &Mystring::operator=(constMystring &rhs);
s2 = s1; // We write this

s2.operator=(s1); // operator=method is called

// example 2 in Mystring.cpp file

Mystring &Mystring::operator=(const Mystring &rhs) {
	if (this == &rhs)
	return *this;

delete [] str;
str = new char[std::strlen(rhs.str) + 1];
std::strcpy(str, rhs.str);

return *this;
}

// -> Copy Assignment

Mystring &Mystring::operator=(const Mystring &rhs) {
		std::cout << "Copy assignment" << std::endl;
		if (this==&rhs)
		return *this;
		delete [] this->str;
		str = new char [std::strlen(rhs.str) + 1];
		std::strcpy(this->str, rhs.str);
		return *this;
}

Overloading assignment operator (move)

// method in Mystring.h file
Mystring( Mystring &&source); // move constructor

Mystring &operator=(Mystring &&rhs); // move assignment

// Move constructor in Mystring.cpp file
Mystring::Mystring(Mystring &&source)
	:str(source.str) {
	source.str = nullptr;
	std::cout << "Move constructor used" <<std::endl;
}

// Move assignment
Mystring &Mystring::operator=(Mystring &&rhs) {
	std::cout << "Using move assignment" << std::endl;
	if (this == &rhs)
	return *this;
	delete [] str;
	str = rhs.str;
	rhs.str = nullptr;
	return *this;
}

Overloading operators as member functions

// // //
Mystring larry1 {"LARRY"};
Mystring larry2;

larry1.display(); // Larry

larry2 = -larry1; // larry1.operator-()

larry1.display(); // LARRY
larry2.display(); // larry
// // //
// creaty second object with lowercase version of the string
// create overloaded member function (operator)

Mystring Mystring::operator-() const{
	char *buff = new char[std::strlen(str) + 1]; // new storage on the heap for the string
	std::strcpy(buff, str);
	for (size_t i=0; i<std::strlen(buff); i++)
		buff[i] = std::tolower(buff[i]); // class function from cc-type header-file
	Mystring temp {buff};
	delete [] buff;
	return temp;
}

Overloading Operators as Global Functions

// Make lowercase
bool operator==(const Mystring &lhs, const Mystring &rhs) { // two input arguments
	return (std:strcmp(lhs.str, rhs.str) == 0);
}

// Concatenation
Mystring operator+(const Mystring &lhs, const Mystring &rhs) {
	char *buff = new car[std::strlen(lhs.str) + std::strlen(rhs.str) + 1];
	std::strcpy(buff, lhs.str);
	std::strcat(buff, rhs.str);
	Mystring temp {buff};
	delete [] buff;
	return temp;
}

stream insertion and extraction operators (<<,>>)

// stream insertion operator (<<)

std::ostream &operator<<(std::ostream &os, const Mystring &obj) {
	os << obj.str; // if friend function
	// os << obj.get_str(); // if not friend function
	return os;
}

// Return a reference to the ostream so we can keep inserting
// Don't return ostream by value
// stream extraction operator (>>)

std::istream &operator>>(std::istream &is, Mystring &obj) {
	char *buff = new char[1000];
	is >> buff;
	obj = Mystring{buff}; // If you have copy or move assignment
	delete [] buff;
	return is;
}

// Return a reference to the istream so we can keep inserting
// Update the object passed in

int main() {
	Mystring larry {"Larry"};
	Mystring moe {"Moe"};
	Mystring curly;

	cout << "Enter the third stooge's first name: ";
	cin >> curly;

	cout << "The three stooges are " << larry << ", " << moe << ", and" << curly << endl;

	cout << "\nEnter the three stooges names separated by a space: ";
	cin >> larry >> moe >> curly;

	cout >> "The three stooges are " << larry << ", " << moe << ", and" << curly << endl;

	return 0
}