C++面向对象编程
封装:1.抽象出数据成员、成员函数
2.访问控制,类本身1)private 外界不可见,不能直接访问2)外界不可见,不能直接访问;子类可以访问protected3)public外界可以直接访问
继承:
继承访问控制:
1.不能直接拿父亲的私房钱:派生类不能访问基类的私有成员
2. 可以问父亲要钱:通过protected/public的成员函数
3. 儿子总是比外人亲:派生类可以访问父类的protected成员,其他代码不可以
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Father{ 8 private: 9 int money; 10 protected: 11 int room_key; 12 public: 13 void it_skill(void) 14 { 15 cout<<"father's it skill"<<endl; 16 } 17 int getMoney(void) 18 { 19 return money; 20 } 21 22 void setMoney(int money) 23 { 24 this->money = money; 25 } 26 27 }; 28 class Son : public Father{ 29 private: 30 int toy; 31 public: 32 void play_game(void) 33 { 34 int m; 35 /*money -= 1; 36 *错:不能直接拿父亲的私房钱 37 *但是可以问他要 38 */ 39 cout<<"son play game"<<endl; 40 m = getMoney(); 41 m -- ; 42 setMoney(m); 43 /*外人不能拿父亲的房间钥匙 44 *但是儿子可以 45 * 46 */ 47 room_key = 1; 48 } 49 }; 50 int main(int argc,char **argv) 51 { 52 Son s; 53 s.setMoney(10); 54 cout<<s.getMoney()<<endl; 55 56 s.it_skill(); 57 s.play_game(); 58 return 0; 59 }
1.无论哪种继承方式,在派生类内部使用父类时并无差别
2. 不同的继承方式,会影响这两方面:外部代码对派生类的使用、派生类的子类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Father{ 8 private: 9 int money; 10 protected: 11 int room_key; 12 public: 13 int address; 14 void it_skill(void) 15 { 16 cout<<"father's it skill"<<endl; 17 } 18 int getMoney(void) 19 { 20 return money; 21 } 22 23 void setMoney(int money) 24 { 25 this->money = money; 26 } 27 28 }; 29 class Son_pub : public Father{ 30 private: 31 int toy; 32 public: 33 using Father::room_key; 34 void play_game(void) 35 { 36 int m; 37 /*money -= 1; 38 *错:不能直接拿父亲的私房钱 39 *但是可以问他要 40 */ 41 cout<<"son play game"<<endl; 42 m = getMoney(); 43 m -- ; 44 setMoney(m); 45 /*外人不能拿父亲的房间钥匙 46 *但是儿子可以 47 * 48 */ 49 room_key = 1; 50 } 51 }; 52 53 class Son_pro : protected Father{ 54 private: 55 int toy; 56 public: 57 using Father::room_key; 58 void play_game(void) 59 { 60 int m; 61 /*money -= 1; 62 *错:不能直接拿父亲的私房钱 63 *但是可以问他要 64 */ 65 cout<<"son play game"<<endl; 66 m = getMoney(); 67 m -- ; 68 setMoney(m); 69 /*外人不能拿父亲的房间钥匙 70 *但是儿子可以 71 * 72 */ 73 room_key = 1; 74 } 75 }; 76 77 class Son_pri : private Father{ 78 private: 79 int toy; 80 public: 81 82 void play_game(void) 83 { 84 int m; 85 /*money -= 1; 86 *错:不能直接拿父亲的私房钱 87 *但是可以问他要 88 */ 89 cout<<"son play game"<<endl; 90 m = getMoney(); 91 m -- ; 92 setMoney(m); 93 /*外人不能拿父亲的房间钥匙 94 *但是儿子可以 95 * 96 */ 97 room_key = 1; 98 } 99 }; 100 101 class Grandson_pub : public Son_pub{ 102 public: 103 void test(void) 104 { 105 room_key = 1; 106 address = 2; 107 } 108 109 110 }; 111 112 class Grandson_pro:public Son_pro{ 113 public: 114 void test (void) 115 { 116 room_key = 1; 117 address = 2; 118 } 119 120 }; 121 122 class Grandson_pri:public Son_pri{ 123 public: 124 void test(void) 125 { 126 //room_key = 1; 127 //address = 2; 128 } 129 130 131 }; 132 133 int main(int argc,char **argv) 134 { 135 Son_pub s_pub; 136 Son_pro s_pro; 137 Son_pri s_pri; 138 139 140 s_pub.play_game(); 141 s_pro.play_game(); 142 s_pri.play_game(); 143 144 s_pub.it_skill(); 145 //s_pro.it_skill();//error次在s_pro中把Father的it_skill()函数由public改为了protected 146 //s_pri.it_skill();//error次在s_pri中把Father的it_skill()函数由public改为了private 147 148 Grandson_pub gs_pub; 149 Grandson_pro gs_pro; 150 151 gs_pub.address = 2; 152 //gs_pro.address = 2; // error 153 154 return 0; 155 }
调整访问控制:
儿子继承来的财产,他可以捐给别人,也可以私藏(前提:Son看得见这些财产):
Son可见到的成员,Son可以修改它的权限。private: using Father::getMoney;(Son的子类就是用不了Father中的getMoney()函数)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Father{ 8 private: 9 int money; 10 protected: 11 int room_key; 12 public: 13 void it_skill(void) 14 { 15 cout<<"father's it skill"<<endl; 16 } 17 int getMoney(void) 18 { 19 return money; 20 } 21 22 void setMoney(int money) 23 { 24 this->money = money; 25 } 26 27 }; 28 class Son : public Father{ 29 private: 30 int toy; 31 public: 32 using Father::room_key; 33 void play_game(void) 34 { 35 int m; 36 /*money -= 1; 37 *错:不能直接拿父亲的私房钱 38 *但是可以问他要 39 */ 40 cout<<"son play game"<<endl; 41 m = getMoney(); 42 m -- ; 43 setMoney(m); 44 /*外人不能拿父亲的房间钥匙 45 *但是儿子可以 46 * 47 */ 48 room_key = 1; 49 } 50 }; 51 int main(int argc,char **argv) 52 { 53 Son s; 54 s.setMoney(10); 55 cout<<s.getMoney()<<endl; 56 57 s.it_skill(); 58 s.play_game(); 59 s.room_key = 1;//因为在Son中改变了room_key的权限,所以可以访问 60 return 0; 61 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Father{ 8 private: 9 int money; 10 protected: 11 int room_key; 12 public: 13 void it_skill(void) 14 { 15 cout<<"father's it skill"<<endl; 16 } 17 int getMoney(void) 18 { 19 return money; 20 } 21 22 void setMoney(int money) 23 { 24 this->money = money; 25 } 26 27 }; 28 class Son_pub : public Father{ 29 private: 30 int toy; 31 public: 32 using Father::room_key; 33 void play_game(void) 34 { 35 int m; 36 /*money -= 1; 37 *错:不能直接拿父亲的私房钱 38 *但是可以问他要 39 */ 40 cout<<"son play game"<<endl; 41 m = getMoney(); 42 m -- ; 43 setMoney(m); 44 /*外人不能拿父亲的房间钥匙 45 *但是儿子可以 46 * 47 */ 48 room_key = 1; 49 } 50 }; 51 52 class Son_pro : protected Father{ 53 private: 54 int toy; 55 public: 56 using Father::room_key; 57 void play_game(void) 58 { 59 int m; 60 /*money -= 1; 61 *错:不能直接拿父亲的私房钱 62 *但是可以问他要 63 */ 64 cout<<"son play game"<<endl; 65 m = getMoney(); 66 m -- ; 67 setMoney(m); 68 /*外人不能拿父亲的房间钥匙 69 *但是儿子可以 70 * 71 */ 72 room_key = 1; 73 } 74 }; 75 76 class Son_pri : private Father{ 77 private: 78 int toy; 79 public: 80 using Father::room_key; 81 void play_game(void) 82 { 83 int m; 84 /*money -= 1; 85 *错:不能直接拿父亲的私房钱 86 *但是可以问他要 87 */ 88 cout<<"son play game"<<endl; 89 m = getMoney(); 90 m -- ; 91 setMoney(m); 92 /*外人不能拿父亲的房间钥匙 93 *但是儿子可以 94 * 95 */ 96 room_key = 1; 97 } 98 }; 99 100 int main(int argc,char **argv) 101 { 102 Son_pub s_pub; 103 Son_pro s_pro; 104 Son_pri s_pri; 105 106 107 s_pub.play_game(); 108 s_pro.play_game(); 109 s_pri.play_game(); 110 111 s_pub.it_skill(); 112 //s_pro.it_skill();//error次在s_pro中把Father的it_skill()函数由public改为了protected 113 //s_pri.it_skill();//error次在s_pri中把Father的it_skill()函数由public改为了private 114 return 0; 115 }
此为验证基类成员在派生类中的访问控制属性
复写基类中的函数,此时子类就会调用自己的与父类中相同名字的函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Father{ 8 private: 9 int money; 10 protected: 11 int room_key; 12 public: 13 int address; 14 void it_skill(void) 15 { 16 cout<<"father's it skill"<<endl; 17 } 18 int getMoney(void) 19 { 20 return money; 21 } 22 23 void setMoney(int money) 24 { 25 this->money = money; 26 } 27 28 }; 29 class Son : public Father{ 30 private: 31 int toy; 32 public: 33 using Father::room_key; 34 void play_game(void) 35 { 36 int m; 37 /*money -= 1; 38 *错:不能直接拿父亲的私房钱 39 *但是可以问他要 40 */ 41 cout<<"son play game"<<endl; 42 m = getMoney(); 43 m -- ; 44 setMoney(m); 45 /*外人不能拿父亲的房间钥匙 46 *但是儿子可以 47 * 48 */ 49 room_key = 1; 50 } 51 void it_skill(void)//复写了父类中的相同名字的函数 52 { 53 cout<<"son's it skill"<<endl; 54 } 55 }; 56 int main(int argc,char **argv) 57 { 58 Son s; 59 60 s.setMoney(10); 61 cout<<s.getMoney()<<endl; 62 63 s.it_skill(); 64 s.play_game(); 65 66 s.room_key = 1; 67 68 return 0; 69 }
派生类对象s的空间 :
money 基类部分 (Father)
toy 派生部分 (Son)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class person{ 8 private: 9 char *name; 10 int age; 11 public: 12 int address; 13 person() 14 { 15 name = NULL; 16 17 } 18 person (char*name) 19 { 20 this->name = new char[strlen(name)+1]; 21 strcpy(this->name,name); 22 } 23 person(char *name, int age) 24 { 25 cout <<"person(char*, int), name = "<<name<<", age= "<<age<<endl; 26 this->age = age; 27 28 this->name = new char[strlen(name) + 1]; 29 strcpy(this->name, name); 30 } 31 32 person(person &per) 33 { 34 cout <<"person(person &)"<<endl; 35 this->age = per.age; 36 37 this->name = new char[strlen(per.name) + 1]; 38 strcpy(this->name, per.name); 39 } 40 41 ~person() 42 { 43 cout << "~person()"<<endl; 44 if (this->name) { 45 cout << "name = "<<name<<endl; 46 delete this->name; 47 } 48 } 49 50 void setName(char *name) 51 { 52 if (this->name) { 53 delete this->name; 54 } 55 this->name = new char[strlen(name) + 1]; 56 strcpy(this->name, name); 57 } 58 int setAge(int a) 59 { 60 if (a < 0 || a > 150) 61 { 62 age = 0; 63 return -1; 64 } 65 age = a; 66 return 0; 67 } 68 void printInfo(void) 69 { 70 cout<<"name = "<<name<<", age = "<<age<<endl; 71 } 72 73 }; 74 class Student : public person { 75 private: 76 int grade; 77 void setGrade(int grade) {this->grade = grade;} 78 int getGrade(void) {return grade;} 79 public: 80 void printInfo(void)//复写 81 { 82 cout<<"Student "; 83 person::printInfo(); 84 } 85 }; 86 void test_func(person &p)//调用的person中的部分 87 { 88 p.printInfo(); 89 } 90 int main(int argc, char **argv) 91 { 92 person p("lisi", 16); 93 94 Student s; 95 s.setName("zhangsan"); 96 s.setAge(16); 97 98 test_func(p); 99 test_func(s); /* person &p = s里面的person部分; 100 * p引用的是"s里面的person部分" 101 *相当于是只是操作派生类student中继承的person部分的内容 102 */ 103 s.printInfo(); 104 105 return 0; 106 }
多继承:一个派生类可以有多个基类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Sofa{ 8 public: 9 void watchTV(void) 10 { 11 cout<<"watch TV"<<endl; 12 } 13 14 }; 15 class Bed{ 16 public: 17 void sleep(void) 18 { 19 cout<<"sleep"<<endl; 20 } 21 22 23 }; 24 class Sofabed : public Sofa,public Bed{ 25 26 27 }; 28 29 int main(int argc,char **argv) 30 { 31 Sofabed s; 32 s.watchTV(); 33 s.sleep(); 34 return 0; 35 }
问题:二义性
class Sofa里有weight, class Bed里也有weight
那么Sofabed就有2个weight,
既别扭,也有二义性──用哪个weight ?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Sofa{ 8 private: 9 int weight; 10 public: 11 void watchTV(void) 12 { 13 cout<<"watch TV"<<endl; 14 } 15 void setWeight(int weight) 16 { 17 this->weight = weight; 18 } 19 int getWeight(void)const 20 { 21 return weight; 22 } 23 24 }; 25 class Bed{ 26 private: 27 int weight; 28 public: 29 void sleep(void) 30 { 31 cout<<"sleep"<<endl; 32 } 33 void setWeight(int weight) 34 { 35 this->weight = weight; 36 } 37 int getWeight(void)const 38 { 39 return weight; 40 } 41 42 43 }; 44 class Sofabed : public Sofa,public Bed{ 45 46 47 }; 48 49 int main(int argc,char **argv) 50 { 51 Sofabed s; 52 s.watchTV(); 53 s.sleep(); 54 55 //s.setWeight(100);//出现二义性,不知道调用的是哪个类中setWeight()函数 56 s.Sofa::setWeight(100);//解决方法 57 return 0; 58 }
解决方法:虚基类使得:多个类派生出的对象只继承一个基类对象,即:Sofabed的基类Sofa, Bed共享一个Furniture对象
1.从Sofa, Bed中取出公共特性,创建新类Furniture: 它含有weight
2.Sofa, Bed虚拟继承Furniture
3.Sofabed多重继承Sofa, Bed
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Furniture{ 8 private: 9 int weight; 10 public: 11 void setWeight(int weight) 12 { 13 this->weight = weight; 14 } 15 int getWeight(void)const 16 { 17 return weight; 18 } 19 20 }; 21 22 class Sofa : virtual public Furniture{ 23 private: 24 int a; 25 public: 26 void watchTV(void) 27 { 28 cout<<"watch TV"<<endl; 29 } 30 31 }; 32 class Bed : virtual public Furniture{ 33 private: 34 int b; 35 public: 36 void sleep(void) 37 { 38 cout<<"sleep"<<endl; 39 } 40 }; 41 class Sofabed : public Sofa,public Bed{ 42 private: 43 int c; 44 45 }; 46 47 int main(int argc,char **argv) 48 { 49 Sofabed s; 50 s.watchTV(); 51 s.sleep(); 52 53 s.setWeight(100); 54 return 0; 55 }
构造顺序:
1. 虚拟基类构造函数:按继承顺序,只执行一次
2. 非虚拟基类构造函数:按继承顺序
3. 类的对象成员(按声明的顺序)
4. 类自己的构造函数
这个即为构造顺序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Furniture{ 8 private: 9 int weight; 10 public: 11 void setWeight(int weight) 12 { 13 this->weight = weight; 14 } 15 int getWeight(void)const 16 { 17 return weight; 18 } 19 Furniture() 20 { 21 cout<<"Furniture"<<endl; 22 } 23 24 }; 25 26 class Vertification3C{ 27 public: 28 Vertification3C(){cout<<"Verfification3C()"<<endl;} 29 30 }; 31 32 class Sofa : virtual public Furniture,virtual public Vertification3C{ 33 private: 34 int a; 35 public: 36 void watchTV(void) 37 { 38 cout<<"watch TV"<<endl; 39 } 40 Sofa(){cout<<"Sofa()"<<endl;} 41 42 }; 43 class Bed : virtual public Furniture{ 44 private: 45 int b; 46 public: 47 void sleep(void) 48 { 49 cout<<"sleep"<<endl; 50 } 51 Bed(){cout<<"Bed()"<<endl;} 52 }; 53 class Sofabed : public Sofa,public Bed{ 54 private: 55 int c; 56 public: 57 Sofabed() 58 { 59 cout<<"Sofabed()"<<endl; 60 } 61 62 }; 63 64 class LeftRightCom{ 65 public: 66 LeftRightCom(){cout<<"LeftRightCom"<<endl;} 67 }; 68 class Data{ 69 public: 70 Data(){cout<<"Data()"<<endl;} 71 }; 72 class Type{ 73 public: 74 Type(){cout<<"Type()"<<endl;} 75 }; 76 class LeftRightSofabed : public Sofabed, public LeftRightCom { 77 private: 78 Data date; 79 Type type; 80 81 public: 82 LeftRightSofabed() { cout <<"LeftRightSofabed()"<<endl; } 83 84 }; 85 86 int main(int argc,char **argv) 87 { 88 LeftRightSofabed s; 89 return 0; 90 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Furniture{ 8 private: 9 int weight; 10 public: 11 void setWeight(int weight) 12 { 13 this->weight = weight; 14 } 15 int getWeight(void)const 16 { 17 return weight; 18 } 19 Furniture() 20 { 21 cout<<"Furniture()"<<endl; 22 } 23 24 }; 25 26 class Vertification3C{ 27 public: 28 Vertification3C(){cout<<"Verfification3C()"<<endl;} 29 30 }; 31 32 class Sofa : virtual public Furniture,virtual public Vertification3C{ 33 private: 34 int a; 35 public: 36 void watchTV(void) 37 { 38 cout<<"watch TV"<<endl; 39 } 40 Sofa(){cout<<"Sofa()"<<endl;} 41 42 }; 43 class Bed : virtual public Furniture{ 44 private: 45 int b; 46 public: 47 void sleep(void) 48 { 49 cout<<"sleep"<<endl; 50 } 51 Bed(){cout<<"Bed()"<<endl;} 52 }; 53 class Sofabed : public Sofa,public Bed{ 54 private: 55 int c; 56 public: 57 Sofabed() 58 { 59 cout<<"Sofabed()"<<endl; 60 } 61 62 }; 63 64 class LeftRightCom{ 65 public: 66 LeftRightCom(){cout<<"LeftRightCom()"<<endl;} 67 }; 68 class Data{ 69 public: 70 Data(){cout<<"Data()"<<endl;} 71 }; 72 class Type{ 73 public: 74 Type(){cout<<"Type()"<<endl;} 75 }; 76 class LeftRightSofabed : public Sofabed,virtual public LeftRightCom { 77 private: 78 Data date; 79 Type type; 80 81 public: 82 LeftRightSofabed() { cout <<"LeftRightSofabed()"<<endl; } 83 84 }; 85 86 int main(int argc,char **argv) 87 { 88 LeftRightSofabed s; 89 return 0; 90 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <unistd.h> 4 5 using namespace std; 6 7 class Furniture{ 8 private: 9 int weight; 10 public: 11 void setWeight(int weight) 12 { 13 this->weight = weight; 14 } 15 int getWeight(void)const 16 { 17 return weight; 18 } 19 Furniture() 20 { 21 cout<<"Furniture()"<<endl; 22 } 23 24 }; 25 26 class Vertification3C{ 27 public: 28 Vertification3C(){cout<<"Verfification3C()"<<endl;} 29 30 }; 31 32 class Sofa : virtual public Furniture,virtual public Vertification3C{ 33 private: 34 int a; 35 public: 36 void watchTV(void) 37 { 38 cout<<"watch TV"<<endl; 39 } 40 Sofa(){cout<<"Sofa()"<<endl;} 41 42 }; 43 class Bed : virtual public Furniture,virtual Vertification3C{ 44 private: 45 int b; 46 public: 47 void sleep(void) 48 { 49 cout<<"sleep"<<endl; 50 } 51 Bed(){cout<<"Bed()"<<endl;} 52 }; 53 class Sofabed : public Sofa,public Bed{ 54 private: 55 int c; 56 public: 57 Sofabed() 58 { 59 cout<<"Sofabed()"<<endl; 60 } 61 Sofabed(char *abc){cout<<"Sofabed(char *abc)"<<endl;} 62 63 }; 64 65 class LeftRightCom{ 66 public: 67 LeftRightCom(){cout<<"LeftRightCom()"<<endl;} 68 LeftRightCom(char *abc) { cout <<"LeftRightCom(char *abc)"<<endl; } 69 }; 70 class Data{ 71 public: 72 Data(){cout<<"Data()"<<endl;} 73 Data(char *abc) { cout <<"Date(char *abc)"<<endl; } 74 }; 75 class Type{ 76 public: 77 Type(){cout<<"Type()"<<endl;} 78 Type(char *abc) { cout <<"Type(char *abc)"<<endl; } 79 }; 80 class LeftRightSofabed : public Sofabed,virtual public LeftRightCom { 81 private: 82 Data date; 83 Type type; 84 85 public: 86 LeftRightSofabed() { cout <<"LeftRightSofabed()"<<endl; } 87 LeftRightSofabed(char *str1, char *str2, char *str3) : Sofabed(str1), LeftRightCom(str2), date(str3) { cout <<"LeftRightSofabed()"<<endl; } 88 89 }; 90 91 int main(int argc,char **argv) 92 { 93 LeftRightSofabed s("abc", "2343", "yyy");; 94 return 0; 95 }