我写了一些代码如下。 这里有一个外部类和一个内部类。 我想要一个类似于java的内部静态类的功能。 所以我将内部类对象声明为static。 输出很好:
#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;
答案 0 :(得分:2)
由于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
的其他问题。
由于您以z
的形式提供X::getZ()
的访问器方法,更好的解决方案是避免使用静态成员变量,并将静态实例放在X::getZ()
函数中本身。由于z
需要正确初始化X
的实例,因此应提供一个。
class X {
//...
public:
static Z & getZ() {
static X x;
static Z z(x);
return z;
}
private:
int i;
};
X::getZ()
的返回类型更改为对静态实例的引用,以便可以操作该实例。
答案 1 :(得分:1)
虽然我无法理解这句话。
这是在类X
中声明的静态变量的定义。以下是它的每个部分的含义:
X::Z
表示正在定义的静态数据成员的类型是Z
,它在类X
中定义。X::z
表示我们正在定义一个名为z
的静态成员,该成员在类X
内声明= X::getZ()
表示将z
初始化为getZ()
成员函数返回的值。但是,这不是一个好的代码,因为getZ
在变量有机会初始化之前使用它初始化的z
。
答案 2 :(得分:0)
这是静态变量X::z
的定义。如果稍后在需要数据成员存在于物理内存中的上下文中使用某些静态数据成员,则它们需要命名空间范围定义。
该定义具有普通变量声明的格式,但其名称被限定为表示它是静态成员:
X::Z
是成员的类型,X::z
是指定其名称的限定ID。此语句将其值初始化为静态成员函数X::getZ()
的返回值,该值本身就是。
请注意,X::getZ()
之后的未定义行为会使z
处于未初始化状态。