為每一個軟件行業的從業人員,無論是開發人員、項目經理、還是測試人員,也要不斷適應這個趨勢,我認為C++編譯只會使我們的工作更簡單和更輕松,希望本文能教會你更多東西。
如果這是你購買的庫的設計問題,你對它無計可施除了換一個更好的庫),但你可以將你自己的代碼組織得更好一些,以求得將修改代碼後的重新編譯工作降到最少。這樣的設計會更好,更有可維護性,因為它們展示了更好的概念上的分離。
看看這個典型的面向對象的C++編譯程序例子:
- class Shape {
- public: // 使用Shapes的用戶的接口
- 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;
- // ...
- };
設計思想是,用戶通過Shape的public接口來操縱它們,而派生類例如Circle和Triangle)的實現部分則共享由protected成員表現的那部分實現implementation)。這不是一件容易的事情:確定哪些實現部分是對所有的派生類都有用的,並將之共享出來。
因此,與public接口相比,protected成員往往要做多得多的改動。舉例來說,雖然理論上“中心”(center)對所有的圖形都是一個有效的概念,但當你要維護一個三角形的“中心”的時候,是一件非常麻煩的事情——對於三角形,當且僅當它確實被需要的時候,計算這個中心才是有意義的。
protected成員很可能要依賴於實現部分的細節,而Shape的用戶譯注:user此處譯為用戶,指使用Shape類的C++編譯,下同)卻不見得必須依賴它們。舉例來說,很多大多數?)使用Shape的代碼在邏輯上是與“顏色”無關的,但是由於Shape中“顏色”這個定義的存在,卻可能需要一堆復雜的頭文件,來結合操作系統的顏色概念。
當protected部分發生了改變時,使用Shape的代碼必須重新編譯——即使只有派生類的實現部分才能夠訪問protected成員。於是,基類中的“實現相關的信息”(information helpful to implementers)對用戶來說變成了象接口一樣敏感的東西,它的存在導致了實現部分的不穩定,用戶代碼的無謂的重編譯當實現部分發生改變時),以及將頭文件無節制地包含進用戶代碼中因為“實現相關的信息”需要它們)。有時這被稱為“脆弱的基類問題”(brittle base class problem)。
一個很明顯的解決方案就是,忽略基類中那些象接口一樣被使用的“實現相關的信息”。換句話說,使用接口,純粹的接口。也就是說,用抽象基類的方式來表示接口:
- class Shape {
- public: //使用Shapes的用戶的接口
- virtual void draw() const = 0;
- virtual void rotate(int degrees) = 0;
- virtual Point center() const = 0;
- // ...
- // 沒有數據
- };
- 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;
- // ...
- };
現在,用戶對C++編譯與派生類的實現部分的變化之間的關系被隔離了。我曾經見過這種技術使得編譯的時間減少了幾個數量級。