Chinaunix首页 | 论坛 | 博客
  • 博客访问: 96819
  • 博文数量: 12
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 485
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-12 22:46
文章分类

全部博文(12)

文章存档

2011年(1)

2009年(11)

我的朋友

分类: C/C++

2009-06-26 09:25:24

我们知道,C++是一种面向对象的编程语言,我们常用它来进行面向对象的程序开发。但是,面向过程的语言如C是否可以进行面向对象的编程呢?可以说是,也可以说否。说否,是因为C语言并没有面向对象语言的诸多特征,包括其核心特征即封装、继承和多态。说是,是因为我们都知道,面向对象编程的实质其实是一种编程思维方式,跟使用的语言并无必然关系,但是使用面向对象的语言可以使程序员更好地实现这一思维方式。在这里主要讨论“是”的这一方面。

“对象”是“类”的实例。对象在产生时会自动调用其构造函数,而在消亡时会自动调用其析构函数,这是C++中的概念。这个东西听起来很神秘也很迷人,它咋就这样智能呢?初学者尤其会产生这种想法。况且一门新的语言总要衍生出很多概念,譬如说封装啊,继承啊,多态啊,重载啊等等,真有给人一种神秘、高级的感觉。其实它的确是高级的,不过这里不讨论它的高级,这里是想窥探它的本质,就算是“一斑”也可,“窥一斑而见全豹”嘛。

C++的构造函数与析构函数的实现是在编译器层。编译器会在对象定义处生成调用构造函数的代码,而在退出作用域处生成析构函数的代码。所以看起来就“自动”了。

譬如说,有一个Game类:
class Game
{
private:
    Game();
    ~Game();

    int m_var1;
    int m_var2;
 
public:
    void Play();
}

其实现是:

Game::Game()
{
    m_var1 = 1;
    m_var2 = 2;
}

Game::~Game()
{
    m_var1 = 0;
    m_var2 = 0;
}

void Game::Play()
{
    m_var1++;
    m_var2++;
}

void TestGame()
{
    Game g;

    g.Play();
}

那么如果用C来模拟:

#include

#define __DEBUG

typedef struct _Game Game;
struct _Game
{
    void (*GameConstructFunc)(Game* this);  /*构造函数指针*/
    void (*GameDestroyFunc)(Game* this);    /*析构函数指针*/

    int m_var1;
    int m_var2;

    void (*PlayFunc)(Game* this);           /*成员函数Play的指针*/
};

/*抽象对象的共同行为:这个例子中只包括构造和析构*/
typedef struct _OBJECT
{
    void (*virtualConstuctFunc)(struct _OBJECT *this);
    void (*virtualDestroyFunc)(struct _OBJECT *this);
} OBJECT;

/*构造函数实现*/
void GameConstruct(Game* this)
{
    this->m_var1 = 1;
    this->m_var2 = 2;
#ifdef __DEBUG
    printf("Construct\n");
#endif
}

/*析构函数实现*/
void GameDestroy(Game* this)
{
    this->m_var1 = 0;
    this->m_var2 = 0;
#ifdef __DEBUG
    printf("Destroy\n");
#endif
}

/*成员函数Play的实现*/
void Play(Game* this)
{
    this->m_var1++;
    this->m_var2++;
#ifdef __DEBUG
    printf("Play\n");
#endif
}

/*构造对象,由于没有编译器的帮助,构造只能“手动”调用,
实际应用中其实在所有对象之上会存在一个“对象管理器”,
它就具有构造对象的行为*/
void CreateObject(OBJECT *obj)
{
    obj->virtualConstuctFunc(obj);
}

/*析构对象,由于没有编译器的帮助,构造只能“手动”调用,
实际应用中其实在所有对象之上会存在一个“对象管理器”,
它就具有析构对象的行为*/
void DestroyObject(OBJECT *obj)
{
    obj->virtualDestroyFunc(obj);
}

/*使用实例*/
void TestGame()
{
    /*定义对象*/
    Game g = {
        GameConstruct,
        GameDestroy,
        0,
        0,
        Play
        };
   
    /*构造对象*/
    CreateObject((OBJECT*)&g);
    /*调用对象的行为*/
    g.PlayFunc(&g);
    /*析构对象*/
    DestroyObject((OBJECT*)&g);
}

/*测试程序*/
int main(void)
{
    TestGame();
    return 0;
}

在上面的代码中,有些东西是不是似曾相识?譬如this指针。

C++语言会靠编译器实现类似的功能,当然更加强大。语言强大的功能,大部分都是在编译器层实现,因为源程序一旦转化为机器码,就已经丧失了语言的特性(拥有解释器的语言除外,例如Java,它有虚拟机,虚拟机是对应于程序的运行阶段的)。例如C++语言中,数据访问权限的限制(即私有和公有性质),继承的实现等等,都是由编译器完成的。语言和编译器是相辅相成的,缺一不可。

目前C语言在嵌入式设备上的编程还占有重要分量,运用面向对象的思想来进行C程序开发,对于某些复杂的应用程序是大有裨益的。一些嵌入式游戏开发在游戏引擎的设计中就应用了此种思想。

 
阅读(1681) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~