inline内联函数为什么不能是虚函数?

1. inline内联函数为什么不能是虚函数?

虚函数可以是内联函数,内联是可以修饰虚函数的,但是当虚函数表现多态性的时候不能内联
理由如下:内联是在发生在编译期间,编译器会自主选择内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。 inline virtual唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如 Base::who()),这只有在编译器具有实际对象而不是对象的指针或引用时才会发生。

2. 编译器对inline函数的处理步骤
  • 将 inline 函数体复制到 inline 函数调用点处;
  • 为所用 inline 函数中的局部变量分配内存空间;
  • 将 inline 函数的的输入参数和返回值映射到调用方法的局部变量空间中;
  • 如果 inline 函数有多个返回点,将其转变为 inline 函数代码块末尾的分支(使用 GOTO);
3. 类模板、函数模板与虚函数?
4. 为什么要避免头文件重复包含呢
  1. 在编译c或c++程序时候,编译器首先要对程序进行预处理,预处理其中一项工作便是将源程序中 #include的头文件完整的展开,如果多次包含相同的头文件,会导致编译器在后面的编译步骤多次编译该头文件,工程代码量小还好,工程量一大会使整个项目编译速度变的缓慢,后期的维护修改变得困难。
  2. 第一点讲的头文件重复包含的坏处其实还能忍,但是头文件重复包含带来的最大坏处是会使程序在编译链接的时候崩溃。

那么如何避免它呢?

通常有两种做法:条件编译和**#pragma once**。

区别:

  1. #ifndef 是通过定义独一无二的宏来避免重复引入的,这意味着每次引入头文件都要进行识别,所以效率不高。但考虑到 C 和 C++ 都支持宏定义,所以项目中使用 #ifndef 规避可能出现的“头文件重复引入”问题,不会影响项目的可移植性。
  2. 和 ifndef 相比,#pragma once 不涉及宏定义,当编译器遇到它时就会立刻知道当前文件只引入一次,所以效率很高。但值得一提的是,并不是每个版本的编译器都能识别 #pragma once 指令,一些较老版本的编译器就不支持该指令(执行时会发出警告,但编译会继续进行),即 #pragma once 指令的兼容性不是很好

注意#pragma once 只能作用于某个具体的文件,而无法向 #ifndef 那样仅作用于指定的一段代码。

5. 声明与定义

**“声明”:**只是声明某个符号(变量或函数)的存在,即告诉编译器,这个符号是在其他文件中定义的,我这里先用着,你链接的时候再到别的地方去找找看它到底是什么吧。

**“定义”:**则是要按C++语法完整地定义一个符号(变量或者函数),告诉编译器在此处分配存储空间建立变量和函数。

**头文件的作用:**就是被其他的.cpp包含进去的, 本身并不参与编译。但实际上,它们的内容却在多个.cpp文件中得到了编译。通过"定义只能有一次”的规则,很容易可以得出:头文件中应该只放变量和函数的声明,而不能放它们的定义。因为一个头文件的内容实际上是会被引 入到多个不同的.cpp文件中的,并且它们都会被编译。放声明当然没事,如果放了定义,那么也就相当于在多个.cpp文件中出现了对同一个符号(变量或函数)的定义,因此就会报“重复定义的错误”。

**总结:**声明是将一个名称引入程序;定义提供了一个实体(类型、变量、对象、函数)在程序中的唯一描述。

**所以:**一个符号,在整个程序中可以被声明多次,但只允许被定义一次。

6. 内部链接与外部链接

1. 内部链接:内部链接意味着对符号名的访问仅限于当前编译单元。即:对于任何其他编译单元都是不可见的,在链接的时候不会与其它编译单元中同样的名称相冲突,则这个符号具有内部链接。

具体有

  1. 静态(static)全局变量的定义、静态自由函数的定义、静态友元函数的定义;
  2. 类的声明与定义;
  3. 内联函数定义;
  4. Union共同体/结构体/枚举类型定义;
  5. const常量定义;
  6. 各种声明;

C++又补充规定,extern const联合修饰时,extern将压制const的内部链接属性。

用内部链接定义的一个重要的例子就是类的定义。类的定义如下。因此,它不能够在同一作用域的编译单元内重复定义。如果需要在其他编译单元使用,类必须被定义在头文件且被其他文件包含。仅仅在其他文件中使用class Point;声明是不行的,原因就是类的定义是内部链接,不会在目标文件导出符号。也就不会被其他单元解析它们的未定义符号。

class Point{int d_x;                             // 内部链接int d_y;public:Point(int x,int y):d_x(x),d_y(y){}   // 内部链接int x() const{return d_x;}           // 内部链接int y() const{return d_y;}           // 内部链接
};

因此:具有内部链接的符号无法作用于当前文件外部,要让其影响程序的其他部分,可以将其放在.h文件中。此时在所有包含此.h文件的源文件都有自己的定义且互不影响。

2. 外部链接:外部链接意味着这个定义不局限于单个的编译单元。在.o文件中,具有外部链接的定义产生外部符号,这些外部符号可以被所有其他编译单元访问,用来解析其他编译单元中未定义的符号,即:一个名称在链接时可以和其他编译单元交互,那么这个名称就具有外部链接。

因此:因此它们在整个程序中必须是唯一的,否则将会导致重复定义

​ 具体有:

​ 1.类的非内联函数(包括成员函数和静态成员函数)的定义
​ 2.类的静态成员变量的定义
​ 3.名字空间或全局非静态的自由函数,非静态变量,非友元函数的定义

 class A{static int a;       // 类的静态成员声明,内部链接void fun();         // 类的非内联成员函数声明,内部链接static void fun2(); // 类的非内联静态成员函数声明,内部链接void fun2(){...};   // 类内实现函数定义,若为内联则为内部链接,若为非内联则为外部链接}int A::a = 1;           // 类的静态成员定义,外部链接void A::fun(){...};     // 类的非内联成员函数定义,外部链接static void A::fun2(){...}; //类的非内联静态成员函数定义,外部链接namespace A{...}  // 名字空间定义,外部链接void fun3(){...}; // 全局非静态自由函数定义,外部链接int b;            // 全局非静态变量,外部链接

所以,拥有外部链接的实体如果放在头文件中并且被多个.cpp文件包含,可能就会出现链接冲突错误,因为每个包含这个拥有外部链接实体的.cpp都会分配空间,当多个编译单元链接的时候,连接器就会面对多个相同的名字,无法正常链接到正确的对象。

因此:由于cpp文件中存储的是成员函数的实现,而成员函数具有外部链接特性,会在目标文件产生符号。在此文件中此符号是定义过的。其他调用此成员函数的目标文件也会产生一个未定的符号。两目标文件连接后此符号就被解析。

判断一个符号是内部链接还是外部链接的一个很好的方法就是看该符号是否被写入.o文件,由于声明只对当前编译单元有用,因此声明并不将任何东西写入.o文件。

宏是内部链接还是外部链接

都不是,宏在预处理环节时就被替换掉了,而内部链接与外部链接是针对编译环节与链接环节而言的

7. 在.h中和.cpp中include头文件有什么区别

在 .h 里面 include 的好处是:如果全部在一个.h, 那么每个.c/.cpp文件只需要一个#include 语句这样不仅输入量减少,而且代码也美观多了代码也主次分明了毕竟。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5.13 BCC工具之urandomread.py简介

一,工具简介 urandomread工具用于演示如何在内核跟踪点进行插桩。 二,代码示例 注意,该示例要求内核版本Linux 4.7+(并在内核编译选型中使能BPF_PROG_TYPE_TRACEPOINT)。 #!/usr/bin/pythonfrom __future__ import print_function from bcc import BPF from bcc.utils…

Centos7挂载磁盘

1 查看未挂载的磁盘 命令: fdisk -l红框圈中的即是本次要挂载的磁盘,/dev/vdb 与 /dev/vda 相比,其没有下方的 /dev/vda1 等信息,代表 /dev/vdb 磁盘并没有进行过分区操作,是一个新加的硬盘。 2 对新建的磁盘进行分…

基于SSM的宁夏旅游网站平台(有报告)。Javaee项目。ssm项目。

演示视频: 基于SSM的宁夏旅游网站平台(有报告)。Javaee项目。ssm项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构,通过Spring …

CDF和PDF的比较

以下内容来自ChatGPT,科技改变生活 Cumulative Distribution Function (CDF)(累积分布函数)和 Probability Density Function (PDF)(概率密度函数)是统计学和概率论中两个重要的概念,用于描述随机变量的性…

K8S之运用污点、容忍度设置Pod的调度约束

污点、容忍度 污点容忍度 taints 是键值数据,用在节点上,定义污点; tolerations 是键值数据,用在pod上,定义容忍度,能容忍哪些污点。 污点 污点是定义在k8s集群的节点上的键值属性数据,可以决…

Open CASCADE学习|管道建模

​这是用Open CASCADE Technology (OCCT)库来创建一个管道模型的示例。OCCT是一个开源的几何建模库,广泛应用于CAD/CAM/CAE和其他几何建模应用中。 在下面的代码中,首先创建了一些点,并用这些点来构建B样条曲线,进而创建边(Edges…

Java+Vue+MySQL,国产动漫网站全栈升级

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

软件测试经典面试题:如何进行支付功能的测试?

非现金支付时代&#xff0c;非现金支付已经成为了生活不可或缺的一部分&#xff0c;我们只需要一台手机便可走遍全国各地&#xff08;前提是支付宝&#xff0c;微信有钱<00>&#xff09;,那么作为测试人员&#xff0c;支付测试也是非常重要的一环&#xff0c;那么下面我就…

【漏洞复现-通达OA】通达OA swfupload_new存在前台SQL注入漏洞

一、漏洞简介 通达OA(Office Anywhere网络智能办公系统)是由北京通达信科科技有限公司自主研发的协同办公自动化软件,是与中国企业管理实践相结合形成的综合管理办公平台。通达OA为各行业不同规模的众多用户提供信息化管理能力,包括流程审批、行政办公、日常事务、数据统计…

作业2024/2/18

1.思维导图 2.定义一个基类Animal&#xff0c;其中有一个虚函数perform ()&#xff0c;用于在子类中实现不同的表演行为。 #include <iostream>using namespace std; class Animal { private:public:void virtual perform() 0;}; class Tiger:public Animal { private:…

树莓派驱动从认识框架到写驱动

​​​​​​参考文章&#xff1a;详细到吐血 —— 树莓派驱动开发入门&#xff1a;从读懂框架到自己写驱动_树莓派 编译驱动-CSDN博客 目录 一、对驱动的认识 为什么要学习驱动&#xff1f; 设备号的作用 二、基于内核驱动框架编写驱动代码流程 1、根据上层需求&…

从零开发短视频电商 Nginx一个域名部署多个VUE前端

这里介绍的是所有请求不管是前端还是后端都是在一个域名下。 但是 但是 但是&#xff0c;如果你能控制域名的映射强烈建议你使用多个二级域名来实现。 1.打开 Nginx 的配置文件 nginx.conf&#xff0c;该文件通常位于 /etc/nginx/ 或者 /usr/local/nginx/conf/ 中。 2.修改ngi…

ClickHouse从入门到精通(高级)

第1章 Explain查看执行计划 第2章 建表优化 第3章 ClickHouse语法优化规则 第4章 查询优化 第5章 数据一致性(重点) 第6章 物化视图 第7章 MaterializeMySQL引擎 第8章 常见问题排查

Python Selenium实现自动化测试及Chrome驱动使用!

本文将介绍如何使用Python Selenium库实现自动化测试&#xff0c;并详细记录了Chrome驱动的使用方法。 通过本文的指导&#xff0c;读者将能够快速上手使用Python Selenium进行自动化测试。 并了解如何配置和使用Chrome驱动来实现更高效的自动化测试。 一、Python Selenium简…

Java_方法(重载方法签名等详解)

在之前我们学习C语言时&#xff0c;当我们想要重复使用某段代码的功能时&#xff0c;我们会将这段代码定义为一个函数&#xff0c;而在java中我们把这段重复使用的代码叫做方法。 方法的定义 类体的内容分为变量的声明和方法的定义&#xff0c;方法的定义包括两部分&#xff1…

【C++】C++入门—初识构造函数 , 析构函数,拷贝构造函数,赋值运算符重载

C入门 六个默认成员函数1 构造函数语法特性 2 析构函数语法特性 3 拷贝构造函数特性 4 赋值运算符重载运算符重载赋值运算符重载特例&#xff1a;前置 与 后置前置&#xff1a;返回1之后的结果后置&#xff1a; Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&…

算法练习-01背包问题【含递推公式推导】(思路+流程图+代码)

难度参考 难度&#xff1a;困难 分类&#xff1a;动态规划 难度与分类由我所参与的培训课程提供&#xff0c;但需 要注意的是&#xff0c;难度与分类仅供参考。且所在课程未提供测试平台&#xff0c;故实现代码主要为自行测试的那种&#xff0c;以下内容均为个人笔记&#xff0…

嵌入式面试:瑞芯微

文章目录 一、2024 秋招1.1 IIC的速率范围 :1.2 linux驱动子系统汇总 :1.3 linux关抢占情况汇总 :1.4 操作或者读写一个文件时,从用户态到内核态再到物理介质的流程(考点:虚拟文件系统) :一、2024 秋招 1.1 IIC的速率范围 : i2c的速率在100kbit/s--3.4Mbits之间 标准模…

静态curl库编译与使用(c++)

静态curl库编译与使用 静态curl库编译与使用&#xff1a;mingw https://curl.se/windows/ // 测试&#xff1a;设置URL地址 // curl_easy_setopt(curlHandle, CURLOPT_URL, “https://ipinfo.io/json”); // curl_easy_setopt(curlHandle, CURLOPT_SSL_VERIFYPEER, 0L); // c…

【机器学习】机器学习是什么以及有哪些应用场景

机器学习是什么以及有哪些应用场景 一、机器学习是什么二、机器学习有哪些应用场景三、如何学习机器学习 一、机器学习是什么 机器学习&#xff08;Machine Learning, ML&#xff09;是一种计算机科学技术&#xff0c;它允许计算机系统在没有明确编程的情况下通过从数据中学习…