第一个:
我在头文件class1.h中定义了一个全局变量g1。其中c1.h被多个文件所#include,所以我只能把g1定义为static的变量。如果我做如下定义:
#ifndef TEST1
#define TEST1
int g1;
#endif
则显示如下错误test1 error LNK2005: "int g1" (?g1@@3HA) already defined in class1.obj,请问这是为什么?
------------------------------------------------------
第二个:
如果我在一个类中定义一个static的变量,然后在类中访问他则报错。
如:
class1.h
class class1
{
public:
static int m_itest1;
class1(void);
~class1(void);
};class1.cpp
#include "StdAfx.h"
#include "class1.h"class1::class1(void)
{
m_itest1=1;
}显示错误:test1 error LNK2001: unresolved external symbol "public: static int class1::m_itest1" (?m_itest1@class1@@2HA)请大家指点,我用的vc.net

解决方案 »

  1.   

    用全局变量的话,不是在每个用到全局变量的文件中都要#include "包含全局变量的那个头文件 "的。你可以只载一个文件中include头文件,其他的只要用extern声明即可。例如:
    //head1.h
    int g_intxxx;//g_intxxxx是全局变量
    ...
    //cpp1.cpp
    extern int g_intxxxx;//声明g_intxxxx在其他文件中已经定义。
    func1()
    {
      g_intxxxx++;
    }
    ...
    //cpp2.cpp
    extern int g_intxxxx;
    func2()
    {
      g_intxxxx--;
    }
    .....
    多次包含一个头文件肯定要出链接时错误的,也可以看一下MSDN关于错误的解释,挺有帮助的。
      

  2.   

    2:static不能在类定义里面用吧
      

  3.   

    对于第二个问题,对静态成员访问时,你需要加上class scope运算符。
    用m_itest1时必须象这样用class1::m_itest1 = 1;
      

  4.   

    第一个:
    #ifndef TEST1
    #define TEST1
    int g1;
    #endif
    只防止一个.h文件在一个.cpp文件中被多次包含,所以并没有防止这个全局变量在工程中被多次重复定义。可以用楼上的方法来实现。第二个:
    类的静态成员变量要在类的外面以下列方式初始化:class1::m_itest1 = 1;而不能在构造函数中初始化,这是C++要求的。
      

  5.   

    to: bqt(周扒皮) 
    extern是我第一个试的,也报那个错误。
    你说的第二个问题的解决方法,我也试过了,也是不行,还是那个错误。另外在类本身访问静态成员不用加class scope运算符,(查了书)
    to:LIFEForSoft(据我所知)
    static可以在类里面用,这可是很有用的。有人知道吗?这个问题困扰我一天了,谁能帮忙解决可以在加分的:)
      

  6.   

    对于第一个问题:我同意周扒皮的建议
     #include "*.h"意思是在编译是将*.h文件加入此文件,如果在*.h中定义了一个变量,就如同在此文件中又定义了此变量一边,因此报错:"int g1" (?g1@@3HA) already defined in ,工程全局变量的定义最好在*.cpp中,让后在用到的文件中在用extern type var声明一下即可.
    对于第二个问题:扒皮说的也没错
    不管是常量还是变量,只要在类中声明就是它的成员函数
      

  7.   

    第一个问题我又试了试,如果在另外的cpp中使用extern还是报上面的错,如果连带class1.cpp中也使用extern编译的时候倒是不报错,可是运行的时候报错。
    第二个问题,如果我换作在成员函数中对这个static的变量付值,或者访问这个变量仍然产生这个错误,这是为什么?
      

  8.   

    static
    static declaratorWhen modifying a variable, the static keyword specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless another value is specified. When modifying a variable or function at file scope, the static keyword specifies that the variable or function has internal linkage (its name is not visible from outside the file in which it is declared). In C++, when modifying a data member in a class declaration, the static keyword specifies that one copy of the member is shared by all the instances of the class. When modifying a member function in a class declaration, the static keyword specifies that the function accesses only static members.For related information, see auto, extern, and register.Example// Example of the static keyword
    static int i;         // Variable accessible only from this filestatic void func();   // Function accessible only from this fileint max_so_far( int curr )
    {
       static int biggest;    // Variable whose value is retained
                              //    between each function call
       if( curr > biggest )
          biggest = curr;   return biggest;
    }// C++ onlyclass SavingsAccount
    {
    public:
       static void setInterest( float newValue )  // Member function
          { currentRate = newValue; }             //    that accesses
                                                  //    only static
                                                  //    members
    private:
       char name[30];
       float total;
       static float currentRate;    // One copy of this member is
                                    //    shared among all instances
                                    //    of SavingsAccount
    };// Static data members must be initialized at file scope, even
    //    if private.
    float SavingsAccount::currentRate = 0.00154;
      

  9.   

    Initializing Static Members
    Static member initialization occurs in class scope. Therefore, they can access other member data or functions. For example:class DialogWindow
    {
    public:
        static short  GetTextHeight();
    private:
        static short nTextHeight;
    };short DialogWindow :: nTextHeight = GetTextHeight();Note that in the preceding definition of the static member nTextHeight, GetTextHeight is implicitly known to be DialogWindow :: GetTextHeight.//////Access Control and Static Members
    When you specify a base class as private, it affects only nonstatic members. Public static members are still accessible in the derived classes. However, accessing members of the base class using pointers, references, or objects can require a conversion, at which time access control is again applied. Consider the following example:class Base
    {
    public:
        int Print();             // Nonstatic member.
        static int CountOf();    // Static member.
    };// Derived1 declares Base as a private base class.
    class Derived1 : private Base
    {
    };
    // Derived2 declares Derived1 as a public base class.
    class Derived2 : public Derived1
    {
        int ShowCount();    // Nonstatic member.
    };
    // Define ShowCount function for Derived2.
    int Derived2::ShowCount()
    {
       // Call static member function CountOf explicitly.
        int cCount = Base::CountOf();     // OK.   // Call static member function CountOf using pointer.
        cCount = this->CountOf();  // Error. Conversion of
                                   //  Derived2 * to Base * not
                                   //  permitted.
        return cCount;
    }In the preceding code, access control prohibits conversion from a pointer to Derived2 to a pointer to Base. The this pointer is implicitly of type Derived2 *. To select the CountOf function, this must be converted to type Base *. Such a conversion is not permitted because Base is a private indirect base class to Derived2. Conversion to a private base class type is acceptable only for pointers to immediate derived classes. Therefore, pointers of type Derived1 * can be converted to type Base *.Note that calling the CountOf function explicitly, without using a pointer, reference, or object to select it, implies no conversion. Therefore, the call is allowed.Members and friends of a derived class, T, can convert a pointer to T to a pointer to a private direct base class of T.
      

  10.   

    对于第二个问题,我想说的是静态的类成员在定义时需要加上class scope!使用的时候和一般非静态成员没有区别。还有就是象qing_li73(bluemoon) 
    所说的
    // Static data members must be initialized at file scope, even
    //   if private m_itest1
    但是const static int类型的静态成员可以在声明的时候赋初值。例:
    ...
    private:
      static const int buf_size = 1024;
    ...
      

  11.   

    对于第二个问题,在《Effective C++》条款一中有解释如下:
    另外,定义某个类(class)的常量一般也很方便,只有一点点不同。要把常量限制在类中,首先要使它成为类的成员;为了保证常量最多只有一份拷贝,还要把它定义为静态成员:
        class GamePlayer {
    private:
    static const int NUM_TURNS = 5; // constant eclaration 
    int scores[NUM_TURNS]; // use of constant
    ...
    };还有一点,正如你看到的,上面的语句是NUM_TURNS的声明,而不是定义,所以你还必须在类的实现代码文件中定义类的静态成员:const int GamePlayer::NUM_TURNS; // mandatory definition;
    // goes in class impl.file你不必过于担心这种小事。如果你忘了定义,链接器会提醒你。
      

  12.   

    另外建议把全局变量定义在一个Globals.h的头文件中,其他文件使用其中的全局变量,就用extern方式使用。
      

  13.   

    1.在.H文件中直接声明 class class1;
      在.CPP中include "class1.h"2.必须要先初始话才能用
      

  14.   

    第二个问题我自己也琢磨明白了,然后才看到sjsj(悠行者) 的答案:(
    第一个问题是全局变量放在cpp文件中声明就一切正常了,谁能帮忙解释一下是为什么吗?
      

  15.   

    第一个问题是这样的:你在头文件中定义了变量,那么每一个包含此头文件的文件都会定义一个这样的变量,当然会引起变量冲突!所以在头文件中只能声明变量,也就是加上extern关键词。
    第二个问题就是在你的类的实现文件(.cpp文件)中实现静态变量并赋初值:
      int GamePlayer::NUM_TURNS = 1;
    然后就可以象成员变量一样不加类名修饰符调用了。
      

  16.   

    microsoftwin(流星雨点) :
      不是不能用,我已经用过了。如果是public静态变量的话,其它所有函数都可以引用;protect或private静态变量,其它函数就只能通过类自己定义的接口对它进行操作。