面向對象語言的編譯過程-以C++為例(一)
來源:程序員人生 發布時間:2013-12-10 15:47:40 閱讀次數:3666次
摘要:
概述面向對象語言的重要概念和實現技術
以C++語言為例,介紹如何將C++程序翻譯成C程序
實際的編譯器大都把C++程序直接翻譯成低級語言程序
關于面向過程的高級語言的編譯過程想必大家不陌生。《編譯原理》類的課程多是以C語言(C的子集)為例,介紹高級語言的編譯過程。但是自從面向對象語言產生以來(I love OO programming,yeah),面向對象的編程語言明顯在編程語言中占據了主流的位置。面向對象的編程語言有三個明顯的特點:封裝(Encapsulation),繼承(Inheritance),和多態(Polymorphism)——以上是一道常見的面試題,各位童鞋請注意。最初的面向對象語言往往只提供部分的面向對象特性,比如VB(oh,I love VB so much)。
面向對象的三個特性給代碼復用帶來的極大的好處,同時也改變了程序員的理念,使邏輯開發更接近于現實世界,而面向對象從根本上說是一種世界觀,是對現實世界的一種認識方式,扯遠了。
那么編譯器是如何理解這三個特性的呢?我們以C++為例,看編譯器如何把面向對象的程序翻譯成面向過程的程序,也就是把C++翻譯成C語言,實際的編譯器往往直接把C++程序翻譯成低級語言,但是也有特例,比如ObjectC,就是把C++翻譯成C語言,而以C語言(或C語言的子集,不甚了解)作為中間代碼的。
翻譯的過程如下:
1. 將C++語言中一個類的所有非靜態屬性構成一個C語言的結構體類型,取類的名字作為結構體類型的名字
2. 類的靜態屬性是該類的所有對象所共有的,應當翻譯成C中的全局變量,但是需要改一個名字
3. C++語言中類的對象聲明不加翻譯就成了C語言中相應結構體類型的變量聲明
4. 將C++語言中類的非靜態方法翻譯成C語言的函數,對應的方法和函數的區別有下面幾點:
函數的名字必須在原來方法名的基礎上修改
函數聲明增加一個形參this
在函數體中出現的函數調用也要增加一個實參
在方法中對本對象的非靜態屬性的訪問,改成對this相應域的訪問。在方法中對其它對象的非靜態屬性的訪問不必修改
5. 類的靜態方法在定義和調用的地方都需要改名
我們舉一個例子,以下是一個簡單的面向對象的程序,主要體現了面向對象的封裝特性:
#include <iostream>
using namespace std;
class Test
{
public:
//一個靜態變量
static int c;
int a;
static void printc();
void printa();
};
int Test::c;//靜態變量初始化
void Test::printc()
{
cout<<c<<endl;
}
void Test::printa()
{
cout<<a<<endl;
}
int main()
{
Test t;
t.a=1;
Test::c=2;
t.printa();
Test::printc();
return 0;
}
-------------------------------------------偶是華麗的分割線--------------------------------
以下是翻譯之后的C語言版本,這里的C語言版本放到C99的編譯器里不能直接運行,因為其中類似Test t;的寫法是C++的,C語言中需要寫成struct Test t;這里這么寫只是為了看起來明晰。
-------------------------------------------偶是華麗的分割線--------------------------------
#include <iostream>
using namespace std;
int Test_c;//靜態變量翻譯成全局變量,但是需要改名
struct Test//類翻譯成結構體
{
int a;//成員變量不變
};
void Test_printc()//方法改名,靜態方法基本不變
{
cout<<Test_c<<endl;
}
void Test_printa(Test& th)//方法改名,成員函數加一個參數
//(此處應為this指針,但是this關鍵字為編譯器保留字,用th代替)
{
cout<<th.a<<endl;//對成員函數的引用變為對this域中相應變量的引用
}
int main()
{
Test t;//類變量聲明不加翻譯就成了C語言中相應的結構體類型的變量聲明
t.a=1;//對類成員函數的引用不變
Test_c=2;//靜態變量的引用變為對全局變量的引用
Test_printa(t);//對類成員函數的引用傳入對象作為參數
Test_printc();//對類靜態成員函數的引用改成直接對函數的引用
return 0;
}
總結:
本文介紹了面向對象語言的特性,通過封裝特性介紹了編譯器對面向對象語言的翻譯過程,以一段簡單的程序解釋了C++語言向C語言的編譯過程。由此我們可以得到如下啟示:
靜態變量可作為全局變量理解
類的成員函數類似于一種映射,編譯之后編譯器會為成員函數增加一個對當前對象的引用,從而把對成員變量的引用變為對this域的引用,并且更改所有成員函數的引用處
編譯器會對成員函數,靜態成員函數和靜態成員改名,不同的編譯器對此的處理不一樣,我記得微軟的編譯器是在類名之后加@@,所以我們如果看到LinkError的話都會從錯誤信息中看到一串陌生的函數名,實際就是編譯器在處理封裝之后的結果。
下一篇文章我們會結合面向對象繼承和多態的特性對面向對象語言翻譯過程進行分析,不要走開,精彩繼續。
文章出處:http://www.cnblogs.com/sdqxcxh/ 作者:布拉德比特
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈