
1.友元类实现对数据的隐藏和封装类中的数据成员一般定义为私有类型这样的情况下类内通过成员函数才能够读取。友元是一种允许非成员函数或者非当前类的成员函数访问一个类的私有成员的一种机制破坏封装的特性。友元的实现方式友元函数友元类友元成员函数1.1 友元函数友元函数不属于任何一个类是类外的一个函数但是可以访问类内的私有成员。友元函数需要类内“声明”类外定义。例客厅 卧室#include iostream #include string #include string.h using namespace std; class Room { private: string bed_room$$$$$$$$$$; public: string living_room*****; // 声明友元函数 friend void fun(Room r); }; void fun(Room r) { cout r.living_room endl; cout r.bed_room endl; } int main() { Room r1; cout r1.living_room endl; fun(r1); return 0; }友元函数使用需要注意友元函数内部没有this指针友元函数的声明可以放置在类的任何位置不受权限修饰符的影响一个友元函数理论上可以访问多个类分类在每一个类中进行声明1.2 友元类当一个类B成为了另一个类Test的“好朋友”时类test中的所有成员都可以被类B访问此时类B就是类Test的友元类。#include iostream #include string #include string.h using namespace std; class Test { private: int a; public: Test(int a):a(a){} void fun() { cout a endl; } // 声明友元类 friend class B; }; class B { public : void test_print(Test t) { cout t.a endl; } void test_a(Test t) { cout t.a endl; } }; int main() { Test t1(10); t1.fun (); // 10 B b1; b1.test_print (t1); // 10 b1.test_a (t1); // 10 return 0; }友元类使用的时候需要注意友元关系不能继承友元关系不具有交换性友元关系不具有传递性1.3 友元成员函数使类B中的成员函数称为类Test的友元成员函数这样类B的该成员函数就是类Test的友元成员函数也就可以访问类Test的所有成员步骤在Test类中声明友元成员函数成员函数在类外进行定义在类B中声明此成员函数在类B之前声明类Test#include iostream #include string #include string.h using namespace std; // 4.在类B之前声明类Test class Test; class B { public: // 3.在类B中声明此成员函数 void test_friend(Test t); }; class Test { private: int a; public: Test(int a):a(a){} void fun() { cout a endl; } // 1.在Test类中声明友元成员函数 friend void B::test_friend(Test t); }; // 2.成员函数在类外进行定义 void B::test_friend(Test t) { cout t.a endl; } int main() { Test t1(100); B b1; b1.test_friend (t1); // 100 return 0; }2.运算符重载c中可以把部分的运算符看成是函数此时运算符也就是可以重载。本质是函数重载#include iostream #include string #include string.h using namespace std; class Test { private: int a; public: Test(int a):a(a){} int get_a() { return a; } }; int main() { Test t1(1); Test t2(1); Test t3 t1t2; // 报错 // int a11; // int b11; // int ca1b1; cout t3.get_a () endl;// 2 return 0; }重载的方式友元函数运算符重载成员函数运算符重载2.1 友元函数运算符重载双目运算为例运算符函数名operator 符号#include iostream #include string #include string.h using namespace std; class Test { private: int a; public: Test(int a):a(a){} int get_a() { return a; } friend Test operator (const Test t1,const Test t2); }; Test operator (const Test t1,const Test t2) { // Test t3; // t3.a t1.at2.a; // return t1.at2.a; return Test(t1.at2.a);} int main() { Test t1(1); Test t2(1); // Test t4t2; Test t3 t1 t2; cout t3.get_a () endl;// 2 return 0; }单目运算符为例#include iostream #include string #include string.h using namespace std; class Test { private: int a; public: Test(int a):a(a){} int get_a() { return a; } friend Test operator (const Test t1,const Test t2); friend Test operator (Test t1); // 前置 friend Test operator (Test t1,int); // 后置 }; Test operator (const Test t1,const Test t2) { // Test t3; // t3.a t1.at2.a; // return t1.at2.a; return Test(t1.at2.a); } Test operator (Test t1) { return t1.a; } Test operator (Test t1,int) { return t1.a; } int main() { Test t1(10); Test t2(1); // Test t4t2; Test t3 t1 t2; cout t3.get_a () endl;// 11 cout (t1).get_a () endl; // 11 cout (t1).get_a () endl; // 11 return 0; }2.2 成员函数运算符重载成员函数中有this指针所以成员函数运算符重载可以比友元函数运算符重载少一个参数。因为this指针默认接收第一个参数。this指针默认指向第一个参数#include iostream #include string #include string.h using namespace std; class Test { private: int a; public: Test(int a):a(a){} int get_a() { return a; } // friend Test operator (const Test t1,const Test t2); // friend Test operator (Test t1); // 前置 // friend Test operator (Test t1,int); // 后置 Test operator (const Test t2); Test operator (); // 前置 Test operator (int); // 后置 }; Test Test::operator (const Test t2) { return Test(this-at2.a); } Test Test::operator () { return this-a; } Test Test::operator (int) { return this-a; } int main() { Test t1(10); Test t2(1); // Test t4t2; Test t3 t1 t2; cout t3.get_a () endl;// 11 cout (t1).get_a () endl; // 11 cout (t1).get_a () endl; // 11 cout (t1).get_a () endl; // 12 return 0; }2.3 特殊运算符重载部分运算符不支持友元函数运算符重载只支持成员函数运算符重载。2.3.1 赋值运算符重载如果程序员不写那么编译器会自动添加#include iostream #include string #include string.h using namespace std; class Test { private: int a; public: Test(int a):a(a){} int get_a() { return a; } // 编译器添加的运算符重载 Test operator (const Test t) { cout 运算符 endl; this-at.a; return *this; } }; int main() { Test t1(10); Test t2(1); t2t1; // 调用赋值运算符重载 Test t3(t1);// 拷贝构造函数 Test t4t2; // 拷贝构造函数 return 0; }2.3.2 类型转换运算符重载必须使用成员函数运算符且格式比较特殊。函数名operator 要转化成的类型不需要写返回值的类型#include iostream #include string #include string.h using namespace std; class Test { private: int a; public: Test(int a):a(a){} int get_a() { return a; } // 编译器添加的运算符重载 Test operator (const Test t) { cout 运算符 endl; this-at.a; return *this; } operator int() { return this-a; } operator string() { string shello; return s; } }; int main() { Test t1(10); Test t2(1); t2t1; // 调用赋值运算符重载 int at1; string bt1; cout a endl;// 10 cout b endl;// string return 0; }注意重载的运算符一定在c语言中已经存在的运算符不能创建新的运算符所以运算符重载不支持函数的默认值重载时不能改变运算符的优先级以及结合性以及语义运算符重载必须包含自定义的数据类型一般情况下双目运算符建议使用友元函数运算符重载单目运算符建议使用成员函数运算符重载3.std:: string字符串类字符串对象是一种特殊类型的容器专门设计用于操作字符序列#include iostream #include string #include string.h using namespace std; int main() { string s; // 调用无参构造 // 判断是否为空 cout s.empty () endl; // 1 bool:true:1 false:0 string s1hello;// 调用有参构造 string s2(abc);// 调用有参构造 cout (s1s2) endl; // 0 string s3(s2); // 调用拷贝有参构造 s3s2 // 保留几个字符 // 参数1char * 字符串 // 参数2整型数值 string s4(ABCD,3); cout s4 endl; // ABC // 不保留前几个字符 // 参数1string 对象 // 参数2整型数值 string s5(s1,3); cout s5 endl; // lo // 保存几个字符 // 参数1整型数值 // 参数2char字符 string s6(5,A); cout s6 endl; // AAAAA // 交换 swap(s5,s6); cout s5 endl;// AAAAA cout s6 endl;// lo // 拼接 string s7s5s6; cout s7 endl;// AAAAAlo // 最后追加字符串 s7.append (hhhhh); cout s7 endl;// AAAAAlohhhhh // 最后追加字符 s7.push_back (B); cout s7 endl;// AAAAAlohhhhhB // 插入 // 参数1插入位置 // 参数2插入的内容 s7.insert (1,22); cout s7 endl;// A22AAAAlohhhhhB // 删除 // 参数1从第几个元素开始删除 // 参数2删除的字符数量 s7.erase (4,10); cout s7 endl;// A22AB // 替换 // 参数1起始位置(下标) // 参数2替换的字符个数 // 参数3替换的内容 s7.replace (1,2,*); cout s7 endl;// A*AB // 清空 s7.clear (); cout -----: s7 endl;// -----: // string --- char * char c[20]; strcpy(c,s5.c_str ()); // 在尾部会添加\0 cout c endl; // AAAAA char c1[20]; // string -- char * // 参数1保存的数组 // 参数2字符个数 // 参数3位置 s5.copy(c1,6,0); cout c1 endl;// AAAAA return 0; }