黑马程序员 4 类和对象
4.4友元
友元的目的是让一个函数或者是类 访问另一个函数的私有成员
友元的关键字为 friend
4.4.1全局函数做友元
1 #include2 #include<string> 3 using namespace std; 4 5 class Building 6 { 7 //goodGay全局函数是 Building好朋友,可以访问Buiding中私有成员 8 friend void goodGay(Building* building); 9 10 11 public: 12 Building() 13 { 14 m_SittingRoom = "客厅"; 15 m_BedRoom = "卧室"; 16 } 17 18 19 public: 20 string m_SittingRoom;//客厅 21 22 private: 23 string m_BedRoom;//卧室 24 }; 25 26 27 //全局函数 28 void goodGay(Building *building) 29 { 30 cout << "好基友全局函数 正在访问:" << building->m_SittingRoom << endl; 31 cout << "好基友全局函数 正在访问:" << building->m_BedRoom << endl; 32 } 33 34 void test01() 35 { 36 Building building; 37 goodGay(&building); 38 } 39 40 41 int main() 42 { 43 test01(); 44 return 0; 45 }
4.4.2类做友元
1 #include2 #include<string> 3 using namespace std; 4 5 //类做友元 6 class Building; 7 class GoodGay; 8 9 class GoodGay 10 { 11 public: 12 13 GoodGay(); 14 15 void visit();//参观函数 访问Building 中的属性 16 17 Building* building; 18 19 20 }; 21 22 class Building 23 { 24 //GoodGay类是本来的好朋友,可以访问本类中私有成员 25 friend class GoodGay; 26 27 public: 28 Building(); 29 30 31 public: 32 string m_SittingRoom;//客厅 33 private: 34 string m_BedRoom; 35 }; 36 37 //类外写成员函数 38 Building::Building() 39 { 40 m_SittingRoom = "客厅"; 41 m_BedRoom = "卧室"; 42 } 43 GoodGay::GoodGay() 44 { 45 //创建建筑物对象 46 building = new Building; 47 } 48 49 void GoodGay::visit() 50 { 51 cout << "好基友正在访问" << building->m_SittingRoom << endl; 52 cout << "好基友正在访问" << building->m_BedRoom << endl; 53 } 54 55 void test01() 56 { 57 GoodGay gg; 58 gg.visit(); 59 } 60 61 int main() 62 { 63 test01(); 64 65 return 0; 66 }
4.4.3成员函数做友元
1 #include2 #include<string> 3 using namespace std; 4 5 class Building; 6 class GoodGay 7 { 8 public: 9 10 GoodGay(); 11 12 void visit();//让visit函数可以访问Building中私有成员 13 void visit2();//让visit2函数不可以访问Building中的私有成员 14 15 Building* building; 16 }; 17 18 class Building 19 { 20 //告诉编译器 GoodGay类下的visit成员函数作为本类的好朋友,可以访问私有的成员 21 friend void GoodGay::visit(); 22 23 public: 24 Building(); 25 26 public: 27 string m_SittingRoom;//客厅 28 29 private: 30 string m_BedRoom;//卧室 31 32 }; 33 34 //类外实现成员函数 35 Building::Building() 36 { 37 m_SittingRoom = "客厅"; 38 m_BedRoom = "卧室"; 39 } 40 41 GoodGay::GoodGay() 42 { 43 building = new Building; 44 } 45 46 void GoodGay::visit() 47 { 48 cout << "visit函数正在访问:" << building->m_SittingRoom << endl; 49 cout << "visit函数正在访问:" << building->m_BedRoom << endl; 50 } 51 void GoodGay::visit2() 52 { 53 cout << "visit函数正在访问:" << building->m_SittingRoom << endl; 54 //cout << "visit函数正在访问:" << building->m_BedRoom << endl; 55 } 56 57 void test01() 58 { 59 GoodGay gg; 60 gg.visit(); 61 gg.visit2(); 62 63 } 64 65 int main() 66 { 67 test01(); 68 69 return 0; 70 }
4.5运算符
运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
4.5.1加号运算符重载
作用:实现两个自定义数据类型相加的运算
总结1:对于内置的数据类型的表达式的运算符是不可能改变的
总结2:不要滥用运算符重载
1 #include2 using namespace std; 3 //加号运算符重载 4 5 class Person 6 { 7 public: 8 9 //1.成员函数重载+号 10 //Person operator+(Person& p) 11 //{ 12 // Person temp; 13 // temp.m_A = this->m_A + p.m_A; 14 // temp.m_B = this->m_B + p.m_B; 15 // return temp; 16 //} 17 int m_A; 18 int m_B; 19 }; 20 //2.全局函数重载+号 21 Person operator+(Person& p1, Person& p2) 22 { 23 Person temp; 24 temp.m_A = p1.m_A + p2.m_A; 25 temp.m_B = p1.m_B + p2.m_B; 26 return temp; 27 } 28 //函数重载的版本 29 Person operator+(Person& p1, int num) 30 { 31 Person temp; 32 temp.m_A = p1.m_A + num; 33 temp.m_B = p1.m_B + num; 34 return temp; 35 } 36 37 void test01() 38 { 39 Person p1; 40 p1.m_A = 10; 41 p1.m_B = 10; 42 Person p2; 43 p2.m_A = 10; 44 p2.m_B = 10; 45 46 //成员函数重载本质调用 47 //Person p3 = p1.operator+(p2); 48 49 //全局函数重载的本质调用 50 Person p3 = operator+(p1, p2); 51 52 Person p3 = p1 + p2; 53 //运算符重载 也可以发生函数重载 54 55 Person p4 = p1 + 10;//Person +int 56 57 cout << "p3.m_A=" << p3.m_A << endl; 58 cout << "p3.m_B=" << p3.m_B << endl; 59 cout << "p4.m_A=" << p4.m_A << endl; 60 cout << "p4.m_B=" << p4.m_B << endl; 61 62 63 } 64 65 //1.成员函数重载+号 66 67 //2.全局函数重载+号 68 69 int main() 70 { 71 test01(); 72 return 0; 73 }
4.5.2左移运算符重载
1 #include2 using namespace std; 3 4 //左移运算符重载 5 6 class Person 7 { 8 public: 9 //利用成员函数重载 左移运算符 p.operator<<(cout) 简化版本 p< 10 //不会利用成员函数重载<<运算符,因为无法实现cout在左侧 11 12 13 int m_A; 14 int m_B; 15 }; 16 //只能利用全局函数重载左移运算符 17 ostream &operator<<(ostream &cout, Person &p)//本质 operator<<(cout ,p)简化 cout< 18 { 19 cout << "m_A=" << p.m_A << "m_B=" << p.m_B; 20 return cout; 21 } 22 23 24 void test01() 25 { 26 Person p; 27 p.m_A = 10; 28 p.m_B = 10; 29 30 cout << p << "hello world " << endl; 31 32 } 33 34 int main() 35 { 36 test01(); 37 38 return 0; 39 }
4.5.3自增运算符重载
1 #include2 using namespace std; 3 //重载自增运算符 4 //自定义整型 5 6 class MyInteger 7 { 8 friend ostream& operator<<(ostream& cout, MyInteger myint); 9 public: 10 MyInteger() 11 { 12 m_Num = 0; 13 } 14 15 //重载前置++运算符 返回引用为了一直对一个数据进行递增操作 16 MyInteger& operator++() 17 { 18 //先进行++运算 19 m_Num++; 20 21 //再将自身做范围 22 return *this; 23 } 24 25 //重载后置++运算符 26 27 //void operator++(int) int代表占位参数,可以用于区分前置和后置递增 28 MyInteger operator++(int) 29 { 30 //先 记录当时结果 31 MyInteger temp = *this; 32 //后 递增 33 m_Num++; 34 //最后将记录结果做返回 35 return temp; 36 } 37 38 private: 39 int m_Num; 40 }; 41 42 //重载一下左移运算符 43 ostream& operator<<(ostream& cout, MyInteger myint) 44 { 45 cout << myint.m_Num; 46 return cout; 47 } 48 49 void test01() 50 { 51 MyInteger myint; 52 53 cout << ++(++myint) << endl; 54 cout << myint << endl; 55 } 56 57 void test02() 58 { 59 MyInteger myint; 60 61 cout << myint++ << endl; 62 cout << myint << endl; 63 } 64 65 int main() 66 { 67 test01(); 68 test02(); 69 70 //int a = 0; 71 // 72 //cout << ++(++a) << endl; 73 //cout << a << endl; 74 75 76 return 0; 77 }
4.5.4关系运算符重载
1 #include2 using namespace std; 3 //赋值运算符重载 4 class Person 5 { 6 7 public: 8 9 Person(int age) 10 { 11 m_Age=new int(age); 12 } 13 14 ~Person() 15 { 16 if (m_Age != NULL) 17 { 18 delete m_Age; 19 m_Age = NULL; 20 } 21 } 22 //重载赋值运算符 23 Person& operator=(Person& p) 24 { 25 //编译器提供浅拷贝 26 //m_Age = p.m_Age; 27 28 //应该先判断是否有属性在堆区,如果有,先释放干净,然后再深拷贝 29 if (m_Age != NULL) 30 { 31 delete m_Age; 32 m_Age = NULL; 33 } 34 //深拷贝 35 m_Age = new int(*p.m_Age); 36 37 //返回对象本身 38 return *this; 39 } 40 41 int *m_Age; 42 43 }; 44 45 void test01() 46 { 47 Person p1(18); 48 49 Person p2(20); 50 51 Person p3(30); 52 53 p3=p2 = p1;//赋值操作 54 55 cout << "p1的年龄为:" << *p1.m_Age << endl; 56 cout << "p2的年龄为:" << *p2.m_Age << endl; 57 cout << "p3的年龄为:" << *p3.m_Age << endl; 58 } 59 60 int main() 61 { 62 test01(); 63 64 /*int a = 10; 65 int b = 20; 66 int c = 30; 67 68 c = b = a; 69 70 cout << "a=" << a << endl; 71 cout << "b=" << b << endl; 72 cout << "c=" << c << endl;*/ 73 74 75 76 77 78 system("pause"); 79 return 0; 80 }
4.5.5关系运算符重载
1 #include2 #include<string> 3 using namespace std; 4 5 //重载关系运算符 6 7 class Person 8 { 9 public: 10 Person(string name, int age) 11 { 12 m_Name = name; 13 m_Age = age; 14 } 15 //重载==号 16 17 bool operator==(Person &p) 18 { 19 if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) 20 { 21 return true; 22 } 23 return false; 24 } 25 bool operator!=(Person& p) 26 { 27 if (this->m_Name == p.m_Name && this->m_Age == p.m_Age) 28 { 29 return false; 30 } 31 return true; 32 } 33 34 string m_Name; 35 int m_Age; 36 }; 37 38 void test01() 39 { 40 Person p1("Tom", 18); 41 42 Person p2("Tom", 18); 43 44 if (p1 == p2) 45 { 46 cout << "p1和p2是相等的" << endl; 47 } 48 49 50 } 51 52 int main() 53 { 54 test01(); 55 return 0; 56 }
4.5.4函数调用运算符重载
1 #include2 #include<string> 3 using namespace std; 4 //函数调用运算符重载 5 6 //打印输出类 7 class MyPrint 8 { 9 public: 10 //重载函数调用运算符 11 void operator()(string test) 12 { 13 cout << test << endl; 14 } 15 }; 16 17 void Myprint02(string test) 18 { 19 cout << test << endl; 20 } 21 22 void test01() 23 { 24 MyPrint myPrint; 25 26 myPrint("hello world");//由于使用起来非常类似于函数调用,因此成为仿函数 27 28 Myprint02("hello world"); 29 } 30 //仿函数非常灵活,没有固定写法 31 //加法类 32 33 class MyAdd 34 { 35 public: 36 37 int operator()(int num1,int num2) 38 { 39 return num1 + num2; 40 } 41 }; 42 43 void test02() 44 { 45 MyAdd myadd; 46 int ret=myadd(100, 100); 47 cout << "ret=" << ret << endl; 48 49 //匿名函数对象 50 cout << MyAdd()(100, 100) << endl; 51 } 52 53 int main() 54 { 55 //test01(); 56 test02(); 57 return 0; 58 }
4.6继承
4.6.1继承的基本语法
1 #include2 using namespace std; 3 4 //普通实现页面 5 6 //Java页面 7 // 8 //class Java 9 //{ 10 //public: 11 // void header() 12 // { 13 // cout << "首页、公开课、登录、注册...(公共头部)" << endl; 14 // } 15 // void footer() 16 // { 17 // cout << "帮助中心、交流合作、站内地图..(公共底部)." << endl; 18 // 19 // } 20 // void left() 21 // { 22 // cout << "Java、Python、C++、...(公共分类列表" << endl; 23 // } 24 // void content() 25 // { 26 // cout << "Java学科视频" << endl; 27 // } 28 //}; 29 // 30 ////Python页面 31 //class Python 32 //{ 33 //public: 34 // void header() 35 // { 36 // cout << "首页、公开课、登录、注册...(公共头部)" << endl; 37 // } 38 // void footer() 39 // { 40 // cout << "帮助中心、交流合作、站内地图..(公共底部)." << endl; 41 // 42 // } 43 // void left() 44 // { 45 // cout << "Java、Python、C++、...(公共分类列表" << endl; 46 // } 47 // void content() 48 // { 49 // cout << "Python学科视频" << endl; 50 // } 51 //}; 52 ////C++页面 53 //class CPP 54 //{ 55 //public: 56 // void header() 57 // { 58 // cout << "首页、公开课、登录、注册...(公共头部)" << endl; 59 // } 60 // void footer() 61 // { 62 // cout << "帮助中心、交流合作、站内地图..(公共底部)." << endl; 63 // 64 // } 65 // void left() 66 // { 67 // cout << "Java、Python、C++、...(公共分类列表" << endl; 68 // } 69 // void content() 70 // { 71 // cout << "C++学科视频" << endl; 72 // } 73 //}; 74 75 //继承实现页面 76 77 //公共页面类 78 class BasePage 79 { 80 public: 81 void header() 82 { 83 cout << "首页、公开课、登录、注册...(公共头部)" << endl; 84 } 85 void footer() 86 { 87 cout << "帮助中心、交流合作、站内地图..(公共底部)." << endl; 88 89 } 90 void left() 91 { 92 cout << "Java、Python、C++、...(公共分类列表" << endl; 93 } 94 }; 95 //Java页面 96 class JAVA :public BasePage 97 { 98 public: 99 void content() 100 { 101 cout << "Java学科视频" << endl; 102 } 103 }; 104 class Python :public BasePage 105 { 106 public: 107 void content() 108 { 109 cout << "Python学科视频" << endl; 110 } 111 }; 112 class CPP :public BasePage 113 { 114 public: 115 void content() 116 { 117 cout << "C++学科视频" << endl; 118 } 119 }; 120 121 void test01() 122 { 123 cout << "Java下载视频页面如下:" << endl; 124 JAVA ja; 125 ja.header(); 126 ja.footer(); 127 ja.left(); 128 ja.content(); 129 130 cout << "--------------" << endl; 131 cout << "Python下载视频页面如下:" << endl; 132 Python py; 133 py.header(); 134 py.footer(); 135 py.left(); 136 py.content(); 137 138 cout << "--------------" << endl; 139 cout << "C++下载视频页面如下:" << endl; 140 CPP cpp; 141 cpp.header(); 142 cpp .footer(); 143 cpp.left(); 144 cpp.content(); 145 } 146 147 148 149 150 int main() 151 { 152 test01(); 153 return 0; 154 }