C++中的this指针、访问控制和构造函数

C++中的this指针、访问控制和构造函数

this指针

在C++中,this指针是一个特殊的指针,它指向当前对象的地址。每个非静态成员函数(包括成员函数模板)都有一个this指针作为其隐含参数,这意味着在成员函数内部,this可以用来引用调用该成员函数的对象。this指针是自动传递给成员函数的,但在成员函数的参数列表中不可见。

this指针的用途

1. 明确成员访问

当局部变量(例如函数参数)的名称与类的成员变量名称相同时,可以使用this指针来区分它们,明确指出是对成员变量的访问。

class Example {
public:int value;void setValue(int value) {this->value = value; // 明确指出成员变量value}
};
2. 实现链式调用

this指针可以用于实现函数的链式调用。通过在成员函数的末尾返回*this,可以连续调用同一个对象上的其他成员函数。

class Example {
public:Example& setValue(int value) {this->value = value;return *this;}Example& doSomething() {// 操作return *this;}
};Example obj;
obj.setValue(5).doSomething(); // 链式调用
3. 返回对象自身的引用或指针

在某些情况下,可能需要从成员函数返回调用它的对象自身的引用或指针,this提供了这种能力。

class Example {
public:Example* getThis() {return this; // 返回当前对象的指针}
};
4. 比较对象

this指针可以用于比较两个对象是否相同,即它们是否是内存中同一个对象的两个引用。

class Example {
public:bool compare(const Example& other) const {return this == &other; // 比较两个对象的地址}
};

注意事项

  • 在静态成员函数中不能使用this指针,因为静态成员函数不属于任何对象实例。
  • this是一个常量指针,不能修改它本身的值,即不能使this指向另一个对象,但可以修改this所指向的对象的成员。
  • 在构造函数和析构函数中使用this指针时需要小心,特别是在构造函数中,因为对象可能还没有完全构造完成。

总的来说,this指针在C++类的成员函数中自动可用,提供了一种访问调用函数的当前对象的便捷方式。

访问控制

在C++中,访问控制是面向对象编程的一个核心特性,它定义了如何访问类的成员(包括数据成员和成员函数)。访问控制旨在提高数据的封装性和安全性,通过限制对类成员的访问来防止外部代码随意修改对象的内部状态。

C++提供三种访问控制级别:publicprivateprotected,这些访问控制符可以用于类的成员变量和成员函数。

Public(公有)

  • public成员在任何地方都可以被访问,无论是类的内部还是外部。
  • 使用公有成员可以提供类的接口,允许外部代码通过这些接口与对象交互。

Private(私有)

  • private成员只能被其所在类的成员函数、友元函数和友元类访问。
  • 私有成员用于实现类的内部细节,隐藏类的实现,这是封装的一个重要方面。

Protected(受保护)

  • protected成员可以被其所在类的成员函数、友元函数和友元类访问,同时也可以被派生类访问。
  • protected访问控制符主要用于继承场景,允许派生类访问基类的成员,而不对外界公开。

访问控制与继承

在继承中,基类成员的访问权限在派生类中可能会有所变化,这取决于继承的类型(publicprotectedprivate继承):

  • 公有继承(public:基类的公有成员和受保护成员在派生类中保持其原有的访问级别,基类的私有成员在派生类中不可访问。
  • 保护继承(protected:基类的公有成员和受保护成员在派生类中都变成受保护成员,基类的私有成员在派生类中不可访问。
  • 私有继承(private:基类的公有成员和受保护成员在派生类中都变成私有成员,基类的私有成员在派生类中不可访问。

示例

class Base {
public:int publicMember;
protected:int protectedMember;
private:int privateMember;
};class Derived : public Base {void func() {publicMember = 1;    // OK: public成员在派生类中可访问protectedMember = 2; // OK: protected成员在派生类中可访问// privateMember = 3; // 错误: private成员在派生类中不可访问}
};int main() {Base b;b.publicMember = 1; // OK: public成员在外部可访问// b.protectedMember = 2; // 错误: protected成员在外部不可访问// b.privateMember = 3;   // 错误: private成员在外部不可访问
}

总之,C++中的访问控制是实现封装和继承的关键机制,它帮助程序员定义类成员的可见性和可访问性,以确保对象的内部状态被适当地保护。

构造函数

在C++中,构造函数是一种特殊的成员函数,它在创建类的对象时自动调用,用于初始化对象。构造函数的主要目的是为对象的成员变量设置初始值,并执行任何必要的设置或分配资源的操作。

构造函数的特点

  1. 与类同名:构造函数的名称必须与类名相同。
  2. 无返回类型:构造函数没有返回值,也不声明返回类型,连void也不写。
  3. 可以被重载:一个类可以有多个构造函数,它们通过参数列表的不同进行区分。
  4. 自动调用:构造函数在创建类的新对象时被自动调用。

构造函数的类型

  1. 默认构造函数:不带任何参数(也可以是所有参数都有默认值)的构造函数。如果类中没有定义任何构造函数,编译器会自动生成一个默认构造函数(只在没有其他构造函数时)。

    class Example {
    public:Example() { /* 默认构造函数体 */ }
    };
    
  2. 参数化构造函数:带有参数的构造函数,用于通过提供的参数初始化对象的成员变量。

    class Example {
    public:Example(int a, double b) { /* 构造函数体 */ }
    };
    
  3. 拷贝构造函数:以同类的对象作为参数的构造函数,用于初始化一个对象为另一个同类型对象的副本。

    class Example {
    public:Example(const Example& other) { /* 拷贝构造函数体 */ }
    };
    
  4. 移动构造函数(C++11引入):以同类对象的右值引用作为参数的构造函数,用于实现对象的移动语义,而非复制。

    class Example {
    public:Example(Example&& other) noexcept { /* 移动构造函数体 */ }
    };
    

构造函数的使用

  • 直接初始化:使用圆括号来初始化对象。

    Example obj1; // 调用默认构造函数
    Example obj2(5, 3.14); // 调用参数化构造函数
    
  • 拷贝初始化:使用等号和另一个对象来初始化新对象。

    Example obj3 = obj2; // 调用拷贝构造函数
    
  • 列表初始化(C++11引入):使用花括号来初始化对象。

    Example obj4{}; // 调用默认构造函数
    Example obj5{5, 3.14}; // 调用参数化构造函数
    
  • 移动初始化:使用std::move来强制调用移动构造函数。

    Example obj6 = std::move(obj5); // 调用移动构造函数
    

注意事项

  • 当定义了其他构造函数时,编译器不再自动生成默认构造函数。如果需要,默认构造函数必须显式定义。
  • 拷贝构造函数和移动构造函数对于实现值语义和管理资源非常重要。
  • 在构造函数中使用初始化列表(而非在构造函数体内赋值)通常更有效,特别是对于引用和常量成员变量。

构造函数是C++面向对象编程中的一个基本概念,正确理解和使用构造函数对于创建稳定、高效的C++程序至关重要。

struct和class

在C++中,struct(结构体)和class(类)都是用户自定义类型的关键构建块,它们提供了数据封装的功能。尽管structclass在很多方面非常相似,它们之间主要的区别在于默认的访问控制和继承类型。

默认访问控制和继承

  • struct的成员默认是public的,而class的成员默认是private的。这意味着,除非你明确指定访问级别,否则struct成员在外部是可访问的,而class成员则不是。
  • 当使用struct继承另一个structclass时,继承默认是public的;而在class中继承另一个class时,继承默认是private的。

用法和语义

  • struct:在C++中,struct通常用于定义简单的数据结构,其中主要包含数据成员而没有太多的函数成员(方法)。struct特别适用于当你想要打包一些数据在一起时,这与C语言中的struct用法类似。
  • classclass则通常用于定义更复杂的数据结构,它不仅包含数据成员,还包含操作这些数据的成员函数。class是实现面向对象编程(OOP)概念(如封装、继承、多态)的主要工具。

示例

下面是一个structclass的简单示例,以展示它们的基本用法:

struct Point {int x, y; // 默认publicPoint(int x, int y) : x(x), y(y) {} // 构造函数也是public
};class Rectangle {
private:Point topLeft, bottomRight; // 默认privatepublic:Rectangle(const Point& tl, const Point& br) : topLeft(tl), bottomRight(br) {}void printCorners() { // 成员函数是publiccout << "Top Left: (" << topLeft.x << ", " << topLeft.y << ")"<< ", Bottom Right: (" << bottomRight.x << ", " << bottomRight.y << ")" << endl;}
};int main() {Point p(0, 0); // 直接访问Point的成员变量Rectangle r(Point(0, 10), Point(10, 0)); // 通过构造函数初始化Rectangler.printCorners(); // 调用Rectangle的成员函数
}

总结

尽管structclass在C++中非常相似,两者都可以用来定义含有数据成员和成员函数的类型,但它们在默认访问控制和默认继承类型上有所不同。选择使用struct还是class取决于你的特定需求,以及你对类型成员的默认访问权限的期望。一般而言,如果一个类型主要用于存储数据,并且你希望其成员默认为公有,那么使用struct可能更合适;如果你需要更多的封装和面向对象的特性,那么class将是更好的选择。

示例代码

#include <iostream>
#include <string>
using namespace std;// 定义student类
class student {
private:string name; // 私有成员变量:学生的姓名double score; // 私有成员变量:学生的分数public:// student类的构造函数// 当创建student对象时,此构造函数被自动调用以初始化对象student(string n, double s) {name = n; // 初始化姓名score = s; // 初始化分数cout << "构造函数\n"; // 打印构造函数被调用的消息}// 打印学生信息的成员函数void print() {// 使用this指针访问成员变量,打印学生的姓名和分数cout << this->name << " " << this->score << endl;}// 访问器函数:获取学生的姓名string get_name() { return name; }// 访问器函数:获取学生的分数double get_score() { return score; }// 修改器函数:设置学生的姓名void set_name(string n) { name = n; }// 修改器函数:设置学生的分数void set_score(double s) { score = s; }
};int main() {// 创建一个名为stu的student对象,使用参数化构造函数初始化姓名和分数student stu("cz", 90);// 使用修改器函数更新stu对象的姓名和分数stu.set_name("Li ping");stu.set_score(78.5);// 调用stu对象的print函数打印更新后的学生信息stu.print();//print(&stu);// 使用访问器函数获取并打印stu对象的姓名和分数cout << stu.get_name() << " " << stu.get_score() << endl;return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/755756.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IO空间和内存空间的区别

1&#xff0c;IO空间&#xff1a;一个特有的空间&#xff0c;与内存空间独立的空间&#xff0c;同样利用IO空间可以操作数据&#xff0c;只不过是利用对应的IO端口操作函数。 2&#xff0c;内存空间&#xff1a;内存地址的寻址范围&#xff0c;例如32位操作系统内存空间为2的32…

【IJCAI】CostFormer即插即用的MVS高效代价体聚合Transformer,FaceChain团队出品

一、论文题目&#xff1a; CostFormer: Cost Transformer for Cost Aggregation in Multi-view Stereo&#xff0c;https://arxiv.org/abs/2305.10320 二、论文简介&#xff1a; 多视角立体是三维重建的一种重要实现方式&#xff0c;该方式会从一系列同一场景但不同视角的二维…

c++算法学习笔记 (10) 位运算

1.求n的二进制位表示中第k位是几&#xff1a; #include <iostream> using namespace std; int main() {int n 10;for (int i 3; i > 0; i--){ // 求n的第i位cout << ((n >> i) & 1) << " ";} // 输出1 0 1 0return 0; } 2.lowbit…

解析JS加密解密中的生成器构造

前言 之前JS解密的客户&#xff0c;有一部分代码里是有生成器构造出来代码&#xff0c;一些基础比较薄弱的客户以及技术就看起来比较费劲看不懂了&#xff0c;这里特意写一篇文章为这部分客户服务。尽量言简意赅&#xff0c;以下是示例代码&#xff1a; function YV(YD) {ret…

【动态规划】【 数位dp】2827. 范围中美丽整数的数目

本文涉及知识点 数位dp 动态规划汇总 LeetCode2827. 范围中美丽整数的数目 给你正整数 low &#xff0c;high 和 k 。 如果一个数满足以下两个条件&#xff0c;那么它是 美丽的 &#xff1a; 偶数数位的数目与奇数数位的数目相同。 这个整数可以被 k 整除。 请你返回范围 [l…

仿懂车帝的二手车交易平台功能介绍

二手车交易平台app是一款功能丰富的二手车交易平台&#xff0c;以下是其主要功能介绍&#xff1a; 二手车信息展示&#xff1a;APP首页展示各类二手车信息&#xff0c;包括车型、品牌、价格等&#xff0c;用户可以轻松浏览并选择自己感兴趣的车辆。搜索与筛选功能&#xff1a;…

Ethereum, BSC, Polygon, Arbitrum, Base, OPBNB 链打符文代码

Ethereum, BSC, Polygon, Arbitrum, Base, OPBNB 代码创建了一个 Web3 实例,并根据配置文件中的 RPC URL 和链 ID 连接到区块链。 3. 接下来,代码定义了一些变量,如发送者钱包地址、发送者私钥、接收者钱包地址和输入消息。 4. `UpdateBalance` 函数用于获取发送者钱包…

哈希技术解析:从哈希函数到哈希桶迭代器的全面指南

文章目录 引言一、哈希表与哈希函数1、哈希表的基本原理2、哈希函数的作用与特点3、哈希冲突的处理方法 二、哈希桶及其迭代器1、 哈希桶a.定义哈希桶结构b.哈希函数c.哈希桶的插入、查找、删除 2、 哈希桶的迭代器a.类型定义与成员变量b.构造函数c.解引用与比较操作d.递增操作…

Liunx进程间通信

进程间通信 进程间通信进程间通信的基本概念进程间通信的目的 管道匿名管道进程池 命名管道 system V进程间通信system V进程间通信基本概念system V共享内存共享内存和管道的对比 system V 信号量信号量同步和互斥 进程间通信 进程间通信的基本概念 进程间通信就是在不同进程…

6-LINUX-- C 程序的编译与调试

一.环境搭建 1.gcc的安装 1>.切换到管理员模式 sudo su ----> 输入密码 2>.apt install gcc //C语言的编译环境 3>.apt install g //c编译环境的搭建 4>.install update //软件升级 2.gcc分步编译链接 &#xff08;1&#xff09;预编译 gcc -E…

计算机生物科技在基因编辑中的应用及其前景

一、引言 基因编辑&#xff0c;作为一种能够精准修改生物体基因组的技术&#xff0c;近年来受到了广泛的关注。 而计算机生物科技作为连接计算机科学与生物学的桥梁&#xff0c;为基因编辑技术的快速发展提供了强大的支持。通过利用计算机算法和数据分析方法&#xff0c;研究人…

Dashe Media全球新闻稿发布协助您实现传播目标-海外媒体宣发

亚太区新闻稿发布网络 Dashe Media 是唯一一家于亚太区拥有专有记者网络和网上新闻媒体发布网络的全球新闻通讯社 Dashe Media 在该地区的 26 个国家拥有 200,000 名记者和编辑数据库&#xff0c;涵盖 500 个新闻类别、68,000 个新闻媒体和 1,500 个在线新闻媒体合作伙伴&…

合并两个 Git 仓库,保存所有提交记录

将两个 Git 代码库合并成一个同时保留修改记录的过程&#xff0c;可以通过几个步骤完成。 这里提供一种常见的方法&#xff0c;使用git remote和git merge命令来实现。 假设场景 代码库A&#xff1a;原始代码库&#xff0c;希望将另一个代码库合并到这个库中。代码库B&#…

鸿蒙Harmony应用开发—ArkTS声明式开发(容器组件:Refresh)

可以进行页面下拉操作并显示刷新动效的容器组件。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 支持单个子组件。 从API version 11开始&#xff0c;Refresh子组件会跟随手势下拉而下移…

HarmonyOS 通知意图

之前的文章 我们讲了 harmonyos 中的 基础和进度条通知 那么 今天 我们来说说 任何给通知添加意图 通知意图 简单说 就是 当我们点击某个通知 如下图 然后 就会拉起某个 应用 就例如说 我们某个微信好友发消息给我们 我们 点击系统通知 可以直接跳到你们的聊天界面 好 回到…

JavaScript中的继承方式详细解析

什么是继承 继承是面向对象编程中的一个重要概念&#xff0c;它指的是一个对象&#xff08;或类&#xff09;可以获得另一个对象&#xff08;或类&#xff09;的属性和方法。在继承中&#xff0c;被继承的对象通常称为父类&#xff08;或基类、超类&#xff09;&#xff0c;继…

(css)vue 自定义背景 can‘t resolve

(css)vue 自定义背景 can’t resolve 旧写法&#xff1a; background-image: url(/assets/images/step-bg.jpg);background-size: 100% 100%; 新写法&#xff1a; background-image: url(~/assets/images/step-bg.jpg);background-size: 100% 100%; 解决参考&#xff1a;https…

深度学习PyTorch 之 transformer-中文多分类

transformer的原理部分在前面基本已经介绍完了&#xff0c;接下来就是代码部分&#xff0c;因为transformer可以做的任务有很多&#xff0c;文本的分类、时序预测、NER、文本生成、翻译等&#xff0c;其相关代码也会有些不同&#xff0c;所以会分别进行介绍 但是对于不同的任务…

【RabbitMQ | 第七篇】RabbitMQ实现JSON、Map格式数据的发送与接收

文章目录 7.RabbitMQ实现JSON、Map格式数据的发送与接收7.1消息发送端7.1.1引入依赖7.1.2yml配置7.1.3RabbitMQConfig配置类——&#xff08;非常重要&#xff09;&#xff08;1&#xff09;创建交换器方法&#xff08;2&#xff09;创建队列方法&#xff08;3&#xff09;绑定…

代码随想录算法训练营第27天|93.复原IP地址、78.子集、90.子集二

目录 一、力扣93.复原IP地址1.1 题目1.2 思路1.3 代码1.4 总结 二、力扣78.子集2.1 题目2.2 思路2.3 代码2.4 总结 三、力扣90.子集二3.1 题目3.2 思路3.3 代码3.4 总结 一、力扣93.复原IP地址 &#xff08;比较困难&#xff0c;做起来很吃力&#xff09; 1.1 题目 1.2 思路 …