在c++中通过类定义对象,而类与类之间也有着复杂的关系,所以题外话,我能理解到c++的编写者可能就想通过计算机语言去模拟世界万物之间的关系,这篇帖子主要从横向和纵向去讨论类之间关系

而在一个类中想要使用另一个类中的内容,无非三种方式,1.直接传参 2.传地址 3.在一个类中去定义另一个类

从横向来看,可以分为1.依赖 2.关联 3.聚合 4.复合,接下来用UML类图展示一下这几种横向关系

 

 第一种,依赖,一个对象的一个功能需要依赖另一个对象存在,被依赖的对象作为工具使用,   在上图的例子中,CComputer 这个类对于CPerson来说,是作为Coding的一个工具,CComputer不是CPerson的一个特性,所以是依赖关系

第二种,关联,就类似于朋友之间的平等关系,关联的特点是随时建立,随时解除,利用指针去指向CFriend的地址

第三种,聚合,相当于强版本的关联,但聚合的目的是为了统一进行管理同类型的对象,就像是一个家庭,或者是一个班级,所以一般这里的对象都需要new出来的, 在聚合的析构里可以统一删除,统一创建

第四种,复合,又叫组合,是属于CPerson的一部分,类似于脑袋,双手

之所以建立这种类之间的关系,也是根据c++的单一性这个特点,每一个部分都是一个独立的个体,一个类的修改不会影响到其他的部分,也可以进行任意组合,下面是针对这个类图的代码

  1 #include <iostream>
  2 #include <time.h>
  3 using namespace std;
  4 
  5 
  6 class CHead
  7 {
  8 public:
  9     void Say()
 10     {
 11         cout << "张个大嘴,哇啦哇啦" << endl;
 12     }
 13 };
 14 
 15 class CHand
 16 {
 17 public:
 18     void Move()
 19     {
 20         cout << "比比划划" << endl;
 21     }
 22 };
 23 
 24 class CComputer
 25 {
 26 public:
 27     void Coding()
 28     {
 29         cout << "C++ Coding....." << endl;
 30     }
 31 };
 32 
 33 class CFriend
 34 {
 35 public:
 36     int rp;
 37 public:
 38     CFriend()
 39     {
 40         rp = rand()%10;
 41     }
 42 public:
 43     void Play()
 44     {
 45         cout << "哈哈哈哈哈哈" << endl;
 46     }
 47 };
 48 
 49 
 50 
 51 class CPerson
 52 {
 53 public:
 54     CHead head;    //  组合
 55     CHand hand;
 56     CFriend* m_pFriend;   //  关联一个朋友
 57 public:
 58     CPerson()
 59     {
 60         m_pFriend = 0;
 61     }
 62 public:
 63     void FindFriend(CFriend* pFriend)
 64     {
 65         if(pFriend == 0)
 66             return;
 67 
 68         if(pFriend->rp > 4)
 69         {
 70             m_pFriend = pFriend;
 71         }
 72     }
 73     void ChickenDinner()
 74     {
 75         if(m_pFriend == 0)
 76         {
 77             cout << "~~~~(>_<)~~~~玩的不开心" << endl;
 78         }
 79         else
 80         {
 81             m_pFriend->Play();
 82         }
 83     }
 84     void Say()
 85     {
 86         head.Say();
 87         hand.Move();
 88     }
 89     void Coding(CComputer& cm)   //  依赖一个电脑
 90     {
 91         head.Say();
 92         cm.Coding();
 93     }
 94 };
 95 
 96 
 97 
 98 class CFamily
 99 {
100 public:
101     CPerson* pArr[5];    //  聚合到 家庭中
102 public:
103     CFamily()
104     {
105         for(int i=0;i<5;i++)
106             pArr[i] = 0;
107     }
108     ~CFamily()
109     {
110         for(int i=0;i<5;i++)
111         {
112             if(pArr[i] != 0)
113             {
114                 delete pArr[i];
115                 pArr[i] = 0;
116             }
117         }
118     }
119 public:
120     void PushPerson(CPerson* ps)
121     {
122         if(ps == 0)
123             return;
124         for(int i=0;i<5;i++)
125         {
126             if(pArr[i] == 0)
127             {
128                 pArr[i] = ps;
129                 return;
130             }
131         }
132     }
133     void AllPersonCoding(CComputer& cm)
134     {
135         for(int i=0;i<5;i++)
136         {
137             if(pArr[i] != 0)
138             {
139                 pArr[i]->Coding(cm);
140             }
141         }        
142     }
143 };
144 
145 
146 
147 
148 int main()
149 {
150 
151     //srand((unsigned int)time(0));
152 
153     //CComputer cm;
154     //CFriend ff;
155 
156     //CPerson ps;
157     //ps.Say();
158     //ps.Coding(cm);
159 
160     //ps.FindFriend(&ff);
161     //ps.ChickenDinner();
162 
163     //--------------------------------------------------
164     CPerson* ps1 = new CPerson;
165     CPerson* ps2 = new CPerson;
166     CPerson* ps3 = new CPerson;
167 
168     CComputer cm;
169     CFamily fm;
170     fm.PushPerson(ps1);
171     fm.PushPerson(ps2);
172     fm.PushPerson(ps3);
173     fm.AllPersonCoding(cm);
174 
175     system("pause");
176     return 0;
177 }

 

而从纵向关系来看的关系有1.继承 2.多态

首先来说继承,继承中分为基类(父类),派生类(子类),继承的优点就是,提高代码的复用性,在派生类中,基类的所有成员都可以使用,而具体能否使用就得看继承的方式了

a.public继承,子类,public不变,protected不变,private变成不可访问的

b.protected 继承,子类,public->protected, protected不变, private变成不可访问的

c.private继承,子类,public->private, protected->private,private变成不可访问的

而需要注意的两点是

  1. 继承的方式影响的是派生类的派生类
  2. 继承的方式影响的只是基类的成员,不影响本类的访问修饰符

 

继承中还有一点就是继承关系的构造析构

  1. 继承里子类构造的初始化列表里默认为父类的初始化(很重要的一点)
  2. 局部顺序

子类构造->子类初始化列表->完成父类构造->完成子类构造->完成子类析构->回收子类空间->完成父类析构(在虚析构当中,虚函数完成的只是通过父类析构找到子类析构的过程,之后的过程和这个是一样的)

做一个小实验可以很好的看出来顺序

 1 #include<iostream>
 2 using namespace std;
 3 
 4 class CPerson
 5 {
 6 public:
 7     CPerson()
 8     {
 9         cout << "CPerson()" << endl;
10     }
11     ~CPerson()
12     {
13         cout << "~CPerson()" << endl;
14     }
15 };
16 class CSon : public CPerson
17 {
18 public:
19     CSon()
20     {
21         cout << "CSon" << endl;
22     }
23     ~CSon()
24     {
25         cout << "~CSon" << endl;
26     }
27 };
28 int main()
29 {
30     {
31         CSon cs;
32     }
33 
34 
35 
36     system("pause");
37     return 0;
38 }

 

第二个,多态,可以看一下上一篇帖子里 对于多态的讨论

 

 

2019-05-30 11:31:45 编程小菜鸟自我反思,大家可以留下自己的建议和意见,谢谢!!!

posted on 2019-05-30 11:32  coding小菜鸟  阅读(819)  评论(0编辑  收藏  举报