詳細(xì)說(shuō)明C++編譯的編寫(xiě)及其代碼問(wèn)題
為每一個(gè)軟件行業(yè)的從業(yè)人員,無(wú)論是開(kāi)發(fā)人員、項(xiàng)目經(jīng)理、還是測(cè)試人員,也要不斷適應(yīng)這個(gè)趨勢(shì),我認(rèn)為C++編譯只會(huì)使我們的工作更簡(jiǎn)單和更輕松,希望本文能教會(huì)你更多東西。
如果這是你購(gòu)買(mǎi)的庫(kù)的設(shè)計(jì)問(wèn)題,你對(duì)它無(wú)計(jì)可施(除了換一個(gè)更好的庫(kù)),但你可以將你自己的代碼組織得更好一些,以求得將修改代碼后的重新編譯工作降到最少。這樣的設(shè)計(jì)會(huì)更好,更有可維護(hù)性,因?yàn)樗鼈冋故玖烁玫母拍钌系姆蛛x。
看看這個(gè)典型的面向?qū)ο蟮?FONT>C++編譯程序例子:
- class Shape {
- public: // 使用Shapes的用戶(hù)的接口
- virtual void draw() const;
- virtual void rotate(int degrees);
- // ...
- protected: // common data (for implementers of Shapes)
- Point center;
- Color col;
- // ...
- };
- class Circle : public Shape {
- public:
- void draw() const;
- void rotate(int) { }
- // ...
- protected:
- int radius;
- // ...
- };
- class Triangle : public Shape {
- public:
- void draw() const;
- void rotate(int);
- // ...
- protected:
- Point a, b, c;
- // ...
- };
設(shè)計(jì)思想是,用戶(hù)通過(guò)Shape的public接口來(lái)操縱它們,而派生類(lèi)(例如Circle和Triangle)的實(shí)現(xiàn)部分則共享由protected成員表現(xiàn)的那部分實(shí)現(xiàn)(implementation)。這不是一件容易的事情:確定哪些實(shí)現(xiàn)部分是對(duì)所有的派生類(lèi)都有用的,并將之共享出來(lái)。
因此,與public接口相比,protected成員往往要做多得多的改動(dòng)。舉例來(lái)說(shuō),雖然理論上“中心”(center)對(duì)所有的圖形都是一個(gè)有效的概念,但當(dāng)你要維護(hù)一個(gè)三角形的“中心”的時(shí)候,是一件非常麻煩的事情——對(duì)于三角形,當(dāng)且僅當(dāng)它確實(shí)被需要的時(shí)候,計(jì)算這個(gè)中心才是有意義的。#t#
protected成員很可能要依賴(lài)于實(shí)現(xiàn)部分的細(xì)節(jié),而Shape的用戶(hù)(譯注:user此處譯為用戶(hù),指使用Shape類(lèi)的C++編譯,下同)卻不見(jiàn)得必須依賴(lài)它們。舉例來(lái)說(shuō),很多(大多數(shù)?)使用Shape的代碼在邏輯上是與“顏色”無(wú)關(guān)的,但是由于Shape中“顏色”這個(gè)定義的存在,卻可能需要一堆復(fù)雜的頭文件,來(lái)結(jié)合操作系統(tǒng)的顏色概念。
當(dāng)protected部分發(fā)生了改變時(shí),使用Shape的代碼必須重新編譯——即使只有派生類(lèi)的實(shí)現(xiàn)部分才能夠訪(fǎng)問(wèn)protected成員。于是,基類(lèi)中的“實(shí)現(xiàn)相關(guān)的信息”(information helpful to implementers)對(duì)用戶(hù)來(lái)說(shuō)變成了象接口一樣敏感的東西,它的存在導(dǎo)致了實(shí)現(xiàn)部分的不穩(wěn)定,用戶(hù)代碼的無(wú)謂的重編譯(當(dāng)實(shí)現(xiàn)部分發(fā)生改變時(shí)),以及將頭文件無(wú)節(jié)制地包含進(jìn)用戶(hù)代碼中(因?yàn)椤皩?shí)現(xiàn)相關(guān)的信息”需要它們)。有時(shí)這被稱(chēng)為“脆弱的基類(lèi)問(wèn)題”(brittle base class problem)。
一個(gè)很明顯的解決方案就是,忽略基類(lèi)中那些象接口一樣被使用的“實(shí)現(xiàn)相關(guān)的信息”。換句話(huà)說(shuō),使用接口,純粹的接口。也就是說(shuō),用抽象基類(lèi)的方式來(lái)表示接口:
- class Shape {
- public: //使用Shapes的用戶(hù)的接口
- virtual void draw() const = 0;
- virtual void rotate(int degrees) = 0;
- virtual Point center() const = 0;
- // ...
- // 沒(méi)有數(shù)據(jù)
- };
- class Circle : public Shape {
- public:
- void draw() const;
- void rotate(int) { }
- Point center() const { return center; }
- // ...
- protected:
- Point cent;
- Color col;
- int radius;
- // ...
- };
- class Triangle : public Shape {
- public:
- void draw() const;
- void rotate(int);
- Point center() const;
- // ...
- protected:
- Color col;
- Point a, b, c;
- // ...
- };
現(xiàn)在,用戶(hù)對(duì)C++編譯與派生類(lèi)的實(shí)現(xiàn)部分的變化之間的關(guān)系被隔離了。我曾經(jīng)見(jiàn)過(guò)這種技術(shù)使得編譯的時(shí)間減少了幾個(gè)數(shù)量級(jí)。