2012-05-08 178 views
20

我是一名Java開發人員,對於C++我很新。我需要實現某種實用程序類,並且我正在考慮將這些方法實現爲靜態方法。但是,我遇到了關於命名空間函數vs靜態方法的this stackoverflow question,並且熟悉命名空間函數是首選方法。所以我想知道是否有關於如何實現名稱空間函數的文章或例子。例如,我應該如何在頭文件中聲明名稱空間函數?如果頭只包含像類頭文件和實現應該在cpp文件中的函數定義,還是應該直接在頭文件中實現函數?C++命名空間函數

基本上,我試圖實現一個應用程序來解析包含一些命令的文本文件。所以我正在考慮實現靜態幫助器方法來處理文本處理。例如readCommand(字符串行)。如果我的方向不對,請告訴我。謝謝

+1

C++繪製函數和類之間存在相當明顯的區別。從你的問題中不清楚你有興趣使用哪一個。 – Shep

+0

嗨謝,謝謝你的評論。我在我的問題中增加了更多細節。它回答你的問題嗎? –

回答

19

我該如何在頭文件中聲明名稱空間函數?

namespace MON { 
// extern: 
t_ret func(const t_param& pValue); 
// 'inline': 
inline t_ret inline_func(const t_param& pValue) { ... } 
} // << MON 

頭應該只包含像類的頭文件和實現應該是CPP文件函數定義,或者我應該馬上實施的頭文件的功能呢?

取決於您是否希望它們(可能)內聯或導出。這通常歸結爲最小化依賴關係。

擴大出口上或內聯:

你往往青睞的外部函數在C減少依賴++。這相當於從聲明一個類的方法分離的定義:

file.hpp

namespace MON { 
// extern: 
t_ret func(const t_param& pValue); 
} // << MON 

file.cpp

#include "hefty_stuff.hpp" 

MON::t_ret MON::func(const t_param& pValue) { ... } 
但是

,它在時間的關鍵該定義在某些情況下是可見的,通常用於表現或者當您知道尺寸很重要並且標題不包括許多地方時。因此,inline變體也是一種選擇。

內聯函數仍然可以導出,並且可以根據請求內聯函數 - 但是,可以合併任何內聯函數副本(具體而言,實現可以自由假定所有定義相同,並且該函數的任何副本都是不必要)。

與導出的定義,你可以選擇性地限制(或隔離)的包括依賴關係。即#include "hefty_stuff.hpp"不需要在標題中使用file.hpp中的功能。


基本上,我試圖實現應用程序解析包含一些命令的文本文件。所以我正在考慮實現靜態幫助器方法來處理文本處理。

好吧,static這裏應該避免。 C++使用一個定義規則。 static只會導致大量不必要的副本。此外,一個匿名的命名空間是C++的方式到C的static功能:

namespace { 
t_ret func(const t_param& pValue) { ... } 
} // << anon 

注:匿名的命名空間也可能會造成不必要的副本。你將它們用作靜態函數的替代品的原因是,如果你想要或需要偏離一個定義規則,並且不想在可能被「解析」的範圍中聲明該符號。


最後一點問候template<>聲明。使用模板時,除非編譯器支持extern模板,否則該定義必須在使用位置可見。對於模板,您可以通過多種方式完成定義可視性。通常,人們只需簡單地聲明定義,或者爲包含在標題末尾或根據需要的定義添加標題。使用模板,函數不需要聲明爲inline以避免多重定義錯誤。

+0

非常感謝Justin。你能解釋一些關於「潛在內聯或輸出」的點嗎,或者指出一些我應該閱讀的文章呢? –

+2

@KHein yup - 擴展 – justin

+0

@Justin,你忘了提及模板函數。 – Griwes

1

我應該如何在頭文件中聲明名稱空間函數?

namespace YourNamespace 
{ 
    void fun1(); 
    void fun2(); 
} 

應該只包含頭象類的頭文件和實現應該是CPP文件函數定義,或者我應該馬上實施的頭文件的功能呢?

如果你的函數在命名空間中是靜態的,你可以在頭文件中實現函數,或者你必須在cpp文件中實現。

+0

不完全正確,可以在頭中實現非靜態函數。 – juanchopanza

+1

@juanchopanza:只有你聲明他們是「內聯」的。 –

+0

@Kerrek SB:同意 –

12

你可以在頭聲明功能:

namespace A { 
    void foo(); 
} 

,並在.cpp實現:

namespace A { 
    void foo() { std::cout << "foo!"; } 
} 

你也可以把實施的頭,並確保其聲明inline以避免破壞one definition rule

namespace A { 
    inline void foo() { std::cout << "foo()!"; } 
} 

不是e將實現放入頭中意味着客戶端代碼對實現具有編譯依賴性,並且具有用於實現的頭文件。在上面的例子中,客戶端代碼現在依賴於頭部,如果我們做一些微不足道的事情就像在打印輸出中添加感嘆號一樣,我們需要重新編譯所有客戶端代碼,而不是重新鏈接。

把模板函數的實現在頁眉或在用頭包含的文件是非常重要的,這些不能在.cpp去:

namespace B { 
    template <class T> 
    inline void foo(const T& t) { std::cout << t.name() << "\n"; } 
} 
+0

+1用於將標題中的模板功能實現。除非編譯器支持extern模板,否則定義必須在使用位置可見。 – milesma