【问题标题】:Owner of nested class object嵌套类对象的所有者
【发布时间】:2013-09-05 12:11:37
【问题描述】:

在 C++/C++11 中,如何获取嵌套类实例化的“所有者”的引用/指针?例如:

class A
{
public:
    friend class B;
    class B
    {
    public:
        Foo bar(int i) { return get_owner().x[...]; }

    private:
        A& get_owner()
        { // How to do this? Pseudo code:
            return (A*)(this - offsetof(A, b));
        }
    };

    B b;
};

注意:在我的例子中,A 不是standard layout type,因为它有私有和公共成员变量。

背景:我想为复杂属性实现“零成本”语法糖,它可以访问所属类中的数据结构并允许 A 的用户编写,例如,

A a;
...
x = a.nodes[5];
y = a.nodes.size();
for (auto n: a.nodes)  // using a.nodes.begin() and a.nodes.end()
    ...

注意 2:我可能会使用肮脏的技巧来做到这一点,但有没有一种可移植的、符合标准的方法来做到这一点?
如果没有,我将不得不实现 B 以便我可以编写“a.nodes(5)”和“for (auto n: a.nodes())”,但这看起来相当难看。

编辑:我已经考虑过给 B 一个对 A 的引用,但是我不能为 A 使用默认的复制/移动构造函数/赋值运算符。在我的情况下这不会那么糟糕,但我好奇是否有其他解决方案。

【问题讨论】:

  • 恐怕声明一个嵌套类,不会像你想的那样做。
  • 在另一个内部定义的类之间没有任何关系。它与命名空间中的类几乎相同。
  • 您不能在 C++ 中执行此操作,因为嵌套在其他类中的类没有对其外部类的引用。内部类的外部类与其说是所有者,不如说是一个命名空间。
  • @user1233963 在 C++11 中,AA::B 之间存在某种程度的关系,因为A::B 被视为成员 属于A,因此可以访问A 的私有成员。
  • @Oswald:看起来不像是真的ideone.com/ntsSnO

标签: c++ c++11 nested-class


【解决方案1】:

A 类的每个实例都有B 类的成员,B 类不知道这一事实。

创建从BA 的映射的唯一方法是创建一个。你自己。不存在这样的映射,因为并非每个B 实例都需要A 实例相关联。只有那些作为A 的一部分创建的实例才是,B 无法知道它是否是A 的一部分。

当然,除非你告诉它。这将需要存储每个B-object 的状态; B 必须存储指向它所属的 A 的指针/引用。

背景:我想为复杂属性实现“零成本”语法糖,它可以访问所属类中的数据结构并允许 A 的用户编写,例如,

这在 C++ 中是不可能的;现在最好放弃它。即使B 为空,也没有要求它们不会占用A 中的空间。实际上,要求它们占用A 中的空间。类实例的每个成员都有一个地址,并且不允许两个成员拥有相同的地址。空基优化仅适用于 基类,不适用于成员。

因此“零成本”是不可能的。由于B 实例将不得不占用A 中的空间,您不妨通过存储指向A 成员的指针/引用来充分利用该空间。

【讨论】:

    【解决方案2】:

    将成员添加到B,指向所有者。

    【讨论】:

    • 这不是 OP 想要的“零成本”
    • @ArneMertz 没错,但这样的零成本解决方案不存在。
    • 这实际上是我考虑的第一个解决方案,但是我无法使用默认的复制构造函数和赋值运算符。诚然,这是一个很小的代价,但我很好奇是否存在其他解决方案。
    • 您在伪代码中设想的解决方案要求A::B 的赋值运算符和所有构造函数都是私有的,以确保B 在创建的A 之外不存在它。特别是,您也不能使用默认的复制构造函数和赋值运算符(好吧,在 C++11 中您可以,但您必须明确声明您需要它)。
    • 我不在乎是否有人会愚蠢到在 A 之外实例化 A::B,所以我将 A::B 的特殊成员函数保留为默认和公共。因此,我不明白为什么我不能在我设想的解决方案中使用 A 的默认复制/移动构造函数/赋值运算符。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 2018-06-21
    • 2017-06-18
    • 1970-01-01
    • 2020-02-21
    • 1970-01-01
    • 2017-12-17
    相关资源
    最近更新 更多