c++ 虚函数常见问题

1 虚函数,虚表基础

虚函数,虚表基础

2 虚函数表保存在哪里 ?

虚函数表在编译的时候确定。在 linux 下,保存在只读数据段的重定位段,这个段的名字是 .data.rel.ro。

如下代码,编译之后,使用 readelf -t a.out 可以查看看到这一段的大小是 0x68,如果从代码中删除一个虚函数,比如把函数 Do2() 不用 virtual 修饰,可以看到这个段的大小减小了 16。由此,可以验证虚函数表保存在了 .data.rel.ro。

#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdio.h>

class Base {
public:
  Base() {
  }

  ~Base() {
  }

  virtual void Do1(int d) {
    std::cout << d << std::endl;
  }

  virtual void Do2(int d) {
    std::cout << d << std::endl;
  }
};

class Derived : public  Base {
public:
  Derived() {
  }

  ~Derived() {
  }

  virtual void Do1(int d) {
    std::cout << d << std::endl;
  }

  virtual void Do2(int d) {
    std::cout << d << std::endl;
  }
};


int main() {
  Base *b = new Derived();
  b->Do1(1);
  b->Do2(2);
  delete b;
  return 0;
}

将 Base() 和 Derived() 中的函数 Do2() 不用 virtual 修饰,可以看到 .data.rel.ro 的大小减小了 16。

3 基类构造函数和析构函数中调用的虚函数是基类的还是派生类的 ?

基类构造函数和析构函数中调用的虚函数是基类的还是派生类的 ?

3 哪些函数不能声明为虚函数 ?

3.1 构造函数

构造函数声明为虚函数,编译错误如下。

访问虚函数首先要通过对象的地址找到虚函数表的地址,然后找到对应的虚函数来执行。也就是说虚函数的调用依赖于对象。而调用构造函数的时候,这个对象还不存在,所以构造函数不能声明为虚函数。

3.2 静态函数

静态函数声明为虚函数,编译错误如下。

与构造函数类似,静态函数中也没有 this 指针,所以静态函数不能声明为虚函数。

3.3 函数模板

函数模板不能声明为虚函数。编译报错如下。虚函数表需要在类定义的时候就要确定,对于函数模板来说,类定义的时候,这个函数有多少实例是不确定的,所以函数模板不能定义为虚函数。

#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdio.h>

class Base {
public:
  Base() {
  }

  ~Base() {
  }

  template <class T>
  virtual void Do1(T d) {
    std::cout << d << std::endl;
  }

  void Do2(int d) {
    std::cout << d << std::endl;
  }
};

int main() {
  Base *b = new Base();
  b->Do1(1);
  b->Do2(2);
  delete b;
  return 0;
}

函数模板不能声明为虚函数。但是类模板中的函数可以声明为虚函数,因为对于类模板来说,在定义一个实例的时候,这个类的定义就是确定的,虚函数表的大小也是确定的。

#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdio.h>

template <class T>
class Base {
public:
  Base() {
  }

  ~Base() {
  }

  virtual void Do1(T d) {
    std::cout << d << std::endl;
  }

  void Do2(int d) {
    std::cout << d << std::endl;
  }
};

int main() {
  Base<int> *b = new Base<int>();
  b->Do1(1);
  b->Do2(2);
  delete b;
  return 0;
}

4 inline 函数可以声明为虚虚函数

如下代码,Base 是基类,其中有一个 inline 虚函数 Do1()。Derived1 和 Derived2 是 Base 的派生类。分别创建 Base、Derived1、Derived2 的一个对象,然后通过指针调用函数 Do1()。代码编译没有问题,运行也没有问题。

#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdio.h>

class Base {
public:
  virtual ~Base() {
  }

  virtual inline void Do1(int d) {
    std::cout << d << std::endl;
  }
};

class Derived1 : public Base{
public:
  virtual inline void Do1(int d) {
    std::cout << d << std::endl;
  }
};

class Derived2 : public Base{
public:
  virtual inline void Do1(int d) {
    std::cout << d << std::endl;
  }
};

void Do(Base *b, int data) {
  b->Do1(data);
}

int main() {
  Base *b = new Base();
  Base *b1 = new Derived1();
  Base *b2 = new Derived2();

  Do(b, 10);
  Do(b1, 20);
  Do(b2, 30);
  return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/645889.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue3 vite项目配置了proxy代理情况下查看真实的接口调用地址

vite配置了proxy代理情况下如何查看真实的接口调用地址? 使用vite进行代理 在vite.config.ts配置了代理 在浏览器查看请求头和响应头发现只有代理前的url&#xff0c;没有显示代理后的路径 然后发现一个bypass函数&#xff0c;但是此函数只能修改res响应头的数据&#xff0…

Visual Studio 的调试(一)

最近事儿很多昂&#xff0c;更新速度相较以往慢了许多&#xff0c;备考六月份的四级&#xff0c;还有学校的期末等等&#xff0c;事儿真的太多啦&#xff0c;所以后面的更新速度也会放慢一点&#xff0c;实在是抽不开身啊诸位&#xff0c;相当抱歉&#xff0c;还望诸君见谅 言…

原哥花了1个多月的时间终于开发了一款基于android studio的原生商城app

大概讲一下这个app实现的功能和前后端技术架构。 功能简介 广告展示商品展示跳转淘宝联盟优惠卷购买发布朋友圈宝妈知识资讯商品搜索朋友圈展示/点赞/评论登陆注册版本升级我的个人资料商品和资讯收藏我的朋友圈意见反馈 安卓端技术选型 Arouter组件化daggerrxjavaretrofit…

遇见问题-VMware虚拟机打开运行一段时间后卡死

1.问题原因 因为Windows自带的虚拟化软件Hyper-V与VMware存在冲突。 2.关闭Hyper-V 1.打开【控制面板】-【程序和功能】-【启用或关闭Windows功能】3.关闭HV主机服务 1.右击计算机-》管理-》服务和应用名称-》服务-》找到HV主机服务-》右击属性停止服务 -》启动类型设置为禁…

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(十三)

本系列课程&#xff0c;将重点讲解Phpsploit-Framework框架软件的基础使用&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; 接上一篇文章内容&#xff0c;讲述如何进行Phpsploit-Framework软件的基础使用和二次开发。 我们&#xff0c;继续讲一…

乡村振兴的农业品牌建设:打造农业品牌,提升农产品附加值,增强乡村经济竞争力,实现美丽乡村经济繁荣

目录 一、引言 二、农业品牌建设的重要性 &#xff08;一&#xff09;提升农产品附加值 &#xff08;二&#xff09;增强乡村经济竞争力 &#xff08;三&#xff09;实现美丽乡村经济繁荣 三、农业品牌建设的现状及问题 &#xff08;一&#xff09;现状 &#xff08;二…

python-10(爬虫)

1.网络爬虫 1.1.引言 我们平时都说Python爬虫&#xff0c;其实这里可能有个误解&#xff0c;爬虫并不是Python独有的&#xff0c;可以做爬虫的语言有很多例如&#xff1a;PHP、JAVA、C#、C、Python。 为什么Python的爬虫技术会异军突起呢&#xff1f; Python火并不是因为爬…

兵器室管控系统|DW-306是一套成熟系统

概述 智慧兵器室管理系统&#xff08;DW-S306&#xff09;是依托互3D技术、大数据、RFID技术、数据库技术、AI、视频分析技术对RFID智能仓库进行统一管理、分析的信息化、智能化、规范化的系统。 本解决方案利用现有内部网络&#xff0c;部署部队智能兵器室管理系统&#xff…

使用Django框架搭建Web应用

文章目录 简介安装Django创建一个Django项目创建一个Django应用编写视图配置URL运行开发服务器总结与拓展数据库集成管理后台表单处理模板引擎安全性 简介 Django 是一款基于 Python 语言的开源 Web 应用框架&#xff0c;采用了 MVC&#xff08;模型-视图-控制器&#xff09;设…

数据库系统原理实验报告6 | 视图

整理自博主本科《数据库系统原理》专业课自己完成的实验报告&#xff0c;以便各位学习数据库系统概论的小伙伴们参考、学习。 专业课本&#xff1a; ​ ———— 本次实验使用到的图形化工具&#xff1a;Heidisql ​ 目录 一、实验目的 二、实验内容 1&#xff0e;根据EDUC数…

Matlab中函数或变量 ‘eeglab‘ 无法识别

EEGLAB 没有安装或添加到 MATLAB 路径中&#xff1a; 确保已经安装了 EEGLAB&#xff0c;并且将其添加到 MATLAB 的路径中。您可以通过在 MATLAB 命令窗口中运行 which eeglab 来检查是否能够找到 EEGLAB。 EEGLAB 函数路径设置错误&#xff1a; 如果已经安装了 EEGLAB&#x…

信息系统项目管理师0131:输出(8项目整合管理—8.7监控项目工作—8.7.3输出)

点击查看专栏目录 文章目录 8.7.3 输出8.7.3 输出 工作绩效报告工作绩效信息可以用实体或电子形式加以合并、记录和分发。基于工作绩效信息,以实体或电子形式编制形成工作绩效报告,以制定决策、采取行动或引起关注。根据项目沟通管理计划,通过沟通过程向项目干系人发送工作绩…

Top期刊:针对论文Figure图片的7个改进建议

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 通过对来自细胞生物学、生理学和植物学领域的580篇论文&#xff0c;进行检查和归纳总结&#xff0c;来自德国德累斯顿工业大学的Helena Jambor及合作者&#xff0c;在PLOS Bio…

Linux网络编程:HTTPS协议

目录 1.预备知识 1.1.加密和解密 1.2.常见加密方式 1.2.1.对称加密 1.2.2.非对称加密 ​编辑 1.3.数据摘要&#xff08;数据指纹&#xff09;和数据签名 1.4.证书 1.4.1.CA认证 1.4.2.证书和数字签名 2.HTTPS协议 2.1.自行设计HTTPS加密方案 2.1.1.只使用对称加密 …

Linux-组管理和权限管理

1 Liunx组的基本介绍&#xff1a; 在Linux中的每个用户必须属于一个组&#xff0c;不能独立于组外。在Linux中每个文件都有所有者、所在组、其他组的概念 所有者所在组其它组改变用户所在的组 2 文件/目录的所有者 一般文件的创建者&#xff0c;谁创建了该文件&#xff0c;就…

Selenium 自动化测试工具<2>(Selenium 常用API的使用方法)

文章目录 浏览器操作浏览器最大化设置浏览器的大小浏览器的前进和后退操作浏览器滚动条 键盘事件单个按键用法键盘组合键用法 鼠标事件不同窗口搜索定位一组元素定位多层框架下拉框定位alert、confirm、prompt 的处理上传文件操作自动截屏 继上一篇文章对 Selenium API 的使用&…

【微机原理及接口技术】可编程并行接口芯片8255A

【微机原理及接口技术】可编程并行接口芯片8255A 文章目录 【微机原理及接口技术】可编程并行接口芯片8255A前言一、8255A的内部结构和引脚1.与外设接口&#xff08;数据端口&#xff09;2.与处理器接口 二、8255A的工作方式三、8255A的编程1. 写入方式控制字&#xff1a;控制字…

想转行程序员的朋友,有什么想问的在评论区随便问,我知道的都告诉你。

你想转行程序员吗&#xff1f; 我自己是法学院毕业后&#xff0c;通过2年的努力才转行程序员成功的。 我发现对于一个外行来说&#xff0c;找不到一个适合自己的方向&#xff0c;光靠努力在一个新的行业里成功异常艰难。即使你非常努力&#xff0c;但方向错了也会做大量的无用…

向npm发布自己写的vue组件,使用vite创建项目

向npm发布自己写的vue组件&#xff0c;使用vite创建项目 创建项目 pnpm create vite输入项目名称 由于我的组件是基于 ant-design-vue和vue的&#xff0c;需要解析.vue文件&#xff0c;我又安装了下面4个。 然后执行 pnpm i安装依赖 vite.config.ts import { defineC…

太狠了,凌晨5点面试。。

(关注数据结构和算法&#xff0c;了解更多新知识) 网上看到一网友发文说收到面试邀请&#xff0c;面试时间竟然是早晨5点&#xff0c;这是要猝死的节奏。有的网友说应该是下午 5 点&#xff0c;如果是下午 5 点直接写下午 5 点就行了&#xff0c;或者写 17 点也行&#xff0c;直…