Effective C++学习第三天

1:为多态基类声明virtual析构函数

       当我们创建一个base class指针指向新生成的derived class时,当删除基类指针时,如果base class是一个non-virtual析构函数时,实际执行的结果通常是derived class中的base成分被销毁,derived成分没有被销毁;

      通常解决这种问题的方法是把base class中的析构函数声明为virtual;

      并不是只有析构函数可以声明为virtual,其他的函数也可以,virtual函数的目的是为了让derived class客制化,也就是实现动态联编;

     任何class中只要带有virtual函数都需要提供一个virtual析构函数;

    想要实现虚函数,对象必须提供某些信息,来决定运行期决定那个virtual函数被调用,通常这个信息有vptr(virtual table pointer)来表示,vptr指向一个函数指针构成的数组,称为vtbl(virtual table),每一个带有virtual函数的class都有一个对应的vtbl,对象调用virtual函数的时候,实际上调用的是vptr指向的vtbl;

     一般来说,如果不想把base class用于继承,一般不要定义virtual函数,毕竟vptr指针会占内存的;不要试图去继承一个不带虚析构函数的类,这样会出问题的;

     抽象类(不能被实体化的类,不能用这种类来创建对象):类中带一个pure virtual析构函数,通常作为base classes;由于析构的顺序和初始化的顺序相反,因此在声明纯虚析构函数时,需要给虚析构函数提供一份定义,这样编译器在derived class的析构函数创建一个对base class析构函数的调用动作,即使在base class中未发生析构,代码如下:

 class AMOV{

public:

         virtual ~AMOV() =0;//pure virtual析构函数

};

AMOV::~AMOV() { }

    结论:polymorphic(带多态性质的)base classes应该声明一个virtual析构函数,如果class带有任何的virtual函数,那么应该有一个virtual析构函数;

             classes的设计目的如果不是作为base classes使用,或不是为了多态性就不应该声明virtual析构函数;

2:别让异常逃离析构函数

        在两个异常同时存在的情况下,程序若不结束执行就会导致不明确的行为;

class dbconnection{                                                         class dbconn{//管理对吧connection对象

public:                                                                               public:

          static dbconnction create();//创建对象                           ~dbconn()  {      db.close() ;   }//关闭数据库连接

          void close();//关闭系统                                               private:  dbconnection db;

};                                                                                       };

 问题:如果close()调用失败,就会产生异常,而析构函数中没有处理异常的机制,异常在析构函数向上抛出;

解决方案:在析构函数中建立异常处理机制或者直接吞掉异常(如果在吞掉异常后,程序依旧可以可靠的运行);                    ~dbcnn(){

               try {db.close();}

               catch(...){//捕获异常

                           std::abort() ;//终止程序              //方案1需要这一句        //方案2不需要

                          }

}

另外一种比较好的方法就是:重新设计dbconn接口,设置一个普通函数让用户判断是否会产生异常,

class dbcnn{

public:

 void close(){

             db.close();

             closed=true;

             } 

~dbcnn() {

if(!closed){

        try{

                db.close();

         }

         catch(...){

        }

    }

  }

private:

            dbconnection db;

            bool closed;

};

3:不要在构造和析构函数中调用virtual函数

          对于构造函数而言,不能在构造过程中调用virtual函数的原因:base class在构造过程中,virtual函数不会下降到derived class,因为在base class构造函数执行时derived class的成员还没有初始化,如果此时virtual函数下降到derived class中,势必会调用未初始化的变量,而C++不允许这一现象发生,在base class构造期间,virtual函数不再是virtual函数;更本质的原因是在derived class对象的base class构造期间,对象是base class而不是derived class,不只是virtual函数会被编译器解析为base class,若使用运行期类型信息(如dynamic_cast和typeid),也会把对象视为base class类型,因此对象在derived class构造函数开始执行前不会成为一个derived class对象;

         对于析构函数也是同样的道理(构造和析构的顺序相反):一旦derived class析构函数开始执行,对象内的derived class成员变量便呈现出未定义状态(因为被析构了),进入base class析构函数后对象变成一个base class对象;

        为了防止传值过程中出现意外指向未初始化的成员变量,可以充分利用static关键字;

4:令operator=返回一个reference to*this

      为了使操作符实现连锁操作,操作符必须返回一个reference指向操作符的左侧实参;


     

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/382395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux创建指定大小的文件

一、生成文件大小和实际占空间大小一样的文件 dd if/dev/zero ofname.file bs1M count1 文件名称name.file bs1M表示每一次读写1M数据,count50表示读写 50次,这样就指定了生成文件的大小为50M。 二、生成文件大小固定,但实际不占空间命令 …

Effective C++学习第四天

条款11:在operator中处理自我赋值的现象虽然我们在平时可能不会出现显示自我赋值的现象,当加入指针或者引用时,可能会出现不同的指针或引用指向同一对象(对象的不同别名),这时候我们就得考虑对象是否是同一…

Effective C++学习第五天

条款14:在资源管理类中小心copy行为当我们深入理解“资源取得时机是初始化时机(RAII)”概念,并以此作为“资源管理类”的核心时,我们可能会遇到将RAII对象复制的情况,一般有两种情况处理这个现象&#xff1…

Redis运维和开发学习笔记(2) redis持久化

Redis运维和开发学习笔记(2) redis持久化 文章目录Redis运维和开发学习笔记(2) redis持久化持久化持久化方式一:RDB触发~~的三种~~方式1. save命令2. bgsave配置触发机制RDB 总结持久化方式二:AOFAOF的三种策略三种策略的优缺点AOF重写机制持久化 redis将所有数据保存在内存中&…

Effective C++学习第六天

条款18:让接口更容易被正确使用,不易被误用设计接口的原则:正确性、高效性、封装性、维护性、延展性以及协议的一致性;设计原则:1)导入新类型来预防很多客户端的错误,多使用系统类型&#xff08…

Redis运维和开发学习笔记(4) Redis参数意义

Redis运维和开发学习笔记(4) Redis参数意义 文章目录Redis运维和开发学习笔记(4) Redis参数意义参数意义参数意义 Client连接 问题 id567800790 addr10.18.17.217:37310 fd1572 name age2039114 idle2034860 flagsN db0 sub0 psub0 multi-1 qbuf0 qbuf-free0 obl0 oll0 omem0 …

Effective C++学习第七天

条款23:宁以non-memeber、non-friend替换member函数non-member/non-friend可以给对象带来更大的封装性,从两个方面来考虑:1)考虑封装,越多东西被封装,它们就越不可见,就越少人看到它&#xff0c…

Redis运维和开发学习笔记(5) 主从复制和sentinel哨兵模式

Redis运维和开发学习笔记(5) 主从复制和sentinel哨兵模式 主从复制 将主节点的数据改变同步给从节点 作用 备份数据读写分离 存在的问题: 手动干预切主等操作主节点的写能力受到单机限制主节点的存储能力受到单机限制 主从模式的故障恢复 当主节点发生故障时&am…

Effective C++学习第八天

条款26:尽可能延后变量定义式的出现时间当你定义了一个变量,如果在使用变量之前出现异常,那么你得承受一次构造成本和析构成本,而且你没有使用该变量;本条款给出的建议是延迟变量的定义,直到非得使用该变量…

Redis运维和开发学习笔记(6) 监控Redis工作状态-info命令

Redis运维和开发学习笔记(6) 监控Redis工作状态-info命令 文章目录Redis运维和开发学习笔记(6) 监控Redis工作状态-info命令info serverinfo clientinfo memoryinfo persistenceinfo statsinfo commandstatsinfo cpuinfo clusterinfo keyspaceinfo server Redis服务器相关的通用…

Effective C++学习第九天

条款32:确定你的public继承塑模出is-a模型class D(derived)以public形式继承class B(base),则每一个类型为D的对象同时也是一个类型为B的对象,反之不成立,因此B比D表现出更加一般化的…

Effective C++学习第十天

条款36:绝不重新定义继承而来的non-virtual函数non-virtual函数执行的是静态绑定,在编译器就已经决定,因此对象对用的函数只和指针的类型有关,而与指针所指的对象无关;记住non-virtual函数的性质:不变性凌驾…

Redis运维和开发学习笔记(7) 内存管理和过期策略

Redis运维和开发学习笔记(7) 内存管理和过期策略 文章目录Redis运维和开发学习笔记(7) 内存管理和过期策略内存回收策略惰性删除定时任务删除maxmemory过期策略allkeys-lru主从搭建测试搭建完毕主从测试结果volatile-lru测试结果volatile-ttl测试结果allkeys-lru内存回收策略 …

Effective C++学习第十一天

条款41:了解隐式接口和编译期多态面向对象编程世界总是以显式接口(源码可见的接口)和运行期多态(virtual)解决问题;对于templates及泛型编程的世界,隐式接口和编译期多态显得更加重要&#xff1…

Redis源码分析(零)学习路径笔记

文章目录第一阶段第二阶段 熟悉Redis的内存编码结构第三阶段 熟悉Redis数据类型的实现第四阶段 熟悉Redis数据库的实现第五阶段 熟悉客户端和服务器端的代码实现第六阶段 这一阶段主要是熟悉Redis多机部分的代码实现关于测试方面的文件有一些工具类的文件如下SORT命令的实现一些…

Effective C++学习第十二天

条款47:请使用traits classes表现类型信息STL有五类迭代器分类,input迭代器(只读,一次,向前)、output迭代器(可写,一次,向前)、forward迭代器(读/…

Redis源码分析(一)redis.c //redis-server.c

Redis源码分析(一)redis.c //redis-server.c 入口函数 int main() 4450 int main(int argc, char **argv) {4451 initServerConfig();4452 if (argc 2) {4453 ResetServerSaveParams();4454 loadServerConfig(argv[1]);4455 …

Linux 学习

1.linux文本命令行语言环境设置命令 查看当前语言环境: echo ¥LANG 修改: LANG选择的语言环境’ 引申:https://blog.csdn.net/huoyunshen88/article/details/41113633 2.linux中的硬链接和软连接 linux中文件的储存方式&#xf…

vivo C/C++工程师视频面试总结 20180802

1.自我介绍:有点儿紧张了,直接把自己简历上的一些信息信息说了一遍,说完之后在介绍了一下自己的平时的爱好和兴趣,感觉面试官没有理我,直接进入下一环节了。 2.项目详情:主要是自己最近的一个项目和自己负…

Redis源码分析(二)redis-cli.c

文章目录1. int main()2. parseOptions(int argc, char **argv) 进行ip和port的改变3. lookupCommand(char *name) 查找命令,判断命令合法3.2 strcasecmp(name,cmdTable[j].name)3.1 redisCommand cmdTable[]4. cliSendCommand(int argc, char **argv)4.1 cliConnec…