具有共享私有数据的模板函数
我在以下情况中寻找'最佳实践':
通常,有两种常见的方法可以在两个(或更多)非成员函数之间共享私有数据,具有不同的优点和缺点:
// Example 1: using 'static' class
// HPP
namespace foo {
class bar
{
private:
static const char* const s_private;
bar();
public:
static void s_method0();
static void s_method1();
}; /* class bar */
} /* namespace foo */
// CPP
namespace foo {
const char* const bar::s_private = "why do I need to be visible in HPP?";
void bar::s_method0() { std::cout << "s_method0 said: " << s_private << std::endl; }
void bar::s_method1() { std::cout << "s_method1 said: " << s_private << std::endl; }
} /* namespace foo */
// Example 2: using unnamed-namespace
// HPP
namespace foo {
void bar0();
void bar1();
} /* namespace foo */
// CPP
namespace foo {
namespace {
const char* const g_anonymous = "why do I need external linkage?";
} /* unnamed-namespace */
void bar0() { std::cout << "bar0 said: " << g_anonymous << std::endl; }
void bar1() { std::cout << "bar1 said: " << g_anonymous << std::endl; }
} /* namespace foo */
// Example 3: using static keyword in namespace-scope
// HPP
namespace foo {
void bar0();
void bar1();
} /* namespace foo */
// CPP
namespace foo {
static const char* const g_internal = "nobody outside this file can see me and I don't have external linkage";
void bar0() { std::cout << "bar0 said: " << g_internal << std::endl; }
void bar1() { std::cout << "bar1 said: " << g_internal << std::endl; }
} /* namespace foo */
我更喜欢“示例3”,因为它尽可能接近意图。
但现在我正在使用模板化函数运行某些问题。 '示例1'似乎是解决此问题的唯一方法:
// HPP
namespace foo {
class bar
{
private:
static const char* const s_private;
bar();
public:
template<typename T> static void s_method0() { std::cout << "s_method0 said: " << s_private << std::endl; }
template<typename T> static void s_method1() { std::cout << "s_method1 said: " << s_private << std::endl; }
}; /* class bar */
} /* namespace foo */
// CPP
namespace foo {
const char* const bar::s_private = "why do I need to be visible in HPP?";
} /* namespace foo */
这令人不满意。特别是因为还有其他(在这种情况下是方法)非成员函数,它应该在同一个(在这种情况下是类)范围内,不需要访问这个私有数据。
有人知道一个优雅的解决方案吗?
谢谢你的帮助。
最好的祝福。
没有找到相关结果
已邀请:
4 个回复
峨躬坎抬焚
命名空间(Loki)或
命名空间(Boost,有时会有更长和更具描述性的名称来防止冲突)。 这很烦人,但你在实践中没有太多可以做的......虽然我实际上有一个解决你的具体问题;)
跳,我在一个邪恶的宏的标题中实现了地方:)
死搭胯
和
访问
以外的任何东西,那么你必须把它们全部放在专门的课堂上。就这么简单。即使对于非模板也是如此。
烫珊
到现在为止一切似乎都没问题。但是如果我们尝试在其他翻译单元中使用我们的标题会发生什么?让我们来看看:
会发生什么,我们以2个未解决的外部结束。那么,链接器只是一个白痴吗?他不是。考虑到什么是未命名的命名空间,我们知道发生了什么。未命名的命名空间在每个翻译单元中具有唯一标识符。因此,在我们的main.cpp中,链接器不知道source.cpp中私有数据的定义。 那么,如果我们在main.cpp中定义这个私有数据会发生什么 - 只是为了把问题带到头上 - ?
现在,所有内容都在编译并正确地“链接” - 或者更确切地说,似乎是这样。 这是该程序的控制台输出:
这意味着:如果您正在寻找未定义的行为,那么您就是这样。 换句话说:基于上面的解释:不要在头文件中使用未命名的命名空间来封装私有共享数据。 最后一个问题是,“解决方案是什么?” 如果您不想使用“静态”(实用程序)类,则应该更喜欢我的第一个发布的解决方案(仅更改代码):
我期待着任何评论。最好的祝福。
董碘奴星
编辑2: 已废除的答案。这个代码不起作用!张贴下面的解释。 编辑: 在'真实代码'中,我将用未命名的命名空间替换命名空间细节。这样就可以使用相同的名称范围在不同的头文件中添加其他共享资源: