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 <stdio.h>
#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程式開發,對於某些複雜的應用程式是大有裨益的。一些嵌入式遊戲開發在遊戲引擎的設計中就應用了此種思想。另外,在作業系統和系統軟體的編程中,也可以常常見到類似的應用,有興趣的可以看看它們的源碼。