请记住:设计类时,如果是映射世界里的概念,不要考虑算法,只以这个世界为边界来设计它,不要因为算法里的某个需要而给它加上错误的成员。 因此,将“名词性概念”映射成类,“名词性概念”的属性和状态映射为成员变量,“名词性概念”的功能映射为成员函数。那么“动词性概念”怎么办?映射成没有成员变量的类?前面也看见,由于过于别扭,实际中这种做法并不常见(STL中也只是将其作为一种技巧),故经常是将它映射为函数,虽然这有背于面向对象的思想,但要易于理解得多,进而程序的架构要简明得多。 随着面向对象编程思想的问世,一种全新的设计方式诞生了。由于它是如此的好以至于广为流传,但理解的错误导致错误的思想遍地而生,更糟糕的就是本末倒置,将这个设计方式称作面向对象的编程思想,它的名字就是封装。 封装 先来看现在在各类VC教程中关于对象的讲解中经常能看见的如下的一个类的设计。 class Person { private: char m_Name[20]; unsigned long m_Age; bool m_Sex; public: const char* GetName() const; void SetName( const char* ); unsigned long GetAge() const; void SetAge( unsigned long ); bool GetSex() const; void SetSex( bool ); }; 上面将成员变量全部定义为private,然后又提供三对Get/Set函数来存取上面的三个成员变量(因为它们是private,外界不能直接存取),这三对函数都是public的,为什么要这样?那些教材将此称作封装,是对类Person的内部内存布局的封装,这样外界就不知道其在内存上是如何布局的并进而可以保证内存的有效性(只由类自身操作其实例)。 首先要确认上面设计的荒谬性,它是正宗的“有门没锁”毫无意义。接着再看所谓的对内存布局的封装。回想在《C++从零开始(十)》中说的为什么每个要使用类的源文件的开头要包含相应的头文件。假设上面是在Person.h中的声明,然后在b.cpp中要使用类Person,本来要#include "Person.h",现在替换成下面: class Person { public: char m_Name[20]; unsi