C++ 在构造函数和析构函数中调用虚函数究竟会怎么样?

2023-05-16

首先摘取一段来自《Effective C++》的解释:

派生类对象构造期间进入基类的构造函数时,对象类型变成了基类类型,而不是派生类类型。 同样,进入基类析构函数时,对象也是基类类型。

再来看一段经验性的总结:

  • 从语法上讲,调用完全没有问题。
  • 但是从效果上看,往往不能达到需要的目的。

接着写段代码来探究一下究竟能否达到需要的目的,在此之前,我们先搞清楚目的是什么?

既然在子类中的构造和析构函数中都调用虚函数,那么我们肯定是希望子类中的构造和析构函数都能调用自己的虚函数版本,例如在下例中,我们的目的是:

  • A 在构造时先调用 Base 类构造函数(Base 类的构造函数中调用了虚函数),再调用 A 的构造函数(A 类的构造函数中调用了虚函数)
  • A 在析构时先调用 A 类析构函数(A 类的析构函数中调用了虚函数),再调用 Base 类的析构函数(Base 类的析构函数中调用了虚函数)

我们要探究的是:

  • Base 类的构造函数中调用 Base 版本的虚函数,A 类的构造函数中调用 A 版本的虚函数
  • A 类的析构函数中调用 A 版本的虚函数,Base 类的析构函数中调用 Base 版本的虚函数

此探究目的符合:派生类对象构造期间进入基类的构造函数时,对象类型变成了基类类型,而不是派生类类型。 同样,进入基类析构函数时,对象也是基类类型。

接下来我们写段代码验证其正确与否:

#include<iostream>
using namespace std;

class Base
{
public:
    Base()
    {
       Function();
       cout << "Base constructor" << endl; 
    }

    virtual void Function()
    {
        cout << "Base::Fuction" << endl;
    }

	virtual ~Base()
	{
		Function();
		cout << "Base destructor" << endl; 
	}
};

class A : public Base
{
public:
    A()
    {
      Function();
      cout << "A constructor" << endl; 
    }

    virtual void Function()
    {
        cout << "A::Function" << endl;
    }

	virtual ~A()
	{
		Function();
		cout << "A destructor" << endl; 
	}
};

int main()
{
    Base* a = new Base;
	delete a;

	cout << "-------------------------" <<endl;

	Base* b = new A;//语句1
	delete b;
}

以上代码输出为:

结果符合:

  • Base 类的构造函数中调用 Base 版本的虚函数,A 类的构造函数中调用 A 版本的虚函数
  • A 类的析构函数中调用 A 版本的虚函数,Base 类的析构函数中调用 Base 版本的虚函数

那么,为什么说:

  • 但是从效果上看,往往不能达到需要的目的?

因为,类设计者可能希望在基类指针指向子类对象时,通过该基类指针调用的虚函数版本应该是子类的虚函数版本。但是,很明显我们看到:

  • 在进入基类构造函数时,调用了基类版本的虚函数
  • 在进入基类虚构函数时,调用了基类版本的虚函数

这可能与预期不相符合。

毕竟,如果我们需要这样的结果的话,为什么不在一开始就把该虚函数声明为普通函数呢?这样可以达到同样的效果:

  • 将该虚函数声明为普通函数的话,同样达到了上述实验一样的效果

这便是所谓的:

  • 但是从效果上看,往往不能达到需要的目的
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 在构造函数和析构函数中调用虚函数究竟会怎么样? 的相关文章

  • 0长度数组的使用,重点掌握的知识

    0长度的数组在ISO C和C 43 43 的规格说明书中是不允许的 xff0c 但是GCC的C99支持的这种用法 GCC对0长度数组的文档参考 xff1a Arrays of Length Zero 如下代码片段 xff0c 哪个更简洁更灵
  • Freertos中检测内存的剩余函数

    static uint16 t prvTaskCheckFreeStackSpace const uint8 t pucStackByte
  • 重定位

    一 必须知道的几个概念 1 链接地址和运行地址 运行地址 xff0c 顾名思义就是程序运行的时候的地址 xff0c 也就是你用工具将代码下载到RAM的那个地址 xff0c 也叫加载地址 链接地址 xff0c 由链接脚本指定的地址 为什么需要
  • CC2541低功耗的实现方法

    转自 xff1a http blog csdn net mzy202 article details 42091537 CC2541 CC2540 实现超低功耗是非常重要的 xff1a 我们来总结一下实现方法 xff1a 1 xff0c 有
  • Macbook pro/air 2013 late -2014 使用转接卡更换NVME SSD休眠不醒问题的解决办法

    2021年1月更新 xff0c 发现升级 big sur 11 1之后 xff0c 固件版本变成了429 0 0 0 睡眠问题又回来了 xff0c 每次都睡死 xff0c 不醒 于是我按老办法 xff0c 把mbp114的nvme驱动刷到m
  • stm32使用stlink v2.0下载的sw接线方式

    stm32的sw下载需要用到4根线 GND VCC SWCLK SWDIO xff0c 对应好即可 xff0c 相比较3根线的方式 xff0c 优先推荐4根线下载方式
  • stm32芯片的焊接

    stm32的焊接 xff0c 使用到东西 xff1a 松香 xff0c 维修佬 xff0c 烙铁 1 首先将stm32的一个角的脚上涂上维修佬 xff0c 要特别特别少 xff0c 太多了 xff0c 容易粘连到其他脚上面 xff0c 不好
  • Modbus-RTU通讯协议中CRC校验码的计算步骤

    在CRC计算时只用8个数据位 xff0c 起始位及停止位 xff0c 如有奇偶校验位也包括奇偶校验位 xff0c 都不参与CRC计算 CRC计算方法是 xff1a 1 预置1个16位的寄存器为十六进制FFFF xff08 全1 xff09
  • 一个很好的makefile例子(经典)

    转自http www cnblogs com sld666666 archive 2010 04 08 1707789 html 相信在unix下编程的没有不知道makefile的 xff0c 刚开始学习unix平台 下的东西 xff0c
  • 无线传输距离计算公式

    转自一篇文档 无线传输距离计算 Pr dBm 61 Pt dBm Ct dB 43 Gt dB FL dB 43 Gr dB Cr dB Pr xff1a 接受端灵敏度 Pt 发送端功率 Cr 接收端接头和电缆损耗 Ct 发送端接头和电缆损
  • hex文件解析

    Keil开发环境编程时对源程序进行编译链接后都 可以 成一个可执行文件即 hex文件 xff0c 但是有不完全是一个可执行文件 然后 可以 通过烧录工具烧写到对应的单片机的 flash中 xff0c 当然也还有其他方法可以进行烧录 大家在编
  • Ubuntu下如何挂载以及卸载U盘?

    l 在挂载U盘前 xff0c 首先运行命令cat proc partitions xff0c 看看现在系统中有哪些分区 插上u盘以后 xff0c 再次运行上述命令 xff0c 看看多出来什么分区 xff08 通常是sda1 xff0c 由于
  • 链接脚本文件的写法

    对于 lds文件 xff0c 它定义了整个程序编译之后的连接过程 xff0c 决定了一个可执行程序的各个段的存储位置 虽然现在我还没怎么用它 xff0c 但感觉还是挺重要的 xff0c 有必要了解一下 先看一下GNU官方网站上对 lds文件
  • Ubuntu18.04+思岚激光雷达A2M7+ROS测试

    Ubuntu18 04 43 思岚激光雷达A2M7 43 ROS测试 1 测试环境搭建 测试环境 xff1a Ubuntu18 04 43 ROS Melodic测试工具 xff1a 思岚科技激光雷达A2M7 43 USB转接工具 2 下载
  • ROS系统的串口数据读取和解析

    原帖地址 xff1a https blog csdn net Tansir94 article details 81357612 一 Ubuntu下的串口助手cutecom 下载 xff1a sudo apt get install cut
  • tcp buffer设置

    本文基于CENTOS DEBIAN UBUNTU 编写 我有两台位于不同数据中心的服务器 xff0c 都用来处理很多并行的大文件传输 但是处理大文件 xff0c 网络性能非常差 并且涉及到一个大文件 xff0c 会导致性能降级 我怎样通过调
  • URL模块之parse方法

    url parse urlString boolean boolean parse这个方法可以将一个url的字符串解析并返回一个url的对象 参数 xff1a urlString指传入一个url地址的字符串 第二个参数 xff08 可省 x
  • Makefile 知识点记录

    Makefile 知识点记录 1 依赖类型 xff1a normal Prerequisites xff0c order only prerequisites normal Prerequisites xff1a 标准依赖具有两层含义的声明
  • 视频矩阵系统中三代OSD字符叠加技术全面解析

    视频矩阵系统中三代OSD字符叠加技术全面解析 屏显信息更丰富 中文效果更出色 使用设置更灵活 视频矩阵系统中三代OSD字符叠加技术全面解析 前言 xff1a 在以矩阵为控制中枢的视频监控系统中 xff0c 大量的视频信号需要在数目有限的监视
  • CV_...报错

    在出错的程序里面添加相应的头文件即可 1 CV LOAD IMAGE COLOR was not declared in this scope include 34 opencv2 imgcodecs legacy constants c

随机推荐