news 2026/4/16 19:05:39

02 C++面相对象、构造函数、初始化列表、引用、string

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
02 C++面相对象、构造函数、初始化列表、引用、string

C++ 面向对象、构造函数、初始化列表、引用、string

一、面向过程与面向对象对比

1. 核心思想差异

  • 面向过程:以“步骤”为核心,按顺序执行操作。例如操作文件需依次调用openread/writeclose,开发者需关注每一步的实现细节。
  • 面向对象:以“对象”为核心,对象包含属性(数据)和方法(操作)。操作文件时,文件作为对象,自带打开/读写/关闭方法,开发者只需调用对象的方法,无需关注内部实现。

2. 代码示例对比(以 LCD 操作为例)

  • 面向对象风格(简洁高效,无需关注初始化细节):
    MyLcd l;// 创建 LCD 对象(自动完成初始化)l.DrawRectangle(200,100);// 调用对象方法画矩形l.DrawCircle(300,700,300);// 调用对象方法画圆l.LcdClose();// 调用对象方法关闭设备

3. 优缺点总结

  • 面向对象:开发效率高、代码易维护,但对象创建有轻微性能开销。
  • 面向过程:执行效率略高,但代码复用性差、复杂项目维护难度大。

二、构造函数(Constructor)

1. 核心作用

对象实例化时自动调用,用于初始化对象的成员变量,解决“对象使用前必须初始化”的问题(如 LCD 设备需先打开才能使用)。

2. 语法规则

  • 无返回值(连void都不能写),函数名与类名完全一致。
  • 支持重载(可定义多个参数不同的构造函数)。
  • 若未手动定义,编译器会自动生成一个“无参、无功能”的默认构造函数。
  • 一旦手动定义任意构造函数,编译器不再自动生成默认构造函数。

3. 常见用法

#include<iostream>#include<cstring>usingnamespacestd;classPerson{private:intage;charname[32];public:// 1. 无参构造(默认构造)Person(){age=0;name[0]='\0';// 字符串初始化(避免垃圾值)}// 2. 单参构造(int 类型)Person(inta){age=a;name[0]='\0';}// 3. 单参构造(字符串类型)Person(constchar*n){age=0;strncpy(name,n,sizeof(name)-1);// 安全拷贝,避免数组越界name[sizeof(name)-1]='\0';}// 4. 多参构造Person(inta,constchar*n){age=a;strncpy(name,n,sizeof(name)-1);name[sizeof(name)-1]='\0';}// 5. 带默认参数的构造函数Person(inta=18,constchar*n="unknown"){age=a;strncpy(name,n,sizeof(name)-1);name[sizeof(name)-1]='\0';}};

4. 对象实例化与构造函数调用

  • 推荐使用{}初始化(C++11 新标准,避免歧义):
    Person p1;// 调用无参构造Person p2{18};// 调用单参构造(int)Person p3{"penglei"};// 调用单参构造(字符串)Person p4{20,"ZhangSan"};// 调用多参构造Person p5{22,"LiSi"};// 调用带默认参数的构造(覆盖默认值)
  • 注意:Person p();会被编译器识别为“函数声明”,而非对象实例化,需避免。

5. 访问权限

  • 构造函数通常设为public(允许外部实例化对象)。
  • 特殊场景设为private(如单例模式,限制对象创建数量)。

6. 练习:People 类设计

classPeople{private:intage;string name;// 后续改用 string 类,更安全便捷string addr;public:// 无参构造People():age(0),name("unknown"),addr("unknown"){}// 全参构造People(inta,conststring&n,conststring&ad):age(a),name(n),addr(ad){}// 打印信息voidShowInfo(){cout<<"Age: "<<age<<", Name: "<<name<<", Addr: "<<addr<<endl;}};// 调用示例intmain(){People p1;p1.ShowInfo();// 输出:Age: 0, Name: unknown, Addr: unknownPeople p2{25,"WangWu","Beijing"};p2.ShowInfo();// 输出:Age: 25, Name: WangWu, Addr: Beijingreturn0;}

三、析构函数(Destructor)

1. 核心作用

对象生命周期结束时自动调用,用于清理资源(如关闭文件、释放动态内存、解绑设备等),避免资源泄漏。

2. 语法规则

  • 无返回值,无参数(因此无法重载,一个类只能有一个析构函数)。
  • 函数名前加~,与类名一致。
  • 若未手动定义,编译器会自动生成一个“无功能”的默认析构函数。

3. 用法示例

classMyLcd{private:intfd=-1;// 文件描述符unsignedint*plcd=nullptr;// 内存映射指针public:// 构造函数:打开 LCD 设备MyLcd(){fd=open("/dev/fb0",O_RDWR);if(fd==-1){cerr<<"LCD open failed!"<<endl;return;}// 内存映射等初始化操作...cout<<"LCD initialized!"<<endl;}// 析构函数:关闭设备、释放资源~MyLcd(){if(plcd!=nullptr){munmap(plcd,800*480*4);// 释放内存映射plcd=nullptr;}if(fd!=-1){close(fd);// 关闭文件fd=-1;}cout<<"LCD resource released!"<<endl;}};

4. 调用顺序

  • 遵循“先构造,后析构”原则:先创建的对象最后被销毁,后创建的对象先被销毁。
  • 示例:
    intmain(){MyLcd l1;// 构造 l1MyLcd l2;// 构造 l2// 生命周期结束时,先析构 l2,再析构 l1return0;}// 输出:// LCD initialized!// LCD initialized!// LCD resource released!// LCD resource released!

5. 注意事项

  • 析构函数仅用于“清理资源”,不建议写入业务逻辑。
  • 避免在构造函数/析构函数中使用return(可能导致初始化/清理不完整)。

四、构造函数初始化列表

1. 核心用途

解决“构造函数体内无法初始化某些成员”的问题,例如:

  • 常量成员(const修饰,必须初始化且不可修改)。
  • 引用成员(必须在定义时初始化)。
  • 父类无默认构造函数时,需通过初始化列表传递参数。
  • 效率更高:直接初始化成员变量,而非先默认构造再赋值。

2. 语法规则

类名(参数列表):成员变量1(初始值1),成员变量2(初始值2),...{// 构造函数体(可选,用于后续逻辑处理)}
  • 初始值可来自构造函数参数、常量或表达式。
  • 成员变量初始化顺序与“声明顺序”一致,与初始化列表中的顺序无关。

3. 用法示例

classStudent{private:constintid;// 常量成员(必须初始化)int&scoreRef;// 引用成员(必须初始化)string name;public:// 初始化列表初始化常量、引用、普通成员Student(intstudentId,int&score,conststring&studentName):id(studentId),scoreRef(score),name(studentName){// 构造函数体可省略(无额外逻辑时)}voidShow(){cout<<"ID: "<<id<<", Name: "<<name<<", Score: "<<scoreRef<<endl;}};// 调用示例intmain(){intmathScore=95;Student stu{1001,mathScore,"ZhaoLiu"};stu.Show();// 输出:ID: 1001, Name: ZhaoLiu, Score: 95mathScore=98;// 修改被引用的变量stu.Show();// 输出:ID: 1001, Name: ZhaoLiu, Score: 98(引用同步变化)return0;}

4. 注意事项

  • 若成员变量是数组(如char name[32]),初始化列表无法直接赋值,需在构造函数体内用strcpy等函数处理。
  • 推荐优先使用初始化列表初始化成员变量,尤其是常量、引用和自定义类型成员。

五、引用(Reference)

1. 核心概念

引用是变量的“别名”,与原变量指向同一块内存空间,操作引用等价于操作原变量。用于替代指针,解决指针的野指针、空指针等安全问题。

2. 语法规则

  • 定义格式:类型& 引用名 = 原变量;(必须在定义时初始化)。
  • 引用类型必须与原变量类型一致(或存在赋值兼容,如子类引用指向父类对象)。
  • 定义后,引用不能重新绑定到其他变量。

3. 基础用法

inta=1024;int&b=a;// b 是 a 的别名,与 a 共享内存b=2048;// 修改 b 等价于修改 acout<<a<<endl;// 输出:2048cout<<&a<<" "<<&b<<endl;// 地址相同

4. 核心用途

(1)函数参数传递(替代指针,更安全)
// 引用版 swap 函数(无需解引用,简洁安全)voidswap(int&a,int&b){inttemp=a;a=b;b=temp;}// 调用示例intmain(){intx=10,y=20;swap(x,y);// 直接传变量,无需传地址cout<<x<<" "<<y<<endl;// 输出:20 10return0;}
(2)函数返回值(避免拷贝,提升效率)
  • 注意:禁止返回局部变量的引用(局部变量生命周期结束后释放,引用会变成“悬空引用”)。
  • 允许返回:静态变量、全局变量、类成员变量、传入的引用参数。
// 正确示例:返回静态变量的引用int&getStaticValue(){staticintval=0;// 静态变量,生命周期与程序一致val++;returnval;}// 正确示例:返回传入的引用参数string&appendStr(string&s,conststring&suffix){s+=suffix;returns;}// 调用示例intmain(){cout<<getStaticValue()<<endl;// 输出:1cout<<getStaticValue()<<endl;// 输出:2string str="Hello";appendStr(str," World");cout<<str<<endl;// 输出:Hello Worldreturn0;}

5. 引用与指针的区别(必须掌握)

特性引用指针
初始化定义时必须初始化可定义时不初始化(野指针风险)
空值无空引用(更安全)有空指针(nullptr
重新绑定一旦绑定,无法修改可随时改变指向的变量
内存开销不占用额外内存(仅别名)占用内存(存储变量地址)
多级使用无多级引用(int&& a是右值引用,非多级)有多级指针(int** p
安全性高(无野指针、无需解引用)低(需手动管理,避免野指针)
传参/返回值简洁直观,无需解引用需用*解引用,&取地址

六、string 类(字符串处理)

1. 核心优势

替代 C 语言的char*字符串,解决数组越界、手动管理内存等问题,提供丰富的字符串操作接口,安全且便捷。

2. 头文件

#include<string>// 注意:不是 <string.h>(C 语言头文件)usingnamespacestd;// 或 using std::string;

3. 构造函数(常用)

// 1. 无参构造(空字符串)string s1;// 2. 用字符构造(n 个 ch)strings2(5,'a');// s2 = "aaaaa"// 3. 用 C 风格字符串构造strings3("hello");// s3 = "hello"// 4. 用 C 风格字符串的前 n 个字符构造strings4("hello world",5);// s4 = "hello"// 5. 用初始化列表构造string s5{'h','e','l','l','o'};// s5 = "hello"// 6. 拷贝构造(用其他 string 对象构造)strings6(s3);// s6 = "hello"string s7=s3;// 等价于 s6

4. 赋值操作(operator=)

string s;s='A';// 赋值单个字符s="hello";// 赋值 C 风格字符串string s2="world";s=s2;// 赋值 string 对象s+="!";// 追加字符串(operator+= 重载)

5. 字符串拼接(operator+)

string s1="Hello";string s2="World";string s3=s1+" "+s2;// s3 = "Hello World"

6. 字符串比较(重载运算符)

支持==!=<><=>=,按字典序比较:

string a="apple";string b="banana";cout<<(a<b)<<endl;// 输出:1(true,"apple" 字典序小于 "banana")cout<<(a=="apple")<<endl;// 输出:1(true)

7. 字符串访问(常用接口)

string s="abcdefg";// 1. operator[]:无越界检查(效率高)charc1=s[2];// c1 = 'c's[3]='X';// s = "abcefg" → 修正:s 变为 "abcXefg"// 2. at():有越界检查,越界抛异常(安全)charc2=s.at(4);// c2 = 'e'try{s.at(10);// 越界,抛 std::out_of_range 异常}catch(constexception&e){cerr<<e.what()<<endl;}// 3. front() / back():获取首/尾字符charfirst=s.front();// 'a'charlast=s.back();// 'g'// 4. data() / c_str():返回 C 风格字符串(const char*)constchar*cStr=s.c_str();// 用于兼容 C 语言接口(如 open、printf)printf("%s\n",cStr);// 输出:abcXefg

8. 容量与大小(常用接口)

string s="hello";cout<<s.size()<<endl;// 输出:5(字符个数)cout<<s.length()<<endl;// 输出:5(与 size() 等价)cout<<s.empty()<<endl;// 输出:0(false,非空)cout<<s.max_size()<<endl;// 输出:字符串最大可容纳的字符数(系统相关)s.clear();// 清空字符串(size() 变为 0)cout<<s.empty()<<endl;// 输出:1(true)

9. 字符串操作(常用接口)

string s="hello";// 1. 追加s.push_back('!');// 尾部追加字符 → "hello!"s+=" world";// 尾部追加字符串 → "hello! world"// 2. 插入s.insert(5,",");// 在索引 5 处插入字符 → "hello,! world"// 3. 删除s.erase(5,1);// 从索引 5 开始,删除 1 个字符 → "hello! world"// 4. 查找size_t pos=s.find("world");// 查找子串,返回起始索引(6)if(pos!=string::npos){// 找到返回索引,未找到返回 string::nposcout<<"Found at: "<<pos<<endl;}// 5. 替换s.replace(6,5,"C++");// 从索引 6 开始,替换 5 个字符 → "hello! C++"// 6. 截取子串string sub=s.substr(6,3);// 从索引 6 开始,截取 3 个字符 → "C++"

10. 兼容 C 语言接口

当需要调用 C 语言函数(如openfopen)时,用c_str()转换为const char*

string path="/mnt/share/test.txt";// 调用 C 语言 open 函数intfd=open(path.c_str(),O_RDWR);if(fd==-1){perror("open failed");}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 14:11:23

NotebookLM 分享笔记

NotebookLM 分享笔记&#xff1a;您的私人 AI 研究助理 Google NotebookLM | AI 研究工具与思考伙伴 NotebookLM 是 Google 推出的一款以 AI 为核心的专业研究与笔记工具。它与通用型聊天机器人&#xff08;如 Gemini&#xff09;的核心区别在于&#xff0c;它不是在公共网络…

作者头像 李华
网站建设 2026/4/16 9:24:37

notepad++ 安装

下载地址 https://github.com/notepad-plus-plus/notepad-plus-plus/releases/tag/v8.8.9

作者头像 李华
网站建设 2026/4/15 21:31:56

2026毕设ssm+vue基于的智慧酒店系统论文+程序

本系统&#xff08;程序源码&#xff09;带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容关于酒店客房管理系统的研究&#xff0c;现有研究主要以单体酒店或传统 C/S 架构为主&#xff0c;专门针对“SSM&#xff08;SpringSpringM…

作者头像 李华
网站建设 2026/4/16 9:18:24

2025年休闲解压台球手游成新宠,究竟好玩在哪?

在快节奏的现代生活中&#xff0c;人们对于休闲解压的需求日益增长。2025年&#xff0c;休闲解压台球手游成为了新宠&#xff0c;其中《天天台球》更是备受瞩目&#xff0c;那么这类手游究竟好玩在哪呢&#xff1f;真实体验&#xff0c;还原赛场氛围《天天台球》最大的亮点之一…

作者头像 李华
网站建设 2026/4/16 15:48:13

Flink 实时风控系统的万字实战笔记

一、 宏观战场&#xff1a;不只是“快”那么简单很多人对实时风控有个误区&#xff0c;觉得只要用了Flink&#xff0c;接了Kafka&#xff0c;事儿就成了。大错特错。在银行场景下&#xff0c;准确性&#xff08;Accuracy&#xff09;和低延迟&#xff08;Low Latency&#xff0…

作者头像 李华
网站建设 2026/4/16 10:53:49

TypeScript开发全攻略:高效上手

前端TypeScript开发指南&#xff1a;从入门到精通 什么是TypeScript&#xff1f; TypeScript是微软开发的一种开源编程语言&#xff0c;它是JavaScript的超集&#xff0c;为JavaScript添加了静态类型检查。TypeScript最终会被编译成纯JavaScript&#xff0c;可以在任何支持Java…

作者头像 李华