c :静态成员(静态成员变量、静态成员函数、const静态成员属性、单例模式、成员变量和函数的存储 、this指针、常函数、常对象)

不管这个类创建了多少个对象,静态成员只有一个拷贝,这个拷贝被所有属于这个类的对象共享。


目录

一、静态成员变量

二、 静态成员函数

 三、const静态成员属性

四、单例模式

五、成员变量和函数的存储

六、this指针

6.1 this指针工作原理

6.2 this指针使用

6.3 this指针的本质和常函数(const修饰成员函数)

6.4 常对象(const修饰对象)


 

一、静态成员变量

在一个类中,若将一个成员变量声明为static,这种成员称为静态成员变量。与一般的数据成员不同,无论建立了多少个对象,都只有一个静态数据的拷贝。静态成员变量,属于某个类,所有对象共享。

静态变量,是在编译阶段就分配空间,对象还没有创建时,就已经分配空间。

  1. 静态成员变量必须在类中声明,在类外定义
  2. 静态数据成员不属于某个对象,在为对象分配空间中不包括静态成员所占空间。
  3. 静态数据成员可以通过类名或者对象名来引用。
class Person{
public:
	//类的静态成员属性
	static int sNum;
private:
	static int sOther;
};

//类外初始化,初始化时不加static
int Person::sNum = 0;
int Person::sOther = 0;

int main()
{
	//1. 通过类名直接访问
	Person::sNum = 100;
	cout << "Person::sNum:" << Person::sNum << endl;

	//2. 通过对象访问
	Person p1, p2;
	p1.sNum = 200;

	cout << "p1.sNum:" << p1.sNum << endl;
	cout << "p2.sNum:" << p2.sNum << endl;

	//3. 静态成员也有访问权限,类外不能访问私有成员
	//cout << "Person::sOther:" << Person::sOther << endl;
	Person p3;
	//cout << "p3.sOther:" << p3.sOther << endl;

	system("pause");
	return EXIT_SUCCESS;
}

 

二、 静态成员函数

在类定义中,前面有static说明的成员函数称为静态成员函数。静态成员函数使用方式和静态变量一样,同样在对象没有创建前,即可通过类名调用。静态成员函数主要为了访问静态变量,但是,不能访问普通成员变量

静态成员函数的意义:不在于信息共享和数据沟通,而在于管理静态数据成员,完成对静态数据成员的封装。

普通成员函数可访问静态成员变量、可以访问非静态成员变量

静态成员函数可访问静态成员变量,不可以访问非静态成员变量

class Person{
public:
	//普通成员函数可以访问static和non-static成员属性
	void changeParam1(int param){
		mParam = param;
		sNum = param;
	}
	//静态成员函数只能访问static成员属性
	static void changeParam2(int param){
		//mParam = param; //无法访问
		sNum = param;
	}
private:
	static void changeParam3(int param){
		//mParam = param; //无法访问
		sNum = param;
	}
public:
	int mParam;
	static int sNum;
};

//静态成员属性类外初始化
int Person::sNum = 0;

int main(){

	//1. 类名直接调用
	Person::changeParam2(100);

	//2. 通过对象调用
	Person p;
	p.changeParam2(200);

	//3. 静态成员函数也有访问权限
	//Person::changeParam3(100); //类外无法访问私有静态成员函数
	//Person p1;
	//p1.changeParam3(200);
	return EXIT_SUCCESS;
}

 

 三、const静态成员属性

如果一个类的成员,既要实现共享,又要实现不可改变,那就用 static const 修饰。

定义静态const数据成员时,最好在类内部初始化

class Person{
public:
	//static const int mShare = 10;
	const static int mShare = 10; //只读区,不可修改
};
int main(){

	cout << Person::mShare << endl;
	//Person::mShare = 20;

	return EXIT_SUCCESS;
}

 

四、单例模式

Singleton(单例):在单例类的内部实现只生成一个实例,同时它提供一个静态的getInstance()工厂方法,让客户可以访问它的唯一实例;为了防止在外部对其实例化,将其默认构造函数和拷贝构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。

单利固定格式:

class Printer
{
private:
	Printer() {};	    	             // 1、构造函数私有化
	Printer(const Printer &) {};         // 2、拷贝函数私有化

	static Printer* singlePrinter;		 // 3、指针私有化

public:
	static Printer* getInstance()		 // 5、对外提供getInstance
	{
		return singlePrinter;
	}
};

Printer * Printer::singlePrinter = new Printer;   //4、初始化指针

void test()
{
	Printer* p1 = Printer::getInstance();   //单例实例化
}

 

五、成员变量和函数的存储

空类占用的内存空间:1字节

1、非静态成员变量 属于类的对象上
2、静态成员变量  不属于类对象上
3、非静态成员函数  不属于类对象上  只有一份实例
4、静态成员函数  不属于类对象上    只有一份实例

 

六、this指针

6.1 this指针工作原理

c++的数据和操作也是分开存储,并且每一个非内联成员函数(non-inline member function)只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码

那么问题是:这一块代码是如何区分那个对象调用自己的呢?

c++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象。

c++规定,this指针是隐含在对象成员函数内的一种指针。当一个对象被创建后,它的每一个成员函数都含有一个系统自动生成的隐含指针this,用以保存这个对象的地址,也就是说虽然我们没有写上this指针,编译器在编译的时候也是会加上的。因此this也称为“指向本对象的指针”,this指针并不是对象的一部分,不会影响sizeof(对象)的结果。

   this指针是C++实现封装的一种机制,它将对象和该对象调用的成员函数连接在一起,在外部看来,每一个对象都拥有自己的函数成员。一般情况下,并不写this,而是让系统进行默认设置。

成员函数通过this指针即可知道操作的是那个对象的数据。This指针是一种隐含指针,它隐含于每个类的非静态成员函数中。This指针无需定义,直接使用即可。

注意:静态成员函数内部没有this指针,静态成员函数不能操作非静态成员变量。

下图是 c++编译器对普通成员函数的内部处理

 

6.2 this指针使用

使用场景:

  • 当形参和成员变量同名时,可用this指针来区分
  • 在类的非静态成员函数中返回对象本身,可使用return *this.
class Person
{
public:
	
	Person(int age)            //每一个非静态成员函数内部都隐藏加了一个this指针
	{
//1、this可以解决名称冲突
		this->age = age;
	}

//2、在类的非静态成员函数中返回对象本身
	Person&  personAddAge(Person & p)
	{
		this->age += p.age;
		return  *this;             // *this指向p2的本体  this指向p2的指针
	}

	int age;
};

void test01()
{
	Person p1(10);
	cout << "p1的年龄为: " << p1.age << endl;


	Person p2(10);
	p2.personAddAge(p1).personAddAge(p1).personAddAge(p1);     //链式编程思想

	cout << "p2的年龄为: " << p2.age << endl;  

}

 

6.3 this指针的本质和常函数(const修饰成员函数)

  1. this指针的本质 :指针常量
  2. this指针的类型: Person * const  this
  3. 如果想让指针指向的值也不可以修改(常函数),this指针的类型即是:  const Person * const this
  4. 每个非静态成员函数内部都加了this指针

常函数的格式:

返回值类型 函数名() const
例子:void showAge() const

  • 用const修饰的成员函数时,const修饰this指针指向的内存区域,成员函数体内不可以修改本类中普通成员变量。
  • 当成员变量类型符前用mutable修饰时例外。
class Person{
public:
	Person(){
		this->mAge = 0;
		this->mID = 0;
	}
	//在函数括号后面加上const,修饰成员变量不可修改,除了mutable变量
	void sonmeOperate() const{
		//this->mAge = 200; //mAge不可修改
		this->mID = 10;
	}
	void ShowPerson(){
		cout << "ID:" << mID << " mAge:" << mAge << endl;
	}
private:
	int mAge;
	mutable int mID;
};

int main(){

	Person person;
	person.sonmeOperate();
	person.ShowPerson();

	system("pause");
	return EXIT_SUCCESS;
}

 

 

6.4 常对象(const修饰对象)

  1. 常对象只能调用const的成员函数
  2. 常对象可访问 const 或非 const 数据成员,不能修改,除非成员用mutable修饰
class Person{
public:
	Person(){
		this->mAge = 0;
		this->mID = 0;
	}
	void ChangePerson() const{
		mAge = 100;
		mID = 100;
	}
	void ShowPerson(){
        this->mAge = 1000;
		cout << "ID:" << this->mID << " Age:" << this->mAge << endl;
	}

public:
	int mAge;
	mutable int mID;
};

void test(){	
	const Person person;
	//1. 可访问数据成员
	cout << "Age:" << person.mAge << endl;
	//person.mAge = 300; //不可修改
	person.mID = 1001; //但是可以修改mutable修饰的成员变量
	//2. 只能访问const修饰的函数
	//person.ShowPerson();
	person.ChangePerson();
}

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值