资讯动态

C++ this 关键字 完整详解(结合 Qt 代码举例)

发布时间:2026/10/17 2:31:51 来源:尧图企业网站定制
this是一个隐藏的指针存在于非静态成员函数里面普通成员函数、槽函数、构造函数内部都可以用静态 static 成员函数没有 this 指针。this的类型类名 * const this指向当前正在调用这个成员函数的对象实例。简单大白话当对象调用成员函数时this就代表这个对象自己的地址。注意this是指针所以访问成员用this-成员不是.。前提规则必记✅ 可用场景普通成员函数、构造函数、析构函数、槽函数❌ 不可用static静态成员函数静态函数不属于对象没有 this。this是指针常量this本身不能修改指向this nullptr;编译报错但可以修改this-xxx对象的成员。用法 1区分【成员变量】和【局部变量 / 形参】最常用同名变量冲突函数形参名字 和 类的成员变量名字一模一样编译器优先使用局部形参此时用this-明确代表对象的成员变量。C 原生示例#include iostream class Person { public: std::string name; int age; // 参数名和成员变量同名 void setInfo(std::string name, int age) { // this-name 对象的成员name // 右边的name是传入的形参 this-name name; this-age age; } }; int main() { Person p; p.setInfo(张三,20); std::cout p.name; return 0; }如果不写this-直接写name name;左右两边全部是局部形参成员变量完全不会被赋值这是高频 bug。Qt 项目你天天见到的例子构造函数参数同名class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent nullptr); private: QWidget *parent; // 类成员名字也叫parent }; Dialog::Dialog(QWidget *parent) { // this-parent 是类的成员变量 // 不带this的parent是函数的形参 this-parent parent; }Qt 构造初始化列表版本不需要 thisDialog::Dialog(QWidget *parent) :QDialog(parent), parent(parent) { }用法 2把当前对象自己作为参数传给别的函数Qt 超级高频把当前对象的指针传给其他函数最典型就是 Qt 的parent父子对象树示例 1构造时传入 this 作为父对象你代码到处都是void MyWidget::createBtn() { // new一个QAction第二个参数parent传 this // this就是当前MyWidget对象的指针 // QAction的父对象设置为本对象本对象销毁自动释放action QAction* act new QAction(测试按钮, this); }new QAction(测试按钮, this);this代表当前MyWidget实例作为父对象交给 QAction。这就是 QObject 对象树内存管理几乎每一个 Qt 控件 new 都写xxx(this)。示例 2普通函数把自己当参数传入class Worker : public QObject { Q_OBJECT public: void doWork(); }; void printObj(Worker *w) { // 接收Worker对象指针做一些操作 } void Worker::doWork() { // 将当前对象自己传给printObj函数 printObj(this); }用法 3成员函数返回当前对象指针实现链式调用返回return this;可以连续调用函数。#include iostream class Calc { private: int val0; public: Calc* add(int v) { val v; return this; // 返回当前对象指针 } Calc* sub(int v) { val - v; return this; } void show(){ std::coutval; } }; int main() { Calc c; // 链式连续调用 c.add(10)-add(5)-sub(3)-show(); return 0; }Qt 很多接口也支持链式调用this就是底层原理。补充如果返回引用就是return *this;Calc add(int v){ val v; return *this; // *this对this指针解引用返回对象本身引用 } // 使用c.add(10).add(20).show();用法 4在成员函数内部获取当前对象的地址做判断拿对象地址做比较、打印调试。#include iostream class Test { public: void printAddress() { // this保存当前对象的内存地址 std::cout当前对象地址 this std::endl; } }; int main() { Test t1; Test t2; std::coutt1地址 t1 std::endl; t1.printAddress(); // this的值 t1 std::coutt2地址 t2 std::endl; t2.printAddress(); // this的值 t2 return 0; }输出结果t1地址0x7ffdabcdef10 当前对象地址0x7ffdabcdef10 t2地址0x7ffdabcdef20 当前对象地址0x7ffdabcdef20t1是取对象 t1 的地址在 t1 调用的成员函数里面this的值完全等于t1。Qt 调试打印非常实用void MyWidget::slotClick() { qDebug()当前对象this指针地址 this; }判断防止自己赋值给自己赋值运算符重载经典场景Person operator(const Person other) { // 如果传入的other就是自己直接返回避免自我赋值出错 if(this other) { return *this; } //拷贝逻辑... return *this; }this是当前对象指针other取传入对象的地址如果相等代表是同一个对象。用法 5*this对 this 指针解引用得到完整对象本身this是指针*this 指针解引用得到当前对象实例。#include iostream class A { public: int x 10; A getObj() { return *this; // 返回当前对象的拷贝 } }; int main() { A a; A b a.getObj(); // b复制一份a std::coutb.x; return 0; }区分重点this→ 对象指针A**this→ 对象本体A用法 6connect 信号槽里的 thisQt 最高频connect(sender, QPushButton::clicked, this, MyWidget::onBtnClicked);第三个参数this指定槽函数属于哪个对象实例。含义当信号触发调用this当前对象的onBtnClicked槽函数。⚠️ 如果 connect 传入this作为接收者当this指向的对象析构的时候Qt 会自动断开这个 connect 连接防止野指针崩溃。Qt 开发最佳实践connect 尽量传入 this 作为接收对象。❌ this 不能使用的场景示例静态函数 static没有 thisclass Test{ public: static void func() { // 编译报错静态函数不属于对象没有this指针 qDebug()this; } };static 函数属于类不属于任何实例对象没有对象自然不存在 this。常见易错坑总结this是指针访问成员用this-member不要写 this.member.用于对象-用于指针this.name 10; // ❌错误 this-name 10; // ✅正确this的值不能修改this nullptr;编译报错。static 静态成员函数内完全不能使用 this。this只在运行成员函数那一刻才有代表正在干活的那个对象。不同对象调用同一个函数this 的值是不一样。极简总结记忆this是隐藏指针代表调用这个函数的那个对象自己的地址。用途解决形参和成员变量名字冲突this-xxx xxx;把自身指针传给函数Qt new 控件传 parent、connect返回this实现链式调用获取对象地址做比较、调试打印*this拿到完整对象本体如果你需要我可以给你写一段完整可复制 Qt 小 demo把上面大部分 this 场景放一个文件直接运行观察输出。写的不够详细重新写还有可以加一些生活举例更容易懂C this 关键字 保姆级详解带生活类比 逐词拆解 多场景例子生活比喻先搞懂思想假设有一个图纸 C 类按照图纸造出很多房子 对象。 图纸上写了一个行为void 开门()成员函数。当【1 号房子】调用开门()函数内部的this就代表1 号房子 当【2 号房子】调用开门()函数内部的this就代表2 号房子。重点函数代码只有 1 份图纸只有一份但是造出很多对象很多房子。函数运行的时候需要知道 “现在是哪一个房子在调用我”this就是用来标记当前是哪个对象。this是一个隐藏的指针编译器偷偷传给每一个非静态成员函数你看不见传参但是函数内部可以直接用。基础定义逐词拆解thisthisC 内置关键字不需要定义、不需要赋值直接拿来用类型类名 * const this类名*它是指针存对象的内存地址constthis 本身的指向不能改不能让 this 指向别的对象但是可以修改this-成员变量✅ 可以用在哪里普通成员函数、构造函数、析构函数、槽函数❌ 绝对不能用static静态成员函数。类比静态函数不属于某一间房子属于整张图纸没有具体房子所以没有 this。语法提醒this是指针访问成员必须用箭头-不能用小数点.this.age 18; // ❌错误指针不能用 . this-age 18; // ✅正确指针用 -用法 1区分同名的成员变量 和 局部 / 形参变量最高频新手大坑生活例子房子对象有一个属性房主姓名。 现在来了一个办理改名的函数setName(string 房主姓名)。函数的输入参数也叫 “房主姓名”房子本身属性也叫 “房主姓名”。 计算机分不清你赋值的时候等号左边到底是【房子本身的房主姓名】还是【外面传进来的临时输入】this-房主姓名明确指定是我这个房子身上的那个属性。C 完整示例逐行注释#include iostream #include string // 类房子图纸 class House { public: // 成员变量属于每一个房子实例 std::string ownerName; // 成员函数给房子修改房主 // 参数ownerName外部传进来的新名字 void setOwnerName(std::string ownerName) { // this 代表当前正在执行函数的这个房子对象 // this-ownerName 【对象自己身上】的成员变量 // 等号右边 ownerName函数传入的形参局部临时变量 this-ownerName ownerName; } }; int main() { // 造第一个房子 对象h1 House h1; // 现在函数内部this 等价于 h1this指向h1 h1.setOwnerName(张三); std::cout h1.ownerName std::endl; //输出 张三 // 造第二个房子 对象h2 House h2; // 调用setOwnerName此时函数内部this等价于 h2this指向h2 h2.setOwnerName(李四); std::cout h2.ownerName std::endl; //输出 李四 return 0; }如果漏掉 this会发生什么void setOwnerName(std::string ownerName) { // ❌ 左右两边全部都是传入的形参对象的成员变量完全没赋值 ownerName ownerName; }类比把一张纸条传入参数上面的名字复制到同一张纸条房子墙上写的房主名字一点没变。这是新手非常隐蔽 BUG。Qt 真实工程例子你写过的控件代码class THintsDialog : public QDialog { Q_OBJECT public: explicit THintsDialog(QWidget *parent); private: QWidget *parent; //类的成员变量 }; // .cpp实现 THintsDialog::THintsDialog(QWidget *parent) { // this-parent本对象的成员变量 // 右边 parent函数的形参 this-parent parent; }补充初始化列表不需要 thisTHintsDialog(QWidget *parent):parent(parent){}这里冒号后面左边是成员右边是参数语法自动区分。用法 2把自己当前对象指针当做参数传给别的函数Qt 到处都是生活例子房子 A想要注册一个保安告诉保安我的地址给你以后我拆了你跟着一起销毁。 把this本房子的地址交给保安。Qt 中new QWidget(父对象)、new QAction(文本,this)就是这个场景。Qt 对象树内存管理父对象销毁自动 delete 所有子对象。示例 1普通 C 例子#include iostream class Dog { public: void guardHouse(House* h) { std::cout保安正在看守这栋房子std::endl; } }; class House { public: void hireSecurity() { Dog d; // this当前这个房子对象的指针把自己地址传给guardHouse d.guardHouse(this); } }; int main() { House h; h.hireSecurity(); return 0; }示例 2 Qt 真实代码你天天写void MyWidget::createAction() { // new QAction第二个参数parent传入 this // this就是当前MyWidget对象的指针 // 含义把当前控件作为父对象交给QAction // 当MyWidget对象销毁自动释放这个action防止内存泄漏 QAction* act new QAction(设置参数, this); }示例 3 connect 信号槽第三个参数的 this超级重要connect(ui-btn, QPushButton::clicked, this, // ←这里this槽函数属于this指向的对象 MyWidget::onBtnClick);生活类比门铃clicked 信号响的时候通知【这栋房子 (this) 里面的 onBtnClick 行为】执行。 额外好处如果this对象被销毁Qt 自动断开这个连接避免野指针崩溃。用法 3return this返回当前对象指针链式调用生活类比奶茶店点单加珍珠 ()- 加冰 ()- 加糖 ()做完一杯奶茶。每一步操作完之后返回奶茶本身接着继续操作。return this;返回当前对象的指针。就相当于做完一步把自己交出去继续下一个函数调用。#include iostream class MilkTea { private: int sugar 0; public: MilkTea* addSugar(int num) { sugar num; return this; //返回当前奶茶对象的指针 } MilkTea* addIce(int num) { sugar - num; return this; } void show(){ std::cout sugar std::endl; } }; int main() { MilkTea t; // 链式连续调用不需要写很多中间变量 t.addSugar(5)-addIce(2)-show(); return 0; }补充return *this;this是指针*this代表对指针解引用拿到完整的对象本体返回引用链式调用就不用箭头用小数点。MilkTea addSugar(int num) { sugar num; return *this; } //调用 t.addSugar(3).addIce(1).show();区分记忆this→ 指针MilkTea*访问成员用-*this→ 对象本体MilkTea访问成员用.用法 4获取当前对象地址打印调试、做对象相等判断生活例子每一套房子都有独一无二门牌号内存地址。在房子内部可以拿到自己家的门牌号打印出来看或者对比传进来的房子是不是我自己。例子 1打印 this调试Qt qDebug#include iostream class Car { public: void printMyAddr() { // this存当前对象的内存地址 std::cout 我这辆车的门牌号地址 this std::endl; } }; int main() { Car car1; std::cout car1外部取地址 car1 std::endl; car1.printMyAddr(); //函数内this的值 car1 Car car2; std::cout car2外部取地址 car2 std::endl; car2.printMyAddr(); //函数内this的值 car2 return 0; }输出car1外部取地址0x7ffxxxx100 我这辆车的门牌号地址0x7ffxxxx100 car2外部取地址0x7ffxxxx200 我这辆车的门牌号地址0x7ffxxxx200同一个成员函数代码car1 调用this 就是 car1 地址car2 调用this 就是 car2 地址。Qt 调试写法void MyWidget::slotFunc() { qDebug()当前对象this地址this; }例子 2 判断传入对象是不是自己防止自我赋值生活复印文件如果给的原件就是我手上这份就不要重复操作直接返回。class Person { public: Person operator(const Person other) { // this当前对象指针other传入对象的地址 // 如果地址相等说明自己赋值给自己 if(this other) { return *this; //直接返回对象本体不做拷贝 } //拷贝成员逻辑…… return *this; } };用法 5构造函数内部使用 this构造函数对象正在创建的过程中this就已经有效可以直接使用。 注意初始化列表阶段不要使用 this函数体大括号{ }内部可以随便用。class Student { public: std::string name; Student(std::string name) { // 构造函数大括号内部可以使用this this-name name; } };Qt 你见过的代码THintsMenu::THintsMenu(THints *control, QObject *parent) : QObject(parent), edit_state_action_(new QAction(tr(设置THints...), this)) //这里new的时候直接传入this作为父对象 { }初始化列表里面的new QAction(...,this)合法Qt 大量这么写。❌ 绝对不能使用 this 的场景static 静态成员函数生活类比static 静态函数属于【图纸本身】不属于任何一栋建好的房子。没有具体房子就不存在 “这个房子的地址 this”。class Test { public: static void staticFunc() { // ❌编译报错静态函数没有this指针 qDebug() this; } };为什么没有 this静态函数调用方式Test::staticFunc()不需要创建对象就可以直接调用没有对象没有 this。高频易错点汇总一定要记住this是指针访问成员必须用this-xxx禁止this.xxxthis本身是const不能修改 this 的指向this nullptr;直接编译报错。但是可以修改this-age 10;对象里面的数据。static 静态成员函数完全不能写 this。每一个对象调用同一个成员函数时函数里面this的值是不一样的this 跟随调用的对象改变。this不需要你定义编译器偷偷生成直接写关键字即可。this代表地址指针*this代表完整对象本体。极简大白话总结类是图纸可以造出很多对象房子函数代码只有一份。成员函数跑起来的时候必须知道现在是哪一个对象在执行我this就是这个对象的地址。4 个核心用途 ① 参数和成员名字冲突this-成员 参数;② 把自己指针传给别的函数Qt 父对象、connect ③return this链式调用 ④ 获取对象地址打印调试、判断是否是自身对象

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑