c++注解(4)——现代c++类
一.类组成
我认为c++的类由四部分组成:
-
成员函数
-
成员变量
-
权限
-
this指针
写类一定要明确一个核心思想:一切的操作都以成员变量为核心
,成员函数和权限还有this指针只是c++的语法糖而已
1.this指针
-
this指针,指向对象的内存地址
-
this指针参与成员函数的重载决议,一般作为第一个成员函数的第一个参数
-
想要将this指针智能指针化,可以public继承std::shared_from_this
2.成员函数
-
成员函数的第一个参数应该是
Self* this
,如果成员函数是const属性的,那么第一个参数可以理解为const Self* this
,这也是为什么const对象无法调用非const成员函数的原因 -
static的成员函数没有this指针
3.权限
-
public用来暴露接口,private和protected都可以隐藏成员变量和成员函数
-
private和protected的区别是在继承方面,如果不使用继承,private和protected没有区别,如果使用继承,子类无法访问父类private成员,但是可以访问protected成员
4.成员变量
- 成员变量是我认为是类的核心所在,其他的东西都是为成员变量服务
二.类特种函数规则
c++11中有6大特殊函数,构造函数,析构函数,拷贝构造函数,拷贝赋值函数,移动构造函数,移动赋值函数
1.c++98的失误
- 当一个类中存在析构函数时,证明类中有可能存在指向堆中的指针,需要使用析构函数来释放,这是标准的RAII手法,理论上来说,这种情况下不应该存在默认的拷贝构造函数和拷贝赋值函数,因为可能会造成double free的情况,但是事实情况c++98允许其存在,
这是一个不得不说的失误
2.大三律
-
大三律:析构函数,拷贝构造函数,拷贝赋值函数,你只要声明了其中一个,就必须声明另外两个,原因和c++98失误的原因一样
-
大三律没有在c++98中得到重视,是一件痛心的事
3.c++11中特种函数生成规则
-
默认构造函数:当类中不包含用户声明的构造函数时会生成
-
默认析构函数:当类中不包含用户声明的析构函数时会生成
-
默认拷贝构造函数:当类中不包含用户声明的拷贝构造函数时会生成,如果类中声明了移动操作,则默认拷贝构造函数会被删除
-
默认拷贝赋值函数:当类中不包含用户声明的拷贝赋值函数时会生成,如果类中声明了移动操作,则默认拷贝赋值函数会被删除
-
默认移动构造和移动赋值:当类中不包含用户声明的拷贝操作,移动操作,析构函数时才会出现
4.最佳实践
- 对于默认特种函数要心里有数,对于非数据语义的类,应该使用
delete关键字
默认删掉,这也是boost库中noncopyable存在的意义,不过我更建议生动删掉
class Test { public: Test() ~Test(); Test(const Test&) = delete; Test& operator=(const Test&) = delete; };
三.传统c++面向对象
传统的c++面向对象的核心思想是:public继承+虚函数实现的多态
1.继承
-
c++支持三种权限的继承,但实际上只有
public继承最有用
-
继承不推荐使用,耦合强度仅次于友元
-
多继承更加不提倡,简直是噩梦
2.虚函数
-
虚函数多态的本质是在类的内存布局中有一个虚函数表,并且是按照偏移而不是名字来执行相应函数的
-
虚函数的二进制兼容性差,因为是按照偏移来寻址,所以增加或删除虚函数会破坏二进制兼容性
-
虚函数不推荐使用,除非你能保证这个抽象会是一直正确,不然应该避免使用
-
c++11中使用override关键字,可以避免派生类中忘记重写虚函数的错误
-
如果使用public继承+虚函数多态,一定要将析构函数写成虚函数的形式,不然有可能导致内存泄漏
四.现代面向对象
-
传统的面向对象的写法思维是,我写一个类,类里面有一个虚函数,你继承我的类,重写该虚函数
-
现代的面向对象思维是,我写一个类,类里面设置一个std::function,提供一个注册接口,你使用的时候只需要将lambda或者普通函数注册到给std::function即可
两者达到的效果是一样的,都可以实现多态的效果,但是现代的面向对象,少了继承那种叠床架屋的写法,所有的类更加平坦,灵活性也更高
五.对象语义和数据语义
类可以分为对象语义和数据语义
-
数据语义:将数据封装到类内,允许拷贝,例如string,vector都是数据语义的类
-
对象语义:不应该允许拷贝的类,比如你封装一个文件描述符,拷贝一次没有意义,这是因为文件描述符从使用上来说应该是对象语义的
对于对象语义来说,应该默认删掉拷贝运算,对于数据语义来说,可以重载相关运算符,如加减乘除