c++ - 别名定义来自私有(private)子结构的静态成员

标签 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 = {…};

在某些时候,为了编码人员的理智,他们会希望缩短此操作的语法。


问题

我天真的尝试(参见 [B])通过 using 指令为 i 定义别名 符合预期 ,因为 Data 结构是 private。将代码块 [B] 替换为 [A] 会产生(在 VS2017 中):

error C2248: 'foo::bar::MyClass::Data': cannot access private struct declared in class 'foo::bar::MyClass'

Ideone (gcc?) 在 [B] 处导致类似的错误:

error: ‘struct foo::bar::MyClass::Data’ is private within this context


问题

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

其他问题(例如 using alias for static member functions?)与我的问题很相似,但似乎不相关。

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

最佳答案

Why doesn't [B] work, while [A] does?

private 东西(类/成员名)只能在几个地方使用,包括定义(这是 [A])但不能使用别名(在不允许使用类型的范围内)

How might I define i with its hierarchy chain/tree/prefix aliased (preferably via using)? Bonus: What is the preferred nomenclature for what I've been calling the namespace/class/structure hierarchy chain/tree/prefix when referencing a member?

您仍然可以缩短 namespace 部分:

 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

关于c++ - 别名定义来自私有(private)子结构的静态成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55543675/

相关文章:

c++ - 如何在没有 std::move 的情况下 move 临时对象

.net - 在多线程期间共享数据 - 非静态变量可以吗?

file - 使用 JSP/Tomcat 私下提供文件?

c++ - 无法在 Visual Studio 中到达断点

c++ - 异常消息为空

java - 修饰符 static 只允许在常量变量声明中

c++ - 类和许多可以访问它的私有(private)数据的函数

javascript - 模块模式中的私有(private)变量

c++ - 使用 QComboBox C++ 进行过滤

java - 没有从提交到线程池的作业中获取任何输出