Effective C++ 读书笔记1

条款1 视C++为一个语言联邦

     今天的C++已经是个多重范型编程语言,一个支持过程形式、面向对象形式、函数形式、泛型形式、元编程形式的语言。为了理解C++,必须认识其主要的次语言,总共4个:

1.C

2.Object-Oriented C++

3.Template C++

4.STL


条款2 尽量以const, enum, inline替换#define(即宁可以编译器替换预处理器)

1.

       #define ASPECT_RATIO 1.653

       ASPECT_RATIO没有进入编译器的symbol table,错误信息会提到1.653而不是ASPECT_RATIO,这样查找这个符号就会花费时间,所以应该这样:

const double AspectRatio = 1.653

      有两种特殊情况:

      一。第一常量指针。应该写为:const char* const authorName = "Scott Meyers";

      二。class专属常量。为了确保次常量最多只有一份实体,必须让它成为一个static成员。通常C++要求你对所使用的任何东西提供一个定义式,但如果它是class专属常量又是static且为整数类型(int, char, bool),则需要特殊处理:只要不去它们的地址,可以声明并使用它们而无需提供定义式。      

class GamePlayer{

      private:
            static const int Num = 5;//常量声明式
            int scores[Num];
}


class TestClass{

private:
	static const double d = 1.2;//这里居然可以初始化double类型的,但是在公司电脑的eclipse上就不行,奇怪,同是cdt,版本也相同
	static const int i = 22;
};
//const double TestClass::d = 1.2; //此时不能加static,static只用于声明,此处是定义;同理,不能在定义静态函数时加上static;但是改法则不适用于全局static 函数

     如果编译器不支持static整型常量在class内的初值设定,可改用所谓的“the enum hack”补偿做法。
class GamePlayer{
     private:
           enum {NumTurns = 5};
           int scores[NumTruns];
};
2.#define常用来实现宏,看起来像函数,但是不会导致函数调用的开销
  #define CALL_WITH_MAX(a,b) f((a)>(b)? (a):(b))  //以a和b中的最大值调用函数f
   int a = 5, b = 0;
   CALL_WITH_MAX(++a, b); //a被累加两次   
   CALL_WITH_MAX(++a, b+10); //a被累加一次
    
   可以使用template inline来替代上述表示://template可以实现和参数类型无关,inline可以消除函数调用的开销
  
 template<typename T>
inline void CallWithMax(const T&a, const T& b)
{
    f(a>b? a: b)
}

 有了const, enum 和inline,只能降低对预处理器的需求,但不能完全消除,#include是必需品,而#ifdef/#ifndef在控制编译中扮演重要角色
   
条款3  尽可能使用const

1. 注意:
    如果被指物为常量,有两种写法:
    const int* cpi;
    int const* cpi;注意不是int *const cpi;
2. const成员函数
   将const实施于成员函数的目的,是为了确认该成员函数可作用于const对象。该类函数比较重要,因为:一,得知哪个函数可以改动对象内容哪个不行很重要;二,使操作const对象成为可能(条款20说,改善C++程序效率的一个根本方法是以pass by reference-to-const方式传递对象,而此技术可行的前提是,我们有const成员函数可用来处理取得的const对象)许多人漠视一件事实:两个成员函数如果只是常量性不同,可以被重载,这是一个重要的C++特性:
    


class TestBlock{

public:
	const char& operator[](size_t position) const{

		return text[position];
	}
	char& operator[](size_t position){

		return text[position];
	}

private:
	string text;
};
void print(const TextBlock* ctb){

std::cout << ctb[0];//此处调用的是const operator[]版本的:不太明白,函数的参数个数和类型完全相同,编译器是如何判断该调用哪个版本的operator[]的呢?
}


void print(){
    TextBlock tb;
     tb[0] = 'x';//注意:如果non-const operator[]返回类型不是reference-to-char,而不是char,那么这里将会出错,因为如果函数返回值是内置类型,那么改动函数返回值从来都是不合法的。貌似有点说不通,为什么不能修改函数反悔值,却能修改函数返回的reference?? 
}

const成员函数的两个阵营:
一是bitwise(又称为physical constness),认为成员函数不能更改对象内的任何一个bit,不幸的是许多成员函数虽然不十足具备const性质却能通过bitwise测试,也就是说,一个更改了指针所指物的成员函数虽然不能算是const,但如果只有指针(而非其所指物)隶属于对象,那么称此函数为bitwise const不会引发编译器异议。
class CTextBlock{
public:
    char& operator[] (std::size_t position) const{
            
             return pText[position];
     }
private:
     char* pText;
}

const CTextBlock cctb("hello");
char* pc = &cctb[0];
*pc='j' //虽然调用了const函数,没有改变内部成员变量,但返回的指针最终还是导致改变了成员的值

二是logical constness,主张一个const成员函数可以修改它所处理对象内的某些bits:
class CTextBlock{
	
public:
	std::size_t length() const;
private:
	char* pText;
	mutable std::size_t testLength;
	mutable bool lengthIsValid;
};
std::size_t CTextBlock::length() const{
	
	if(!lengthIsValid){
		
		testLength = std::strlen(pText);//可以修改成员变量
		lengthIsValid = true;//可以修改成员变量
	}
};

2.在const和non-const成员函数中避免重复
   上述的实现中两个相互重载的函数造成了代码的重复,为了实现代码复用,可以使用non-const版本调用const版本:
class TextBlock{
public:
    const char& operator[] (std::size_t position) const {
             //...
             //....
             //....
             return text[position];
      }

      char& operator[] (std::size_t position){
              return const_cast<char&>(static_cast<const TextBlock&>(*this)[position]);//为*this加上const,调用const op[]:这里不是很理解,为什么一定需要把*this转为const TextBlock&????
       }
};
    上述代码有两次类型转换,第一次用来为*this添加const(这使接下来条用operator[]时得以调用const版本);第二次则是从const operator[]返回值中移除const;更值得了解的是,
反向做法------令const版本调用non-const版本以避免重复是不应该的。const成员函数承诺绝不改变其对象的逻辑状态,non-const成员函数却没有这般承诺。如果在const函数
调用non-const函数:你曾经承诺不改动的那个对象被改动了。实际上若要令这样的代码通过编译,你必须使用一个const_cast将*this身上的const性质解放掉(????)































   

你可能感兴趣的:(C++,读书,Class,语言,reference,编译器)