《随笔3》——隐藏的this指针、Stataic数据成员、Stataic静态成员函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34536551/article/details/83474866

目录

隐藏的this指针

静态数据成员

static 成员函数


隐藏的this指针


●  对于类的非静态成员,每一个对象都有自己的一份拷贝, 即每个对象都有自己的数据成员, 不过成员函数却是每个对象共享的。 那么调用共享的成员函数是如何区分自己的的数据成员呢,答案就是通过类中隐藏的this 指针。

●  this 指针是隐含在每个类成员函数中的指针, 其指向正在操作此函数的类对象,其类型为当前类类型的指针类型,在const函数中, 为当前类类型的const指针类型。 this指针的作用域是在类内部, 当在类的非静态成员函数中访问类的非静态成员时, 编译器会自动将对象本身的地址作为一个隐含参数传递给函数。

●  注意: 类的静态成员函数中没有this指针



void func(void *p, int val);
class A
{
public:
	int getA()
	{
		return a;
	}
	void setA(int val);
	friend void func(void *p, int val);
private:
	int a;
};
void func(void *p, int val)
{
	A *pp = (A*)p;  得到对象指针
	pp->a = val;
}
void A::setA(int val)
{
	func(this, val); 调用全局函数,this 表示当前对象指针
}
int main()
{
	A aa;
	aa.setA(500);
	int x = aa.getA();
	cout << "输出x的值:" << x << endl;
	system("pause");
	return 0;
}

在调用函数func时第一个参数是this 指针, 表明将对象aa 的指针传入 func中,然后通过对象aa 改变其中的成员变量a的值。

通过对象aa 调用setA() 函数, 在该函数的内部,this指针持有aa 对象的地址。 以这样的方式, 成员函数可以访问对象内的任何元素。

this指针将作为隐藏的参数传递给每个成员函数, 且this指针通常是函数接受的第一个参数、其后是已声明的其他参数, 假定setA() 函数如下:

void setA(A *this,int val);

在调用该函数时,应该这样:

aa.setA(&aa,500);

● 隐藏的this 指针应该注意的问题

this指针不能被修改,绝不能给它赋值,需要在成员函数内部修改this指针的情况很少见

什么时候必须使用this指针

利用this指针去除歧义的时候。

当我们希望返回对调用某函数的对象的引用时, 必须使用*this。

另一种情况是: 我们希望获得对象的地址,也必须显式使用this 指针。


静态数据成员


●  有时可能需要一个或多个公共的数据成员能够被类的所有对象共享,或者在程序的任意点需要统计已创建的特定类类型对象的数量。 在C++中,可以定义static数据成员和static成员函数用于解决同一个类的不同对象之间数据和函数共享的问题,

用一个类的不同对象的静态成员使用同一个内存空间, 但是又不会破坏封装。

● 通常, 非static 数据成员存在于类类型的每个对象中, 不像普通的数据成员,static 数据成员独立于该类的任意对象而存在; 每个static数据成员是与类关联的对象,并不与该类的对象关联。

类还可以定义static 成员函数,该函数没有this形参,可以直接访问所属类的static 成员, 但不能直接使用所属类的非static 成员。

●  使用类的static 成员好处有:

有利于类的封装, 可以把static成员定义为私有,防止外部访问。

static 成员与特定的类相关联。,在外部使用必须使用类名字做前辍, 程序更加清晰。

static成员的名字是在类的作用域中,可以避免命名冲突。

 静态数据成员可以被所有类的对象共享。这就意味着无论定义多少个类对象, 每个类的只有一个静态数据成员的拷贝,从而实现同类对象之间的数据共享。

如果某一个对象修改了static数据成员,其他对象的static数据成员也将被改变。 声明一个静态数据变量添加前辍关键字static。 

● 非静态数据成员随着对象的创建而被多次创建和初始化,而静态数据成员不同于非静态的数据成员,

一个类的静态数据成员仅创建和初始化一次,且在程序开始执行时创建, 然后被该类的所有对象共享。

● 下面看代码例子:

class Student
{
public:
	static int getCount();  
	static int count;

	void outPutAge(int data = age)  定义个成员函数,static数据成员可以作为默认参数
	{
		cout << data << endl;
	}
	void outPutSex(bool s = sex) 错误: 类的普通数据成员不能作为默认参数
	{

	}
	Student myStudent1;  错误,非static数据成员不能定义为所属类的对象
	static Student myStudent2; static 数据成员可以是当前类的类型
   
	Student *myStudent3; 正确, 允许定义类的所属类型的指针类型对象
     static Student &myStudent4();
	
private:
	 bool sex;
	static int age;
};
int Student::age = 1;  在类外初始化私有的static数据,要添加 类名::
int Student::getCount()  在类外定义static 函数不需要添加static
{
	return count; 在类的内部使用static 数据成员,不需要使用类名::
}
int main()
{
	Student myStudent;
	Student::count = 1;  利用作用域运算符在类外使用类名初始化公有的static数据
	int temp = Student::getCount(); 调用静态成员函数
	myStudent.count = 2; 使用点运算符还可以使用该类的对象初始化公有的static数据

	Student::age = 2; 错误: 在类外不能初始化 私有static数据
	
	Student *s = &myStudent; 声明一个指针指向该类型对象, 间接调用成员
	s->getCount();  通过指针调用static 成员函数
	s->count; 指针调用公有的static数据成员

	Student &ss = myStudent;
	ss.getCount();
	ss.count;


	system("pause");
	return 0;
}

在程序的执行过程中, 即使有多个 Student 类的对象, 也仅有一个 Student::age 的存在。

注意: static数据成员能够被类的成员函数访问,但不能在构造函数中初始化。 这是因为static数据成员在构造函数被调用之前就已经存在了。静态数据成员可以在定义时初始化,并且必须在类和所有成员函数之外。


static 成员函数


 在static成员函数中, 不可以使用this指针, 因为static成员函数是同一个类所有对象共用的。

注意:static 成员函数仅能访问static 数据成员,不能访问非static的数据成员,也不能访问非static 的成员函数, 这是因为static成员函数没有this指针。

如果要访问非静态成员,必须通过参数传递的方式得到对象名, 在通过对象名来引用。

static成员函数在类外的调用方式如下:

 类名 :: 静态成员函数名 (实参表)

或者

 对象名 :: 静态成员函数名 (实参表)

注意: 对于公有的static成员函数,可以通过类名或者对象名调用; 非公有的static成员函数,只能通过对象名调用。

● 下面看代码示例:

class Time
{
public:
	void print();
	static void getTime()const; 错误,静态成员函数不能定义为const成员函数
	static void setTime(const char *p);
	static void getDate();
	void setDate(int a = 9);
private:
	static  char szTime[60];
	int date;
};
char Time::szTime[60] = "12:00:00"; 初始化static 数据成员

void Time::setTime(const char *p)
{
	strcpy_s(Time::szTime, p);
}
void Time::getDate()
{
	cout << date << endl;  static 成员函数不能访问非静态的成员数据
	setDate(5); static 成员函数也不能访问非静态的成员函数

}
void  Time::setDate(int a)
{
	getDate(); 但是,非静态的成员函数可以访问静态的成员函数
	date = a;
}
void Time::print()
{
	cout << Time::szTime << endl;
}
int main()
{
	Time myTime;
	myTime.print();

	Time::setTime("15:00:00");  通过类名调用static成员函数
	myTime.print();

	myTime.setTime("16:00:00"); 通过类对象调用static成员函数
	myTime.print();
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34536551/article/details/83474866
今日推荐