在类中使用静态类成员是一种常见做法。考虑以下定义:
foo.h中
class foo
{
public:
virtual ~foo();
protected:
foo();
static foo ms_oFooStaticObject;
}
Foo.cpp中
foo foo::ms_oFooStaticObject;
foo::foo(){}
foo::~foo(){}
void main()
{
int i;
}
编译上面的代码时没有编译器错误,你只需在步进模式下运行并观察正在执行的静态c-tor。
这怎么可能?这是一个编译器错误吗?我正在使用带有SP1的Visual Studio 2005(专业版)(SP.050727-7600)
答案 0 :(得分:4)
这不是编译器错误 - 构造正在定义的类的静态实例不会触发递归构造(作为类型foo
的非静态成员会这样做),所以它非常好。
在ms_oFooStaticObject
的定义(foo.cpp)中,foo
是一个完整的类型,protected
可以访问ms_oFooStaticObject
的构造函数{{1}}
答案 1 :(得分:1)
@ user797308:我假设如果有人声明并定义了一个名为ms_oFooStaticObject的全局变量,那么你就没有问题了。换句话说,不是定义foo foo::ms_oFooStaticObject;
定义foo ms_oFooStaticObject;
(当然,这需要构造函数是公共的)。
普通旧的vanilla全局变量通过extern <type> <global_name>;
声明,并使用<type> <global_name>;
定义(可能带有一些初始值)。
类中的那些静态成员实际上只是全局变量,其名称前面加上了类名。类定义正在声明它们。将类foo中的ms_oFooStaticObject声明视为与extern foo ms_oFooStaticObject;
类似。变量的定义怎么样?这就是foo foo::ms_oFooStaticObject;
声明正在做的事情。
与全局变量的比较非常贴切。与全局变量相关的行李很多。将类的静态成员视为与一般的全局变量具有相同类型的问题是个好主意。
修改强>
Nawaz的回应引发了一个想法。 user797308的问题可能是foo::ms_oFooStaticObject
本身受到保护,那么如何在文件范围内定义?答案是,因为语言要求在文件范围定义那些静态数据成员,所以语言当然必须允许这样的定义,即使对于具有非公开可见性的静态成员也是如此。
答案 2 :(得分:0)
由于您在foo.cpp文件中执行的foo::foo()
变量定义,执行了构造函数static
:
foo foo::ms_oFooStaticObject;
您正在调用class foo
。
答案 3 :(得分:0)
让我猜一下。我想你好奇,因为foo
是protected
,因此,你认为以下行必须给出错误,因为它试图从外部调用非公共构造函数。
foo foo::ms_oFooStaticObject; //definition lies outside the class
嗯,事实并非如此。 ms_oFooStaticObject
不是一个全局对象,虽然起初似乎,看到它的定义在类之外。
事实是ms_oFooStaticObject
仍然是类的成员,即使它的定义在类之外。与任何会员一样,它不仅可以访问protected
个成员,还可以访问private
个成员:
class A
{
A() { cout << "constructed" << endl; } //private constructor
static A a;
};
A A::a; //okay - member has access to private constructor!
A b; //error - non-member doesn't has access to private constructtor
编译并查看错误消息以及行号:http://www.ideone.com/qocH0
顺便说一句,您的main()
是非标准的,它应该是其中之一:
int main();
int main(int argc, char *argv[]);