静态成员

静态成员

静态数据成员

可以定义类的静态成员,能够实现同类的多个对象之间数据共享。使用类的静态成员的优点是:

  • 静态成员的名字是在类的作用域中,因此可以避免与其他类的成员或全局对象名字冲突
  • 静态成员可以实施封装,可以是私有成员,而全局对象不可以
  • 静态成员是与特定类关联的,结构清晰

(1)静态数据成员
例:

class employee { //雇员类定义
	privateint empNo;
		int id;
		char *name;
		static int count; //静态数据成员
		...
};

静态数据成员是类的一种特殊数据成员,它以关键字static开始,声明形式为:

class 类名 { //类体
	...
	static 数据成员类型 数据成员名列表; //静态数据成员声明
	...
}

例如:

class Data { //Data类定义
	public:
		static int count; //静态数据成员
		int maxlevel; //非静态公有数据成员
		Data(int i=0) { ...,count++; } //构造函数
	private:
		int level; //非静态私有数据成员
};
int Data::count=0; //静态数据成员定义且初始化

count设计的目的是计数Data类总共有多少个实例化对象
在这里插入图片描述
关于静态数据成员的说明:
(1)通常,非静态数据成员存在于类类型的每个对象中,静态数据成员则独立于该类的任何对象,在所有对象之外单独开辟空间存储。在为对象所分配的空间中不包括静态数据成员所占的空间
(2)如果只声明了类而未定义对象,则类的非静态数据成员是不占存储空间的,只有在定义对象时,才为对象的数据成员分配空间。但是只要在类中定义了静态数据成员,即使不定义任何对象,也为静态数据成员分配空间,它可以在尚未建立对象时就被引用
(3)访问静态成员时同样需要遵守公有及私有访问规则
(4)静态数据成员必须在类外部定义一次(仅有一次),静态成员不能通过类构造函数进行初始化,而是在类外定义时进行初始化。定义静态数据成员的方式为:

数据成员类型 类名::静态数据成员名 = 初始化式;

(5)静态数据成员可用作默认实参,非静态数据成员不能用作默认实参,因为它的值不能独立于所属的对象而使用。例如:

class Data { //Data类定义
	...
	Data& setbkcolor(int bkcolor);
	static const int bkcolor = 5;
};

(6)有了静态数据成员,各对象之间实现了数据共享,因此可以不使用全局变量

class test {
	private:
		int x;
		int y;
	public:
		static int num;
		static int Getnum() {
			x+=5; //错误,静态成员函数不能调用非静态数据成员
			num+=15;
			return num;
		}
};

int test::num=10;

int main() 
{
	test a;
	cout<<test::num<<endl; //输出10
	text::num=20;
	cout<<test::num<<endl; //输出20
	cout<<test::Getnum()<<endl; //输出35
	cout<<a.Getnum()<<endl; //输出50
	return 0;
}

静态成员函数

成员函数也可以定义为静态的,在类中声明函数的前面加static就成了静态成员函数,声明的一般形式为:

class 类名 { //类体
	...
	static 返回类型 函数名(类型1 参数名1,类型2 参数名2...;
	...
};

例如:

static int getcount() { return count; } //静态成员函数

和静态数据成员一样,静态成员函数是类的一部分,而不是对象的一部分。如果要在类外调用公有的静态成员函数,可以类作用域运算符(::)和通过对象名调用静态成员函数,例如:

cout<<Data::getcount()<<'\t'<<d.getcount();

静态成员函数与非静态成员函数的根本区别是:非静态成员函数有this指针,而静态成员函数没有this指针。因此,静态成员函数不能访问本类中的非静态成员。静态成员函数就是专门为了访问静态数据成员的
静态成员函数不能被声明为const

静态成员举例:

#include<iostream>
using namespace std;

class CTest {
	public:
		CTest() { s_total++; id=s_total; cout<<"构造"<<id<<" "; }
		~CTest() { s_total--; cout<<"析构"<<id<<" "; }
		static int gettotal() { return s_total; }
	private:
		static int s_total;
		int id;
};
int CTest::s_total=0;
int main() {
	CTest a,b,c;
	CTest *p=new CTest;
	cout<<"合计="<<CTest::gettotal()<<" ";
	delete p;
	cout<<"合计="<<CTest::gettotal()<<" ";
	return 0;
}

静态成员举例

class Test {
	public:
		void init() { }
		static void output() { }
};
int main()
{
	Test::init();
	Test::output();
	return 0;
}
  • 编译出错,因为不能通过类名来调用类的非静态成员函数init

静态成员举例

class Test {
	public:
		void init() { }
		static void output() { }
};
int main()
{
	Test t;
	t.init();
	t.output();
	return 0;
}
  • 编译通过,类的对象可以使用静态成员函数和非静态成员函数

静态成员举例

class Test {
	public:
		void init() { }
		static void output() { cout<<x<<endl; }
	private:
		int x;
};
int main()
{
	Test t;
	t.output();
	return 0;
}
  • 编译出错,因为静态成员函数中不能引用非静态成员
  • 静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间

静态成员举例

class Test {
	public:
		void init() { output(); }
		static void output() { }
};
int main()
{
	Test t;
	t.output();
	return 0;
}
  • 编译通过,因为类的非静态成员函数可以调用静态成员函数,但反之则不能

静态成员举例

class Test {
	public:
		Test() { m++; }
		~Test() { m--; }
		static void output() { cout<<m<<endl; }
	private:
		static int m;
};
int main()
{
	Test t;
	t.output();
	return 0;
}
  • 链接错误,因为类的静态数据成员在使用前必须先初始化
  • 如果在main函数前加上int Point::m=0;,再编译链接无错误,运行程序将输出1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值