c++ 类的静态成员,类的常成员

C++ 数据共享与保护

最近学习了 c++ 的常成员函数,常对象,常引用,静态函数成员,静态数据成员,学完之后感觉有些混乱于是写博客予以总结和记忆。

类中的静态成员

静态数据成员

顾名思义,就是类中的某些属性他是静态。这句话可以用下面这个例子来理解。

如果将类比作是一个工厂,对象是工厂中生产出的产品,那么静态数据成员就是存放在工厂中的,属于工厂,而不是属于每个产品

静态数据成员特点:

  • 静态数据成员的一般用法是 类名::标识符
  • 静态数据成员是用 static 修饰
  • 静态数据成员在类中定义,在类外声明,之所以这样做是由于,在类被初始化时,非静态数据成员的存储空间与所属对象存储同时分配,而静态成员需要单独分配,也就是在类外部声明时分配

静态数据成员代码举例

	#include <iostream>
	using namespace std;
	
	//点类的定义
	class Point {
	public:
		Point(int x = 0, int y = 0) :x(x), y(y) {  //构造函数
			count++;
		}
	
		Point(Point& p) {				          //复制构造函数
			x = p.x;
			y = p.y;
			count++;
		}
	
		~Point() { count--; }					//析构函数
	
		int getX() { return x; }
		int getY() { return y; }
	
		void showCount() {						//输出静态数据成员
			cout << "点类的个数:" << count << endl;
		}
	
	private:
		int x, y;
		//静态数据成员,用于记录一共声明了多少个点类
		static int count; 
	};
	
	int Point::count = 0;  //在类的外部初始化静态数据成员
	

主函数测试

	int main()
	{
		Point a(4, 5); //定义点类 a,会使得 count 增加1
		a.showCount();
	
		Point b(a);
		b.showCount();
	
		return 0;
	}

对于静态数据成员的访问,不应该是由某一个具体的对象来访问,因为,有时候可能连对象都没有声明就需要访问静态数据成员,所以访问静态数据成员应该是用类来访问比较合理,因为静态数据成员它不属于任何对象,是整个类所共有的。

静态函数成员

类中的一些函数他是静态的。

静态函数成员的特点:

  • 可以通过类名和对象名调用,习惯用类名调用
  • 可以直接访问类的静态数据和函数成员,
  • 访问非静态的成员必须通过对象名
  • 静态函数成员一般是用来访问静态数据成员的

解决这个问题的方法就是使用静态函数成员
将上面代码中 Point 类中的 showCount 方法改造成静态函数成员,因为它只访问静态数据成员

	static void showCount() {						//输出静态数据成员
		cout << "点类的个数:" << count << endl;
	}

改造之后就可以用 类名::静态函数名 这样的方法来访问静态数据成员了

Point::showCount();

注意:

  • 静态成员函数可以直接访问该类的静态数据和函数成员,而访问非静态成员必须通过对象名,是因为对静态函数成员的调用是没有目的对象的,而调用非静态成员函数是隐含了当前对象在其中的,所以需要指定静态函数成员调用的是哪一个对象的非静态成员。

静态成员总结

  • 静态数据成员
    • 用 static 关键字来声明
    • 习惯声明方式是 (static 数据类型 成员名)
    • 习惯访问方式是 类名::标识符
    • 需要在类中定义,类外初始化声明
  • 静态函数成员
    • 在函数名前加上 static 关键字
    • 习惯使用方法是 类名::函数名
    • 可以直接访问类的静态数据和函数成员,访问非静态成员,需要通过   对象名 . 属性  来访问

常类型的对象和数据

常类型的包括,常对象,常成员函数,常数据数据成员,常引用,是由 const 来修饰注意与 静态类型的数据区分

常对象

常对象:他的数据成员不能被改变,也就是说常对象必须进行初始化,而且不能被更新。

常对象特点:

  • 数据成员不能被改变
  • 常对象只能调用,对象中的常函数,不能调用其他非常函数

举例:

	class A {
		public:
		A(int i,int j):x(i),y(j){}
		void  show() {
			cout << "x:" << x << "y:" << y << endl;
		}
		private:
		int x, y;
	};
	
	const A a(3, 4);

这里就相当于声明了一个常对象 a,a 的 x 和 y 被声明后就不能在改变了,当我使用 show() 方法时

a.show()

发现 a 这个对象不能调用 show 函数
在这里插入图片描述
这里就引申出一个常对象的特点,如果一个对象声明为常对象时,则通过该对象只能调用它的常成员函数,不能调用其他函数。

void  show() const {
		cout << "x:" << x << "y:" << y << endl;
	}

当我将 show 函数声明为常函数时, 常对象就可以调用了。

常函数

常函数用 const 来修饰
习惯声明格式:类型说明符 函数名(参数表)const;

常函数的特点:

  • 无论调用常函数的对象是否是常对象,在常函数调用期间,都被视作常对象,所以常成员函数不能修改对象的数据成员
  • 两个个函数,函数名相同,是否添加了 const 修饰也可以作为函数重载的区分,而且,当时使用非常对象调用这个函数时,编译器一般选择不带 const 关键字的函数

代码举例

	#include <iostream>
	using namespace std;
	
	class R {
	public:
		R(int r1,int r2):r1(r1),r2(r2){}
		void print() {
			cout << r1 << ":" << r2 << endl;
			cout << "无 const" << endl;
		}
		void print()const {
			cout << r1 << ":" << r2 << endl;
			cout << " const" << endl;
		}
	private:
		int r1, r2;
	};

主函数调用

int main()
{

	R r(5, 4);
	r.print();
	const R rr(12, 22);
	rr.print();
	return 0;
}

在这里插入图片描述

常数据成员

类中的数据也可以是常量,而且一旦说明了类中的某个数据成员是常数据成员,那么任何函数都不能对其赋值

常数据成员的特点:

  • 用 const 来修饰
  • 习惯声明方式:const 数据类型 常量名
  • 常数据成员只能通过初始化列表来获得初值
  • 特别的,类中的静态常量如果是整型或者枚举类型,那么可以直接在类中定义常量值

代码举例

	class A {
	public:
		A(int i);
	
		void  show() {
			cout << "a:" << a << " b:" << b << endl;
		}
	private:
		const int a; //常数据成员
		static const int b; //静态常数据成员
	};
	
	const int A::b = 10;  //静态常数据成员需要在类外部声明
	
	A::A(int i) :a(i){} //常数据成员只能通过初始化列表来获取初值

主函数调用

int main()
{
	A a1(3),a2(0);
	a1.show();
	a2.show();
	return 0;
}

运行结果
在这里插入图片描述
b 是静态常数据成员,也就是类的属性,一经初始化后所有的对象共有这个属性,而且他是常类型的,他的值也不能在改变。

常引用

可以参照复制构造函数来学习。

常引用特点:

  • 常引用引用的对象不能被更新
  • 常引用可以绑定到常对象
  • 不能修改数据成员

终!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值