C++面向对象高级编程(侯捷)笔记1

侯捷C++面向对象高级编程

本文是学习笔记,仅供个人学习使用,如有侵权,请联系删除。

如果你对函数参数何时该传引用(&)、何时该传值,对函数返回值是否传引用(&),对构造函数的初始列的语法,对如何重载操作符operator,对友元函数friend的作用,对函数名称后面加const的意思,对C++标准库中临时对象 typename()的用法,等存在疑惑,那么你就应该学习一下这门课。

学习地址:

Youtube: C++面向对象高级编程(侯捷)

B站: 侯捷C++之C++面向对象高级编程(上)

文章目录

  • 侯捷C++面向对象高级编程
    • 2 头文件和类的声明
    • 3 构造函数
    • 4 参数传递与返回值
    • 5 操作符重载与临时对象
      • 操作符重载1——成员函数
      • 操作符重载2——非成员函数
    • 6 复习Complex类的实现过程

2 头文件和类的声明

头文件的防卫式声明:guard

#ifndef _COMPLEX_

#define _COMPLEX_

#endif

作用:防止重复声明

头文件布局

#ifndef __COMPLEX__
#define __COMPLEX__
// 0. 前置声明
# include<cmath>
class ostream;
class complex;complex& __doapl(conplex* ths, const complex& r);// 1. 类——声明
class complex
{...    
};// 2. 类——定义
complex::function ...
#endif

不使用模板的复数(complex)类

class complex
{public:// 构造函数complex(double r = 0, double i = 0): re(r), im(i) // // 构造函数的初始化列{}// 成员函数complex& operator += (const complex&);  double real() const { return re;}double imag() const { return im;}private:double re, im;  // 私有数据friend complex& __doapl(complex*, const complex&);  // 友元函数
};// 使用
{complex c1(2, 1);complex c2;...
}

模板简介:使用模板的复数(complex)类

template<typename T>
class complex
{public:complex(T r = 0, T i = 0): re(r), im(i)  // 构造函数的初始化列{}complex& operator += (const complex&);T real() const { return re;}T imag() const { return im;}private:T re, im;friend complex& __doapl(complex*, const complex&);
};// 使用模板的例子,指定T的具体类型
{complex<double> c1(2.5, 1.5);complex<int> c2(2, 6);...
}

3 构造函数

inline:函数若在class body内定义完成,便自动成为inline候选人

补充 函数名后面加const的作用:比如上面的 double real() const;

c++ 函数前面和后面 使用const 的作用:

  • 前面使用const 表示返回值为const

  • 后面加 const表示函数不可以修改class的成员

请看这两个函数

  • const int getValue();

  • int getValue2() const;

参考:https://blog.csdn.net/SMF0504/article/details/52311207

构造函数:名称和类名相同,没有返回值类型

// 构造函数不好的写法
class complex
{public:complex(double r = 0, double i = 0){ re = r; im = i;} // 在赋值阶段做,效率差private:double re, im;
};// 构造函数好的写法
// 等价于上面
class complex
{public:complex(double r = 0, double i = 0): re(r), im(i) {}  // 初始列,在初始化阶段做,效率高private:double re, im;
};

创建对象的例子

{complex c1(2, 1);complex c2;complex* p = new complex(4);...
}

构造函数的重载(overloading):cpp允许同名函数存在,比如构造函数可以有多个。

构造函数可以被放在private区,在设计模式中,单例模式(singleton)便是这样做的

class A 
{
public:static A& getInstance();setup() { ... }
private:A();A(const A& rhs);...
}A& A::getInstance() 
{static A a;return a;
}

外界调用时

A::getInstance().setup();

4 参数传递与返回值

常量成员函数:在函数名后面加const,表示函数不改变成员内容:

double real() const { return re;}
double imag() const { return im;}

参数传递:

pass by value :传具体的值

pass by reference(to const):传引用

传引用,相当于c语言中的传指针

class complex
{public:complex(double r = 0, double i = 0): re(r), im(i) {}complex& operator += (const complex&); // 传引用,速度快double real() const { return re;}double imag() const { return im;}private:double re, im;friend complex& __doapl(complex*, const complex&); // 传引用
};

使用举例:

{complex c1(2, 1); // 构造函数传参,double类型,传值complex c2;c2 += c1;  // +=运算,传的是引用:const complex&,速度快cout << c2;
}

使用const的原因是:使用引用传递,不希望对方对内容进行修改。

不使用const,表示可以对该内容进行修改,比如下面的os参数

ostream&
operator << (ostream& os, const complex& x)
{return os << "(" << real(x) << "," << imag(x) << ")";
}

返回值传递

return by value

return by reference(to const)

friend 友元:自由取得friend的private成员

这会打破类的封装性

class complex
{
private:double re, im;friend complex& __doapl(complex*, const complex&); // 友元函数的声明
};// 友元函数的定义
inline complex&
__doapl(conplex* ths, const complex& r)
{ths->re += r.re;  // 可以直接获取complex的私有成员变量ths->im += r.im;return *ths;
}

相同class的各个objects互为友元,可以访问到私有数据,打破封装性

class complex
{public:complex(double r = 0, double i = 0): re(r), im(i){}int func(const complex& param){ return param.re + param.im;}private:double re, im;
};

使用举例

{complex c1(2, 1); complex c2;c2.func(c1); // c2这个复数调用func函数,直接拿到c1这个复数的实部和虚部,并求和
}

什么情况下不能return by reference?

local objects局部对象的引用不要传出去,因为在函数结束的时候,局部变量的生命周期已经结束了。

5 操作符重载与临时对象

操作符重载1——成员函数

do assignment plus是 __doapl函数的含义

inline complex& // 接收端,不用管接收形式,可以是引用,可以是值。这里是引用接收
__doapl(conplex* ths, const complex& r)
{ths->re += r.re;  // 可以直接获取complex的私有成员变量ths->im += r.im;return *ths; // 返回指针指向的内容,object
}inline complex&
complex::operator += (const complex& r)  // += 操作符重载
{return __doapl(this, r);  // this指的是调用者,这是一个指针
}{complex c1(2, 1); complex c2(5);c2 += c1; // 这里使用 +=,这里的c2就是调用者,就是上面的this,而c1就是上面的r
}

return by reference:传递者无需知道接收者是以什么形式接收。

上面的inline complex& complex::operator += (const complex& r){}函数的返回类型是complex,而不是void,它的考虑是使用者如下的调用方法:

c3 += c2 += c1;

这样就必须有返回值。

操作符重载2——非成员函数

非成员函数,无this指针

class body之外的各种定义

inline double
imag(const complex& x)
{return x.imag();
}inline double
real(const complex& x)
{return x.real();
}{complex c1(2, 1);cout << imag(c1);cout << real(c1);
}

为了对应client的三种可能用法,开发三个函数: 操作符+号的重载

inline complex 
operator + (const complex& x, const complex& y)
{return complex(real(x) + real(y), imag(x) + imag(y));
}inline complex 
operator + (const complex& x, const double y)
{return complex(real(x) + y, imag(x));
}inline complex 
operator + (double x, const complex& y)
{return complex(x + real(y), imag(y));
}// 使用
{complex c1(2, 1); complex c2;c2 = c1 + c2;c2 = c1 + 5;c2 = 7 + c1;
}

上面这三个函数的返回值为什么是值而不是引用呢?

这里务必不能使用return by reference,因为返回的必定是个local object。具体而言,这里计算的是两者之和,它的结果存在局部变量里面,生命周期离开函数就死亡,reference就会指向错误的东西。

临时对象 typename();

临时想要的对象,不想要给它名称,下一行生命周期就结束了。 比如上面的return complex()

正负号重载

取反negate

inline complex // 这里可以改成return by reference
operator + (const complex& x)
{return x; // 不是local object
}inline complex  // 这里务必不能使用return by reference,因为返回的必定是个local object。
operator - (const complex& x)
{return complex(-real(x), -imag(x));
}// 使用
{complex c1(2, 1); complex c2;cout << -c1;cout << +c1;
}

下面是==重载

inline bool
operator == (const complex& x, const complex& y)
{return real(x) == real(y) && imag(x) == imag(y);
}inline bool
operator == (const complex& x, double y)
{return real(x) == y && imag(x) == 0;
}inline bool
operator == (double x, const complex& y)
{return x == real(y) && imag(y) == 0;
}// 使用
{complex c1(2, 1); complex c2;cout << (c1 == c2);cout << (c1 == 2);cout << (0 == c2);
}

共轭复数的实现以及 << 操作符的重载

<< 操作符的重载ostream& operator << (ostream& os, const complex& x){}中,为什么传入的参数ostream& os不用加const呢?这是因为output流的状态一直在改变,所以不能用const。

inline complex
conj (const complex& x)
{return complex(real(x), -imag(x));
}#include<iostream.h>
ostream&
operator << (ostream& os, const complex& x)
{return os << "(" << real(x) << "," << imag(x) << ")";
}// 使用
{complex c1(2, 1);cout << conj(c1);  // 输出 (2, -1)cout << c1 << conj(c1); // 输出 (2, 1) (2, -1), 连续输出要求 << 返回值还是ostream,不能是void
}

6 复习Complex类的实现过程

整个complex类的实现过程如上面的笔记所示,这里不再展示。另外,complex这个类是class without pointer member(s),后面会将class with pointer member(s),讲的是string类。

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

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

相关文章

声明式管理方法

声明式管理方法&#xff08;yaml&#xff09;文件&#xff1a; 1&#xff0c;适合对资源的修改操作 2&#xff0c;声明式管理依赖于yaml文件&#xff0c;所有的内容都在yamI文件当中 3&#xff0c;编辑好的yaml文件&#xff0c;还是要依靠陈述式命令发布到k8s集群当中 发布的…

数据损毁!250 亿美金的 Pinterest,在数据库选型上的翻车经历

原文链接 Pinterest 是一个以图片为主的社交网络&#xff0c;用户可以将图片保存或 "钉 / pin" 在自己的图板上。Pinterest 在 2019 年上市&#xff0c;目前市值 250 亿美金。本文内容主要根据 2012 年 Scaling Pinterest 的分享。 2012 年 1 月&#xff0c;Pinteres…

鸿蒙工程目录结构

工程结构 . ├── build ├── build-profile.json5 ├── hvigorfile.ts ├── libs │ └── armeabi-v7a ├── oh-package.json5 ├── oh_modules │ └── types │ └── libentry.so -> ../../src/main/cpp/types/libentry └── src├── ma…

qcom ./development/tools/idegen/idegen.sh 卡住不动

前言 在Android 开发中&#xff0c;有时候我们需要将android 源码导入android studio&#xff0c;就要用到idegen 工具&#xff0c;qcom 高通部分平台发现执行/development/tools/idegen/idegen.sh 不动 分析 通过添加log发现是由于文件遍历进入了死循环&#xff1b; 可以在…

HTML----JavaScript操作对象BOM对象

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 本章要求 了解BOM模型掌握BOM模型实际应用 一.BOM模型概述 BOM&#xff08;浏览器对象模型&#xff09;是JavaScript中的一个重要概念&#xff0c;它提供了一组用于控制浏览器窗口和页面内容的…

力扣热题100道-矩阵篇

矩阵 73.矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法**。** 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]示例…

胡润研究院发布《2023胡润中国最具历史文化底蕴品牌榜》

胡润研究院发布《2023胡润中国最具历史文化底蕴品牌榜》&#xff0c;前十名分别是片仔癀、同仁堂、贵州茅台、五粮液、中国银行、中华、黄山、农业银行、建设银行、汾酒。 榜单调研范围涵盖中国内地具有60年以上历史的为消费者提供产品或服务的品牌&#xff0c;综合考察品牌历史…

C# 语法进阶 委托

1.委托 委托是一个引用类型&#xff0c;其实他是一个类&#xff0c;保存方法的指针 &#xff08;指针&#xff1a;保存一个变量的地址&#xff09;他指向一个方法&#xff0c;当我们调用委托的时候这个方法就立即被执行 关键字&#xff1a;delegate 运行结果&#xff1a; 思…

TikTok舞台背后:短视频如何打破艺术界界限?

TikTok&#xff0c;这个以短视频为媒介的平台&#xff0c;正成为全球年轻一代表达创意的重要舞台。然而&#xff0c;其影响不仅仅停留在娱乐领域&#xff0c;更在艺术界引起了巨大的关注。本文将深入探讨TikTok是如何在短视频的形式下打破传统艺术界的界限&#xff0c;为创作者…

欢迎提交pr共同改进项目, pr的含义?

"提交PR"在软件开发和编程领域是一个常用术语&#xff0c;特别是在使用版本控制系统如Git时。这里的“PR”指的是“Pull Request”&#xff0c;它是一种通知项目维护人员您已经完成了一些代码改动并希望将这些改动合并到主项目中的方式。简单来说&#xff0c;当您对一…

Eureka相关面试题及答案(2024)

1、什么是Eureka&#xff1f; Eureka是一个由Netflix开发的服务发现&#xff08;Service Discovery&#xff09;工具&#xff0c;它是Spring Cloud生态系统中的一个关键组件。服务发现是微服务架构中的一个重要概念&#xff0c;它允许服务实例在启动时注册自己&#xff0c;以便…

【第7期】前端如何实现菜单记忆和用户操作的状态记忆

本期简介 背景一&#xff1a;我们平时使用到管理功能时&#xff0c;会涉及到打开了某个一级菜单&#xff0c;访问了某个二级菜单&#xff0c;打开了相应的页面&#xff0c;那么我们希望一级菜单当前时展开的&#xff0c;二级菜单当前时有选中颜色与其他未访问的菜单进行区分的&…

【银行测试】超细支付功能测试+测试点总结分析(详全)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、支付功能怎么测…

华为鸿蒙应用--文件管理工具(鸿蒙工具)-ArkTs

0、代码 import fs from ohos.file.fs; import { Logger } from ./Logger; import { Constants } from ../constants/Constants; import { toast } from ./ToastUtils;export class FileUtils {/*** 获取目录下所有文件* param filesDir* returns*/static getFiles(filesDir: …

Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的 Options Api 有什么不同

Vue3.0 所采用的 Composition Api 与 Vue2.x 使用的 Options Api 有什么不同? Composition API 解决了什么问题 Composition API 可以说是 Vue3 的最大特点&#xff0c;那么为什么要推出 Composition Api &#xff0c;解决了什么问题? 通常使用 Vue2 开发的项目&#xff0…

Java 将base64编码字符串转换为图片工具类

前言 在一些前后端分离项目中&#xff0c;接口方需要前端把图片转换成base64编码字符串&#xff0c;和表单信息一起通过json接口提交。故在后端中&#xff0c;需要对前端传过来的bas64编码字符串转换成图片文件进行存储。 代码 import lombok.extern.slf4j.Slf4j;import jav…

PostgreSQL10数据库源码安装及plpython2u、uuid-ossp插件安装

PostgreSQL10数据库源码安装及plpython2u、uuid-ossp插件安装 1、环境2、安装包下载3、安装3.1 、解压3.2、配置3.3、编译安装3.4 、启动与关闭 4、安装 uuid-ossp 、plpython2u插件5、参考 1、环境 centos 7 、 postgresql 10.19 2、安装包下载 postgres 源码安装包 3、安…

【面试高频算法解析】算法练习1 二分查找

目录 前言算法解析练习题二分查找在排序数组中查找元素的第一个和最后一个位置搜索旋转排序数组 前言 本篇章开放目的是按算法类型学习算法&#xff0c;学习对应算法理论&#xff0c;并通过练习一些经典算法题深入理解这类算法&#xff0c;避免出现刷了很多算法题&#xff0c;…

golang学习专栏

GOLANG专栏 Golang基础教程 Golang基础教程 Golang练手算法 Golang练手算法 Golang设计模式 Golang设计模式 Golang数据结构和算法 Golang数据结构和算法 Golang并发编程 Golang并发编程 ORM框架Gorm Golang ORM框架gorm Golang源码分析 Golang源码分析 MySQL教程 MySQ…

11.Kubernetes Ingress NGINX Controller 部署

Ingresss是对集群中服务的外部访问进行管理的 API 对象,典型的访问方式是 HTTP。 Ingress 可以提供负载均衡、SSL 终结和基于名称的虚拟托管。 Ingress NGINX Controller 是kubernetes官方维护的 Ingress 控制器 至此、kubernetes必要的组件都已经安装完成,后面可以演示一…