【发布时间】:2012-11-03 04:08:59
【问题描述】:
问题:是否可以从标头访问特定类,同时隐藏该标头中定义的其他命名空间/类?
比如说我有头文件——outcome.hpp:
// outcome.hpp
namespace sports { namespace outcome {
class Injury {};
class Success {};
}}
在另一个头文件中——api.hpp——我希望使用sports::outcome::Injury,而不让包含api.hpp的文件访问sports::outcome::Success。那可能吗?如果是这样,我该如何实现?
附:在实际代码中,api.hpp 包含将调用 Injury 类的方法的模板化方法,因此前向声明是不够的。
我的尝试:
在我的无知中,我试图通过将include 放在内部命名空间中来实现这一点。这是SSCCE:
// api.hpp
namespace sports { namespace api {
namespace internal {
#include "outcome.hpp" // I'm trying to hide symbols within this header
using sports::outcome::Injury;
}
class Boxing {
private:
internal::Injury sustained;
};
}
当它奏效时,我过早地庆祝了:
// This cpp file compiles file \o/
#include "api.hpp"
int main(int argc, char *argv[]) {
sports::api::Boxing b;
// sports::outcome not accessible
}
如何失败:
如果将标准库中的容器用作outcome.hpp 中的类成员,事情就会崩溃。例如,使用这个版本:
// outcome.hpp
#include <vector>
namespace sports { namespace outcome {
class Injury {
private:
std::vector x;
};
// ...
}}
编译失败并出现以下错误:
在 /usr/include/c++/4.6/ext/new_allocator.h:34:0 包含的文件中, 来自 /usr/include/c++/4.6/x86_64-linux-gnu/./bits/c++allocator.h:34, 来自 /usr/include/c++/4.6/bits/allocator.h:48, 来自 /usr/include/c++/4.6/vector:62, 从结果.hpp:1, 来自 api.hpp:5, 来自 main.cpp:1: /usr/include/c++/4.6/new:93:54: 错误:'void* sports::api::internal::operator new(sports::api::internal::std::size_t)' 可能不是在命名空间中声明 /usr/include/c++/4.6/new:94:56: 错误:'void* sports::api::internal::operator new [](sports::api::internal::std::size_t)' 可能不在命名空间内声明 /usr/include/c++/4.6/new:95:35: 错误:'void sports::api::internal::operator delete(void*)' 可能未在命名空间中声明 /usr/include/c++/4.6/new:96:37: 错误:'void sports::api::internal::operator delete [](void*)' 不能在命名空间中声明 /usr/include/c++/4.6/new:97:62: 错误: 'void* sports::api::internal::operator new(sports::api::internal::std::size_t, const sports:: api::internal::std::nothrow_t&)' 不能在命名空间中声明 /usr/include/c++/4.6/new:98:64: 错误:'void* sports::api::internal::operator new [](sports::api::internal::std::size_t, const sports ::api::internal::std::nothrow_t&)' 不能在命名空间中声明 /usr/include/c++/4.6/new:99:58: 错误:'void sports::api::internal::operator delete(void*, const sports::api::internal::std::nothrow_t&)'不能在命名空间中声明 /usr/include/c++/4.6/new:100:60: 错误:'void sports::api::internal::operator delete [](void*, const sports::api::internal::std::nothrow_t& )' 不能在命名空间中声明 /usr/include/c++/4.6/new:103:57: 错误: 'void* sports::api::internal::operator new(sports::api::internal::std::size_t, void*)'不能在命名空间中声明 /usr/include/c++/4.6/new:104:59: 错误: 'void* sports::api::internal::operator new [](sports::api::internal::std::size_t, void* )' 不能在命名空间中声明 /usr/include/c++/4.6/new:107:52: 错误:'void sports::api::internal::operator delete(void*, void*)' 不能在命名空间中声明 /usr/include/c++/4.6/new:108:52: 错误:'void sports::api::internal::operator delete [](void*, void*)' 不能在命名空间中声明我显然做错了。非常感谢您的建议和善意的告白。
【问题讨论】:
-
“暴露命名空间”是什么意思?
-
使用上面的示例,我不希望在包含 api.hpp 的文件中访问
sports::outcome::*。
标签: c++ namespaces scope information-hiding