在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术 友元的目的就是让一个函数或者类 访问另一个类中私有成员 友元的关键字为 friend 友元的三种实现 全局函数做友元 类做友元 成员函数做友元
运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
作用:实现两个自定义数据类型相加的运算 总结1:对于内置的数据类型的表达式的的运算符是不可能改变的 总结2:不要滥用运算符重载
#include<iostream> #include<string> using namespace std; class Person{ public: Person(){} Person(int a,int b) { this->m_A = a; this->m_B = b; } //成员函数实现+号运算符重载 Person operator+(Person& p1) { Person temp; temp.m_A = this->m_A + p1.m_A; temp.m_B = this->m_B + p1.m_B; return temp; } public: int m_A; int m_B; }; 全局函数实现+号运算符重载 //Person operator+(Person& p1,Person& p2) //{ // Person temp = Person(0, 0); // temp.m_A = p1.m_A + p2.m_A; // temp.m_B = p1.m_B + p2.m_B; // return temp; //} //全局函数和成员函数实现加号运算符重载 //全局函数重载等同于 +operator(p1,p2) //局部函数重载等同于 p1.+operator(p2) //最后的调用方式均可以简化为 p3=p1+p2 void test01() { Person p1(10, 10); Person p2(20,20); Person p3 = p1 + p2; cout <<p3.m_A << endl; cout <<p3.m_B << endl; } //重载实现 p3=p2+10 Person operator+(Person& p1,int val) { Person temp(0, 0); temp.m_A = p1.m_A + val; temp.m_B = p1.m_B + val; return temp; } void test02() { Person p2(10, 10); Person p3 = p2 + 10; cout << p3.m_A<< endl; cout << p3.m_B<< endl; } //运算符重载可以实现函数重载 int main() { test02(); system("pause"); return 0; }作用:可以输出自定义数据类型 总结:重载左移运算符配合友元可以实现输出自定义数据类型
#include<iostream> #include<string> using namespace std; class Person{ public: friend ostream& operator<<(ostream& cout, Person& p1); Person(){} Person(int a,int b) { this->m_A = a; this->m_B = b; } //局部函数不能实现左移运算符重载 //void operator<<(ostream& cout) //结果是 p<<cout 不符合正常使用习惯 private: int m_A; int m_B; }; //全局函数实现左移重载 ostream& operator<<(ostream& cout, Person& p1) { cout << "p1.m_A=" << p1.m_A<<" p1.m_B="<<p1.m_B<<endl; return cout; } void test01() { Person p1(10,10); cout << p1<<"欢迎"<<endl; } //运算符重载可以实现函数重载 int main() { test01(); system("pause"); return 0; }通过重载递增运算符,实现自己的整型数据
#include<iostream> #include<string> using namespace std; class MyInteger{ friend ostream& operator<<(ostream& cout, MyInteger& myInt); friend void test01(); public: MyInteger() { num = 0; } //实现前置++ //返回的是本身 因此可以使用引用作为返回值 MyInteger& operator++() { this->num++; return *this; } //实现后置++ 使用占位形式参数形成函数的重载 //返回的是函数内的成员变量,因此需要返回数值,不能返回引用。 MyInteger operator++(int) { MyInteger temp = *this; this->num++; return temp; } private: int num; }; //左移函数重载 ostream& operator<<(ostream& cout,MyInteger& myInt) { cout <<"MyInteger.num="<<myInt.num << endl; return cout; } //实现 前置++运算的重载 void test01() { MyInteger myint; myint++; cout << myint<< endl; } //实现 后置++运算的重载 void test02() { MyInteger myint; ++(++myint); cout <<myint << endl; } int main() { test01(); test02(); system("pause"); return 0; }c++编译器至少给一个类添加4个函数 默认构造函数(无参,函数体为空) 默认析构函数(无参,函数体为空) 默认拷贝构造函数,对属性进行值拷贝 赋值运算符 operator=, 对属性进行值拷贝 如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题
#include<iostream> #include<string> using namespace std; class Person{ public: Person(int age){ //将年龄数据开辟到堆区 this->age = new int(age); } //在结束时删除开辟的堆区 ~Person() { if (age != NULL) { delete age; age = NULL; } } //重复值运算符 深拷贝应用 拷贝构造 Person& operator=(Person& p1) { if (this->age != NULL) { delete this->age; this->age = NULL; } this->age = new int(*p1.age); return *this; } int *age; }; void test01() { Person p1(10); Person p2(20); p1 = p2; cout <<*p1.age << endl; cout <<*p2.age << endl; //链式法则 Person p3(30); p1 = p2 = p3; cout << *p1.age << *p2.age << *p3.age << endl; } int main() { test01(); system("pause"); return 0; }**作用:**重载关系运算符,可以让两个自定义类型对象进行对比操作
#include<iostream> #include<string> using namespace std; class Person{ public: Person(int age,string name) { m_Age = age; m_Name = name; } //重载== 成员函数重载只能传入一个参数 bool operator==(Person& p1) { if (p1.m_Age==m_Age&&p1.m_Name==m_Name) { return true; } else { return false; } } //重载 实现!= bool operator!=(Person& p1) { if (p1.m_Age == m_Age&&p1.m_Name == m_Name) { return false; } else { return true; } } int m_Age; string m_Name; }; void test01() { Person p1(10,"李四"); Person p2(10,"李四"); if (p1==p2) { cout <<"两者相等" << endl; } else { cout << "两者不相等" << endl; } if (p1 != p2) { cout << "两者不相等" << endl; } else { cout << "两者相等" << endl; } } int main() { test01(); system("pause"); return 0; }函数调用运算符 () 也可以重载 由于重载后使用的方式非常像函数的调用,因此称为仿函数 仿函数没有固定写法,非常灵活
#include<iostream> #include<string> using namespace std; class MyPrint{ public: //重载的()操作符 也称为仿函数 void operator()(string text) { cout <<text << endl; } }; void test01() { MyPrint myprint; myprint("Hello World"); } class MyAdd{ public: int operator()(int val1, int val2) { return val1 + val2; } }; void test02() { MyAdd myadd; int result = myadd(1,2); cout <<result << endl; //匿名对象调用 cout <<MyAdd()(3,5) << endl; } int main() { test01(); test02(); system("pause"); return 0; }