导读

作者Scott Meyers在如何有效运用C++方面给出了55个具体的做法,大致分为两类:

  • 一般性的设计策略,集中于"如何在不同的做法中选择一种完成任务"

    • 选择inheritance(继承)还是template(模板)
    • 选择public继承还是private继承
    • 选择private继承还是composition(复合)
    • 选择member函数还是non-member函数
    • 选择pass-by-value还是pass-by-reference
  • 具体细节的特定语言特性
    • 什么是assignment操作符的适当返回类型
    • 何时该令析构函数为virtual
    • operator new无法找到足够内存时,该如何行事

术语

声明式(declaration)是告诉编译器某个东西的名称和类型

extern int x;                       // 对象声明式
std::size_t numDigit(int number); // 函数声明式
class Widget; // 类声明式
template<typename T>
class GraphNode; // 模板声明式

定义式(definition)是编译器为此对象拨发内存的地点

int x;                              // 对象定义式
std::size_t numDigit(int number){ // 函数定义式
return number;
} class Widget{ // 类定义式
public:
Widget();
~Widget();
}; template<typename T> // 模板定义式
class GraphNode{
public:
GraphNode();
~GraphNode();
};

copy构造和copy赋值的区别:一个新对象被定义,一定是构造函数被调用,不可能调用赋值操作

条款01:视C++为语言联邦

C++有四个次语言

  • C:没有模板(templates),没有异常(exceptions),没有重载(overloading)..
  • Object-Oriented C++:C with Classes, 封装,继承,多态,虚函数绑定...
  • Template C++:模板元编程(TMP)...
  • STL:容器,迭代器,算法,函数对象...

条款02:尽量以const,enum,inline替换 #define

这个条款或许更改为"宁可以编译器替代预处理器"比较好

#define ASPECT_RATIO 1.653

ASPECT_RATIO可能从未进入符号表,从未被编译器看见,可以用一个常量来替代宏

const double Aspect_Ratio = 1.653; // 大写名称常用于宏,这里改变名称写法

当以常量替换#define时,有两种特殊情况

  • 定义常量指针

    由于常量定义式通常放在头文件中,因此有必要将指针也声明为const
const char* const authorName = "Scott Meyers";
  • class专属常量

    为了将常量作用域限制为class内,必须让它成为一个成员,为确保常量最多一份,必须让它成为一个static

    通常C++要求你对所有你使用的任何东西提供一个定义式,但是如果是class专属常量且是static且为整数类型(int,char,bool),则特殊处理,只要不取地址,你可以声明他们而无须提供定义式,如下。但如果需要取其地址,就必须提供在实现文件中提供定义式,否则编译不通过。
// GamePlayer.h
class GamePlayer{
public:
static const int print(){ return NumTurns;}
static const int* address(){ return &NumTurns;}
private:
static const int NumTurns = 5; // 常量声明式
};
// GamePlayer.cpp
#include <iostream>
#include "GamePlayer.h" const int GamePlayer::NumTurns; // 定义式,初始值声明式已获得,不能再设初值
int main(){
// GamePlayer::print();
std::cout << GamePlayer::address();
return 0;
}

顺带一提,#define宏无法提供封装性,如果编译器不允许"static整数型class常量"完成"in class初值设定",可以改用"the enum hack"补偿做法,其理论基础是枚举类型的数值可以当成int使用

class GamePlayer{
private:
enum { NumTurns = 5};
int scores[NumTurns];
}

enum hack行为比较像#define而不像const,有时候这正是你想要的,如取地址的合法性(const合法,#define和enum不合法),enum hack还是模板元编程的基础技术(条款48)

宏不会招致函数调用的额外开销,但是容易误用

#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b)) // 以较大值调用f

int a = 5, b = 0;
CALL_WITH_MAX(++a, b); // a被累加两次
CALL_WITH_MAX(++a, b+10); // a被累加一次

而tempalte inline(条款30)可以获得宏带来的效率和所有可预料的行为以及类型安全性

条款03:尽可能使用const

const如果出现在*左边,表明被指物是常量,在右边则表明指针自身为常量

void f(const Widget* pw);        //pw所指之物为常量
void f(Widget const* pw); // 同上

STL中const_iterator指的是所指物不能改动

const成员函数

  • 可以使用const成员函数使接口更容易被理解
  • 可以使操作const对象成为可能,以pass-by-reference-to-const传递对象能够改善程序效率
  • 两个成员函数如果只是常量性不同,可以重载

成员函数如果是const意味着什么?

  • bitwise constness(physical constness)

    不改变对象内的任何一个bit,很容易侦测违反点:编译器只需寻找成员变量的赋值动作即可,这也是C++对常量性的定义,因此const成员函数不可以更改对象内的任何non-static成员变量
  • logical constness

    const成员函数可以修改对象内的某些bits,但是只有在客户端(调用端)侦测不出的情况下才如此

声明为mutable的变量即使在const成员函数中也可以被更改

在const和non-const成员函数中避免代码重复

运用const成员函数实现non-const成员函数,可以使用const_cast进行常量性转除


class TextBook{
public:
const char& operator[](size_t position) const{
return text[position];
} char& char& operator[](size_t position){
return const_cast<char&>(
static_cast<const TextBook&>(*this)
[position]
);
}
};

EffectiveC++01-03的更多相关文章

  1. Tensorflow学习笔记2019.01.03

    tensorflow学习笔记: 3.2 Tensorflow中定义数据流图 张量知识矩阵的一个超集. 超集:如果一个集合S2中的每一个元素都在集合S1中,且集合S1中可能包含S2中没有的元素,则集合S ...

  2. 2016CCPC东北地区大学生程序设计竞赛【01/03/05/06/08】

    吧啦啦啦啦啦啦啦啦啦啦啦能量,ACM,跨!变身!变成一个智障! 04正在酝酿中!!!马上更新!!!!!  01题意:有一个n个点的图,对于任意两个不同的点,他的权值是两个点下标的最小公倍数,求最小生出 ...

  3. Cheatsheet: 2016 03.01 ~ 03.31

    JAVA Quick Java 8 or Java 7 Dev Environments With Docker Printing arrays by hacking the JVM Mobile H ...

  4. 01 ~ 03 headfirst php & mysql

    Question : 难道不是所有web页面原先都放在服务器上吗? 甚至存储在.html文件中的HTML页面? Answer : 没错, 网站的所有文件都存储在服务器上, html, css, php ...

  5. Adding a WebPart to a SharePoint 2013 Master Page 分类: Sharepoint 2015-07-08 01:03 7人阅读 评论(0) 收藏

    On SharePoint 2013 you can not add the Web Parts to the master page the same way of 2010. Please use ...

  6. Cheatsheet: 2015 03.01 ~ 03.31

    Web The Architecture of Algolia's Distributed Search Network No promises: asynchronous JavaScript wi ...

  7. Cheatsheet: 2014 03.01 ~ 03.31

    .NET Should I be concerned about PDB files? async and await -Simplified-Internals Web Performance tr ...

  8. 2019.01.03 bzoj3456: 城市规划(生成函数+多项式取对)

    传送门 生成函数好题. 题意:求n个点的简单(无重边无自环)无向连通图数目 思路: 对简单无向图构造生成函数f(x)=∑n2Cn2xnn!f(x)=\sum_n2^{C_n^2}\frac{x^n}{ ...

  9. Cheatsheet: 2017 03.01 ~ 03.31

    Web New Year, New Blog Day 10 - Using JetBrains Rider with a .NET Core Console Application JavaScrip ...

  10. JavaWeb——升级赛-学生成绩管理系统(2).java---19.01.03

    dao.java package Dao; import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLExcept ...

随机推荐

  1. 第四周总结 & 实验报告(二)

    第四周课程总结 一.String类 1.实例化 (1)直接赋值 public class Xxxx{ public static void main(String args[]){ String a ...

  2. HTTP学习记录:四、头信息(请求和响应)

    学习资源主要为:@小坦克HTTP相关博客 一.请求头信息(Request Header) 请求头信息包含比较多,如下: 1.Cache头域 if-modified-Since 作用:把浏览器端缓存页面 ...

  3. Mysql-5.7 x64安装

    首先在官网下载Mysql:https://dev.mysql.com/downloads/mysql/ 选择ZIP Archive下载. 下载安装之后配置环境变量: 编辑现有环境变量Path: PS: ...

  4. 解析jmeter阶梯加压与请求的计算

    用百度做例子 我们设置阶梯加压线程组的请求参数,如下图 上图表示 1:每隔2秒钟,会在1秒内启动5个线程 2:每次线程加载之后都会运行2s然后开始下一次线程加载 3:最终会加载50个线程并持续运行30 ...

  5. 3D打印技术的学习

    1. 我们使用3D建模软件:123Ddesign来设计 123D design软件保存格式有2种,分别为123dx和stl格式 123dx格式:选择菜单栏中“Save”下的“To my compute ...

  6. django 的 一对多的关系

    USERINFO 用户详情表 USERTYPE 用户类别表 UserType是父表,UserInfo是子表, user_type 是 关联字段 就是新增资源的时候,又对数据库重新查询一遍,太消耗资源了 ...

  7. C++ 统计输入的句子有多少英文字母

    // ConsoleApplication1.cpp: 定义控制台应用程序的入口点.//#include "stdafx.h"#include <iostream>#i ...

  8. 获取IP地址的几种方法

    根据ip获取地址的几种方法 1.调用新浪IP地址库 <script type="text/javascript" src="js/jquery.js"&g ...

  9. c语言中不允许在函数外部给全局变量赋值

    今天,在写条件编译的时候,出现了在函数外部给全局变量赋值的情况,gcc报错,那么c语言为什么不允许在函数外部给变量赋值呢?为什么声明变量的时候可以对变量进行赋值? 出错代码: /* 2 * ===== ...

  10. 小白学Python(20)—— Turtle 海龟绘图

    Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x.纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行 ...