静态成员显式定义

时间:2011-07-12 19:58:09

标签: c++ gcc linker static-linking static-initialization

考虑以下代码:

#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::iWilma Fred::wilma_的静态对象。 但只有int Wilma::i的定义是强制性的吗?

为什么Wilma Fred::wilma_;不是强制性的?

我理解 B行是无操作的答案。关于 C行也可以这么说吗?

2 个答案:

答案 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类中的什么位置?