C++:类和对象(二)

目录

const成员函数

1. 基本语法

2. const 成员函数的作用

(1) 保证对象不被修改

(2) 提高代码安全性

(3) 支持 const 对象

3. 示例

(1) 基本用法

(2) const 对象只能调用 const 成员函数

(3) mutable 成员变量

4. const 成员函数的重载

初始化列表

基本语法

为什么使用初始化列表

使用示例

注意事项

友元函数

一、友元函数的基本概念

1.1 什么是友元函数?

1.2 友元函数的特点

二、友元函数的声明与定义

2.1 声明友元函数

2.2 定义友元函数

三、友元函数的常见用途

运算符重载

static成员

static成员变量

声明和定义

使用示例

static成员函数

声明和定义

使用示例

注意事项

类型转换


const成员函数

在 C++ 中,const 成员函数 是一种特殊的成员函数,它承诺 不会修改 调用它的对象的状态(即不会修改类的成员变量)。const 成员函数的声明方式是在函数参数列表后加上 const 关键字。

1. 基本语法

class MyClass {
public:void nonConstFunc();       // 普通成员函数(可以修改成员变量)void constFunc() const;    // const 成员函数(不能修改成员变量)
};
  • const 成员函数 不能修改类的非 mutable 成员变量。

  • 非 const 成员函数 可以修改成员变量。

const实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改,const休息Date类的Print成员函数,Print隐含的this指针由 Date * const this 变为 const Date * const this

class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// void Print(const Date* const this) const
void Print() const
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};

2. const 成员函数的作用

(1) 保证对象不被修改
  • 如果一个对象被声明为 const(如 const MyClass obj;),则只能调用它的 const 成员函数。

  • 如果尝试调用非 const 成员函数,编译器会报错。

(2) 提高代码安全性
  • 防止函数意外修改对象状态。

  • 使代码更清晰,明确哪些函数会修改对象,哪些不会。

(3) 支持 const 对象
  • 如果一个对象是 const 的,只有 const 成员函数可以被调用。

3. 示例

(1) 基本用法
#include <iostream>
using namespace std;class Counter {
private:int count;
public:Counter() : count(0) {}// 普通成员函数(可以修改成员变量)void increment() {count++;}// const 成员函数(不能修改成员变量)int getCount() const {// count++;  // 错误!不能在 const 函数里修改成员变量return count;}
};int main() {Counter c1;c1.increment();  // 可以调用非 const 函数cout << c1.getCount() << endl;  // 可以调用 const 函数const Counter c2;// c2.increment();  // 错误!不能对 const 对象调用非 const 函数cout << c2.getCount() << endl;  // 可以调用 const 函数return 0;
}
(2) const 对象只能调用 const 成员函数
const Counter c;
c.increment();   //  错误!不能调用非 const 函数
c.getCount();    //  可以调用 const 函数
(3) mutable 成员变量

如果某个成员变量被声明为 mutable,即使在 const 成员函数中也可以修改它。

class Logger {
private:mutable int logCount;  // 可变的,即使在 const 函数里也能修改
public:void log() const {logCount++;  // 允许修改,因为 logCount 是 mutable}
};

4. const 成员函数的重载

可以同时提供 const 和非 const 版本的成员函数,编译器会根据调用对象的 const 性质选择合适的版本。

class Data {
private:int value;
public:int& getValue() {  // 非 const 版本(返回可修改的引用)return value;}const int& getValue() const {  // const 版本(返回只读的引用)return value;}
};int main() {Data d1;const Data d2;d1.getValue() = 10;  // 调用非 const 版本,可以修改// d2.getValue() = 20;  // 错误!调用 const 版本,不能修改cout << d2.getValue();  // 可以读取return 0;
}

初始化列表

初始化列表(Initializer List)是 C++ 中用于初始化类成员的一种特殊语法,它在构造函数体执行之前完成成员的初始化。

基本语法

class MyClass {
public:// 初始化列表语法MyClass(int a, double b) : memberA(a), memberB(b) {// 构造函数体}private:int memberA;double memberB;
};

为什么使用初始化列表

  1. 效率更高:对于类类型成员,使用初始化列表直接调用拷贝构造函数,而在构造函数体内赋值则是先调用默认构造函数再调用赋值运算符。

  2. 必须使用的情况

    • 初始化 const 成员

    • 初始化引用成员

    • 初始化没有默认构造函数的类成员

使用示例
class Example {
public:// 必须使用初始化列表的情况Example(int &ref, int val) : refMember(ref), constMember(val) {// 构造函数体}// 初始化顺序示例Example(int a, int b) : memberB(a), memberA(b) {// 注意:初始化顺序取决于成员声明顺序,而非初始化列表中的顺序}private:int memberA;int memberB;int &refMember;    // 引用成员const int constMember; // const成员
};

注意事项

  1. 初始化顺序:成员的初始化顺序与它们在类中声明的顺序一致,与初始化列表中的顺序无关。

  2. 性能考虑:对于内置类型(int, double等),使用初始化列表或在构造函数体内赋值性能差异不大,但对于类类型,初始化列表通常更高效。

  3. 默认参数:初始化列表可以与默认参数结合使用。

友元函数

一、友元函数的基本概念

友元分为友元类和友元函数

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

1.1 什么是友元函数?

友元函数(friend function)是一个被类声明为"朋友"的非成员函数,它可以访问该类的所有私有和保护成员,就像成员函数一样。友元函数不属于类的成员,但它被授予了访问类私有部分的特权。

class Box {
private:double width;public:Box(double w) : width(w) {}// 声明友元函数friend void printWidth(const Box& box);
};// 友元函数定义
void printWidth(const Box& box) {// 可以访问Box的私有成员widthstd::cout << "Width: " << box.width << std::endl;
}
1.2 友元函数的特点
  1. 非成员性:友元函数不是类的成员函数

  2. 特权访问:可以访问类的私有和保护成员

  3. 单向性:友元关系是单向的,类A声明函数f为友元,不意味着f是类A的成员

  4. 非传递性:友元关系不传递,A是B的友元,B是C的友元,不意味着A是C的友元

  5. 非继承性:友元关系不继承,基类的友元不是派生类的友元

二、友元函数的声明与定义

2.1 声明友元函数

友元函数在类内部声明,使用friend关键字:

class MyClass {
private:int secret;public:MyClass(int s) : secret(s) {}// 声明普通函数为友元friend void showSecret(const MyClass& obj);// 声明其他类的成员函数为友元friend void OtherClass::accessMyClass(const MyClass& obj);
};
2.2 定义友元函数

友元函数的定义与普通函数相同,不需要使用friend关键字,但是它定义在类外面。

void showSecret(const MyClass& obj) {std::cout << "Secret is: " << obj.secret << std::endl;
}

三、友元函数的常见用途

运算符重载

友元函数常用于重载运算符,特别是当运算符的第一个操作数不是类对象时:

class Complex {
private:double real, imag;public:Complex(double r = 0, double i = 0) : real(r), imag(i) {}// 重载<<运算符为友元函数friend std::ostream& operator<<(std::ostream& os, const Complex& c);// 重载+运算符为友元函数friend Complex operator+(const Complex& c1, const Complex& c2);
};std::ostream& operator<<(std::ostream& os, const Complex& c) {os << c.real << " + " << c.imag << "i";return os;
}Complex operator+(const Complex& c1, const Complex& c2) {return Complex(c1.real + c2.real, c1.imag + c2.imag);
}

static成员

在C++中,static关键字用于类的成员时,有特殊的含义和作用。static成员分为static成员变量和static成员函数。

static成员变量

static成员变量是属于类本身的,而不是类的某个特定对象。这意味着:

  1. 类所有对象共享:所有类的对象共享同一个static成员变量

  2. 独立于对象存在:即使没有创建类的任何对象,static成员变量也存在

  3. 存储位置:存储在全局数据区,而不是对象的存储空间中

  4. 静态成员也是类的成员,受public、protected、private访问限定符的限制

声明和定义
class MyClass {
public:static int count;  // 声明static成员变量
};int MyClass::count = 0;  // 定义并初始化static成员变量(必须在类外)
使用示例
#include <iostream>
using namespace std;class Counter {
public:static int count;  // 声明Counter() {count++;}~Counter() {count--;}
};int Counter::count = 0;  // 定义并初始化int main() {cout << "Initial count: " << Counter::count << endl;Counter c1;cout << "After c1: " << Counter::count << endl;{Counter c2;cout << "After c2: " << Counter::count << endl;}cout << "After c2 destroyed: " << Counter::count << endl;return 0;
}

static成员函数

static成员函数也是属于类而非特定对象的,具有以下特点:

  1. 只能访问static成员:不能直接访问类的非static成员变量或成员函数

  2. 没有this指针:因为没有绑定到特定对象

  3. 可通过类名直接调用:不需要通过对象实例调用

声明和定义
class MyClass {
public:static void staticFunc();  // 声明
};void MyClass::staticFunc() {   // 定义// 实现代码
}
使用示例
#include <iostream>
using namespace std;class MathUtility {
public:static int add(int a, int b) {return a + b;}static int subtract(int a, int b) {return a - b;}
};int main() {cout << "5 + 3 = " << MathUtility::add(5, 3) << endl;cout << "5 - 3 = " << MathUtility::subtract(5, 3) << endl;return 0;
}

注意事项

  1. static成员变量必须在类外定义和初始化(C++17引入了inline static可以在类内初始化)

  2. static成员函数不能是const或volatile的

  3. static成员函数不能被声明为virtual

  4. static成员可以被继承,但遵循常规的访问控制规则

  5. 静态成员变量不能在生命位置给缺省值初始化,因为缺省值是给构造函数初始化列表的,静态成员变量不属于某个对象,不走构造函数初始化列表。

类型转换

C++支持内置类型隐式类型转换为类类型对象,需要有相关内置内省为参数的构造函数

构造函数前面加explicit就不再支持隐式类型转换

类类型的对象之间也可以隐式转换,需要相应的构造函数支持

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

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

相关文章

软考中级-软件设计师 23种设计模式(内含详细解析)

23种设计模式 &#x1f3af; 创建型设计模式&#x1f4cc; 抽象工厂&#xff08;Abstract Factory&#xff09; 设计模式&#x1f4cc; 工厂方法&#xff08;Factory Method&#xff09;设计模式&#x1f4cc; 单例&#xff08;Singleton&#xff09;设计模式&#x1f4cc; 生成…

子数组 之 logTrick算法,求解或,与,LCM,GCD

文章目录 gcd的问题最大公约数 求解子数组的&,|,lcm,gcd的最值or计数问题&#xff0c;如果采用暴力的做法&#xff0c;那么时间复杂度会来到o(n^2),其实在求解的过程中&#xff0c;会出现很多的结果不变的情况&#xff0c;所以我们就可以提前结束 存在一定的单调性&#x…

密码学——知识问答

目录 1、阐述公开密钥算法的定义&#xff0c;结合RSA算法说明公钥密码的基本要求。 说明公钥与私钥两种密码学并举例与其应用 1. 公钥密码学&#xff08;非对称加密&#xff09;&#xff1a; 2. 私钥密码学&#xff08;对称加密&#xff09;&#xff1a; 对比公钥与私钥密码…

MySQL 表连接(内连接与外连接)

&#x1f3dd;️专栏&#xff1a;Mysql_猫咪-9527的博客-CSDN博客 &#x1f305;主页&#xff1a;猫咪-9527-CSDN博客 “欲穷千里目&#xff0c;更上一层楼。会当凌绝顶&#xff0c;一览众山小。” 目录 1、表连接的核心概念 1.1 为什么需要表连接&#xff1f; 2、内连接&a…

CI/CD(六) helm部署ingress-nginx(阿里云)

零、修改iptable为ipvs&#xff08;可选&#xff09; 修改 kube-proxy 配置&#xff1a; kubectl edit cm kube-proxy -n kube-system # 将 mode 字段改为 "ipvs" 重启 kube-proxy&#xff1a; kubectl delete pod -l k8s-appkube-proxy -n kube-system 验证 IPVS …

Git 之配置ssh

1、打开 Git Bash 终端 2、设置用户名 git config --global user.name tom3、生成公钥 ssh-keygen -t rsa4、查看公钥 cat ~/.ssh/id_rsa.pub5、将查看到的公钥添加到不同Git平台 6、验证ssh远程连接git仓库 ssh -T gitgitee.com ssh -T gitcodeup.aliyun.com

为Windows10的WSL Ubuntu启动sshd服务并使用Trae远程连接

Windows10的WSL Ubuntu&#xff0c;使用起来非常方便&#xff0c;但是美中不足的是&#xff0c;无法从Windows主机ssh到Ubuntu 。 解决的方法是在Ubuntu安装sshd服务 Ubuntu安装sshd服务 执行命令 sudo apt install openssh-server 安装好后&#xff0c;先本地测试&#x…

unity一个图片的物体,会有透明的效果

如图 想要去掉这个透明效果 选择一个高层级的layer即可。

Windows安装Jenkins配置Allure踩坑,必须单独配置当前windows系统为新的node节点,才可在工具位置中指定节点服务器allure的位置

背景 我为了图省事&#xff0c;在Windows上安装运行Jenkins&#xff0c;通过配置gitee插件拉取代码部署接口自动化项目&#xff0c;配置构建后运行Allure报告&#xff0c;结果报错&#xff1a;找不到Allure和生成的数据。 Allure报错信息 ERROR: Step ‘Allure Report’ abort…

MAC terminal

MAC terminal 苹果打开命令行 command 空格键 terminal

VScode-i18n-ally-Vue

参考这篇文章&#xff0c;做Vue项目的国际化配置&#xff0c;本篇文章主要解释&#xff0c;下载了i18n之后&#xff0c;该如何对Vscode进行配置 https://juejin.cn/post/7271964525998309428 i18n Ally全局配置项 Vscode中安装i18n Ally插件&#xff0c;并设置其配置项&#…

xdoj回忆练

今天是我入职阿里第四个年头&#xff0c;忆往昔&#xff0c;上一篇博客还是自己刚毕业在准备秋招面试的时候&#xff0c;真不得不感慨时间的飞逝。 偶然间打开了xdoj&#xff0c;发现当年自己为造福学弟学妹而创办的新生赛&#xff0c;在两年前已经被学弟学妹们关停了&#xf…

面试八股文--框架篇(SSM)

一、Spring框架 1、什么是spring Spring框架是一个开源的Java平台应用程序框架&#xff0c;由Rod Johnson于2003年首次发布。它提供了一种全面的编程和配置模型&#xff0c;用于构建现代化的基于Java的企业应用程序。Spring框架的核心特性包括依赖注入&#xff08;DI&#xf…

【SQL Server数据库备份详细教程】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

nVisual对接企业微信实现机房设备与连接变更的自动化审批

企业微信的审批可以根据企业实际业务流程创建自动化的审批流&#xff0c;nVisual可以进行机房设备与线缆的可视化规划设计&#xff0c;结合企业微信与nVisual实现机房设备与线缆变更的自动审批&#xff0c;可以显著提高机房运维变更效率与规范性。 一、业务流程 1、业务流程 …

【PCB工艺】时序图(Timing Diagram)

时序图&#xff08;Timing Diagram&#xff09;是描述数字电路信号随时间变化的图示&#xff0c;广泛用于分析和设计时序逻辑电路&#xff0c;如锁存器&#xff08;Latch&#xff09;、触发器&#xff08;Flip-Flop&#xff09;、计数器、状态机等。这篇文章从时序图的原理、构…

华为HG532路由器RCE漏洞 CVE-2017-17215 复现

华为HG532路由器RCE漏洞 CVE-2017-17215 CVE-Description Huawei HG532 with some customized versions has a remote code execution vulnerability. An authenticated attacker could send malicious packets to port 37215 to launch attacks. Successful exploit could l…

调用deepseek大模型时智能嵌入函数

DeepSeek-R1 当前炙手可热,以其强大的自然语言处理和推理能力而广受赞誉。饶是如此,却并不原生支持函数调用(function_call),这是开发过程中不可或缺的一部分。虽有第三方调校的模型支持,然终非官方自带,还需假以时日。本文虽然简短,应该是全网写得最通透的了吧。 …

MATLAB绘图配色包说明

本栏目将分享MATLAB数据分析图表&#xff0c;该贴讲述配色包的使用 将配色包colormap_nclCM文件夹添加到路径close all&#xff08;尽量不要删&#xff09;&#xff0c;使用map colormap(nclCM(309))时会多出来一张空白图片。配色资源来自slandarer&#xff1b;找不到合适颜色…

Scala

Scala 一、Scala 简介 Scala是一种多范式的编程语言&#xff0c;融合了面向对象编程和函数式编程的特性&#xff0c;以下为你详细介绍&#xff1a; 1、起源与发展 ①起源&#xff1a;Scala由瑞士洛桑联邦理工学院的Martin Odersky教授在2001年开始设计&#xff0c;并于2004…