C++如何在构造函数和析构函数中调用虚拟函数

 更新时间:2023年08月02日 09:09:04   作者:lk_HIT  
这篇文章主要介绍了C++如何在构造函数和析构函数中调用虚拟函数问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

C++构造函数和析构函数中调用虚拟函数

C++构造器可以为虚拟函数吗?

不行。

因为构造器调用的时候会设置当前类的虚表地址,然后如果构造函数本身为虚拟函数,那么调用构造函数就需要提前访问虚表,此时虚表指针还没有指向虚表,就没法访问虚表。

构造函数中可以调用虚拟函数吗?

可以。

但是调用虚拟函数就是调用跟调用普通函数效果一样。

因为子类在创建的时候是先调用父类的构造器,父类的构造器先设置好父类的虚表地址,然后再执行构造器中的代码,然后在回到子类构造器,先将虚表地址替换为子类的虚表地址,然后执行子类构造器的代码。

因此如果在父类构造器中调用虚函数,那么此时是从父类的虚表中查找函数地址,查找到的还是父类的虚函数地址。因此会调用父类的虚函数,而不会调用子类的虚函数。

析构函数中可以调用虚拟函数吗?

可以。

但是调用虚拟函数跟调用普通函数没啥区别。

因为析构的时候先执行子类的析构函数,再执行父类的析构函数,在执行当前类的析构函数的时候会先将虚表地址设置为当前类的虚表地址,然后再从虚表里查找函数地址,因此找到的只能是当前的虚函数的地址。

父类的析构函数为什么要为虚函数?

因为如果父类析构函数不为虚函数,那么当对象析构的时候只会调用指针当前类型的析构函数,不会调用父类或者子类的析构函数,会导致资源泄漏。

如果父类的析构函数为虚函数,那么子类的析构函数在析构的时候会先调用子类的析构函数,再调用父类的析构函数。这样子就不会存在资源泄漏。

注:

(1)将子类和父类构造器和析构器调用串起来是编译器实现的

(2)子类和父类都有自己的虚表。子类或者父类的构造器和析构器在最开始都是将虚表设置为当前类的虚表。然后才真正调用构造函数和析构函数里的代码。

C++构造函数和析构函数的调用顺序

1、构造函数的调用顺序 

基类构造函数、对象成员构造函数、派生类本身的构造函数  

2、析构函数的调用顺序

派生类本身的析构函数、对象成员析构函数、基类析构函数(与构造顺序正好相反) 

3、特例 

  • 局部对象,在退出程序块时析构
  • 静态对象,在定义所在文件结束时析构
  • 全局对象,在程序结束时析构 
  • 继承对象,先析构派生类,再析构父类 
  • 对象成员,先析构类对象,再析构对象成员
#include "stdafx.h"
#include <iostream>
using namespace std;
class  Clock
{
public:
    Clock()
    {
        cout << "clock的构造函数" << ",";
    }
    ~Clock()
    {
        cout << "clock的析构函数" << ",";
    }
};
class Date
{
public:
    Date()
    {
        cout << "date的构造函数" << ",";
    }
    ~Date()
    {
        cout << "date的析构函数" << ",";
    }
};
void main()
{
    Clock c;
    Date d;
    system("pause");
}

在使用构造函数和析构函数时,需要特别注意对它们的调用时间和调用顺序。

在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反:最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。

可以简记为:先构造的后析构,后构造的先析构,它相当于一个栈,先进后出

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 详解C++语法中的虚继承和虚基类

    详解C++语法中的虚继承和虚基类

    本文主要介绍了C++语法中的虚继承和虚基类,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-09-09
  • 深入浅析C/C++ 的条件编译

    深入浅析C/C++ 的条件编译

    条件编译是指预处理的时候根据条件编译的指令有条件的选择源程序中的一部分代码送给编译器进行编译,进行有选择性的操作,防止宏替换的内容重复包含,这篇文章主要介绍了C/C++ 的条件编译,需要的朋友可以参考下
    2022-04-04
  • c与c++之间的相互调用及函数区别示例详解

    c与c++之间的相互调用及函数区别示例详解

    这篇文章主要为大家介绍了c与c++相互调用的使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 基于Qt实现可拖动自定义控件

    基于Qt实现可拖动自定义控件

    这篇文章主要为大家详细介绍了如何基于Qt实现可拖动自定义控件,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以了解一下
    2023-04-04
  • C++中set/multiset与map/multimap的使用详解

    C++中set/multiset与map/multimap的使用详解

    这篇文章主要为大家详细介绍了C++中set/multiset与map/multimap的使用,文中的示例代码讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2023-02-02
  • C++当初始化顺序变成未定义行为的实现

    C++当初始化顺序变成未定义行为的实现

    本文主要介绍了C++当初始化顺序变成未定义行为的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-11-11
  • C++实现五子棋游戏

    C++实现五子棋游戏

    这篇文章主要为大家详细介绍了C++实现五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • Qt GUI图形图像开发之QT表格控件QTableView详细使用方法与实例

    Qt GUI图形图像开发之QT表格控件QTableView详细使用方法与实例

    这篇文章主要介绍了Qt GUI图形图像开发之QT表格控件QTableView详细使用方法与实例,需要的朋友可以参考下
    2020-03-03
  • 深入串的模式匹配算法(普通算法和KMP算法)的详解

    深入串的模式匹配算法(普通算法和KMP算法)的详解

    本篇文章是对串的模式匹配算法(普通算法和KMP算法)的应用进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • 如何在C语言中判断socket是否已经断开

    如何在C语言中判断socket是否已经断开

    如果不主动关闭socket的话,系统不会自动关闭的,除非当前进程挂掉了,操作系统把占用的socket回收了才会关闭。小编今天跟大家简单介绍下如何在C语言中判断socket是否已经断开
    2019-05-05

最新评论