More Effective C++学习笔记(6)

news/2024/12/23 3:38:40/

目录

  • 条款32:在未来时态下发展程序
  • 条款33:将非尾端类设计为抽象类
  • 条款34:如何在同一个程序中结合C++和C
  • 条款35:让自己习惯于标准的C++语言

条款32:在未来时态下发展程序

  • 事情总是会改变”是一个事实,因此我们写的程序也应该在保证当下程序功能完全实现的前提下,对未来的扩展变化有所预期的进行设计,而不是简单地只完成当下的程序功能任务。Effective C++和More Effective C++的条款中有许多是帮助你的程序在未来可以轻易实现扩展的技巧。
  • 为了强化其他人理解并修改你的程序,避免错误使用,撰写注释只是很浅薄的一层,万一没有被使用者或修改者注意。更好的做法是“以C++本身”阻止或限制某些行为,例如之前条款中有阻止类派生,阻止对象产生或不产生于heap内等等
  • 请努力写出可移植的代码
  • 好好利用封装,使"系统改变所带来的冲击"得以局部化
  • 标准String类型只有非虚析构函数,因此不要以其作为基类派生出别的类
  • 如果类作为一个基类,一般情况下应当给他配一个虚析构函数

条款33:将非尾端类设计为抽象类

  • 对具有继承体系的对象采用指针互相赋值可能存在一些难以避免的问题,例如基类有数据成员(具体类),用两个基类指针p1,p2指向两个不同的派生类对象,再用指针访问对象互相赋值*p1 = *p2,只会改变p1派生类对象中的基类部分,p1对象派生体系中派生类自己独有的部分并未被p2所指对象赋值,这有时会和我们直观上的理解意思(把一个派生类对象赋值给另一个派生类对象)不符,从而出现错误。
  • 最好的做法就是,如果两个具体类需要建立继承体系(有具体类被当作基类),那么两者肯定有相似之处,完全可以将两个类中的共同或相似部分抽象出来,作为一个新的抽象类(可以将析构函数设为纯虚函数),让两个具体类继承于它。这样利于提升软件的健壮度和扩充度。

条款34:如何在同一个程序中结合C++和C

  • 名称重整:C++编译器往往会自动将函数名重整(例如将abc()重整为xyz()),保证所有函数名称独一无二。但C编译器不会进行重整,同一个函数单独分别在C中编译后的函数调用码和C++中编译后,函数调用码很有可能不一样,从而链接时发生错误。通过在C++函数声明前加入extern “C”,可压抑C++的名称重整。
// this function is in assembler — don't mangle its name
extern "C" 
void twiddleBits(unsigned char bits);
extern "C" {                           // disable name mangling for// all the following functionsvoid drawLine(int x1, int y1, int x2, int y2);void twiddleBits(unsigned char bits);void simulate(int iterations);...
}
#ifdef __cplusplus
extern "C" {
#endifvoid drawLine(int x1, int y1, int x2, int y2);void twiddleBits(unsigned char bits);void simulate(int iterations);...
#ifdef __cplusplus
}
#endif
  • Statics的初始化:静态的类对象和定义在全局的、命名空间中的或文件体中的类对象的构造函数通常在main被执行前就被调用。这个过程称为静态初始化。这和我们对C++和C程序的通常认识相反,我们一直把main当作程序的入口。同样,通过静态初始化产生的对象也要在静态析构过程中调用其析构函数;这个过程通常发生在main结束运行之后。由于C中不认识对象的构造与析构,因此尽量在C++代码中写出main函数,可以调用C中的realmain()。
extern "C"                                // implement this
int realMain(int argc, char *argv[]);     // function in C
int main(int argc, char *argv[])          // write this in C++
{return realMain(argc, argv);
}
  • 动态内存分配:只要new分配的内存使用delete释放,malloc分配的内存用free释放,那么就没问题。用free释放new分配的内存或用delete释放malloc分配的内存,其行为没有定义。注意,有些非标准库函数可能里面有用到动态内存分配,需要明确该函数分配内存。
  • 数据结构的兼容性:C中不存在类与类成员,因此为了实现C++和C数据结构兼容,可以借用指针和函数指针。一般情况下,C++的struct内存布局和C一样。但是如果C++的struct有了虚函数,那么内存布局就会发生变化,两者则不兼容。

条款35:让自己习惯于标准的C++语言

学习并实践新的C++语言特性、模板特性、异常处理机制、转型、内存分配、标准模板库STL等等。


http://www.ppmy.cn/news/1099304.html

相关文章

基于STM32F103 实现按键状态机

文章目录 开发板开发环境前言按键消抖按键硬件原理图软件延时实现思路 实验目的代码按键状态按键信息按键相关定义按键底层配置及状态获取 总结 开发板 正点原子STM32F103ZET6战舰 开发环境 stm32cubeMX Clion 前言 在单片机使用按键时,为了消除按键的抖动&…

Linux使用docker安装elasticsearch-head

一、elasticsearch-head的安装启动 #下载镜像 docker pull alivv/elasticsearch-head #启动 docker run -d --name eshead -p 9100:9100 alivv/elasticsearch-head 查看日志 docker logs -f eshead 出现如下证明启动成功 浏览器访问9100端口,出现以下页面也说明…

js对象转json文件

目录 需求1.首先寻找类似需求的数据2.对数据进行转换3.将转换后的数据转为json文件4.完整代码 需求 需求:在做项目时,遇到了需要制作地址列表的功能,这一般都会用到一些开源的组件库,但是有个问题是不同组件库之间的城市列表数据结…

【Linux】网络编程网络基础(C++)

目录 一、计算机网络背景 二、认识 "协议" 三、网络协议初识 【3.1】协议分层 【3.2】OSI七层模型 【3.3】TCP/IP五层(或四层)模型 四、网络传输基本流程 【4.1】网络传输流程图 【4.2】数据包封装和分用 五、网络中的地址管理 一、计算机网络背景 【独立…

C++11新特性⑤ | 仿函数与lambda表达式

目录 1、引言 2、仿函数 3、lambda表达式 3.1、lambda表达式的一般形式 3.2、返回类型说明 3.3、捕获列表的规则 3.4、可以捕获哪些变量 3.5、lambda表达式给编程带来的便利 VC常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...&a…

【送书活动】全网超50万粉丝的Linux大咖良许,出书了!

前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄,vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

Linux之Shell概述

目录 Linux之Shell概述 学习shell的原因 shell是什么 shell起源 查看当前系统支持的shell 查看当前系统默认shell Shell 概念 Shell 程序设计语言 Shell 也是一种脚本语言 用途 Shell脚本的基本元素 基本元素构成: Shell脚本中的注释和风格 Shell脚本编…

瑞萨GUI(LVGL)入门移植实战教程基于e² studio(更新完结!)

瑞萨GUI(LVGL)移植实战教程 前言 本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 ,LVGL版本 V8.3.8。 如果你想熟悉瑞萨的e studio以及FSP,那么本教程也能也能为你提供很好的入门以及使用指导。 教程理论与实践相结合带你走进 LVGL 、完成 LVGL 的…