2010-04-16 91 views
7

我想轉發在另一個文件中聲明一個類的靜態成員函數。我想要做的是這樣的:正向聲明靜態函數C++

BigMassiveHeader.h:

class foo 
{ 
    static void init_foos(); 
} 

Main.cpp的:

class foo; 
void foo::init_foos(); 
int main(char** argv, int argc) 
{ 
    foo::init_foos() 
} 

這失敗了與「錯誤C2027:使用未定義的類型 '富' 的「

有沒有辦法讓init_foos成爲一個免費函數或者包含BigMassiveHeader.h來完成我想要做的事情? (BigMassiveHeader.h顯着影響編譯時間,並且無處不在。)

+0

是否包含代碼.cpp或BigHeader.h中不應該有效果。畢竟,你使用#include guard或者#pragma一次,所以BigHeader.h只能被編譯一次,對吧? – Kyte 2010-04-16 19:36:11

+2

@Kyte包含保護將每個翻譯單元的BigHeader.h限制爲一次。如果它被包含在許多源文件中,則需要多次編譯。 – KeithB 2010-04-16 19:39:48

+0

那麼有可能將'class foo'的定義分解爲另一個頭文件? – 2010-04-16 20:08:29

回答

10

無論是否爲靜態,您都無法轉發聲明類的成員。

+0

它甚至不是'foo :: init_foos();'的前向聲明,而是一個名爲'init_foos()'的全局函數的聲明。 – 2010-04-16 19:33:14

+6

嚴格地說,C++的說法沒有「前向聲明」這樣的術語。通常來說,「前向聲明」通常意味着「不定義聲明」。考慮到這一點,可以「轉發聲明」一個成員函數。每次你定義一個類時,你都是「向前聲明」它的[非內聯]成員函數。正確的答案是:你不能*聲明*一個沒有*定義類的類成員。詹姆斯麥克奈利斯刪除的答案實際上是正式的答案。 – AnT 2010-04-16 20:04:59

+2

@AndreyT:標準部分27.2標題爲「前向聲明」,並且TC++ PL特別版中有一個索引條目。 – 2010-04-16 20:12:51

0

不,您需要包含標題。抱歉。

如果您必須使用免費函數,或者拆分類。

4

您不能轉發聲明類的成員,但可以在該名稱空間內創建一個名稱空間和一個函數,並轉發聲明。

namespace nsfoo 
{ 
    void init_foos(); 
} 

如果需要的話,您的課程可能會使用此功能。

2

如果你有一個BigMassiveHeader,你應該考慮把它分成幾個SmallCompactHeaders。如果你想表達許多類和函數在語義上屬於一起,你可以把它們放在同一個命名空間中。您始終可以提供包含所有小標題的便利標題。

+0

我們很清楚這一點。 BigMassiveHeader的重構是我們從前輩繼承的一些技術債務,並且分期付款。這實際上是這種努力的一部分。 – 2010-04-16 20:05:40

0

我知道這不是問題的問題,但如果BigMassiveHeader.h不可能太大隨着時間而改變,你應該看看precompiled headers

0

作爲第一個重構,我會使用一個免費調用靜態函數的函數。這不像你的主要方法被多次調用,所以你不會注意到一個額外的調用,並且對現有的代碼做了最少的改變。

當然,你並沒有真正說出你想做什麼,只是你想做什麼。如果你想要做的是在應用程序啓動時調用一次,那麼使用靜態對象初始化,而不是在main中調用它。如果你想要做的是在創建所有靜態對象後調用,那麼它更復雜。

通過靜態對象初始化,我的意思是像這樣的一個.cpp文件,它有權訪問的定義。讓它的朋友和私人防止多個呼叫:

struct call_init_foos { 
    call_init_foos() { foo::init_foos(); } 
} call_init_foos_on_startup; 
0

轉發類的一個方法的聲明,你必須聲明的方法類的一部分(因爲它確實是)。

例如,在你的情況下,增加的main.cpp:

class foo 
{ 
public: 
    static void init_foos(); 
} 

它不是最漂亮的,但它會節省你不必包括整個頭..