C++ this指针的理解和作用
01 C++ 程序到 C 程序的翻译
要想理解 C++ 的 this 指针,我们先把下面的 C++ 代码转换成 C 的代码
class Car
{
public:
	int m_price;         // 成员变量
	void SetPrice(int p) // 成员函数
	{
	    m_price = p;
	}
};
int main()
{
	Car car;
	car.SetPrice(20000); // 给car对象m_price成员变量赋值
	return 0;
}
C 语言是没有类定义的class关键词,但是有跟class类似的定义,那就是结构体struct。
m_price变量是Car类的成员变量,那么我们可以把Car类和成员变量翻译成如下的 C 代码:
// 结构体Car
struct Car
{
    // price变量是属于Car结构体这个域里的变量
    int price;
};
SetPrice函数是Car类的成员函数,但是 C 程序里是没有成员函数这种概念的,所以只能把成员函数翻译成全局的函数:
// 参数1:结构体Car的指针
// 参数2:要设置的价格变量
void SetPrice(struct Car* this, int p)
{
    this->price = p;  // 将传入的Car结构体的price变量赋值
}
为什么要加个 this 的指针呢?我们继续往下看。
在这里我们把上面main函数下面的 C++ 程序翻译 C 程序是这样的:
int main()
{
    struct Car car;
    SetPrice( &car, 20000);
    return 0;
}
所以最终把上述的 C++程序 转换成C 程序的代码如下:
struct Car
{
    int price;
};
void SetPrice(struct Car* this, int p)
{
    this->price = p;
}
int main()
{
    struct Car car;
    SetPrice( &car, 20000); // 给car结构体的price变量赋值
    return 0;
}
02 this指针的作用
其作用就是指向成员函数所作用的对象,
所以非静态成员函数中可以直接使用 this 来代表指向该函数作用的对象的指针。
#include <iostream>
class Car
{
public:
	int m_price;
	void PrintPrice()
	{
		std::cout << m_price << std::endl;
	}
	void SetPrice(int p)
	{
		this->m_price = p; // 等价于 m_price = p;
		this->PrintPrice();// 等价于 PrintPrice();
	}
	Car GetCar()
	{
	    return *this; // 返回该函数作用的对象
	}
};
int main(void)
{
	Car car1, car2;
	car1.SetPrice(20000);
	// GetCar()成员函数返回所作用的car1对象,所把返回的car1赋值给了car2
	car2 = car1.GetCar();
	car2.PrintPrice();   
	return 0;
}
输出结果:
20000
20000
接下来我们下面的代码,你觉得输出结果是什么呢?会出错吗?
class A
{
    int i;
    public:
    void Hello() { cout << "hello" << endl; }
};
int main()
{
    A * p = NULL;
    p->Hello(); //结果会怎样?
}
答案是正常输出hello,你可能会好奇明明 p 指针是空的,不应该是会程序奔溃吗?别着急,我们先把上面的代码转换C程序,就能理解为什么能正常运行了。
void Hello() { cout << "hello" << endl; }
# 成员函数相当于如下形式:
void Hello(A * this ) { cout << "hello" << endl; }
p->Hello();
# 执行Hello()形式相当于:
Hello(p);
所以,实际上每个成员函数的第一个参数默认都有个指向对象的 this 指针,上述情况下如果该指向的对象是空,相当于成员函数的第一个参数是NULL,那么只要成员函数没有使用到成员变量,也是可以正常执行。
下面这份代码执行时,就会奔溃了,因为this指针是空的,使用了 空的指针指向了成员变量i,程序就会奔溃。
class A
{
    int i;
public:
    void Hello() { cout << i << "hello" << endl; }
    // ->> void Hello(A * this ) { cout << this->i << "hello" << endl; }
};
int main()
{
    A * p = NULL;
    p->Hello(); //  ->> Hello(p);
}
03 this指针和静态成员函数
静态成员函数是不能使用 this 指针,因为静态成员函数相当于是共享的变量,不属于某个对象的变量。
04 小结
- 通过将C++程序翻译成C程序的方式,来理解 this 指针,其作用就是指向非静态成员函数所作用的对象,每个成员函数的第一个参数实际上都是有个默认 this 指针参数。 
- 静态成员函数是无法使用this指针, 
C++ this指针的理解和作用的更多相关文章
- 【C++】类中this指针的理解
		转自 苦涩的茶https://www.cnblogs.com/liushui-sky/p/5802981.html C++类中this指针的理解 先要理解class的意思.class应该理解为一种类型 ... 
- 函数指针-如何理解typedef void (*pfun)(void)
		问题: 在刚接触typedef void (*pfun)(void) 这个结构的时候,存在疑惑,为什么typedef后只有一"块"东西,而不是两"块"东西呢?那 ... 
- C++(extern关键字的理解和作用深入)
		extern关键字的理解和作用深入 extern是一个关键字,它告诉编译器存在着一个变量或者一个函数,如果在当前编译语句的前面中没有找到相应的变量或者函数, 也会在当前文件的后面或者其它文件中定义 引 ... 
- C语言教学--二维数组和指针的理解
		对于初学者对二维数组和指针的理解很模糊, 或者感觉很难理解, 其实我们和生活联系起来, 这一切都会变得清晰透彻. 我们用理解一维数组的思想来理解二维数组, 对于一维数组,每个箱子里存放的是具体的苹果, ... 
- 函数指针的理解 from 数据结构
		今天在学习数据结构中遇到一些问题,函数的指针不知道怎么用,给自己科普一哈 1 int LocateElem_Sq(SqList L, LElemType_Sq e, Status(*Compare)( ... 
- C++中this指针的理解
		C++中this指针的理解 先要理解class的意思.class应该理解为一种类型,象int,char一样,是用户自定义的类型.用这个类型可以来声明一个变量,比如int x, myclass my等等 ... 
- C++类中this指针的理解
		先要理解class的意思.class应该理解为一种类型,象int,char一样,是用户自定义的类型.用这个类型可以来声明一个变量,比如int x, myclass my等等.这样就像变量x具有int类 ... 
- c++形参改变实参(对指针的理解
		这几天搞逻辑比较晕,居然把指针的概念都混淆了. eg:int *p;//当然不对指针初始化在有些编译器是通不过编译的,比如VS(尤其是选中了SDL) 指针p是一个对象,定义开始没有分配了内存空间,只是 ... 
- C/C++学习笔记----指针的理解
		指针是C/C++编程中的重要概念之一,也是最容易产生困惑并导致程序出错的问题之一.利用指针编程可以表示各种数据结构,通过指针可使用主调函数和被调函数之间共享变量或数据结构,便于实现双向数据通讯:指针能 ... 
随机推荐
- redis 事务(悲观锁和乐观锁)
			MULTI 开启事务,后续的命令会被加入到同一个事务中 事务中的操作会发送给客服端,但是不会立即执行,而是将操作放到了该事务对应的一个队列中,服务端返回QUEQUD EXEC 执行EXEC后,事务中的 ... 
- Java题库——chapter7 多维数组
			1)Which of the following statements are correct? 1) _______ A)char[ ][ ] charArray = {{'a', 'b'}, {' ... 
- MySQL插入数据时报错Cause: java.sql.SQLException: #HY000的解决方法
			数据库中有字段要求不能为空,但是insert插入的时候,改字段没有值 
- [Spring cloud 一步步实现广告系统] 4. 通用代码模块设计
			一个大的系统,在代码的复用肯定是必不可少的,它能解决: 统一的响应处理(可以对外提供统一的响应对象包装) 统一的异常处理(可以将业务异常统一收集处理) 通用代码定义.配置定义(通用的配置信息放在统一的 ... 
- 使用Kubernetes进行ProxySQL本机群集
			自v1.4.2起,ProxySQL支持本机群集.这意味着多个ProxySQL实例可识别群集; 他们了解彼此的状态,并能够通过根据配置版本,时间戳和校验和值同步最新的配置来自动处理配置更改. Proxy ... 
- socket之线程来提高吞吐量
			线程demo: 线程: package com.company.s5; import java.io.InputStream; import java.io.InputStreamReader; im ... 
- Linux shell--基础指令
			Linux shell--基础指令 浏览Linux文件系统 Linux中最基础也是最必要的一条指令 cd destination cd命令可接受单个参数destination,用以指定想切换到的目录名 ... 
- 记录Android开发中遇到的坑
			1. 出现错误提示:Intel HAXM is required to run this AVD,VT-x is disabled in BIOS的解决办法. 点击SDK图标,安装Intel x86 ... 
- Raspberry Pi (树莓派) 更换源 - stretch 版本
			Raspberry Pi 默认更新源访问速度慢,更换国内源速度提升.更换软件更新源 (/etc/apt/sources.list),更换系统更新源 (/etc/apt/sources.d/raspi. ... 
- USB HOST与 USB OTG的区别及工作原理
			在SmartQ 7上面,同时存在USB HOST与 USB OTG两个接口,我想问一下,这两个接口有什么区别么?我怎么认为HOST属于是多余呢? 麻烦高手解答,感激不尽!!! 转自USB HOST与 ... 
 
			
		