《Effective C++ 3th》——让自己习惯C++


 
视c++为一个语言联邦
尽量以const,enum,inline替换#define
尽可能使用const
确定对象被使用前已先被初始化
 

视C++为一个语言联邦

C++: C with Classes。c++可以看成是C语言与OOP的结合体,并引入STL新特性:
在这里插入图片描述

  • C: C语言部分;
  • Object-Oriented C++: C++中OOP部分;
  • Template C++: C++中模板部分(泛型);
  • STL: C++标准库(泛型)。
     
     

尽量以const,enum,inline替换#define

以编译器替换预处理器。#define缺点:

  • 预处理阶段处理,错误提示不明确;
  • 盲目替换,导致存在多份;
  • 替换时展开导致语义错误

使用const,enum和inline替换的优点:

  • 编译阶段处理,明确的错误提示;
  • 单份代码。
///
// 预处理器处理
// 预处理阶段 --> 盲目替换 --> 编译器
// - 预处理阶段处理,错误提示不明确
// - 盲目替换,导致存在多份
// - 替换时展开导致语义错误
#define ASPECT_RATIO 1.653

///
// 编译器处理
// 编译器
// - 编译阶段处理,明确的错误提示
// - 单份代码
const double AspectRatio = 1.653;

class GamePlayer
{
private:
	enum { NumTurns = 5 }; // 类专属常量enum定义

private:
	static const int NumTurns; // 类专属常量const定义
};
const int GamePlayer::NumTurns = 5;

// inline模板定义
template<typename T>
inline T callWithMax(const T &a, const T &b)
{
	return (a > b ? a : b);
}

方法:

  1. 对于单纯常量,最好以const或者enum替换#define;
  2. 对于形似函数的宏,最好改用inline函数替换#define。
     
     

尽可能使用const

const定义不被改动的语义约束。特点:

  • const出现在 * 号左边,表示被指物是常量;const出现在 * 号右边,表示指针自身是常量;如果出现在 * 号两边,表示被指物和指针都是常量;
 char a = "Hello World!";
 const char *p = a; // a不可变
 char* const p = a; // p不可变
 const char* const p = a; // p和a都不可变
  • 如果被指物不可变,const写在类型前和写在类型后意义相同:
  void f1(const Widget *pw);
  void f2(Widget const *pw); // 意义相同
  • const成员函数:bitwise constness和“概念上的常量性”。
     
     

确定对象被使用前已先被初始化

解决使用与初始化的顺序问题:永远在使用对象之前将它初始化
区别 初始化赋值

ABEntry::ABEntry(const std::string &name, const std::string &address,
                const std::list<PhoneNumber> &phones)
{
    // 此处为赋值,并非初始化
    theName = name;
    theAddress = address;
    thePhones = phones;
    numTimesConsulted = 0;
}

ABEntry::ABEntry(const std::string &name, const std::string &address,
                const std::list<PhoneNumber> &phones)
    :theName(name),
	theAddress(address),
	thePhones(phones),
	numTimesConsulted(0) // 此处为值列初始化
{
}

解决使用和初始化的先后问题:

// 将每个non-local static对象搬到自己的专属函数内。
// 单例模式常见手法
class FileSystem {...};
FileSystem& tfs()
{
    static FileSystem fs;
    return fs;
}

class Directory {...};
Directory::Directory(params)
{
    ...
    std::size_t disks = tds().numDisks();
    ...
}

方法:

  1. 内置对象进行手工初始化,因为C++不保证初始化它们;
  2. 构造函数使用初值列初始化;初值列成员变量的排列次序应该与tam在class中声明次序相同;
  3. 以local static对象替换non-local static对象解决“跨单元的初始化次序”问题。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作者 : Scott Meyers 译序、导读 : 侯捷 译序(侯捷) C++ 是一个难学易用的语言! C++ 的难学,不仅在其广博的语法,以及语法背後的语意,以及语意背後的深层思维,以及深层思维背後的物件模型;C++ 的难学,还在於它提供了四种不同(但相辅相成)的程式设计思维模式:procedural-based,object-based,object-oriented,generic paradigm。 世上没有白吃的午餐。又要有效率,又要有弹性,又要前瞻望远,又要回溯相容,又要能治大国,又要能烹小鲜,学习起来当然就不可能太简单。 在如此庞大复杂的机制下,万千使用者前仆後续的动力是:一旦学成,妙用无穷。C++ 相关书籍之多,车载斗量;如天上繁星,如过江之鲫。广博如四库全书者有之(The C++ Programming Language、C++ Primer),深奥如重山复水者有之(The Annotated C++ Reference Manual, Inside the C++ Object Model),细说历史者有之(The Design and Evolution of C++, Ruminations on C++),独沽一味者有之(Polymorphism in C++, Genericity in C++),独树一帜者有之(Design Patterns,Large Scale C++ Software Design, C++ FAQs),程式库大全有之(The C++ Standard Library),另辟蹊径者有之(Generic Programming and the STL),工程经验之累积亦有之(Effective C++, More Effective C++, Exceptional C++)。 这其中,「工程经验之累积」对已具C++ 相当基础的程式员而言,有著致命的吸引力与立竿见影的帮助。Scott Meyers 的Effective C++ 和More Effective C++ 是此类佼佼,Herb Sutter 的Exceptional C++ 则是後起之秀。 这类书籍的一个共通特色是轻薄短小,并且高密度地纳入作者浸淫於C++/OOP 领域多年而广泛的经验。它们不但开展读者的视野,也为读者提供各种C++/OOP 常见问题或易犯错误的解决模型。某些小范围主题诸如「在base classes 中使用virtual destructor」、「令operator= 传回*this 的reference」,可能在百科型C++ 语言书籍中亦曾概略提过,但此类书籍以深度探索的方式,让我们了解问题背後的成因、最佳的解法、以及其他可能的牵扯。至於大范围主题,例如smart pointers, reference counting, proxy classes,double dispatching, 基本上已属design patterns 的层级! 这些都是经验的累积和心血的结晶。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值