2010年12月2日 星期四

forward declaration

一個小技巧,說真的,在我得知這個技巧時還蠻驚訝的 :P
驚訝之餘也感嘆自己見識太少與能力不足,
竟然有如此巧妙的技巧可以取代我一直覺得理所當然的事,

原文於此:Use forward declaration when possible

大概就是說若你要創造一個名為 B 的類別時,它有個成員為 A 類別的指標,
這種情況我們通常會在 B.h 的上端寫一句 #include "A.h"
這並沒有不對的地方,但當我們更動了 A.h 檔時,
 Compiler 在編譯的時後會重編所有 include A.h 的檔案,這當然包括 Class B
這時我們可以使用 froward declaration 的技巧取代 #include "A.h" 這行指令,
移除該行 include 命令,並在 Class B 的前面事先宣告 Class A;


class A;

class B
{
private:
  A* fPtrA ;
  // 或是連類別 A 一起宣告 class A* fPtrA; 就可以連上面的 class A; 也省略
public:
  void mymethod(const& A) const ;
};


如此可以縮短專案建置的時間,但這有個需要注意的重點,
此處我們只有宣告 Class A 讓編譯 B 時不發生錯誤,A 類別的實際大小並不知道,
所以我們只能在宣告成員變數為 reference 或 pointer 才可以使用這個技巧,
就如同上例 fPtrA 是一個位址,mymethod 所用的參數是一個 reference
因為指標的容量是視你的作業系統為 x86 或 x64 而固定的,沒有例外,
當我們使用其他類別是必須採用繼承或宣告為一個實體時,無可選擇還是要用 include
以下是兩個簡單的例子與說明。


任何種類的繼承需要明確的類別


#include <A.h>

class B : public A
{
};


宣告一個實體 A 而非 Point
因為必須明確的知道 A 類別需要多少記憶體空間而使用 include


#include <A.h>

class C
{
private:
  A fA;
public:
  void mymethod(A par);
}


知道這個眉角是一回事,若問我以後會不會這麼做?答案是,不會…
畢竟一個專案不可能永遠都是自己開發,自己維護,若今天自己很確定的宣告了指標變數,
幾個月後接手的人為了擴充功能而必須改為實體變數,豈不是增加困擾,
再者編譯時間是開發人員成本,不是使用者成本,在 daily build 的環境下成本又變得更不重要,
所以還是尊守老傳統乖乖的寫下明確的 include 指令,又 Class 又 include 的擠在一起也不好看。

2 則留言:

  1. 偶爾逛到,寫點意見,forward declaration 最大的好處是可以減少 build time,如果專案大,是可以縮短非常多的時間的。

    回覆刪除
  2. 用 ptr 比較好,不然會有 binary compatible 的問題

    回覆刪除