【问题标题】:C++: static instance of inner class in outer classC ++:外部类中内部类的静态实例
【发布时间】:2015-05-07 19:13:33
【问题描述】:

我写了一些代码如下。 这里有一个外部类和一​​个内部类。 我想要一个类似于java内部静态类的功能。 所以我将内部类对象声明为静态的。 输出很好:

#include <iostream>

using namespace std;

class X {

    private:
    X() {}
    public:

        class Y {
            public:
                virtual void f() = 0;
        };
        class Z:public Y {
            public:
                Z(X& val) : x(val) {}
                void f() {
                    cout << "Programming";
                    x.i = 5;
                }
            private:
                X& x;
        };
        static Z getZ() {
            return z;
        }
    private:
        static Z z;
        int i;
};

X::Z  X::z = X::getZ();

int main()
{
    X::getZ().f();
    return 0;
}

虽然我无法理解这句话。它是如何工作的?

X::Z  X::z = X::getZ();

编辑:那我该如何初始化内部类的实例呢? 当我在下面分配时,我也会遇到分段错误,这可能是因为自我分配。

 x.i = 5;

【问题讨论】:

  • 和 X::z 由自身的副本初始化...:/
  • ... 这应该是未定义的行为。

标签: c++ static inner-classes


【解决方案1】:

由于z 是一个静态成员变量,它需要一个定义。您正在查看的代码行就是该定义。

X::Z  X::z = X::getZ();

X::Z(注意大写Z)为类型,X::z(注意小写z)为变量,由X::getZ()静态成员函数的返回值初始化。

原来X::getZ() 只是返回X::z。虽然看起来多余,但它禁止执行X::z 的默认构造函数,而是使用复制构造函数。

静态对象在执行静态初始化之前初始化为零。如果对象通过零初始化正确初始化,则 self 上的复制构造函数不会造成任何特别的伤害。但是,在这种情况下,X::Z 有一个引用成员变量x,它被初始化为零。访问 x 会导致未定义的行为。


您添加了一个关于正确初始化静态成员 z 的附加问题。

由于您以X::getZ() 的形式为z 提供访问器方法,因此更好的解决方案是避免使用静态成员变量,并在X::getZ() 函数本身内放置一个静态实例。因为z 需要X 的实例才能正确初始化,所以应该提供一个。

class X {
//...
public:
    static Z & getZ() {
        static X x;
        static Z z(x);
        return z;
    }
private:
    int i;
};

X::getZ() 的返回类型更改为对静态实例的引用,以便可以操作该实例。

【讨论】:

    【解决方案2】:

    虽然我无法理解这句话。

    这是在类X 中声明的静态变量的定义。以下是每个部分的含义:

    • X::Z 表示正在定义的静态数据成员的类型是Z,它在类X 中定义。
    • X::z 意味着我们正在定义一个名为 z 的静态成员,在类 X 中声明
    • = X::getZ() 表示将z 初始化为getZ() 成员函数返回的值。

    但是,这不是一个好的代码,因为 getZ 在变量有机会被初始化之前就使用了它初始化的 z。

    【讨论】:

      【解决方案3】:

      这是静态变量X::z的定义。如果某些静态数据成员稍后在需要数据成员存在于物理内存中的上下文中使用,则它们需要命名空间范围定义。

      定义具有普通变量声明的格式,除了它的名称被限定为表示它是一个静态成员:

      X::Z 是成员的类型,X::z 是指定其名称的限定 ID。该语句将其值初始化为静态成员函数X::getZ()的返回值,也就是它本身。

      请注意,由于X::getZ() 以未初始化状态返回z,此未定义行为。

      【讨论】:

      • 你能告诉我获取上述内部类静态实例的正确方法是什么吗?
      • @tariqzafar 你首先需要一个X 的实例来发送到Z 的构造函数。你可以做static X x; X::Z X::z(x)。
      • 是否可以使用外部类的私有构造函数?
      • @tariqzafar z 不是X,而是Z,因此您不能使用X 的任何构造函数。为什么不把z的类型改成X,然后加上合适的构造函数呢?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-23
      • 2016-01-21
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多