考虑以下代码:
#include<iostream>
using namespace std;
class Wilma
{
public:
static int i;
Wilma()
{
cout<<"\nWilma ctor\n";
cout<<"\ni::"<<i<<"\n";
}
};
class Fred
{
public:
Fred()
{
cout<<"\nFred ctor\n";
}
static Wilma wilma_;
};
int Wilma::i=44;//------------- LINE A
int main()
{
int a=0;
Wilma::i=a;//---------- LINE C
Wilma w;
Fred::wilma_=w;//---------- LINE B
}
这里的行A显式定义了Wilma类的静态int a。(注释掉导致链接器错误) 没有它,链接器会给出未定义的引用错误。(因为Wilma :: i实际上正在使用,如果我不使用它,那么就没有链接器错误。)
对于Fred类的静态Wilma wilma_也应该如此,即它应该被明确定义,因为它也被用在B行的代码中。 但事实并非如此,如果没有明确定义Fred :: wilma_则没有链接器错误。 为什么? 在gcc 4.5.2上测试
修改 我对此有点怀疑...
LINE C 和 LINE B 都试图分别使用类int Wilma::i
和Wilma Fred::wilma_
的静态对象。
但只有int Wilma::i
的定义是强制性的吗?
为什么Wilma Fred::wilma_;
不是强制性的?
我理解 B行是无操作的答案。关于 C行也可以这么说吗?
答案 0 :(得分:3)
Wilma
没有非静态字段。 Fred::wilma_=w;
没有做任何事情。
修改强>
如果没有非静态成员 - 则没有副本。基本上,赋值是一个无操作,可能只是由编译器优化,链接器从未见过它。添加一个非静态成员使该副本成为引用静态变量的实际操作,因此编译器无法对其进行优化并且链接器会看到它。
答案 1 :(得分:1)
您在static int i;
中声明了Wilma
,但从未对其进行过定义。因此,通过在 Line A 中添加,将导致Wilma :: i被定义,这正是编译器所抱怨的。所以你必须定义它在类之外的某个地方,而不是在main之内。
最后,Fred和Wilma类基本上是空的(除了ctor和静态类成员)。他们之间没有什么可复制的。
编辑:根据对@littleadv的评论,如果要执行副本,则必须具有相同的类。如果你在Wilma类中放入一个int j但在Fred类中没有,那么它将无法工作,因为它应该将j放在Fred类中的什么位置?