C++ 类中的静态变量和静态成员函数(转)

来源:互联网 发布:扛旗世界纪录 知乎 编辑:程序博客网 时间:2024/04/30 07:20

静态数据成员:

下面看一个例子:
 #include <iostream.h>
class Point
{
public:
void output()
{
}
static void init()

}
};
void main( void )
{
Point pt;
pt.init();
pt.output();
}
这样编译是不会有任何错误的。



下面这样看
#include <iostream.h>
class Point
{
public:
void output()

}
static void init()

}
};
void main( void )
{
Point::output();
}
这样编译会处错,错误信息:illegal call of non-static member function,为什么?
因为在没有实例化一个类的具体对象时,类是没有被分配内存空间的。



好的再看看下面的例子:
#include <iostream.h>
class Point
{
public:
void output()

}
static void init()

}
};
void main( void )
{
Point::init();
}
这时编译就不会有错误,因为在类的定义时,它静态数据和成员函数就有了它的内存区,它不属于类的任何一个具体对象。



好的再看看下面的例子:
#include <iostream.h>
class Point
{
public:
void output()

}
static void init()
{
   x = 0;
   y = 0;
}
private:
int x;
int y;
};
void main( void )
{
Point::init();
}
编译出错:
illegal reference to data member 'Point::x' in a static member function
illegal reference to data member 'Point::y' in a static member function
在一个静态成员函数里错误的引用了数据成员,
还是那个问题,静态成员(函数),不属于任何一个具体的对象,那么在类的具体对象声明之前就已经有了内存区,
而现在非静态数据成员还没有分配内存空间,那么这里调用就错误了,就好像没有声明一个变量却提前使用它一样。
也就是说在静态成员函数中不能引用非静态的成员变量。



好的再看看下面的例子:
#include <iostream.h>
class Point
{
public:
void output()
{
   x = 0;
   y = 0;
   init(); 
}
static void init()
{

}
private:
int x;
int y;
};
void main( void )
{
Point::init();
}
好的,这样就不会有任何错误。这最终还是一个内存模型的问题,
任何变量在内存中有了自己的空间后,在其他地方才能被调用,否则就会出错。



好的再看看下面的例子:
#include <iostream.h>
class Point
{
public:
void output()
{
}
static void init()
{
   x = 0;
   y = 0;
}
private:
static int x;
static int y;
};
void main( void )
{
Point::init();
}
编译:
Linking...
test.obj : error LNK2001: unresolved external symbol "private: static int Point::y" (?y@Point@@0HA)
test.obj : error LNK2001: unresolved external symbol "private: static int Point::x" (?x@Point@@0HA)
Debug/Test.exe : fatal error LNK1120: 2 unresolved externals
执行 link.exe 时出错.
可以看到编译没有错误,连接错误,这又是为什么呢?
这是因为静态的成员变量要进行初始化,可以这样:
#include <iostream.h>
class Point
{
public:
void output()
{
}
static void init()
{
   x = 0;
   y = 0;
}
private:
static int x;
static int y;
};
int Point::x = 0;
int Point::y = 0;
void main( void )
{
Point::init();
}
在静态成员数据变量初始化之后就不会出现编译错误了。



再看看下面的代码:
#include <iostream.h>
class Point
{
public:
void output()
{
}
static void init()
{
   x = 0;
   y = 0;
}
private:
static int x;
static int y;
};
void main( void )
{
}
编译没有错误,为什么?
即使他们没有初始化,因为我们没有访问x,y,所以编译不会出错。


后记————今天在增加模块checkemailaddr.c and checkemailaddr.h 文件的时候出现的编译连接错误。

static初始化的方法就是

int Point::x = 0;
int Point::y = 0;

link问题还没搞太清楚 在h文件里面定义static 而在cpp文件当中 初始化。

为什么在h文件当中初始化有问题。? 如果在哪初始化 没问题。类声明之后??


C++静态数据成员(static member)—静态成员的初始化不应该在头文件中,静态数据成员被类的所有对象共享、包括派生类的对象,在类中可以声明所属类自己的静态数据成员对象、不可以定义非静态数据成员对象,  

2011-03-08 10:24:27|  分类:C/C++程序设计_基 |字号 订阅

最终总结出静态数据成员的特点有::

          1、静态数据成员仅仅在初始化时,不受访问权限的约束;

          2、静态数据成员最好不要在.h文件中进行声明,而是放在.o文件中声明;

          3、静态数据成员被类的所有对象所共享,包括类的派生类的所有对象;——即派生类和基类共享一个静态成员。

          4、静态数据成员的类型可是所属类自己,即在一个类中可以声明该类自己的类型的静态成员对象,但是,不可以定义普通的成员对象,(指针可以)

          5、在const成员函数中,可以修改static成员变量的值。普通成员变量的值,是不能修改的。

          6、static成员函数只能访问static成员,不能访问非static成员,并且static成员函数不能定义为const函数。

详解 

    类体中的数据成员的声明前加上static关键字,该数据成员就成为了该类的静态数据成员。

        和其他数据成员一样,静态数据成员也遵守public/protected/private访问规则注意::仅仅是初始化时不遵守public/protected/private的规则

        同时,静态数据成员还具有以下特点:

 

1、静态数据成员的定义(初始化)不能在头文件中。 
     静态数据成员实际上是类域中的全局变量。所以,
静态数据成员的定义(初始化)不应该被放在头文件中。 
    其定义方式与全局变量相同。举例如下:
xxx.h文件
class base{
       private:
       static const int _i;           //声明,标准c++支持有序类型在类体中初始化,但vc6不支持。
};

xxx.cpp文件
const int base::_i=10;     //定义(初始化)时不受private和protected访问限制.

           注:不要试图在头文件中定义(初始化)静态数据成员。在大多数的情况下,这样做会引起重复定义这样的错误。即使加上#ifndef #define #endif或者#pragma once也不行。

 

 

2、静态数据成员   的所有对象所共享,包括该类派生类的对象。即派生类对象与基类对象共享基类的静态数据成员。举例如下:
class base{
       public : 
       static int _num;         //声明
};
int base::_num=0;           //静态数据成员的真正定义

class derived:public base{
};

main()
{
      base a; 
      derived b;
      a._num++; 
      cout<<"base class static data number _num is"<<a._num<<endl;
      b._num++;
      cout<<"derived class static data number _num is"<<b._num<<endl;
}
// 结果为1,2;可见派生类与基类共用一个静态数据成员。

 

3、静态数据成员的类型可以是所属类的类型而普通数据成员则不可以。普通数据成员的只能声明为所属类类型的 指针或引用。举例如下:

class base{
        public :
               static base _object1;                       //正确,静态数据成员
               base _object2;                                  //错误
               base *pObject;                                  //正确,指针 
                base &mObject;                              //正确,引用 (这个正确吗?????
};

 

 

4、静态数据成员的值在const成员函数中可以被合法的改变,而不破那个数据成员的值,不能在const成员函数中改变。

#include <iostream>
using namespace std;

class Student
{
 private:
  static int a;
  int b;
 public:
  void change() const;
  void setB(int b);
  int getB();
  static int getA();
};

void Student::change() const
{
          a++;         
 //这个可以,因为a是static成员变量。
          b++;         
//不可以,因为是const函数
}
int Student::getA()
{
         return a;
}
void Student::setB(int b)
{
 this->b = b;
}
int Student::getB()
{
 return b;
}
int Student::a = 5;

int main(int argc,char *argv[])
{
 Student stu;
 stu.setB(10);
 stu.change();
 cout<<Student::getA()<<endl; 
 cout<<stu.getB()<<endl;
 return 0;