条款5 了解c++默默编写并调用哪些函数

编译器自动生成的copy 构造函数,copy赋值操作符,析构函数,构造函数,这些都是public和inline的,此处inline的意思是他们的定义都是在头文件当中的

假设有一个引用类型的数据成员,那么上面的赋值操作是不对的,因为引用不能改变

条款6 如不想使用编译器自动生成的函数,就该明确拒绝

上面的赋值构造函数,赋值操作符都可以有编译器自动生成,为了拒绝使用上面两种函数,可以创建一个将这种函数定义私用成员的类,从而不会使用这些函数

  1. class Uncopyable {
  2. protected:
  3. Uncopyable(){}
  4. ~Uncopyable(){}
  5. private:
  6. Uncopyable(const Uncopyable&);
  7. Uncopyable& operator=(const Uncopyable&);
  8. }
  9.  
  10. class myclass: private Uncopyable{
  11.  
  12. };

条款7 为多态基类声明virtual 析构函数

声明为virtual

应该经析构函数声明为virtual,从而在多态调用时可以层层将各个类层次的资源析构干净,防止内存的泄露等问题

在某些类里声明纯虚析构函数很方便。纯虚函数将产生抽象类——不能实例化的类(即不能创建此类型的对象)。有些时候,你想使一个类成为抽象类, 但刚好又没有任何纯虚函数。怎么办?因为抽象类是准备被用做基类的,基类必须要有一个虚析构函数,纯虚函数会产生抽象类,所以方法很简单: 在想要成为抽象类的类里声明一个纯虚析构函数。

这里是一个例子:

  1. class awov {
  2. public:
  3. virtual ~awov() = 0; // 声明一个纯虚析构函数
  4. };

这个类有一个纯虚函数,所以它是抽象的,而且它有一个虚析构函数,所以不会产生析构函数问题。但这里还有一件事:必须提供纯虚析构函数的定义:

awov::~awov() {} // 纯虚析构函数的定义

这个定义是必需的,因为虚析构函数工作的方式是:最底层的派生类的析构函数最先被调用,然后各个基类的析构函数被调用。 这就是说,即使是抽象类,编译器也要产生对~awov的调用,所以要保证为它提供函数体。如果不这么做,链接器就会检测出来,从而在程序的运行时刻报错

没有必要声明为virtual

有时是没有必要声明为virtual的,因为使用多态的缺点会生成v-table,从而增加编译的复杂度,同时是程序变大,变大的程序在一些内存比较紧缺的嵌入式设备上无法加载进入内存。

有下面几种情况没有必要声明为virtual

一、所有方法为static,则不会存在类的概念,从而已不存在析构的问题

二、虽然使用继承,但是实现为多态的方式,也就是不会通过基类的引用指向继承类(指向继承类时的析构函数调用关系为,首先调用继承类,再去调用base类;构造函数相反)。也就是,此时只能是使用基类的引用指向基类,派生类的引用指向派生类。

上述两种情况都不需要在析构函数上加virtual关键字。

条款9:决不在构造析构过程中调用virtual函数

在构造函数中虚函数都不是虚函数,因此在使用多态是就会出现问题,假设首先对

条款10 为了实现连锁赋值,赋值操作符必须返回一个引用,指向操作符左侧的实参

  1. widget& operator=(const Widget& rhs){
  2. ......
  3. return *this;
  4. }

条款12:赋值对象时勿忘其每一部分 当编写一个copying函数时,应该做到两点:

(1)赋值所有的local变量成员

(2)调用所有base class的copying函数

因为要对一个对象进行赋值,同时也要赋值他的父类中的成员对象,但是这些成员对象有时是private的无法直接访问,这是就需要通过父类的copying函数来进行 例如:

  1. //base class
  2. class class1{
  3. public:
  4. class1(const class1& c);
  5. class1& operator=(const class1&);
  6. private:
  7. int p;
  8. };
  9. class1::class1(const class1& c1){
  10. this->p=c1.p;
  11. }
  12.  
  13. class1& class1::operator=(const class1& c1){
  14. p=c1.p;
  15. return *this;
  16. }
  17. //derived class
  18. class class2:public class1{
  19. public:
  20. class2(const class2&);
  21. class2& operator=(const class2&);
  22. private:
  23. int pp;
  24. };
  25.  
  26. class2::class2(const class2& c2):class1(c2),pp(c2.pp){
  27. }
  28.  
  29. class2& class2::operator=(const class2* c2){
  30. class1::operator=(c2);
  31. pp=c2.pp;
  32. return *this;
  33. }

Effective C++ 随笔(2)的更多相关文章

  1. Effective C++ 随笔(5)

    条款27:尽量稍作转型动作 const_cast:常量性移除 dynamic_cast:安全向下转型 reinterpret_cast: static_cast: 如在子类当中享调用父类当中的某个方法 ...

  2. Effective C++ 随笔(4)

    条款21:必须返回对象时,别妄想返回其reference 例子: Raional类可以执行有理数的一些运算,并且使用heap内存申请 并且其operator*函数为 const Rational&am ...

  3. Effective C++ 随笔(3)

    条款12: 以对象管理资源 两种只能指针: std:auto_ptr<> 当使用copy操作室,原先的智能指针指向为null std:tr1:share_ptr<int> sp ...

  4. Effective C++ 随笔(1)

    条款一 c++ 为一个语言联邦 1.四个层次 C:blocks,语句,预处理器,内置数据类型,数组,指针 面向对象的C++:封装,多态,继承 Template C++ STL 条款二 尽量以const ...

  5. Effective Modern C++翻译(1):序言

    /*********************************************************** 关于书: 书是我从网上找到的effective Modern C++的样章,内 ...

  6. 小王子浅读Effective javascript(一)了解javascript版本

    哈哈,各位园友新年快乐!愚安好久没在园子里写东西了,这次决定针对javascript做一个系列,叫做<小王子浅读Effective javascript>,主要是按照David Herma ...

  7. Linux随笔-鸟哥Linux基础篇学习总结(全)

    Linux随笔-鸟哥Linux基础篇学习总结(全) 修改Linux系统语系:LANG-en_US,如果我们想让系统默认的语系变成英文的话我们可以修改系统配置文件:/etc/sysconfig/i18n ...

  8. AI人工智能系列随笔

    初探 AI人工智能系列随笔:syntaxnet 初探(1)

  9. 【置顶】CoreCLR系列随笔

    CoreCLR配置系列 在Windows上编译和调试CoreCLR GC探索系列 C++随笔:.NET CoreCLR之GC探索(1) C++随笔:.NET CoreCLR之GC探索(2) C++随笔 ...

随机推荐

  1. java遍历当前会话所有Session

    //方法一:通过遍历的方法进行遍历 String FileName=""; HttpSession session=request.getSession();//获取session ...

  2. ThreadExecutorPool 线程池组件

    ThreadExecutorPool是使用最多的线程池组件: Executor是用来执行提交的Runnable任务的对象,并以接口的形式定义,提供一种提交任务(submission task)与执行任 ...

  3. Oracle_高级功能(10) 备份恢复

    备份与恢复Oracle数据库有三种标准的备份方法,分别是导出/导入(EXP/IMP).热备份和冷备份.导出/导入是一种逻辑备份,冷备份和热备份是物理备份.一.导出/导入(Export/Import)利 ...

  4. PHP 语句 函数 字符串处理

    语句: 一:分支语句 1.if(条件1){满足条件1执行} 2.if(条件1){满足条件1执行}else{不满足条件1执行} 3.if(条件1){满足条件1执行}else if(条件2){满足条件2执 ...

  5. linux RCU锁机制分析

    openVswitch(OVS)源代码之linux RCU锁机制分析 分类: linux内核  |  标签: 云计算,openVswitch,linux内核,RCU锁机制  |  作者: yuzhih ...

  6. JSP脚本元素(声明 %! 表达式 %= 脚本 %)

    JSP脚本元素包括声明.表达式.脚本 声明(declaration):用于在JSP页面中声明合法的变量和方法.以“<%!”开始,以“%>”结束. 在JSP页面中,一个声明可以出现在任何地方 ...

  7. Tomcat的下载、安装、启动与关闭

    ubuntu server 16.04 从官网下载 Binary Distributions 版本的相应的压缩包, https://tomcat.apache.org/download-90.cgi ...

  8. Python之路(第二十六篇) 面向对象进阶:内置方法

    一.__getattribute__ object.__getattribute__(self, name) 无条件被调用,通过实例访问属性.如果class中定义了__getattr__(),则__g ...

  9. Python之路(第六篇)Python全局变量与局部变量、函数多层嵌套、函数递归

    一.局部变量与全局变量 1.在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量.全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序. 全局变量没有任何缩进,在任何位置都可 ...

  10. vue中常用的指令

    1. v-textv-text主要用来更新textContent,可以等同于JS的text属性. <span v-text="msg"></span> 2. ...