一、虚函数

只有用virtual声明类的成员函数,使之成为虚函数,不能将类外的普通函数声明为虚函数。因为虚函数的作用是允许在派生类中对基类的虚函数重新定义。所以虚函数只能用于类的继承层次结构中。

一个成员函数被声明为虚函数后,在同一类族中的类就不能再定义一个非virtual的但与该虚函数具有相同的参数(包括个数和类型)和函数返回值类型的同名函数。

根据什么考虑是否把一个成员函数声明为虚函数?

①  看成员函数所在的类是否会作为基类

② 看成员函数在类的继承后有无可能被更改功能,如果希望更改其功能的,一般应该将它声明为虚函数。

如果成员函数在类被继承后功能不需修改,或派生类用不到该函数,则不要把它声明为虚函数。不要仅仅考虑到作为基类而把类中的所有成员函数都声明为虚函数。

应考虑对成员函数的调用是通过对象名还是通过基类指针或引用去访问,如果是通过基类指针或引用去访问的,则应当声明为虚函数。有时在定义虚函数时,并不定义其函数体,即纯虚函数。它的作用只是定义了一个虚函数名,具体功能留给派生类去添加。

说明:使用虚函数,系统要有一定的空间开销。当一个类带有虚函数时,编译系统会为该类构造一个虚函数表(vtbl),它是一个指针数组,存放每个虚函数的入口地址。系统在进行动态关联的时间开销很少,提高了多态性的效率。

二、纯虚函数

有时候,基类中的虚函数是为了派生类中的使用而声明定义的,其在基类中没有任何意义。此类函数我们叫做纯虚函数,不需要写成空函数的形式,只需要声明成:

virtual 函数类型 函数名(形参表列)=0;

注意:纯虚函数没有函数体;

最后面的“=0“并不代表函数返回值为0,只是形式上的作用,告诉编译系统”这是纯虚函数”;

这是一个声明语句,最后应有分号。

纯虚函数只有函数的名字但不具备函数的功能,不能被调用。在派生类中对此函数提供定义后,才能具备函数的功能,可以被调用。

三、虚析构函数

析构函数的作用是在对象撤销之前把类的对象从内存中撤销。通常系统只会执行基类的析构函数,不执行派生类的析构函数。

只需要把基类的析构函数声明为虚函数,即虚析构函数,这样当撤销基类对象的同时也撤销派生类的对象,这个过程是动态关联完成的。

如果将基类的析构函数声明为虚函数时,由该基类所派生的所有派生类的析构函数都自动成为虚函数,即使派生类的析构函数与基类的析构函数名字不相同。

最好把基类的析构函数声明为虚函数,这将使所有派生类的析构函数自动成为虚函数,如果程序中显式delete运算符删除一个对象,而操作对象用了指向派生类对象的基类指针,系统会调用相应类的析构函数。

构造函数不能声明为虚函数。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
usingnamespace std;
classAnimal
{
public:
    Animal()
    {
        cout <<"Animal::Animal() is called" << endl;
    };
    virtual~Animal()
    {
        cout <<"Animal::~Animal() is called" << endl;
    }
    virtualvoid eat()
     {
        cout <<"Animal::eat() is called" << endl;
     }
    virtualvoid walk()
    {
        cout <<"Animal::walk() is called" << endl;
    }
    /* data */
};
classDog : publicAnimal
{
public:
    Dog(intw,int h)
    {
        cout <<"Dog::Dog() is called" << endl;
        this->weight=w;
        this->height=h;
    }
    virtual~Dog()
    {
        cout <<"Dog::~Dog() is called" << endl;
    }
    intweight;
    intheight;
    voideat()
    {
        cout<<"i eat meat"<<endl;
    }
    voidwalk()
    {
        cout<<"run"<<endl;
    }
    /* data */
};
 intmain(int argc, char const *argv[])
{
    /* code */
    Animal *ani=new Dog(12,23);
    Dog *dog=newDog(23,34);
    ani->eat();
    ani->walk();
    dog->eat();
    dog->walk();
    deleteani;
    //delete dog;
    return0;
}

 (C++ 析构函数一般定义为虚函数)如果基类中析构函数没有定义为虚函数,则delete ani的时候,仅仅调用了父类的析构函数,子类的没有调用,如果在父类和子类的构造函数中都有动态内存分配,那么就会存在内存泄漏的问题。一般析构函数最好都写成虚函数,尤其是父类。 

本文有参考:http://blog.csdn.net/lxnkobe/article/details/23115417

http://blog.csdn.net/richerg85/article/details/9217875

“I find that the harder i work,the more luck i seem to have!”

虚函数、纯虚函数、虚函数与析构函数相关推荐

  1. 初入c++(六)虚函数实现多态,虚析构函数,虚函数表和多态实现机制,纯虚函数。

    1.c++多态的概念以及用途. 1.1虚函数实现多态 通过基类指针只能够访问派生类的成员变量,不能够访问派生类的成员函数. 解决问题的办法:使用虚函数(virtual function),只需要在函数 ...

  2. c++ 虚函数多态、纯虚函数、虚函数表指针、虚基类表指针详解

    文章目录 静态多态.动态多态 虚函数 哪些函数类型不可以被定义成虚函数? 虚函数的访问方式 析构函数中的虚函数 虚函数表指针 vptr 多继承下的虚函数表 虚基类表指针 bptr 纯虚函数 抽象类 虚 ...

  3. cnbloger: 北岛知寒, C++ - 虚基类、虚函数与纯虚函数; csdner: Hsuxu, C++虚基类的实现机制

    If the author of the article is not allowed to reprint, this article will be deleted C++ - 虚基类.虚函数与纯 ...

  4. 面试中常被问到(11)虚函数/纯虚函数

    虚函数 如何定义一个虚函数?在基类成员函数前加入virtual关键字,但并不代表此函数不被实现,只是说明允许基类指针调用派生类重写的此函数 一个类只要声明有虚函数或者从基类继承了虚函数,在编译过程中就 ...

  5. C++:多态与虚函数,纯虚函数

    1.多态的机制与虚函数的机制 1.1 多态的机制 1.当在类中使用virtual声明一个函数为虚函数时,在编译时,编译器会自动在基类中默默地安插一个虚函数表指针,同时的.rodata段为这类生成一张虚 ...

  6. 虚函数 纯虚函数 虚基类说明

    原文:http://www.cnblogs.com/ms-frank/archive/2008/01/16/1041310.html 虚基类 在说明其作用前先看一段代码 [cpp] view plai ...

  7. 什么是纯虚函数 纯虚函数的作用 如何定义使用纯虚函数

    什么是纯虚函数 纯虚函数的作用 如何定义使用纯虚函数   一 定义: 纯虚函数是一种特殊的虚函数,它的一般格式如下:  class <类名>  {  virtual <类型>& ...

  8. C++: 虚函数 / 纯虚函数

    虚函数 ● 虚函数是指在基类内部声明的成员函数前添加关键字 virtual 指明的函数 ● 虚函数存在的意义是为了实现多态,让派生类能够重写(override)其基类的成员函数 ● 派生类重写基类的虚 ...

  9. 38.【C++ 虚函数 纯虚函数 虚基类 (最全详解)】

    虚函数.虚基类.纯虚函数 (一).虚函数 1.什么是虚函数: 2.虚函数的格式: 3.关于虚函数的注意事项: 4.虚函数的作用: 5.虚函数访问格式 6.虚函数的各种疑难杂症 [当指针是基类.但虚函数 ...

  10. C/C++基础语法复习(三):C++重载函数,多态,虚函数

    1.重载运算符和重载函数: C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载. 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它 ...

最新文章

  1. 《OpenCV3编程入门》学习笔记8 图像轮廓与图像分割修复(一)查找并绘制轮廓
  2. JVM 生态系统 2018 调查报道
  3. Hive的HQL(2)
  4. 清华校长送给毕业生的五句话,值得一看!
  5. 微服务下分布式事务模式的详细对比
  6. 51NOD 1594:Gcd and Phi——题解
  7. mysql怎么创建文字表_myMySQL数据库 如何将中文转拼音 MySQL数据库使用教程
  8. CSP2020洛谷P7077:函数调用
  9. 计算机本地磁盘D无法扩展,计算机上的本地磁盘D突然无法打开,表明它需要格式化...
  10. 对计算器软件的测试报告,Win7计算器软件测试报告.doc
  11. iview 后台管理系统 搭建
  12. IIS和Asp.Net页面运行机制
  13. Android Wear Hello World
  14. shell脚本if语句的多种条件参数
  15. 用c语言打印乘法口诀表
  16. 手机软件设计大赛报名信息
  17. 2022最新仿绚丽彩虹音乐播放器完整源码
  18. PC端工具 WP7 PC端截图工具WP7 Screen recorder 发布 附使用教程
  19. stable-baselines3学习之Logger
  20. [看门狗]基于Linux的嵌入式系统全程喂狗策略

热门文章

  1. android 剩余内存,Android:如何检查剩余的内存量?
  2. 办公室计算机网络使用情况,企事业单位办公网络的现状及解决方案.doc
  3. python服务器搭建nginx_Nginx简单快速搭建文件服务器
  4. c语言从串口获取数据,如何通过串口来读写数据,请教达人
  5. mysql 批量drop_MySql批量drop table
  6. HAAR、LBP分类器训练
  7. 【Linux】2.Linux source命令
  8. 信息检索的评价指标(Precision, Recall, F-score, MAP)
  9. Apache kafka 工作原理介绍
  10. 对map集合进行排序