美文网首页
C++总结之多态与虚函数

C++总结之多态与虚函数

作者: bluewind1230 | 来源:发表于2018-01-30 17:24 被阅读0次

1.何为多态??多态的作用?
多态的概念:
一个接口,多种方法
多态的作用:
封装可以是得代码模块化;继承可以扩展已经存在的代码,都是为了代代码重用;
多态的目的:接口重用

2.静态联编和动态联编分别表示什么?
在编译的时候能够确定对象所调用的成员函数的地址则为静态联编;
动态联编:指的是在程序运行的时候动态地进行,根据当时的情况来确定调用哪个同名函数(父类指针指向哪个子类,就调用哪个子类的同名函数),实际上是在运行时虚函数的实现

3.类中有虚函数的时候,类有什么变化?
当类中存在虚函数的时候,这个类大小就增加4个字节,这4个字节是虚表指针,存放的是虚函数表的地址;
虚函数表其实是一个指针数组,它里面存放的其实是虚函数的地址

虚函数的几个知识点:

先看一个例子:

#include "stdafx.h"
#include <ostream>
#include <iostream>
using namespace std;

class CClassA {
public:
    virtual void fun_a() {
        cout << "fun:cclassA,这是类A里面的函数" << endl;
    }
};

class CClassB:public CClassA {
public:
    virtual void fun_a() {
        cout << "fun:cclassB,这是类B里面的函数" << endl;
    }
};

int main()
{
    CClassA objA, *pobjA;
    CClassB objB;
    pobjA = &objA;
    pobjA->fun_a();
    pobjA = &objB;//父类指针指向对象B,下面这个函数就是B里面的对象!!!
    pobjA->fun_a();
    return 0;
}


几个重点:

一个空类:一个字节
一个空类里面只有一个整型,此类大小:4个字节

  • 定义基类的公有派生类
  • 基类的公有派生类中重载该虚函数
  • 重载该虚函数不是一般的重载,它要求函数名,返回类型,参数个数,参数类型和顺序完全相同
  • 由于对虚函数进行了重载,派生类中的虚函数前的virtual关键字可以省略.
  • 父类虚表和子类虚表是2个独立的表(由于两个类之间有继承关系),故子类的虚表里面也有父类的虚函数指针,但是如果子类中有和父类中一样的函数名,那么子类中的虚函数就覆盖了子类虚表中所继承的父类虚函数地址;
  • 如果父类中有虚函数,子类中无虚函数,则子类也会生成一个虚表,(因为子类要继承父类的虚函数,但是虚函数又不能随便放,只能生成一个虚表出来!)(以上为个人理解,没有太大偏差,想要理解的更深一点,需要查看相关文献!!!)

4.纯虚函数是一种特殊的虚函数,是一种没有具体实现的虚函数

例子:
class  cclassA
{
virtual <函数类型><函数名>(<参数表>)=0;
}
  • 含有纯虚函数的类是抽象类,抽象类是不能定义对象的(不能实例化)
    含有纯虚函数的类---->抽象类------->不能定义对象!!!!!

  • 析构函数为什么要推荐设计为虚函数??
    首先,先了解一下构造函数的调用顺序:
    基类构造函数-->数据成员的构造函数->派生类构造函数
    执行派生类的析构函数,也需要调用基类以及子对象的析构函数,析构顺序如下:
    派生类析构函数-->数据成员类析构函数----->基类的析构函数
    正常情况下,一个子类被释放的时候,会主动调用其父类析构函数;使用父类指针指向子类对象的时候,只会析构掉父类对象,如果此时子类里有堆空间内存,则会造成内存泄露!(内存泄露是指使用malloc或者new申请内存空间之后,没有freeh或者delete掉,此时申请的那块内存仍然处于占用状态,称为内存泄露!)

故必须将析构函数定义为虚函数,这样释放父类指针的时候便会调用子类的析构函数,也会正常释放掉子类的堆空间!

看下面一个例子:

#include "stdafx.h"
class Base
{
public:
    Base() {
        printf("base 父类构造\n");

    };
    virtual ~Base() {                   //1th在此行加不加virtual有一定区别,而对于一般成员函数,基类中有虚函数,则子类中对应的成员函数不一定声明为虚函数,因为子类继承了父类 
        printf("Base 父类析构\n");
    };
    void fun() {                        //2th
        printf("父类base-fun\n");
    };
};
class son :public Base
{
public:
    son() {
        printf("son 子类构造\n");
    };
     ~son() {                                        //**
        printf("son 子类析构\n");
    }
    void fun() {                         //3th
        printf("子类son-fun\n");
    };
};


int main()
{
    Base *p; //父类指针

    son *pobj = new son; //走到这一步,会先调用父类构造,然后再调用子类构造,new 出子类对象指针,从堆空间中分配出来的,一般创建对象是在栈空间里面

    p = pobj;   //父类指针指向子类对象            
    p->fun();          //注意,这个例子里面函数不是虚函数,所以调用的函数皆为父类里面的函数!!!!!
    delete pobj; //通过父类指针释放子类对象

    
    return 0;
}


**处不管有没有virtual这个关键词,结果都如下:
(验证了上面所说的:如果父类中有虚函数,子类中无虚函数,则子类也会生成一个虚表)


image.png
  • 虚基类的目的是为了解决二义性问题,使用公共基类在其派生类对象中只产生一个基类子对象!!!!!

相关文章

  • 查漏补缺

    C++虚函数: 多态: 静态多态(重载)、动态多态(虚函数) 虚函数 虚函数表:编译器为每个类创建了一个虚函数表...

  • 深刻剖析之c++博客文章

    三大特性 封装、继承、多态 多态 C++ 虚函数表解析C++多态的实现原理 介绍了类的多态(虚函数和动态/迟绑定)...

  • 2020-07-06----《C++类的学习》

    函数重载:同名不同参。 C++类的特点:封装、继承、多态。 //多态与函数重载是啥关系? 虚函数:和软件架构相关 ...

  • Cpp7 C++的多态实现 -- 虚表

    Cpp7 C++的多态实现 -- 虚表 多态的实现原理 总结:1. 当我们在类中定义虚函数时,就会产生虚表2. 多...

  • GeekBand-C++面向对象高级编程(下)-Week2

    对象模型:虚函数表(vtbl)与虚表指针(vptr) 我们知道,C++中,可以通过虚函数来实现多态性,而虚函数是通...

  • C++虚函数注意事项以及构成多态的条件

    C++ 虚函数对于多态具有决定性的作用,有虚函数才能构成多态。 虚函数注意事项 只需要在虚函数的声明处加上 vir...

  • c++面试问题总结

    1.c++面试问题总结:(1)空类的大小,仅含有虚函数类的大小(2)析构函数声明为虚函数的作用(3)C++多态的实...

  • 语法

    virtual 1.virtual声明的函数实现多态就是通用的多态实现 2.纯虚函数C++的纯虚函数用于表示一个类...

  • pwnable.kr之uaf && c++虚函数

    c++的逆向还是要熟悉下。 一、关于c++虚函数 虚函数使得c++能够实现多态,每个类有一个虚表,每个对象在实现的...

  • JAVA 虚函数、抽象函数、抽象类、接口

    Java 虚函数虚函数的存在是为了多态。C++中普通成员函数加上virtual关键字就成为虚函数Java中其实没有...

网友评论

      本文标题:C++总结之多态与虚函数

      本文链接:https://www.haomeiwen.com/subject/ewsczxtx.html