【问题标题】:Shorter scope resolutions for private nested classes私有嵌套类的更短范围解析
【发布时间】:2025-12-13 10:05:02
【问题描述】:

我有这种(简化的)情况:

class Tree {
    class Iterator {
        class Stack {
            // ...
        }
    public:
        // ...
    }
public:
    //...
}

我不想弄乱类的定义,我决定只在类本身内部编写方法声明。稍后(在下面)当我想定义这样的复制赋值运算符时:

Tree::Iterator::Stack& Tree::Iterator::Stack::operator = (const Stack& p_stack) {
// ...
}

我必须处理这些讨厌的范围解决方案。我想知道是否有办法缩短它们,因为据我所知,usingtypedef 不提供任何东西。

编辑:由于这不是 CodeReview,并且@Yulian 要求澄清,这里是简短版本:

我正在制作一个迭代的红黑树实现。提到的class Iterator 用于后序遍历(所以它是特定于后序的),class Stack 是它的实用程序类。在这个短程序中,只有class Tree使用Iterator,只有Iterator使用Stack

在@Yulian 的提醒之后,我记得如果提到的类是单独定义的(甚至可能作为模板),它会更加面向对象,但这是一个小型的、自包含的程序,我正在努力保留它那样。

编辑:自包含也意味着它是一个独立的单文件程序,因此没有任何 .h 文件或外部代码重用。为什么? 因为 ACADEMIA(以及相关的任意限制)。

【问题讨论】:

  • 为什么usingtypedef不给你买东西?
  • 它们是私有类,所以我不能只说 using Stack = Tree::Iterator::Stack; 或类似的东西 - IteratorStack 无法访问。
  • 你可以先声明嵌套类,然后在后面定义类的时候直接定义它的成员函数。但是,我认为代码本身看起来不错。如果你还有一堆命名空间来处理inside函数定义,你实际上可以在每个函数定义中放置using声明。
  • 不嵌套类如何使它不那么小和独立?它可能与您已经使用的代码量大致相同,只是布局不同。
  • 只有 Tree 类可访问,请查看 pimpl idiom

标签: c++ scope nested-class


【解决方案1】:

您可以使用usingtypedef 完全消除范围分辨率。但不是传统方式,因为您的嵌套类被声明为私有的。因此,您必须在每个嵌套类的 public 部分中使用额外的 using 来“公开”它们。不幸的是,这打破了他们的“隐私”

class Tree {
    class Iterator {
        class Stack {
            Stack& operator = (const Stack& p_stack);
        };
    public:
      using Stack_Out = Stack;

        // ...
    };
public:
    using Iterator_Out = Iterator::Stack_Out;
    //...

};

using Stack = Tree::Iterator_Out;

Stack& Stack::operator = (const Stack& p_stack) {
// ...
}

LIVE DEMO

但是,您可以删除范围级别(外部级别除外,即Tree::),而无需通过以下方式公开私有嵌套类:

class Tree {
    class Iterator {
        friend class Tree;
        ^^^^^^^^^^^^^^^^^^
        class Stack {
            Stack operator = (const Stack& p_stack);
        };
    public:

        // ...
    };

    using Stack = Iterator::Stack;
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

public:

}; 

Tree::Stack Tree::Stack::operator = (const Stack& p_stack) {
^^^^^^^^^^^ ^^^^^^^^^^^
}

LIVE DEMO

【讨论】:

  • 嵌套类只有在私有部分声明时才是私有的。
  • 这不会破坏首先让课程私有化的全部意义吗?
  • @Deduplicator 在 OP 中,它们在私有部分中定义。
  • 是的。您应该插入缺少的“您的...声明的”。
  • @GuyGreer 是的,不幸的是。
【解决方案2】:

首先,最好解释一下您想要达到的目标以及您认为这种方法对您的任务有好处的方式。 恕我直言,更好的方法是创建不嵌套的单个类并在 Three 类中使用它们。这种方法称为“HAS A”。它更干净,易于维护和他人理解。如果您提供更多详细信息,我们可以提出更好的类设计。

【讨论】:

  • 谢谢,我现在已经澄清了上下文。
【解决方案3】:

您可以让预处理器帮助您:

#define foobar Tree::Iterator::Stack    
foobar& foobar::operator = (const Stack& p_stack) {
    // ...
}

【讨论】:

  • 正如我被批评的here,预处理器定义在不必要地使用时会污染世界。
  • 绝对不要这样做。