C++面向对象编程思想
作者:不详 发布时间:[ 2010/6/10 10:47:20 ] 推荐标签:
C++面向对象编程思想
前面已说明设计程序是编写程序欲解决的问题的描述,也是编写论调。而论调可以只用“名词性概念”和“动词性概念”表现出来,对象又正好是“名词性概念”的实现,而利用前面说的没有成员变量的类来映射“动词性概念”可以将其转换为对象。因此,一个世界,可以完全由对象组成,而将算法所基于的世界只用对象表现出来,再进行后续代码的编写,这种编程方法被称作面向对象的编程思想。
注意,先设计算法应基于的世界,再全部用对象将其表述出来,然后再设计算法,后映射为代码。但前面在编写商人过河问题时是直接给出算法的,并没有设计世界啊?其实由于那个问题的过于简单,我直接下意识地设计了世界,并且用前面所说的河岸论来描述它。应注意世界的设计完全依赖于问题,而准确地说,前面我并没有设计世界,而是设计了河岸论来描述问题。
接着,由于对象是实例,因此以对象来描述世界在C++中是设计类,通过类的实例来组合表现世界。但应注意,面向对象是以对象来描述世界,但也描述算法,因为算法也会提出一些需要被映射的概念,如前面商人过河问题的算法中的过河方案。但切记,当描述算法时操作了描述世界时定义的类,则一定要保持那个类的设计,不要因为算法中对那个类的实例的操作过于复杂而将那部分算法映射为这个类的一个成员函数,因为这严重遮蔽了算法的实现,破坏了程序的架构。如一个算法是让汽车原地不停打转,需要复杂的操作,那么难道给汽车加一个功能,让它能原地不停地打转?!这是在设计类的时候经常犯的错误,也由于这个原因,一个面向对象编写的代码并不是想象的只由类组成,其也可能由于将算法中的某些操作映射成函数而有大量的全局函数。请记住:设计类时,如果是映射世界里的概念,不要考虑算法,只以这个世界为边界来设计它,不要因为算法里的某个需要而给它加上错误的成员。
因此,将“名词性概念”映射成类,“名词性概念”的属性和状态映射为成员变量,“名词性概念”的功能映射为成员函数。那么“动词性概念”怎么办?映射成没有成员变量的类?前面也看见,由于过于别扭,实际中这种做法并不常见(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]; 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 );
};
然后在b.cpp中照常使用类Person,如下:
Person a, b; a.m_Age = 20; b.GetSex();
这里直接使用了Person::m_Age了,算不做这样蹩脚的动作,依旧#include "Person.h",如下:
struct PERSON { char m_Name[20]; unsigned long m_Age; bool m_Sex; };
Person a, b; PERSON *pP = ( PERSON* )&a; pP->m_Age = 40;

sales@spasvo.com