2012-05-08 55 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