我有一个private
数据结构,埋在许多嵌套的命名空间和类中,如下面的(简化)示例所示。 private
结构包含许多static const
成员(主要是冗长的STL容器),在本例中由单个static const int i
表示。
注意:这里const
的存在似乎并不影响我的问题;它仅仅是为了完整性而包括在内。
#include <iostream>
using std::cout; using std::endl;
namespace foo {
namespace bar {
class MyClass {
struct Data {
static const int i;
// ... + many more
};
public:
int Get() const { return Data::i; }
};
}
}
/////////////////////////////////////////////////////////////////////////////
const int foo::bar::MyClass::Data::i = 42; // [A] <- Verbose; but works fine
// ... + many more // [A]
//using concise = foo::bar::MyClass::Data; // [B] <- Nope; 'Data' is private
//const int concise::i = 42; // [B] <- Ideally
//// ... + many more // [B]
/////////////////////////////////////////////////////////////////////////////
int main()
{
cout << foo::bar::MyClass{}.Get() << endl;
return 0;
}
在数据结构之外定义i
等静态成员是微不足道的(参见[A]
)。但是,随着成员层次结构中名称空间/类/结构的数量增加,为了便于阅读,最好在成员的定义中缩写层次结构(链/树/前缀?)。想象一下像下面这样的东西,很多次:
const std::vector<std::string> foo::bar::baz::MyClass::MySubClass::MySubSubClass::PrivateDataStruct::vecOfStr = {…};
在某些时候,为了编码人员的理智,他们希望缩短这种操作的语法。
由于[B]
结构为i
,我通过using
指令对Data
的定义进行别名的天真尝试(参见private
)没有按预期工作。交换代码块[B]
for [A]
yield(在VS2017中):
错误C2248:'foo :: bar :: MyClass :: Data':无法访问类'foo :: bar :: MyClass'中声明的私有结构
Ideone(gcc?)在[B]
导致类似的错误:
错误:'struct foo :: bar :: MyClass :: Data'在此上下文中是私有的
[B]
没有工作,而[A]
呢?i
及其层次结构链/树/前缀别名(最好通过using
)?其他问题(如using alias for static member functions?)与我的密切相关,但似乎并不适用。
如有任何编辑或建议,请随时改进此问题。
为什么不[B]工作,而[A]呢?
private
stuff(类/成员名称)只能在多个地方使用,包括定义(即[A])但不包含别名(在范围内不允许使用类型)
我如何定义
i
及其层次结构链/树/前缀别名(最好通过使用)?额外奖励:在引用成员时,我一直在调用名称空间/类/结构层次结构链/树/前缀的首选命名法是什么?
您可能仍会缩短名称空间部分:
using namespace foo::bar;
const int MyClass::Data::i = 42;
对于类部分,如果可以接受,您仍然可以在父类中添加一些使用:
class MyClass {
class MySubClass{
friend class MyClass;
class MySubSubClass{
friend class MyClass;
class PrivateDataStruct {
static const std::vector<std::string> vecOfStr;
// ...
};
// ...
};
// ...
};
using inner = MySubClass::MySubSubClass::PrivateDataStruct;
public:
// ...
};
最后:
const std::vector<std::string>
foo::bar::baz::MyClass::MySubClass::MySubSubClass::PrivateDataStruct::vecOfStr = {/*…*/};
变为:
using namespace foo::bar::baz;
const std::vector<std::string> MyClass::inner::vecOfStr = {/*…*/};