C++之static
目录
由关键字static修饰类中成员,成为类的静态成员。类的静态成员为其所有对象共享,不管有多少对象,静态成员只有一份存于公用内存中。静态数据成员被当做该类类型的全局对象。我们不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化。
一、静态属性
在类的设计中,用关键字static修饰的数据成员为静态数据成员。有该类型实例化的所有对象,共享系统为静态成员分配一个存储空间。而这个存储空间是程序执行main函数之前分配的,在实例化对象不再为静态成员分配空间(静态成员数据不再对象空间中)
静态属性也是受类的访问权限控制的
1、设计静态数据成员的目的是信息共享,只会被初始化一次,于实例无关
示例:
class Circle {
private:
static double pi;
double rid;
public:
Circle(double r=0.0):rid(r){}
~Circle(){}
double area()const
{
return pi * rid * rid;
}
};
double Circle:: pi=3.14;
int main()
{
cout << sizeof(Circle) << endl;
Circle cir(12.23);
size_t sz = sizeof(cir);
cout << sz << endl;
return 0;
}
也就是说 static 并不占用Cricle的内存空间(栈区),他在全局数据区分配内存
注意:
与全局变量相比,使用静态数据成员有两个优势:
- 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性
- 可以实现信息隐藏,静态成员可以是private,而全局变量不能
2、静态数据是该类所有对象所共有的,可以提供同一类型的所有对象之间,信息共享或信息交换的一种方式
静态数据成员属于整个类型,使用时可以用以下格式:
类名::静态数据成员名或者 对象.静态数据成员名(前提是可以访问符为public)
示例:
#include <iostream>
using namespace std;
class Box
{
public:
static int objectCount;
// 构造函数定义
Box(double l=2.0, double b=2.0, double h=2.0)
{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
// 每次创建对象时增加 1
objectCount++;
}
double Volume()
{
return length * breadth * height;
}
private:
double length; // 长度
double breadth; // 宽度
double height; // 高度
};
// 初始化类 Box 的静态成员
int Box::objectCount = 0;
int main(void)
{
Box Box1(3.3, 1.2, 1.5); // 声明 box1
Box Box2(8.5, 6.0, 2.0); // 声明 box2
// 输出对象的总数
cout << "Total objects: " << Box::objectCount << endl;
return 0;
}
输出结果:
Constructor called.
Constructor called.
Total objects: 2
3、在类的成员函数中使用静态数据成员,静态数据成员没有this指针,this指针指向类的对象本身,而static静态成员函数不依赖对象调用,它不与任何的对象相联系,所以当然不需要this指针。
4、静态属性的类型是int,short,char等整型,并且是const,可以在类中直接初始化
class A{
public:
static const int a=10;//想在类内定义 必须加const
static void add2();
static void add1()
{
++b;
cout<<b<<endl;
}
private:
static int b;
};
int A:: b=20;
void A::add2()
{
cout<<a<<endl;
}
int main()
{
A::add2();
A::add1();
}
总结:
- 设计静态数据成员目的是信息共享,和信息交流
- 类的静态数据成员为所有类对象所共享,不属于某个具体的实例
- 类的静态数据成员必须在类外定义,定义时不添加static关键字,不能在构造函数的初始化列表中创建
- 类的静态数据成员类型是int,short,char ,longlong,并且是const,可以在类中直接初始化也可以在类外初始化
- 在类的成员函数中使用静态数据成员,静态数据成员之前没有this
- 当类的静态数据成员为公有时,可以在外部函数使用:类名::静态数据成员名或者对象.静态数据成员名
- 可以在类体中定义自身的静态类型对象
二、静态方法
- 如果把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
- 静态成员函数只能访问静态成员数据、其他静态成员函数和类外部的其他函数。
- 静态成员函数有一个类范围,他们不能访问类的 this 指针。可以使用静态成员函数来判断类的某些对象是否已被创建。
- 静态成员函数在类内,类外具体定义实现,都是可以的
注意:
静态成员函数没有this指针,因此在静态成员函数显式的使用this指针都将会导致编译时刻错误,试图访问隐式使用this指针所指向的非静态数据成员也会导致编译时刻错误
静态成员函数与普通成员函数的区别:
- 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。
- 普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针。
示例:
#include <iostream>
using namespace std;
class Box
{
public:
static int objectCount;
// 构造函数定义
Box(double l=2.0, double b=2.0, double h=2.0)
{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
// 每次创建对象时增加 1
objectCount++;
}
double Volume()
{
return length * breadth * height;
}
static int getCount()
{
return objectCount;
}
private:
double length; // 长度
double breadth; // 宽度
double height; // 高度
};
// 初始化类 Box 的静态成员
int Box::objectCount = 0;
int main(void)
{
// 在创建对象之前输出对象的总数
cout << "Inital Stage Count: " << Box::getCount() << endl;
Box Box1(3.3, 1.2, 1.5); // 声明 box1
Box Box2(8.5, 6.0, 2.0); // 声明 box2
// 在创建对象之后输出对象的总数
cout << "Final Stage Count: " << Box::getCount() << endl;
return 0;
}
编译结果:
Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2
例题:
不能使用if,循环,公式,求n的累加
//使用静态数据成员,调用n次构造函数,产生n次累加
class ADD
{
private:
static int a;
static int b;
public:
ADD() {
a += b;
b++;
};
int Getnumber()
{
return a;
}
};
int ADD:: a=0;
int ADD::b=1;
//三目运算符求解
int ADD1(int n)
{
return n == 1 ? 1 : ADD1(n - 1) + n;
}
int main()
{
ADD* x = new ADD[100];
cout << x->Getnumber() << endl;
cout << ADD1(100) << endl;
return 0;
}
为什么static成员函数不能是const?
静态成员函数是属于某个类的,而不是某个对象。所以在类被定义的时候,在对象被定义之前就已经存在了,所以显然也可以看出他不是某个对象,但是const是用来修饰对象的,使对象保持不变,里面的数据成员保持不变,那么对于不是对象的static函数,就不可以用const修饰了。函数中的const其实就是用来修饰this指针的,意味this指向的内容不可变,static成员函数没有this,就不能使用const
更多推荐
所有评论(0)