34

我是一名 Java 开发人员,对 C++ 还很陌生。我需要实现某种实用程序类,并且我正在考虑将这些方法实现为静态的。但是,我遇到了这个关于命名空间函数与静态方法的stackoverflow 问题,显然命名空间函数是首选方法。所以我想知道是否有任何关于如何实现命名空间功能的文章或示例。例如,我应该如何在头文件中声明命名空间函数?header 应该只包含类头文件等函数定义,并且实现应该在 cpp 文件中,还是应该直接在头文件中实现函数?

基本上,我正在尝试实现一个应用程序来解析包含一些命令的文本文件。所以我正在考虑实现静态辅助方法来处理文本处理。例如 readCommand(string line)。如果我的方向错误,请告诉我。谢谢

4

3 回答 3

31

我应该如何在头文件中声明命名空间函数?

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

header 应该只包含类头文件等函数定义,并且实现应该在 cpp 文件中,还是应该直接在头文件中实现函数?

这取决于您是否希望它们(可能)内联或导出。这通常归结为最小化依赖关系。

扩展导出或内联:

您通常倾向于使用 extern 函数来最小化 c++ 中的依赖关系。这相当于将定义与类方法中的声明分开:

文件.hpp

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

文件.cpp

#include "hefty_stuff.hpp"

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

但是,在某些情况下,定义可见有时很重要,通常是为了提高性能,或者当您知道大小很重要并且标题不包含在很多地方时。因此,该inline变体也是一种选择。

内联函数仍然可以导出,并且可以根据要求内联——但是,可以合并任何内联函数副本(具体来说,实现可以自由地假设所有定义都是相等的,并且函数的任何副本都是不必要的)。

使用导出的定义,您可以有选择地限制(或隔离)您的包含依赖项。也就是说,#include "hefty_stuff.hpp"不需要在标题中使用file.hpp.


基本上,我正在尝试实现一个应用程序来解析包含一些命令的文本文件。所以我正在考虑实现静态辅助方法来处理文本处理。

好吧,static这里应该避免。c++ 使用单一定义规则。static只会导致很多不必要的副本。此外,匿名命名空间是 cstatic函数的 c++ 方法:

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

注意:匿名命名空间也可能导致不必要的副本。您将它们用作静态函数的替代品的原因是您想要或需要偏离单一定义规则,并且不想在可能“解析”的范围内声明符号。


最后一点是关于template<>声明的。对于模板,定义必须在使用时可见,除非您的编译器支持外部模板。对于模板,您可以通过多种方式实现定义可见性。通常,人们会简单地在适当的位置声明定义,或者为定义添加一个标题,该标题包含在标题的末尾或根据需要。使用模板,不需要声明函数inline以避免多个定义错误。

于 2012-05-08T05:23:45.733 回答
21

您可以在标头中声明函数:

namespace A {
    void foo();
}

并在 .cpp 中实现:

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

您还可以将实现放在标头中,确保声明它inline以避免违反一个定义规则

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

请注意,将实现放在标头中意味着客户端代码对实现以及用于实现的标头具有编译依赖性。在上面的例子中,客户端代码现在依赖于头部,如果我们做一些琐碎的事情,比如在打印输出中添加一个感叹号,我们需要重新编译,而不是重新链接,所有客户端代码。

将模板函数的实现放在头文件或头文件包含的文件中非常重要,这些不能放在 .cpp 中:

namespace B {
  template <class T>
  inline void foo(const T& t) { std::cout << t.name() << "\n"; }
}
于 2012-05-08T05:24:53.830 回答
2

我应该如何在头文件中声明命名空间函数?

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

header 应该只包含类头文件等函数定义,并且实现应该在 cpp 文件中,还是应该直接在头文件中实现函数?

如果命名空间中的函数是静态的,则可以在头文件中实现函数,或者必须在 cpp 文件中实现。

于 2012-05-08T05:17:00.803 回答