The code on the right side are non-member functions, so we’ll have to declare them as friend functions inside the complex class.

Member Function

complex complex::operator+(const complex& rhs)const{
	return complex(real + rhs.real, img + rhs.img);
}

This is defined as a member function, so we have to add the keyword complex::

Non-Member Function

complex operator+(const complex& lhs, const complex& rhs){
	return (lhs.real + rhs.real, lhs.img + rhs.img);
}
friend complex operator+(const complex&, const complex&);

Copy Constructors

A copy constructor is a constructor that make a copy of an exist object. We have 4 cases to see:

  1. Example: complex a(b);
    1. You’re creating a new complex number called a and initializing it with values of b
    2. Values from b will have to be copied to a
  2. Example: complex a = b; → also called “assignment operator”
    1. You’re assigning the values of b to the values of a
  3. Passing an object to a function by value
    1. A copy of that object is copied, and that copy is sent to the function
  4. Returning an object from a function by value
    1. A copy of the object inside the function is made, and that copy is returned

By default, every class has a copy constructor that copies all the data members to the new object.

Default Copy Constructor

class complex{
	private:
		double real;
		double imaginary;
		
	public:
		complex(){
			real = 0;
			img = 0;
		}
		// ... and so on... other defined functions
		
		// default copy constructor (you don't need to implement this irl)
		complex(const complex& other){
			real = other.real;
			img = other.img;
		}
}

Pointers, Dynamic Memory Allocation, and Copy Constructors

class mystring(){
	private:
		int len;
		char* buf;
	
	public:
		mystring(){
			len = 0;
			buf = nullPtr;
		}
		// constructor
		mystring(char* src){
			buf = new char[strlen(src) + 1];
			strcpy(buf, src);
			len = strlen(src);
		}
		// design a setter function called setstring so we can edit existing strings
		void setstring(char* src){
			if (buf != null)
				delete[] buf;
			buf = new char[strlen(src) + 1];
			strcpy(buf, src);
			len = strlen(src);
		}
		// the default (already existing) shallow copy constructor
		mystring(const mystring& x){
			len = x.len;
			buf = x.buf;
		}
}

Let’s use these things in main… and see the issues with shallow copy

int main(){
	mystring a("Hello");
	mystring b(a);
	
	b.setstring("class"); // the problem with this is that this also changes a
}

1000026276.jpg

1000026277.jpg

Deep Copying

We replaced the shallow copy with a deep copy by dynamically allocating new memory for our b and copying the actual values of a into b. Now, we can modify b without affecting a.