C++静态成员与静态函数
在C语言中,我们知道有static静态变量,生命周期与作用域都跟普通变量有所不同。而在C++的类中,也有静态成员变量同时还有静态成员函数。
一、静态成员
当将类的某个数据成员声明为static时,该静态数据成员只能被定义一次;而且要被同类的所以对象共享;各个对象都拥有类中每一个普通数据成员的副本,但静态数据成员只有一个实例存在,与定义对象多少无关。静态方法就是与该类相关的,是类的一种行为,而不是与该类的实例对象相关,即使没有定义对象,静态成员也是存在的;生存周期一直存在于整个程序的生命周期可以通过对象去访问静态成员,但是这里容易让人产生误解,以为他们是成员变量(静态成员是被所有对象共享的所以也可以去修改它) 我们一般通过 类名::静态成员 去访问它们,可以通过类名直接访问共有静态成员变量。
静态数据成员的用途之一是统计有多少个对象实际存在。
静态数据成员不能在类中初始化,实际上类定义只是在描述对象的蓝图,在其中指定初值是不允许的。也不能在类的构造函数中初始化该成员,因为静态数据成员为类的各个对象共享,否则每次创建一个类的对象则静态数据成员都要被重新初始化。
静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值。
静态成员的值对所有的对象是一样的。静态成员可以被初始化,但只能在类体外进行初始化。
静态成员的定义
int Class::a=10;
数据类型+类名+作用域符号+变量名=10;
注意:不能用参数初始化表对静态成员初始化。一般系统缺省初始为0。
对象使用.(成员运算符)
A a;//对象成员运算符调用静态成员变量
a.x=8;
类和作用域符(::)
A::a; //类和作用域符调用静态成员变量
#include <iostream>
#include <string>
using namespace std;
class Demo{
private:
static int value; //定义静态成员
public:
static int getvalue(){ //定义静态成员函数
return value;
}
};
int Demo::value=1; //类的静态成员变量需要在类外分配内存空间
int main(){
Demo d;
cout<<d.getvalue()<<endl;
return 0;
}
static 成员变量既可以通过对象来访问,也可以通过类来访问。请看下面的例子:
//通过类类访问 static 成员变量
Student::m_total = 10;
//通过对象来访问 static 成员变量
Student stu("小明", 15, 92.5f);
stu.m_total = 20;
//通过对象指针来访问 static 成员变量
Student *pstu = new Student("李华", 16, 96);
pstu -> m_total = 20;
注意:static 成员变量不占用对象的内存,而是在所有对象之外开辟内存,即使不创建对象也可以访问。具体来说,static 成员变量和普通的 static 变量类似,都在内存分区中的全局数据区分配内存
二、静态成员函数
针对静态成员变量的特点,把代码改成这样,统计对象的个数:
#include <iostream>
#include <string>
using namespace std;
class Demo{
private:
static int value1; //定义私有类的静态成员变量
public:
static int value2; //定义共有类的静态成员变量
Demo(){
value1++;
value2++;
}
int getvalue(){
return value1; //类的静态成员变量需要在类外分配内存空间
}
};
int Demo::value1=0; //类的静态成员变量需要在类外分配内存空间
int Demo::value2=0; //类的静态成员变量需要在类外分配内存空间
int main(){
Demo d1;
Demo d2;
Demo d3;
cout<<"Demo::value2="<<Demo::value2<<endl; //通过类名直接调用公有静态成员变量,获取对象个数
cout<<"d3.value="<<d2.value2<<endl; //通过对象名名直接调用公有静态成员变量,获取对象个数
cout<<"d3.getvalue()="<<d3.getvalue()<<endl; //通过对象名调用普通函数获取对象个数
}
在C++中讲究封装性,上面有两个问题:
1.类名或对象名能直接访问成员变量,也就是成员变量能直接被外界修改。
2.使用了一个成员函数来获取当前的对象个数,看起来没问题,但是必须要定义对象,通过对象去调用,但是如果我们不想定义对象,也能使用类的成员函数,就是我们说的静态成员函数。
类成员函数的特性:
1.静态成员函数是类的特殊成员函数,不是对象;
2.静态成员函数属于整个类所有,没有this指针;
3.静态成员函数只能直接访问静态成员变量和静态成员函数;
4.可以通过类名直接访问类的共有静态成员函数;
5.可以通过对象名访问类的公有静态成员函数;
6.定义静态成员变量,直接使用static关键字修饰;
#include <iostream>
#include <string>
using namespace std;
class Demo
{
private:
static int value; //定义私有类的静态成员变量
public:
Demo()
{
value++;
}
static int getValue() //定义类的静态成员函数
{
return value;
}
};
int Demo::value = 0; //类的静态成员变量需要在类外分配内存空间
int main()
{
Demo d1;
Demo d2;
Demo d3;
cout << "Demo::m_value2 = " << Demo::getvalue() << endl; //通过类名直接调用公有静态成员函数,获取对象个数
cout << "d3.getvalue() = " << d3.getvalue() << endl; //通过对象名调用静态成员函数获取对象个数
system("pause");
}
直接能通过类名去访问静态成员函数,获取对象个数,不通过任何对象。
静态成员函数在C++中的作用很强大,包括后边的介绍的单例模式、二阶构造模式,都用到静态成员函数及静态成员变量。
下边的图为静态成员函数与普通成员函数的比较:
静态成员函数 | 普通成员函数 | |
所以对象共享 | √ | √ |
隐含this指针 | × | √ |
访问普通成员变量 | × | √ |
访问静态成员变量 | √ | √ |
通过类名直接调用 | √ | × |
通过对象名直接调用 | √ | √ |
C语言的static和C++static总结:
static在C中的用法,对于C++来说是全盘接受的 两者的不同就在于C++中的类使用
C中的static变量其影响不在于作用域,在于其存储方式
C中的static函数,即内部函数,它其实是将访问权限限值在文件内部,文件外部无法访问
也是一种隐藏机制(类似当成private) 如果要访问需要加上extern 而extern是默认的
C语言中局部静态变量 作用域是函数体内,生存周期是整个程序运行期间