别名来自私有子结构的静态成员的定义

时间:2019-04-05 21:36:15

标签: c++ static private using

背景

我有一个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 = {…};

在某种程度上,出于编码人员的理智,他们希望缩短此操作的语法。


问题

我在{strong>通过[B]指令混淆i的定义方面的幼稚尝试(请参见using)没有达到预期的效果,原因是 Data结构为private 。交换代码块[B]以产生[A](在VS2017中为 ):

  

错误C2248:'foo :: bar :: MyClass :: Data':无法访问在类'foo :: bar :: MyClass'中声明的私有结构

Idone (gcc?)在[B]处产生类似的错误:

  

错误:“ struct foo :: bar :: MyClass :: Data”在此上下文中是私有的


问题

  1. 为什么[B]不起作用[A]却起作用?
  2. 我该如何使用别名的层次结构链/树/前缀定义i (最好通过using)?
  3. 奖金::在引用成员时,我一直称呼命名空间/类/结构层次结构链/树/前缀的首选命名法是什么?

其他问题(例如using alias for static member functions?)听起来很像我,但似乎无关。

请随时通过任何修改或建议来改善此问题。

1 个答案:

答案 0 :(得分:1)

  

为什么[B]不起作用,而[A]起作用?

private的东西(类/成员名)只能在多个地方使用,包括定义([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 = {/*…*/};

Demo