cpp_7.1 类和对象上(三) --- this

本文详细介绍了C语言和C++中结构体成员的访问方式,以及C++中this指针的使用、类型和作用。通过示例代码展示了成员函数内部如何通过this指针操作对象成员,并探讨了this的隐式参数特性、调用约定以及反汇编视角下的成员函数实现。此外,还讨论了成员变量在类中任意位置的编译器处理机制。
摘要由CSDN通过智能技术生成

针对上篇博客中的遗留问题进行解决。
在这里插入图片描述

1 c语言中,结构体如何访问成员

#if 0
struct Student
{
	char _name[20];
	char _gender[3];
	int _age;
};

// 必须要实现一个操作结构体类型变量的方法
void InitStudent(Student* ps, char* name, char* gender, int age)
{
	strcpy(ps->_name, name);
	strcpy(ps->_gender, gender);
	ps->_age = age;
}

// 打印那个学生的信息,必须将该学生类型的结构体类型的变量传进来
void PrintStudent(Student* ps)
{
	printf("%s-%s-%d\n", ps->_name, ps->_gender, ps->_age);
}

int main()
{
	struct Student s1, s2, s3;
	InitStudent(&s1, "Peter", "男", 18);
	InitStudent(&s2, "David", "男", 19);
	InitStudent(&s3, "Lily", "女", 18);

	PrintStudent(&s1);
	PrintStudent(&s2);
	PrintStudent(&s3);
	return 0;
}
#endif

2 c++中,结构体如何访问成员

只是将c中的ps换成this

#if 0
struct Student
{
	char _name[20];
	char _gender[3];
	int _age;
};

// 必须要实现一个操作结构体类型变量的方法
void InitStudent(Student* this, char* name, char* gender, int age)
{
	strcpy(this->_name, name);
	strcpy(this->_gender, gender);
	this->_age = age;
}

// 打印那个学生的信息,必须将该学生类型的结构体类型的变量传进来
void PrintStudent(Student* this)
{
	printf("%s-%s-%d\n", this->_name, this->_gender, this->_age);
}

int main()
{
	struct Student s1, s2, s3;
	InitStudent(&s1, "Peter", "男", 18);
	InitStudent(&s2, "David", "男", 19);
	InitStudent(&s3, "Lily", "女", 18);

	PrintStudent(&s1);
	PrintStudent(&s2);
	PrintStudent(&s3);
	return 0;
}
#endif

1.3 打印this地址来观察当前调用的是哪个对象

  • this只能在成员函数体内使用,不能再主函数中使用
  • this是一个指针,里面存放的是当前对象的地址(所谓的当前对象的地址:成员函数执行时,调用该成员函数的对象)
#if 0
class  Student
{
public:
	// 成员变量
	char _name[20];
	char _gender[3];
	int _age;

public:
	
	void InitStudent(char name[], char gender[], int age);
	{
	
		cout << this << endl;
		strcpy(this->_name, name);
		strcpy(this->_gender, gender);
		this->_age = age;
	}

	void PrintStudent()
	{
		cout << this << endl;
		cout << _name << "-" << _gender << "-" << _age << endl;
	}

	void SetAge(int age)
	{
		cout << this << endl;
		_age = age;
	}
};


int main()
{
	//cout << this << endl;//this只能在成员函数体内使用,不能再主函数中使用
	Student s1, s2, s3;
	s1.InitStudent("Peter", "男", 18);
	s2.InitStudent("David", "男", 19);
	s3.InitStudent("Lily", "女", 18);

	s1.PrintStudent();
	s2.PrintStudent();
	s3.PrintStudent();
	return 0;
}
#endif

在这里插入图片描述

1.4 this的类型为 类类型* const

#if 0
class  Student
{
public:
	// 成员变量
	char _name[20];
	char _gender[3];
	int _age;

public:
	void InitStudent(char name[], char gender[], int age);
	{
		// 不能给this指针来进行赋值----Student* const this
		//                          类类型* const
		//this = nullptr;//报错,提示左操作数不能等于右值
		cout << this << endl;

		// 有了this指针,成员函数就知道现在是在操作那个对象
		// 注意:对成员变量的操作都是通过this指针来进行的
		strcpy(this->_name, name);
		strcpy(this->_gender, gender);
		this->_age = age;
	}

	void PrintStudent()
	{
		cout << this << endl;
		cout << _name << "-" << _gender << "-" << _age << endl;
	}

	void SetAge(int age)
	{
		cout << this << endl;
		_age = age;
	}
};


int main()
{
	Student s1, s2, s3;
	s1.InitStudent("Peter", "男", 18);
	s2.InitStudent("David", "男", 19);
	s3.InitStudent("Lily", "女", 18);

	s1.PrintStudent();
	s2.PrintStudent();
	s3.PrintStudent();
	return 0;
}
#endif

1.5 this是隐形的形参

#if 0
class  Student
{
public:
	// 成员变量
	char _name[20];
	char _gender[3];
	int _age;

public:
	// 成员函数
	// 看起来该函数有三个参数,实际上有4个参数
	// 另外一个参数是:隐藏的this指针
	// 在写代码期间,用户不用显式给出this指针,编译器在编译代码时,会自动加上this指针的参数
	void InitStudent(char name[], char gender[], int age)
	{
		cout << this << endl;	
		strcpy(this->_name, name);
		strcpy(this->_gender, gender);
		this->_age = age;
	}

	void PrintStudent()
	{
		cout << this << endl;
		cout << _name << "-" << _gender << "-" << _age << endl;
	}

	void SetAge(int age)
	{
		cout << this << endl;
		_age = age;
	}

};


int main()
{
	Student s1, s2, s3;
	s1.InitStudent("Peter", "男", 18);
	s2.InitStudent("David", "男", 19);
	s3.InitStudent("Lily", "女", 18);

	s1.PrintStudent();
	s2.PrintStudent();
	s3.PrintStudent();
	return 0;
}
#endif

在这里插入图片描述

1.6 this一般通过ecx寄存器自动传递,有时采用调用约定

1.6.1 ecx寄存器自动传递

#if 0
class  Student
{
public:
	// 成员变量
	char _name[20];
	char _gender[3];
	int _age;

public:
	
	void InitStudent(char name[], char gender[], int age)
	{
		cout << this << endl;

		strcpy(this->_name, name);
		strcpy(this->_gender, gender);
		this->_age = age;
	}

	void PrintStudent()
	{
		cout << this << endl;
		cout << _name << "-" << _gender << "-" << _age << endl;
	}

	void SetAge(int age)
	{
		cout << this << endl;
		_age = age;
	}
};


int main()
{
	Student s1, s2, s3;
	s1.InitStudent("Peter", "男", 18);
	s2.InitStudent("David", "男", 19);
	s3.InitStudent("Lily", "女", 18);

	s1.PrintStudent();
	s2.PrintStudent();
	s3.PrintStudent();

	return 0;
}
#endif

在这里插入图片描述在这里插入图片描述

1.6.2 调用约定

#if 0
class  Student
{
public:
	char _name[20];
	char _gender[3];
	int _age;

public:
	void TestFunc(...){};
};


int main()
{
	Student s1, s2, s3;
	s1.TestFunc(1);
	s2.TestFunc(1, 2);
	s3.TestFunc(1, 2, 3);
	return 0;
}
#endif

在这里插入图片描述

1.6.3 两种方式的报错方式

#if 0
class  Student
{
public:
	char _name[20];
	char _gender[3];
	int _age;

public:
	//声明报错
	void InitStudent(char name[], char gender[], int age);
	void TestFunc(...);
};


int main()
{
	Student s1, s2, s3;
	s1.InitStudent("Peter", "男", 18);
	s2.InitStudent("David", "男", 19);
	s3.InitStudent("Lily", "女", 18);

	s1.TestFunc(1);
	s2.TestFunc(1, 2);
	s3.TestFunc(1, 2, 3);
	return 0;
}
#endif

两种方式的区别:
在这里插入图片描述

1.7 反汇编观察初始化函数

	void InitStudent(char name[], char gender[], int age)
	{
		strcpy(_name, name);
		strcpy(_gender, gender);
		_age = age;
	}

在这里插入图片描述

1.8 成员变量再类中的任意位置,为什么不报错?编译器是如何实现的。

成员变量可以再类的任意位置来进行定义,而且可以再"任意成员函数"中使用。
就相当于:成员变量就类似于成员函数的全局变量

// 成员变量在后,成员变量的使用在前,编译器怎么不报错呢?
// 因为:编译器是这样子来处理类:

/*
1. 先识别类名
2. 再来识别类中的成员变量
3. 最后识别类中的成员函数,并对成员函数进行修改----主要是增加this指针
*/
class  Student
{
public:

	/*
	增加this后:
	void InitStudent(Student* const this, char name[], char gender[], int age)
	{
	    strcpy(this->_name, name);
	    strcpy(this->_gender, gender);
	    this->_age = age;
	}
	*/
	void InitStudent(char name[], char gender[], int age)
	{
		strcpy(_name, name);
		strcpy(_gender, gender);
		_age = age;
	}

	/*
	增加this后:
	void PrintStudent(Student* const this)
	{
		printf("%s\n", this->_name);
		printf("%s\n", this->_gender);
		printf("%d\n", this->_age);
	}
	*/
	void PrintStudent()
	{
		printf("%s\n", _name);
		printf("%s\n", _gender);
		printf("%d\n", _age);
	}

private:
	char _name[20];
	char _gender[3];
	int _age;
};


int main()
{
	Student s1, s2, s3;
	s1.InitStudent("Peter", "男", 18);
	s2.InitStudent("David", "男", 19);
	s3.InitStudent("Lily", "女", 18);

	s1.PrintStudent();
	s2.PrintStudent();
	s3.PrintStudent();
}

在这里插入图片描述
往期链接:
cpp_7类与对象上(二) — 类对象的存储方式
cpp_6.1类与对象上(一)— 类的引入
cpp_6 nullptr
cpp_5.2 auto关键字
cpp_5.1 内联函数
cpp_5 const修饰的变量和宏
cpp_4 引用
cpp_3 函数重载/传址调用/引用
cpp_2 输入输出/函数/重载
cpp_1 命名空间/输入输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值