C++面向对象编程原则及人类示例

来源:互联网 发布:三层和唐唐的淘宝店 编辑:程序博客网 时间:2024/06/02 04:23
================================================================================
标题: C++面向对象编程原则及人类示例
作者: 叶飞虎
日期: 2017.10.12
--------------------------------------------------------------------------------

1. 概述
   在 C++ 面向对象编程中,有很多开发人员无法把控类,以及应该如何编写。在编写类时
有几个原则必须遵循,这样可以使类拥有健壮性及可用性。人类示例 TPerson 描述了类的
生命力,以及类的属性、行为和事件。

   面向对象编程的二个基本特征:封装和继承。
   封装的目的是为了信息隐藏,并保证类数据成员的私有性和一致性,同时数据成员之间
是强耦合,而类与类之间应该弱耦合。

   继承的目的是为了扩充类的多样性,多继承和多态都是继承的扩展方式,而继承会增加
类与类之间的耦合性。


2. 面向对象编程的遵循原则
   a. 类的数据成员尽量放在 private 中,若要开放信息可以通过 public 属性方法操作。
   b. 类属性方法分为: 读取属性和设置属性,读取属性方法名直接用属性名无需添加前缀,
      而设置属性方法前面必须添加前缀 "Set" 并后跟属性名。
   c. 类提供的 public 方法必须具有完备性,如:"Add" 则有 "Delete","Begin" 则有
      "End","Open" 则有 "Close","Start" 则有 "Stop" 等等。
   d. 类的 public 方法必须具有防御能力,保证类成员数据安全,类就像一个封闭的城池,
      public 方法就像城门,为了保证城池安全必须在城门有检查,只有这样才能使城池
      内事物免受破坏。
   e. 类少用继承而多用聚合,通过聚合的方式封装在新的类中,让聚合的成员之间通过行
      为和事件进行关联,并形成成员间的强耦合。若要继承最好使用单类继承,而且单类
      继承也能够解决多类继承问题,即通过聚合新类并继承即可。
   f. 若类内部存在主动向外发起动作时,应该设置事件,并通过事件方式来解决未来问题。
      对象事件就是一个开放的接口,能够绑定相同类型参数和返回值的对象方法,因为无
      需知道方法所属类就可以调用对象方法,具体使用可参见 TPerson 类。


3. 示例代码, 请参见 "Person.cpp"
// =======================================// Unit   : 面向对象编程的人类示例// Version: 1.0.0.0 (build 2017.10.12)// Author : 叶飞虎// Email  : kyee_ye(at)126.com// Copyright (C) Kyee workroom// =======================================// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/* TPerson - 人类 */class TPerson{public:   // 人的存在状态   enum TState   {psNothing,           // 虚无                  psEnding,            // 正在消亡                  psComing,            // 正在孕育                  psLiving};           // 活着   // 性别   enum TSex     {sexUnknown,          // 未知                  sexFemale,           // 女性                  sexMale,             // 男性                  sexNeuter,           // 中性                  sexF2Male,           // 女变性男                  sexM2Female};        // 男变性女   // 其他类别   // ??? ... ...public:   // OnSound 事件   typedef void (TObject::*TDoSound)(void* Sender, const TAudio& ASound);   typedef struct   {      TDoSound    Method;      void*       Object;   } TOnSound;   // OnView 事件   typedef void (TObject::*TDoView)(void* Sender, const TAction& AView);   typedef struct   {      TDoView     Method;      void*       Object;   } TOnView;   // 其他事件   // ??? ... ...public:   TPerson();   virtual ~TPerson();   // 属性   TState         State() const        { return FState; }   bool           Living() const       { return FState == psLiving; }   TDateTime      Birthday() const     { return FBirthday; }   TDateTime      Deathday() const     { return FDeathday; }   THeadInfo      HeadInfo();                            // 如: 头发、五官信息等等   TBodyInfo      BodyInfo();                            // 如: 三围信息等等   TLimbInfo      LimbInfo();                            // 如: 上、下肢信息等等   // ??? ... ...   bool           CanProcreate() const                   // 是否能生育只是从性别上判断                  { return (FSex == sexFemale) || (FSex == sexMale); }   TSex           Sex() const          { return FSex; }  // 性别   KYString       Name() const         { return FSocialInfo.Name(); }   KYString       CertID() const       { return FSocialInfo.CertID(); }   TSocialInfo&   SocialInfo()         { return FSocialInfo; }   // ??? ... ...   TPerson*       Father() const       { return FFather; }   TPerson*       Mother() const       { return FMother; }   long           MateCount() const    { return FMates.Count(); }   TPerson*       Mate(long AIndex) const                  { return (TPerson*)FMates[AIndex]; }   long           ChildCount() const   { return FChildren.Count(); }   TPerson*       Child(long AIndex) const                  { return (TPerson*)FChildren[AIndex]; }   // 设置属性   bool           SetName(const KYString& AName)         // 设置姓名                  { return FSocialInfo.SetName(AName); }   bool           SetCertID(const KYString& ACertID)     // 设置身份标识                  { return FSocialInfo.SetCertID(ACertID); }   // ??? ... ...   // 设置事件   bool           SetOnSound(void* AObject, TDoSound ADoSound);   bool           SetOnView(void* AObject, TDoView ADoView);   // ??? ... ...   // 生命的开始/结束   bool           Begin(TPerson* AFather, TPerson* AMother);   void           End(bool ANeedWait);   // 呼吸/喝/吃   void           Breathe(const TGas& AGas);   void           Drink(const TLiquid& ALiquid);   void           Eat(const TSolid& ASolid);   // ??? ... ...   // 听到声音/看到景象/躯体感受外部信息..   void           Listen(void* Sender, const TAudio& ASound);   void           See(void* Sender, const TAction& AView);   // ??? ... ...   // 结婚/生子   void           Marry(TPerson* AMate);   TPerson*       MakeChild(TPerson* AMate);   // 其他方法   // ??? ... ...protected:   // 状态锁   void           Lock() const         { FLock.Enter(); }   void           Unlock() const       { FLock.Leave(); }   // 状态引用计数增/减 1   bool           IncRefCount();   void           DecRefCount()        { InterlockedDecrement(&FRefCount); }   // 对象次数增/减 1   long           IncObjTimes()        { return InterlockedIncrement(&FObjTimes); }   long           DecObjTimes()        { return InterlockedDecrement(&FObjTimes); }   // 发出声音/产生外观活动/产生性别   void           DoSound(const TAudio& ASound);   void           DoView(const TAction& AView);   void           DoSex(TSex ASex);   // ??? ... ...private:   // 执行初始化/释放相关对象   bool           DoInitObjs();   void           DoFreeObjs();   // 执行开始/结束   bool           DoBegin(TPerson* AFather, TPerson* AMother);   void           DoEnd();   // ??? ... ...private:   TKYCritSect    FLock;               // 状态锁   TState         FState;              // 当前状态   long           FRefCount;           // 状态引用计数   long           FObjTimes;           // 对象引用次数   TDateTime      FBirthday;           // 对象出生时间   TDateTime      FDeathday;           // 对象消亡时间   // 对象的内在实体对象: 内在对象之间强耦合, 并通过血管和神经元关联, 而 DNA 直   //                     接控制实体对象的变化, 产生物种的相似性和多样性。   // 注: 当对象消亡时, 其内在实体对象也随之消亡   TDNA*          FDNA;                // DNA 对象   THead*         FHead;               // 头对象   TBody*         FBody;               // 躯体对象   TLimb*         FLimb;               // 肢体对象   // ??? ... ...   // 对象社会特征   TSex           FSex;                // 性别   TSocialInfo    FSocialInfo;         // 如: 身份证号、姓名、籍贯等等   // ??? ... ...   // 对象关系   TPerson*       FFather;             // 父亲   TPerson*       FMother;             // 母亲   TKYList        FMates;              // 配偶列表   TKYList        FChildren;           // 孩子列表   // 事件   TOnSound       FOnSound;            // 发出声音事件, 如: 说话、鼓掌等等   TOnView        FOnView;             // 行为展示事件, 如: 跳舞等等   // ??? ... ...public:   // 对象引用计数增/减 1(注: APerson 对象必须存在)   static long    _IncRefPerson(TPerson* APerson)                  { return APerson->IncObjTimes(); }   static void    _DecRefPerson(TPerson* APerson)                  { if (APerson->DecObjTimes() == 0) delete APerson; }};// ---------------- 构造函数和析构函数 ----------------// 构造函数TPerson::TPerson() : FMates(true), FChildren(true){   // 初始化   FState         = psNothing;   FRefCount      = 0;   FObjTimes      = 1;   FBirthday      = 0;   FDeathday      = 0;   FDNA           = NULL;   FHead          = NULL;   FBody          = NULL;   FLimb          = NULL;   // ??? ... ...   FSex           = sexUnknown;   // ??? ... ...   FFather        = NULL;   FMother        = NULL;   FOnSound.Method= NULL;   FOnSound.Object= NULL;   FOnView.Method = NULL;   FOnView.Object = NULL;   // 创建对象   // ??? ... ...}// 析构函数TPerson::~TPerson(){   // 生命结束   End(true);   // 释放对象   // ??? ... ...}// ---------------- 私有函数 ----------------// 执行初始化相关对象bool TPerson::DoInitObjs(){   // 初始化   bool result = false;   // 创建 DNA 对象   FDNA  = new TDNA(this);   if (FDNA != NULL)   {      // 创建对象列表      FHead = new THead(this, FDNA);      FBody = new TBody(this, FDNA);      FLimb = new TLimb(this, FDNA);      // 判断是否创建成功      if ((FHead != NULL) && (FBody != NULL) && (FLimb != NULL))      {         // 连接各个对象之间的血管及神经元, 神经中枢在头部对象中         // ??? ... ...         // 设置 FHead 对象事件         FHead->SetOnSound(&TPerson::DoSound);         FHead->SetOnView(&TPerson::DoView);         // ??? ... ...         // 设置 FBody 对象事件         FBody->SetOnSound(&TPerson::DoSound);         FBody->SetOnView(&TPerson::DoView);         FBody->SetOnSex(&TPerson::DoSex);         // ??? ... ...         // 设置 FLimb 对象事件         FLimb->SetOnSound(&TPerson::DoSound);         FLimb->SetOnView(&TPerson::DoView);         // ??? ... ...         // 成功         result = true;      }      else      {         FreeAndNil(FHead);         FreeAndNil(FBody);         FreeAndNil(FLimb);         FreeAndNil(FDNA);      }   }   // 返回结果   return result;}// 执行释放相关对象void TPerson::DoFreeObjs(){   FreeAndNil(FHead);   FreeAndNil(FBody);   FreeAndNil(FLimb);   FreeAndNil(FDNA);}// 执行开始bool TPerson::DoBegin(TPerson* AFather, TPerson* AMother){   // 初始化   bool result = false;   // 生命只有一次   if ((FMother == NULL) && (AFather != NULL) && (AMother != NULL)                         && (AFather != this) && (AFather != AMother)                         && (AMother != this) && AFather->IncRefCount())   {      if (AMother->IncRefCount())      {         // 能否可以生育         if (AFather->CanProcreate() && AMother->CanProcreate()                                     && (AFather->FSex == sexMale)                                     && (AMother->FSex == sexFemale)                                     && DoInitObjs())         {            // 父母对象            FFather = AFather;            FMother = AMother;            // DNA 继承自父母, 并孕育生命            if (FDNA->Inherit(FFather->FDNA, FMother->FDNA) && DoGestate())            {               FBirthday = Now();               result    = true;            }            else               DoFreeObjs();         }         // 引用计数减 1         AMother->DecRefCount();      }      // 引用计数减 1      AFather->DecRefCount();   }   // 返回结果   return result;}// 执行结束void TPerson::DoEnd(){   // 通知内在实体对象衰竭   FHead->Crash();   FBody->Crash();   FLimb->Crash();   // ??? ... ...   // 等待引用计数为 0   while (FRefCount > 0)      Sleep(8);   // 消亡时间   FDeathday = Now();   // 内在实体对象结束   FHead->End();   FBody->End();   FLimb->End();   FDNA->End();   // ??? ... ...   // 执行释放相关对象   DoFreeObjs();}// ---------------- 保护函数 ----------------// 引用计数加 1bool TPerson::IncRefCount(){   // 初始化   bool result = false;   // 引用计数加 1   InterlockedIncrement(&FRefCount);   if (FState == psLiving)      result = true;   else      InterlockedDecrement(&FRefCount);   // 返回结果   return result;}// 发出声音void TPerson::DoSound(const TAudio& ASound){   // 初始化   TOnSound OnSound;   OnSound.Method = NULL;   // 取事件   Lock();   if (FState == psLiving)      OnSound = FOnSound;   Unlock();   // 激发 OnSound 事件   if (OnSound.Method != NULL)      ((TObject*)OnSound.Object->*OnSound.Method)(this, ASound);}// 产生外观活动void TPerson::DoView(const TAction& AView){   // 初始化   TOnView OnView;   OnView.Method = NULL;   // 取事件   Lock();   if (FState == psLiving)      OnView = FOnView;   Unlock();   // 激发 OnView 事件   if (OnView.Method != NULL)      ((TObject*)OnView.Object->*OnView.Method)(this, AView);}// 产生性别void TPerson::DoSex(TSex ASex){   FSex = ASex;}// ---------------- 公有函数 ----------------// 如: 头发、五官信息等等THeadInfo TPerson::HeadInfo(){   // 初始化   THeadInfo result;   // 引用计数加 1   if (IncRefCount())   {      // 取头部信息      result = FHead->Info();      // 引用计数减 1      DecRefCount();   }   // 返回结果   return result;}// 如: 三围信息等等TBodyInfo TPerson::BodyInfo(){   // 初始化   TBodyInfo result;   // 引用计数加 1   if (IncRefCount())   {      // 取躯体信息      result = FBody->Info();      // 引用计数减 1      DecRefCount();   }   // 返回结果   return result;}// 如: 上、下肢信息等等TLimbInfo TPerson::LimbInfo(){   // 初始化   TLimbInfo result;   // 引用计数加 1   if (IncRefCount())   {      // 取肢体信息      result = FLimb->Info();      // 引用计数减 1      DecRefCount();   }   // 返回结果   return result;}// 设置 OnSound 事件bool TPerson::SetOnSound(void* AObject, TDoSound ADoSound){   // 初始化   bool result = false;   // 判断状态   Lock();   if (FState == psLiving)   {      FOnSound.Object = AObject;      FOnSound.Method = ADoSound;      result          = true;   }   Unlock();   // 返回结果   return result;}// 设置 OnView 事件bool TPerson::SetOnView(void* AObject, TDoView ADoView){   // 初始化   bool result = false;   // 判断状态   Lock();   if (FState == psLiving)   {      FOnView.Object = AObject;      FOnView.Method = ADoView;      result         = true;   }   Unlock();   // 返回结果   return result;}// 生命的开始bool TPerson::Begin(TPerson* AFather, TPerson* AMother){   // 初始化   bool result   = false;   bool boolNext = false;   // 更改状态   Lock();   if (FState == psNothing)   {      boolNext = true;      FState   = psComing;   }   Unlock();   // 判断是否继续   if (boolNext)   {      // 执行开始      result   = DoBegin(AFather, AMother);      boolNext = false;      // 更改状态      Lock();      if (FState != psComing)         boolNext = true;      else if (result)         FState   = psLiving;      else         FState   = psNothing;      Unlock();      // 判断是否需要结束      if (boolNext)      {         // 执行结束         if (result)         {            DoEnd();            result = false;         }         // 更改状态(不需要加锁)         FState = psNothing;      }   }   // 返回结果   return result;}// 生命的结束void TPerson::End(bool ANeedWait){   // 初始化   bool boolNext = false;   bool boolWait = false;   // 更改状态   Lock();   if (FState == psLiving)   {      FState   = psEnding;      boolNext = true;   }   else if (FState == psComing)   {      FState   = psEnding;      boolWait = true;   }   else if (FState == psEnding)      boolWait = ANeedWait;   Unlock();   // 判断是否继续   if (boolNext)   {      // 执行结束      DoEnd();      // 更改状态(不需要加锁)      FState = psNothing;   }   else if (boolWait)   // 等待 End 结束      while (FState == psEnding)         Sleep(8);}// 呼吸void TPerson::Breathe(const TGas& AGas){   // 引用计数加 1   if (IncRefCount())   {      // 气体进入身体      // ??? ... ...      // 引用计数减 1      DecRefCount();   }}// 喝void TPerson::Drink(const TLiquid& ALiquid){   // 引用计数加 1   if (IncRefCount())   {      // 液体进入身体      // ??? ... ...      // 引用计数减 1      DecRefCount();   }}// 吃void TPerson::Eat(const TSolid& ASolid){   // 引用计数加 1   if (IncRefCount())   {      // 固体进入身体      // ??? ... ...      // 引用计数减 1      DecRefCount();   }}// 听到声音void TPerson::Listen(void* Sender, const TAudio& ASound){   // 引用计数加 1   if (IncRefCount())   {      // 大脑去分析声音      FHead->AnalyzeSound(Sender, ASound);      // 引用计数减 1      DecRefCount();   }}// 看到景象void TPerson::See(void* Sender, const TAction& AView){   // 引用计数加 1   if (IncRefCount())   {      // 大脑去分析景象      FHead->AnalyzeView(Sender, AView);      // 引用计数减 1      DecRefCount();   }}// 结婚void TPerson::Marry(TPerson* AMate){   // 引用计数加 1   if ((AMate != NULL) && (AMate != this) && AMate->IncRefCount())   {      // 引用计数加 1      if (IncRefCount())      {         // 加入列表         FMates.Add(AMate);         AMate->FMates.Add(this);         // 引用计数减 1         DecRefCount();      }      // 引用计数减 1      AMate->DecRefCount();   }}// 生子TPerson* TPerson::MakeChild(TPerson* AMate){   // 初始化   TPerson* result = NULL;   // 引用计数加 1   if ((AMate != NULL) && (AMate != this) && AMate->IncRefCount())   {      // 引用计数加 1      if (AMate->CanProcreate() && IncRefCount())      {         // 判断能否生育能力         if (CanProcreate() && (FSex != AMate->FSex))         {            // 创建对象            TPerson* objChild = new TPerson;            if (objChild != NULL)            {               // 父母对象               TPerson* objFather = this;               TPerson* objMother = AMate;               if (FSex != sexMale)               {                  objFather = AMate;                  objMother = this;               }               // 判断生命是否孕育成功               if (objChild->Begin(objFather, objMother))               {                  FChildren.Add(objChild);                  AMate->FChildren.Add(objChild);                  result = objChild;               }               else                  delete objChild;            }         }         // 引用计数减 1         DecRefCount();      }      // 引用计数减 1      AMate->DecRefCount();   }   // 返回结果   return result;}// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/* 人类之间交互示例 */// A 和 B 对象TPerson A, B;{   // A 和 B 二个交谈, 设置两者交互事件   A.SetOnSound(&B, (TPerson::TDoSound)&TPerson::Listen);   A.SetOnView(&B,  (TPerson::TDoView)&TPerson::See);   B.SetOnSound(&A, (TPerson::TDoSound)&TPerson::Listen);   B.SetOnView(&A,  (TPerson::TDoView)&TPerson::See);   // A 和 B 结婚   A.Marry(&B);   // A 和 B 生子, 并取名   TPerson* objChild = A.MakeChild(&B);   if (objChild != NULL)      objChild->SetName("A-B-child1");   // ??? ... ...}


================================================================================
原创粉丝点击