Chapter 4 - classes and objects

4.4 friends

In the program, some private properties also want to be accessed by special functions or classes outside the class, so you need to use friend technology

Purpose of friend: let a function or class access private members in another class

Friend keyword: friend

Three implementations of friends:

  • Global function as friend
  • Class as friend
  • Member function as friend

4.4.1 global functions as friends

code

#include<iostream>
using namespace std;
#include<string>

class Building 
{
	//goodGay global function is a good friend of Building. You can access private members in Building
	friend void goodGay(Building *building);
public:
	Building()
	{
		m_SettingRoom = "a living room";
		m_BedRoom = "bedroom";
	}
public:
	string m_SettingRoom;
private:
	string m_BedRoom;

};
//Global function
void goodGay(Building *building) 
{
	cout << "Good friends are visiting:" << building->m_SettingRoom << endl;
	cout << "Good friends are visiting:" << building->m_BedRoom<< endl;
}

void test01() 
{
	Building building;
	goodGay(&building);
}

int main()
{
	test01();

	system("pause");

	return 0;
}

4.4.2 class as friends

code

#include<iostream>
using namespace std;
#include<string>
class Building;

class goodGay 
{
public:
	goodGay();
	void visit();
private:
	Building *building;
};

class Building 
{
	//goodGay is a good friend of this class and can access private members of this class
	friend class goodGay;
public:
	Building();
public:
	string m_SettingRoom;
private:
	string m_BedRoom;
};
//Class write out member function
Building::Building() 
{
	m_SettingRoom = "a living room";
	m_BedRoom = "bedroom";
}
goodGay::goodGay()
{
	building = new Building;
}
void goodGay::visit() 
{
	cout << "Good friends are visiting:" << building->m_SettingRoom << endl;
	cout << "Good friends are visiting:" << building->m_BedRoom << endl;
}

void test01() 
{
	goodGay gg;
	gg.visit();
}

int main() 
{
	test01();

	system("pause");

	return 0;
}

4.4.3 member functions as friends

code

#include<iostream>
using namespace std;
#include<string>

class Building;
class GoodGay 
{
public:	
	GoodGay();
	void visit();
	void visit2();
	Building * building;
};

class Building 
{
	friend void GoodGay::visit();
public:
	Building();
public:
	string m_SettingRoom;
private:
	string m_BedRoom;
};
//Class write out member function
Building::Building() 
{
	m_SettingRoom = "a living room";
	m_BedRoom = "bedroom";
}
GoodGay::GoodGay() 
{
	building = new Building;
}

void GoodGay::visit() 
{
	cout << "visit Accessing:" << building->m_SettingRoom << endl;
	cout << "visit Accessing:" << building->m_BedRoom << endl;
}
void GoodGay::visit2() 
{
	cout << "visit2 Accessing:" << building->m_SettingRoom << endl;
	//Cout < < visit2 accessing: < < building - > m_ BedRoom << endl;
}

void test01()
{
	GoodGay gg;
	gg.visit();
	gg.visit2();
}
int main()
{
	test01();

	system("pause");

	return 0;
}

4.5 operator overloading

Definition: redefine the existing operators and give them another function to adapt to different data types

4.5.1 overload of plus operator

Function: realize the operation of adding two user-defined data types

code

#include<iostream>
using namespace std;
//Plus operator overload
class Person 
{
public:
	//1. Member function overload + sign
	//Person operator+(Person &p) 
	//{
	//	Person temp;
	//	temp.m_A = this->m_A + p.m_A;
	//	temp.m_B = this->m_B + p.m_B;
	//	return temp;
	//}
	int m_A;
	int m_B;
};
//2. Global function overload + sign
Person operator+(Person &p1, Person &p2) 
{
	Person temp;
	temp.m_A = p1.m_A + p2.m_A;
	temp.m_B = p1.m_B + p2.m_B;
	return temp;
}
//Version of function overload
Person operator+(Person &p1,int num)
{
	Person temp;
	temp.m_A = p1.m_A + num;
	temp.m_B = p1.m_B + num;
	return temp;
}
void test01() 
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 10;
	Person p2;
	p2.m_A = 10;
	p2.m_B = 10;
	//Essential call of member function overload
	//Person p3 = p1.operator+(p2);

	//Global function overload intrinsic call
	Person p3 = operator+(p1, p2);
	//Person p3 = p1 + p2;

	//Operator overloading can also occur with function overloading
	Person p4 = p1 + 100;  //Equivalent to Person + int 
	cout << "p3.m_A= " << p3.m_A << endl;
	cout << "p3.m_B= " << p3.m_B << endl;

	cout << "p4.m_A= " << p4.m_A << endl;
	cout << "p4.m_B= " << p4.m_B << endl;
}

int main()
{
	test01();

	system("pause");

	return 0;
}

Summary:

1. The operator of the built-in data type expression cannot be changed

2. Do not abuse operator overloading

4.5.2 shift left operator overload

Function: you can output custom data types

code

#include<iostream>
using namespace std;

class Person 
{
	friend ostream & operator<<(ostream &cout, Person &p);
public:
	Person(int a, int b) 
	{
		m_A = a;
		m_B = b;
	}

private:
	int m_A;
	int m_B;

};
ostream & operator<<(ostream &cout, Person &p) 
{
	cout << "m_A= " << p.m_A << " m_B= " << p.m_B;
	return cout;

}

void test01() 
{
	Person p(10, 10);
	//p.m_A = 10;
	//p.m_B = 10;
	cout << p << endl;
}
int main()
{
	test01();

	system("pause");

	return 0;
}

Summary:

1. Overloading the shift left operator and cooperating with friends can output user-defined data types.

4.5.3 overloading of increment operator

Function: realize your own integer data by overloading the increment operator

code

#include<iostream>
using namespace std;

class MyInteger 
{
	friend ostream& operator<<(ostream& cout, MyInteger myint);
public:
	MyInteger() 
	{
		m_num = 0;
	}
	//Overload the leading + + operator return reference in order to always increment a data
	MyInteger& operator++() 
	{
		m_num++;
		return *this;
	}
	//Overloaded post + + operator int represents a placeholder parameter, which can be used to distinguish pre post increment
	MyInteger operator++(int) 
	{
		//Record the results at that time first
		MyInteger temp = *this;
		//Post increment
		m_num++;
		//Finally, the recorded results are returned
		return temp;
	}

private:
	int m_num;
};

ostream& operator<<(ostream& cout, MyInteger myint) 
{
	cout << myint.m_num;
	return cout;

}

void test01() 
{
	MyInteger myint;

	cout << ++(++myint) << endl;
	cout << myint << endl;

}

void test02() 
{
	MyInteger myint;
	cout << myint++ << endl;
	cout << myint << endl;

}
int main()
{
	//test01();
	test02();
	system("pause");

	return 0;
}

Summary:

1. The pre increment returns a reference and the post increment returns a value

4.5.4 overload of assignment operator

The C + + compiler adds at least four functions to a class

1. Default constructor (no parameters, empty function body)

2. Default destructor (no parameters, empty function body)

3. The default copy constructor copies the value of the attribute

4. The assignment operator operator = copies the value of the attribute

If an attribute in the class points to the heap, the deep and shallow copy problem will also occur during assignment

code

#include<iostream>
using namespace std;

class Person
{
public:
	Person(int age)
	{
		m_Age = new int(age);
	}
	~Person()
	{
		if (m_Age != NULL) 
		{
			delete m_Age;
			m_Age = NULL;
		}
	
	}
	//Overload assignment operator
	Person& operator=(Person &p) 
	{
		//The compiler provides shallow copies
		//m_Age=p.m_Age

		//First judge whether there are attributes in the heap area. If so, release them clean first, and then deep copy them
		if (m_Age != NULL) 
		{
			delete m_Age;
			m_Age = NULL;
		}
		//Deep copy
		m_Age = new int(*p.m_Age);
		//Returns the object itself
		return *this;
	}
	int *m_Age;
};

void test01() 
{
	Person p1(18);
	
	Person p2(20);

	Person p3(30);
	p3=p2 = p1;
	cout << "p1 Your age is:" << *p1.m_Age << endl;
	cout << "p2 Your age is:" << *p2.m_Age << endl;
	cout << "p3 Your age is:" << *p3.m_Age << endl;
}

int main()
{
	test01();
	system("pause");

	return 0;
}

4.5.5 overloading of relational operators

Function: overloads the relational operator, allowing two custom type objects to be compared

code

#include<iostream>
using namespace std;
class Person 
{
public:
	Person(string name, int age) 
	{
		m_Name = name;
		m_Age = age;
	}
	bool operator==(Person &p) 
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) 
		{
			return true;
		}
		return false;
	}
	bool operator!=(Person &p)
	{
		if (this->m_Name == p.m_Name && this->m_Age == p.m_Age)
		{
			return false;
		}
		return true;
	}
	string m_Name;
	int m_Age;
};

int main()
{
	Person p1("mike", 18);

	Person p2("mike", 19);
	if (p1 == p2) 
	{
		cout << "p1 and p2 equal" << endl;
	}
	if (p1 != p2) 
	{
		cout << "p1 and p2 Unequal" << endl;
	}


	system("pause");

	return 0;
}

4.5.6 function call operator overloading

  • The function call operator () can also be overloaded
  • Because the method used after overloading is very similar to the call of a function, it is called an imitation function
  • Imitation function has no fixed writing method and is very flexible

code

#include<iostream>
using namespace std;
#include<string>
class MyPrint 
{
public:
	void operator()(string name) 
	{
		cout << name << endl;
	}

};

void MyPrint02(string  name) 
{
	cout << name << endl;
}
void test01()
{
	MyPrint myprint;
	myprint("hello world");//Because it is very similar to function call, it is called imitation function

	MyPrint02("hello world");
}
//Additive class
class MyAdd 
{
public:
	int operator()(int num1,int num2) 
	{
		return num1 + num2;
	}
};

void test02() 
{
	MyAdd myadd;
	int ret=myadd(100, 100);
	cout << "ret = "<<ret << endl;
	//Anonymous function object
	cout << MyAdd()(100, 100) << endl;

}
int main()
{
	//test01();
	test02();
	
	system("pause");

	return 0;
}

Tags: C++

Posted on Tue, 23 Nov 2021 01:16:58 -0500 by IndianaRogers