c++概念程序语言学习 2008-12-17 21:06:10 阅读19 评论0 字号:大中小 条款1:视C++为一个语言集合,有以下四个独立的部分
C++的内涵 (1) 继承C概念:区块,语句,预处理器,内置数据类型,数组,指针 (2) 对象概念: 类,封装,继承,多态,动态绑定 (3) 范型编程: 模板 (4) STL: template程序库,容器,迭代器,算法,function objects 条款2:用C++特性代替C中的预处理器 C预处理器:#include,#ifdef/#ifndef,#define 用C++特性代替#define 用途 #define用途(1): 定义常量 #define PI 3.14 替换为const double PI=3.14; 好处 (1)用define定义的常量没有进入记号表,不方便调试 (2)用const定义常量将得到更精简的目标代码,因为预处理器处理#define是会盲目的将宏名称替换为3.14,若用const定义常量则不会出现这种问题。 当需要定义class专属常量的时候,不能用#define,因为#define并不重视作用域概念,而用const就可以定义class专属常量。 class Person { public: static const int SIZE = 1024;//这里只是声明,类内部的定义都是声明 char name[SIZE]; //使用该常量 }; 这里看到的 'SIZE' 只是声明式而非定义式。通常C++邀请你对你所使用的任何的东西都提供一个定义式,但是如果它是一个class专属常量又是static且为整数类类型(int,short,char,bool等)则需要特殊处理,只要不取它们的地址,你可以声明并使用它们而无须提供定义式。但如果你取某个class的专属常量的地址,或者你的编译器坚持要看到一个定义式(VC6就是这样),你就必须提供一个定义式如下: const int Person::SIZE ; C++中的两种替代方法: (1) 使用static关键词 class GamePlayer{ private: static const int NumTurns=5; //声明 int scores[Numturns]; } const int GamePlayer::NumTurns; //定义 (2) 使用enum关键词 class GamePlayer{ private: enum{ NumTurns=5 }; int scores[Numturns]; } 另外,enum和#define一样绝不会导致非必要的内存分配。 #define用途(2): 定义函数用途的宏 #define MAX(a,b) f((a)>(b)?(a):(b)) int a =5, b = 1; MAX(++a, b);//a被累加二次 MAX(++a, b+10);//a被累加一次 替换为内联模板函数 template<typename T> inline void MAX(const T&a,const T&b) { f(a>b?a:b); } 好处:避免宏展开带来的不可靠影响 条款3:理解const关键字的深意,并把它运用到程序中去 如果const出现在星号左边,表示被指物是常量;如果const出现在星号右边,表示指针自身是常量。 如果出现在星号两边,表示被指物和指针两者都是常量。 (1)用const修饰变量、指针、迭代器等 表明迭代器不能被修改 例如: vector<int> vec; const vector<int>::iterator iter = vec.begin(); *iter = 10;//OK,没有问题 iter++;//错误,iter是一个const vector<int>::const_iterator cIter = vec.begin(); *cIter = 10;//错误,cIter指向的变量是一个const cIter++;//OK,没有问题 (2)函数返回值声明为const,例如: const Rational operator* (const Rational& lhs, const Rational& rhs) 作用:阻止if(a*b=c)等怪异的赋值语句 (3)const成员函数: 两个函数如果只是常量性不同,是可以被重载的。。 作用1:使class接口比较容易理解 2:可以操作const对象 例子: class TextBlock{ 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) { cout<<ctb[0]; //调用 const函数版本 } 对于const函数的两种争论 (1)const函数不应该改变任何non-const数据成员(反例:如果有指针成员,还是能改变其所指对象) (2)const函数可以改变数据成员,但必须在用户端无法检测到的情况下,这里还要要利用mutable技术 如何避免const成员函数和非const成员函数重载中的消耗问题 实现技术(1),用非const版本调用const版本 例子: const char& operator[](size_t position) const { return name[position]; } char& operator[](size_t position) { return const_cast<char*>( //将原来的op[]返回值的const转除 static_cast<const Person&>(*this)[position] //将non-const类型转换为const类型 ); } (2)在类的private中增加一个函数,包涵所有公共代码 在const成员函数调用non-const成员函数是一中错误行为。 条款4:确定对象在使用之前初始化 成员初始化列表和函数内赋值的涵义 (1)对于类数据成员 成员初始化列表:调用类的copy构造函数进行初始化(高效) 函数内赋值:先后调用default构造函数和copy assignment操作符(低效) (2)对于内置类型数据成员:两种方法效率相同 (3)保证对于所有内置数据类型进行手工初始化 (4)初始化列表中的排列次序要严格符合class中的声明次序,因为编译器永远按照成员变量的声明顺序来初始化,而不管初始化列表。 C++规定,对象的成员变量的初始化动作发生在构造函数本体之前。 C++对“定义于不同编译单元内的not-local static对象”的初始化次序并无明确定义 |
|