EC++学习笔记(一) 习惯c++

条款01:c++多范式编程语言

 

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

1. 提供类型安全检查

2. 去除函数调用开销

3. 避免宏的二义性

const double pi = 3.1415926;
const std::string authorName("wwwjieo0");

 

  宏函数:所有实参必须加上小括号

#define MAX(x, y)  ((x) >= (y) ? (x) : (y))
MAX(++a, b);    //a被累加两次

 

  c++ inline函数实现:

template<class T>
inline T max(const T& x, const T& y) {
    return (x >= y ? x : y);
}

 

  

c语言中的宏仍然是必需品:
#include是必需品,#ifdef和#ifndef扮演 条件编译的角色

 

条款03:尽可能使用const

const 使编译器实施强制保护

char myname[] = "wwwjieo0";
char* p = myname;                   //non-const pointer, non-const data
const char* p = myname;            //non-const pointer, const data
char* const p = myname;            //const pointer, non-const data
const char* const p = myname;     //const pointer, const data

 

  STL迭代器的const:

const std::vector<int>::iterator it = vec.begin();    //it为const,永远指向begin
std::vector<int>::const_iterator it = vec.begin();    //it可以改变,但*it(即容器元素)不可改变

 

const 成员函数:

const 成员函数不可以更改对象任何non-static 成员变量

可以利用 const 成员函数实现其non-const 版本

const Widget& func(int x, int y) const; //已经实现
Widget& func(int x, int y) {
    return const_cast<Widget&>(static_cast<const Widget&>(*this).func(x, y));
}

 

类中的每个non-static 成员函数都有一个隐藏的this参数(第一个参数),这个this指针指向类的实例对象,并且this指针为const pointer
所以 Widget& func(int x, int y) 实际上是 Widget& func(Widget* const this, int x, int y);
而 const 成员版本 Widget& func(int x, int y) const 实际上是 Widget& func(const Widget * const this, int x, int y);
(const int& x)和 (const int x)是重载函数,并不是重复定义

static_cast 将(*this) 加上 const 特性,因为要调用 const 成员函数
const_cast 将 const 成员函数返回值 const Widget& 去除 const 特性,因为要与函数返回值类型相同

注意:不能用non-const 成员函数去实现相应的 const 版本,因为 non-const 函数可能会改变一些值,这不符合 const 函数的要求

 

条款04:确定对象被使用前已被初始化

 

永远在使用对象之前先将它初始化
内置类型:手工初始化,避免未定义行为带来的随机值
自定义类型:确保每一个构造函数都将对象的每一个成员初始化

class Person{
public:
    Person(const string& name, const string& address);
private:
    string    theName;
    string    theAddress;
    int       theId;
};

Person::Person(const string& name, const string& address) {
    theName = name;
    theAddress = address;
    theId = 0;
}

 

c++规定,对象的成员变量的初始化动作发生在进入构造函数的函数体之前
所以上面程序中,构造函数内部并不是初始化,而是赋值操作
真正的初始化动作发生在 default 构造函数(编译器自动生成)自动调用之时

构造函数应该使用 成员初始化列表 替换赋值操作

Person::Person(const string& name, const string& address)
:theName(name),
theAddress(address),
theId(0)
{ }

 

这种方法效率更高,没有首先调用 default 构造函数,而是在进入构造函数的函数体之前利用 copy构造函数直接初始化
总结:总是使用成员初始值列表,并且在初值中列出所有成员变量

c++初始化次序:base class 更早于 derived class,class 的成员变量总是以其声明次序被初始化

你可能感兴趣的:(学习笔记)