本章实际是上分析怎么去设计一个类,设计一个类应该需要包含的基本元素,下面我从如下几个方面做总结。
- class的声明,定义,以及声明后的主体。
- class的构造函数 Constructors 和 析构函数 Destructors。
- 成员种类和成员初始化,multable 和const。
- this指针
- firend友联
- 打造一个 function object 需要重载常见的运算符有哪些
1:class的声明,定义以及声明后的主体。
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 头文件即可。
2:Constructors构造函数和 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++学习的难点之一。