c++学习心得第二期友元+运算符重载

    科技2022-07-21  104

    c++学习心得第二期 友元+运算符重载

    一、友元1 、全局函数做友元2. 类做友元3. 成员函数做友元 二、运算符重载1.加号运算符重载2.左移运算符重载3.递增运算符重载4.赋值运算符重载5. 关系运算符重载6. 函数调用运算符重载

    在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术 友元的目的就是让一个函数或者类 访问另一个类中私有成员 友元的关键字为 friend 友元的三种实现 全局函数做友元 类做友元 成员函数做友元

    一、友元

    1 、全局函数做友元

    #include<iostream> using namespace std; #include <string> //全局函数做友元 class Building{ friend void goodGay(Building *building); public: Building() { this->m_Bedroom = "卧室"; this->m_SittingRoom = "客厅"; } public: string m_SittingRoom; private: string m_Bedroom; }; void goodGay(Building *building) { cout <<"好基友正在访问" <<building->m_SittingRoom<< endl; cout <<"好基友正在访问" <<building->m_Bedroom<< endl; } int main() { Building b; goodGay(&b); system("pause"); return 0; }

    2. 类做友元

    #include<iostream> using namespace std; #include <string> //类做友元 //还没有写Building类在此处做一个声明,在goodGay中需要用到goodGay //一个类想访问另外一个类中的私有成员变量。 class Building; class goodGay{ public: goodGay(); void visit(); private: Building *building; }; class Building{ friend class goodGay; public : Building(); string m_SettingRoom; private: string m_BedRoom; }; Building::Building() { this->m_SettingRoom = "客厅"; this->m_BedRoom = "卧室"; } goodGay::goodGay() { this->building = new Building(); } void goodGay::visit() { cout << "好朋友正在访问" << building->m_SettingRoom << endl; cout << "好朋友正在访问" << building->m_BedRoom << endl; } int main() { goodGay gg; gg.visit(); system("pause"); return 0; }

    3. 成员函数做友元

    #include<iostream> using namespace std; #include <string> //成员函数做友元 class goodGay{ public: goodGay(); void visit(); void visit2(); private: Building *building; }; class Building{ friend void goodGay::visit(); public: Building(); public: string m_SettingRoom; private: string m_BedRoom; }; Building::Building() { this->m_SettingRoom = "客厅"; this->m_BedRoom = "卧室"; } goodGay::goodGay() { building = new Building; } void goodGay::visit() { cout << "gay="<<building->m_SettingRoom<< endl; cout << "gay=" <<building->m_BedRoom << endl;//编译器没有识别出来不用理会 } void goodGay::visit2() { cout << "gay=" << building->m_SettingRoom << endl; } int main() { system("pause"); return 0; }

    二、运算符重载

    运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

    1.加号运算符重载

    作用:实现两个自定义数据类型相加的运算 总结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; }

    2.左移运算符重载

    作用:可以输出自定义数据类型 总结:重载左移运算符配合友元可以实现输出自定义数据类型

    #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; }

    3.递增运算符重载

    通过重载递增运算符,实现自己的整型数据

    #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; }

    4.赋值运算符重载

    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; }

    5. 关系运算符重载

    **作用:**重载关系运算符,可以让两个自定义类型对象进行对比操作

    #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; }

    6. 函数调用运算符重载

    函数调用运算符 () 也可以重载 由于重载后使用的方式非常像函数的调用,因此称为仿函数 仿函数没有固定写法,非常灵活

    #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; }
    Processed: 0.012, SQL: 8