C++ 类的static成员

1,静态(static)成员综述
静态成员:不是任意对象的组成部分,但由给定类的全体对象所共享的数据成员或函数成员。
静态成员是与类关联的对象,而不是像普通的成员那样与类的对象相关联。
静态成员可以是数据成员,或成员函数。
静态成员遵循正常的共有/私有访问规则。
通过关键字static声明静态成员。

2,静态数据成员
2.1 定义方式
静态数据成员必须在类定义体的外部定义,且只能定义一次。静态数据成员不能通过类的构造函数初始化,而是应该在定义时进行初始化。
保证对象正好定义一次的方法是,将static数据成员的定义放在包含类的非内联成员函数定义的源文件中。

class Box
{
public:
	Box() :len(0.0), width(0.0) {}
	Box(double new_len, double new_width) :len(new_len), width(new_width) {}
	double volume() { return len*width*height; }
 
private:
	double len;
	double width;
	static double height;
};
 
//test.c
// 定义、初始化类的静态数据成员
double Box::height = 10;
 
//在main()函数中使用该类
int main()
{
	Box box1(1, 2);
	cout << box1.volume() << endl;
}

输出为120,即1 * 2 * 10
我们在类的定义体外将静态成员height初始化为10.
注意:不要将静态成员的定义放在头文件中,除非你能保证该头文件不会被两个不同的源文件包含,不然会报重复定义错误,相当于是在两个源文件中都定义了同一个变量。对于这种同一头文件被不同源文件包含的情况,使用#ifndef或者#pragma once是没用的。这种预编译宏是为了解决一个源文件两次包含同一个头文件的问题。
同时,对静态数据成员的定义也不能放在main()函数里,否则编译报错:error C2655: “Box::height”: 当前范围内的定义或重新声明非法。
正确的做法,就如上面所说,把它放在定义类的成员函数的源文件中。

2.2 const static数据成员
const static数据成员的值一经定义不能修改。
特别地,当该const static成员是整型时,可以在类的定义体内初始化,但是仍然必须在类的定义体外定义,此时定义时可以不必,也不能再赋值了。如果在类的定义体内和该const static整型成员的定义处都赋值,会报重复初始化错误,哪怕赋的是相同的值。
注意,这种在类的定义体内初始化的写法,只适用于整型!

class Box
{
public:
	Box() :len(0.0), width(0.0) {}
	Box(double new_len, double new_width) :len(new_len), width(new_width) {}
	double volume() { return len*width*height; }
	static Box box;  //该类类型的静态数据成员
 
private:
	double len;
	double width;
	static double height;
	//static const double weight = 50.0; //必须是整型?!!error C2864: 带有类内初始值设定项的静态数据成员必须具有不可变的常量整型
	static const double weight;//不在类内给定初始值的static const则不要求必须是整型。好奇葩!!
	static const int iNr = 10;
	//const static double weight; //const 与static谁前谁后都可以
};
 
// test.c
double Box::height = 10;
const int Box::iNr;
const double Box::weight = 50.3;
Box Box::box(3, 4);
 
int main()
{
	Box box1(1, 2);
	
	cout << Box::box.volume() << endl;
	cout << Box::box.box.volume() << endl;
	cout << Box::box.box.box.volume() << endl;
}

为什么整型会有特殊待遇,感觉很奇葩。

另外请注意,静态数据成员可以是本类类型的,而一般的成员最多是本类类型的指针或引用。
上面的例子中几个cout的输出是相同的,都是120, 3 * 4 * 10

3,静态成员函数
在声明成员函数时,在前面加static即成为静态成员函数。
注意,只能在声明的时候加,在体外定义的时候,不能再加static限定,否则报错:
error C2724: “Bar::callsFooVal”:“static”不应在文件范围内定义的成员函数上使用

静态成员函数与普通成员函数最大的区别是,其没有this指针,所以它不能直接使用类的非静态数据成员但可以直接使用类的静态数据成员。如果一定要使用类的非静态数据成员,就一定要指明对象(估计该对象也只能是全局变量了)。但一般而言还是尽量不要这么使用。

由于static成员不是任何对象的组成部分,没有this指针,不可能修改函数所属的对象,所以其也不能被限定为const。

class Foo
{
public:
	Foo():iVal(0) {}
	Foo(int new_val) :iVal(new_val) {}
	int get_value() { return iVal; }
 
private:
	int iVal;
};
 
class Bar
{
public:	
	int FooVal() { iTimes++; return fool.get_value(); }// 普通的成员函数,也能使用静态数据成员
	static int callsFooVal() { return iTimes; } //使用了静态数据成员
 
private:
	static int iTimes;
	static int i;
	static Foo fool;
};
 
// test.c
Foo Bar::fool(3132);
int Bar::i = 520;
int Bar::iTimes = 0;
//int Bar::iTimes; //OK,自动赋0值
 
int main()
{
	Foo foo_1(520);
	cout << foo_1.get_value() << endl;
 
	Bar bar_1;
	Bar bar_2;
	cout << bar_1.FooVal() << " " << bar_2.FooVal() << endl;
	cout << Bar::callsFooVal() << endl;
}

最终输出:
520
3132 3132
2

注意,静态成员函数只能使用静态数据成员;但是普通的成员函数,既能使用普通的数据成员,也能使用静态数据成员。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值