C++: Essential C++ 读书笔记(chapter4):基于对象的编程风格概要
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
本章实际是上分析怎么去设计一个类设计一个类应该需要包含的基本元素下面我从如下几个方面做总结。
- class的声明定义以及声明后的主体。
- class的构造函数 Constructors 和 析构函数 Destructors。
- 成员种类和成员初始化multable 和const。
- this指针
- firend友联
- 打造一个 function object 需要重载常见的运算符有哪些
1class的声明定义以及声明后的主体。
class的前置声明forward declaration
class的声明是以关键词 class开始其后紧接着一个名称如class Stack
这个声明只是将class 名称告诉编译器并未提供此 class的任何其他信息如class支持的操作行为以及所包含的 data members等。
前置声明使我们可以进行类指针(class pointer)的定义或以此class作为数据型别。
Stack *pt = 0 // 定义一个类指针
void process(const Stack&) // 以Stack作为数据型别
calss的定义
在定义实际的Stack class object 或取用 Stack的任何一个 member之前必须先定义 class本身class定义的主体是这样的
class Stack { public: // 声明一下函数 bool push(const string&); bool pop(string &elem); bool peek(string &elem); bool empty(); bool full(); // 定义size函数 int size() { return _stack.size(); } private: vector<string> _stack; }
member functions的声明和定义
所有 member functions都必须在class主体内进行声明适于是否需要同时定义可以由程序员自由决定。
- 如果在class主体内定义那么这个函数就自定是 内联函数 ,比如size()函数
- 如果在class主体外定义那么就需要使用特殊的语法目的就是在于分辨该函数究竟属于哪一个 class如果希望该函数为 inline那么应该在最前面指定关键系 inline。
// 内联函数 inline bool Stack::empty() { return _stack.empty(); } // 非内联函数 bool Stack::pop(string& elem) { if(empty()) return false; elem = _stack.back(); _stack.pop_back(); return true; }
上述 Stack::empty() 就是告诉编译器 empty()是 Stack class的一个 member class名称之后的两个冒号(Stack::) 是所谓的 class scope resolution类范围决议运算符。
总结
- 对于inline 函数而言定义于class主体或者主体外其实并没有什么分别。
- class 的定义式及其inline member function通常应该放在与class同名的头文件中如 Stack class 的定义和 empty()函数的声明应该放在 Stack.h头文件中。
- 如果用户想要使用Stack那么直接 include Stack.h 头文件即可。
2Constructors构造函数和 Destructors析构函数
Constructors
构造函数的名称必须与class名称相同语法规定constructors不应指定返回型别也不需要返回值它可以被重载例如
class Triangular { public: // 一组重载的构造函数 Triangular(); // 默认构造函数 Triangular(int len); Triangular(int len =1,int beg_pos = 1); private: int _len; itn _beg_pos; }
member initialization
通过构造函数直接初始化
Triangular::Triangular() { _len = 1; _beg_pos = 1; }
成员初始表member initialization list
member initialization list 是紧接在参数表最后的冒号后面以逗号分隔的列表其中欲赋值给member的数值被置于 member名称后面的小括号内
Taiangular::Triangular(const Triangular& rhs):_len(rhs._len), _beg_pos(rhs._beg_pos) { }
Destructors
- 析构函数是与构造函数对立的所谓析构函数是用户自定义的一个 class member一旦某个class提供有 destructor当其objects结束生命时便会自动调用 destructor处理善后所以析构函数主要用来释放构造函数中或者对象声明周期中配置的资源。
- 析构函数有着严格的名称规定class 名称再加上"~"前导符号它绝对不会有返回值也没有任何参数所以也绝不会有重载。
class Matrix { public: Matrix(int row, int col):_row(row),_col(col) { // 构造函数进行资源的配置 _pmat = new double(row*col); } ~Matrix() { // 析构函数进行资源的释放 delete[] _pmat; } private: int _row, _col; double* _pmat; } int main(){ Matrix mat(4,4); }
编译器解释
- 编译器会在 mat 被定义出来的下一刻暗暗施行 Matrix constructor于是_pmat被初始化为一个指针指向程序自由空间(free store)中的一块内存代表一个具有16个double元素的数组在语句区段释放之前main函数出栈之前编译器又会暗暗施行 Matrix Destructor于是释放_pmat所寻址的那块具有16个double元素的数组Matrix 用户不需要知道内存管理的细节。
- 但是 Destructor并非绝对有必要比如Triangular 为例2个 data member都是以储值方式存放这些 member data在class object被定义后便已存在并在 class Triangular结束其生命周期被释放因此 Triangular Destructor并没有什么事情需要做所以我们没有必要非得提供 Destructor不可事实上是否需要定义 析构函数是C++学习的难点之一。