源文件中的私有命名空间
Private namespace in source files
我对私有方法有疑问&功能。假设我有一些不需要在类中的实用工具方法。但这些功能需要调用我不想暴露给用户的其他功能。例如:
Suspect.h
namespace Suspect {
/**
* brief This should do this and that and more funny things.
*/
void VerbalKint(void); // This is for you to use
}
Suspect.cpp
namespace Suspect {
namespace Surprise {
/**
* brief The user doesn't need to be aware of this, as long
* the public available VerbalKint does what it should do.
*/
void KeyserSoze(void) {
// Whatever
}
} // end Surprise
void VerbalKint(void) {
Surprise::KeyserSoze();
}
}
这个布局是有效的。当包含Suspect.h
时,只有VerbalKint
可见。这也可以通过使用一个类并将VerbalKint
标记为静态来实现:
class Suspect {
public:
// Whatever
static void VerbalKint(void);
private:
static void KeyserSoze(void);
};
我想知道这两种方法有什么不同。一个比另一个更好(更快,更容易维护)吗?
你是怎么想的?
如果函数是'free',则应该在*.cpp
中使用匿名命名空间:
namespace Suspect {
namespace Surprise {
namespace {
void KeyserSoze(void) {
// Whatever
}
} // end anon
} // end Surprise
} // end Suspect
甚至:
namespace {
void KeyserSoze(void) {
// Whatever
}
} // end anon
这使它远离客户端,这样他们就不能访问,依赖,或者在链接时与你的导出相冲突。它还可以避免不必要的声明,减少编译时间,如果定义可见,还可以减少链接时间或二进制大小。最后,它使它成为私有的,这样他们就不能依赖它,您也不需要为他们的使用维护它。如果您选择的话,您仍然可以将这些传递给外部世界(在KeyserSoze()
的情况下是函数指针)。
在其他时候,最好在类中声明私有成员函数,然后在*.cpp
中定义它(如果可能)。通常,当您需要与类建立更紧密的关系时(例如,当您需要访问某些成员时),您将选择这种方法。你说在问题中不是这样的,但我只是重申什么时候应该使用私有成员。
最好的方法是在Suspect.cpp
的一个未命名的名称空间中定义所有的帮助函数,而不是在Suspect::Surprise
的名称空间中。
在你的例子中,这将是:
namespace{
void KeyserSoze(){ ... };
}
您可以在Suspect.cpp
中简单地调用KeyserSoze
,而不需要任何命名空间说明符。
您可以在这里找到更多信息:未命名/匿名名称空间与静态函数
另一种选择是将KeyserSoze
声明为static
,但标准不建议这样做。c++标准在7.3.1.1节未命名的命名空间第2段中读到:
在命名空间范围内声明对象时不建议使用static关键字,unnamed-namespace提供了一个更好的选择
实际上,即使当你没有在任何头文件中声明该函数时,它对眼睛是不可见的;如果用户编写声明,它仍然是可用的。
在c++中,隐藏在文件级声明的符号的机制是:
- (全局)变量和函数的
static
-
namespace { ... }
(匿名名称空间)用于任何您想要的内容(更一般,更详细)
// Suspect.cpp
namespace Suspect {
static void KeyserSore() {}
void VerbalKing() { KeyserSore(); }
}
在类和命名空间中添加内容的主要区别是不能在另一个头文件中向类添加额外的静态函数。
:a.h
namespace Fred {
void Somefunc();
}
b.h
namespace Fred {
void Anotherfunc();
}
可以工作,尽管a和b都不知道对方对其名称空间做了什么。这可能会导致如下问题:
刘昀
namespace Fred {
void Thirdfunc();
}
d.h
namespace Fred {
bool Thirdfunc();
}
一切都很好,直到你开始运行程序…
虽然不是不可能,但对于类来说可能性要小得多。
在您的示例中,只有一个源文件,您可能还想考虑使用匿名命名空间,因为它将声明限制在文件范围内,因此文件以外的人不能意外地访问它们(或与它们冲突)。
- 命名空间中具有.h和.cpp文件的类
- 从父命名空间重载类型
- 在命名空间中定义函数还是限定函数
- C++:对不存在的命名空间使用命名空间指令
- 通过继承类使用来自不同命名空间的运算符
- 使用命名空间时出现多个定义错误
- CUDA内核和数学函数的显式命名空间
- 嵌套的匿名命名空间
- CMakeLists.txt中的命名空间表示法
- 类是C++中的命名空间吗
- 在命名空间中使用全局命名空间中的函数
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- '使用命名空间{嵌套在另一个命名空间中的某个命名空间}"
- 是否可以将函数导入命名空间,但不能导出它?
- 命名空间中的unordered_map不会跨源文件"saving"其数据
- 源文件中的未命名命名空间和局部变量
- 使用 clang 解析命名空间:在另一个源文件中包含标头或直接解析标头时,AST 差异
- c++命名空间从不同的源文件
- 源文件中的私有命名空间
- 多个C++源文件中使用的命名空间