【牛客网】—— 虚函数是否能声明为内联

news/2024/5/20 4:11:21 标签: 内联函数, 虚函数, 牛客网

我们来看一下牛客网上的这个题
<a class=牛客网" />
还是先分析一下每个选项之后再重点讲一下A选项

  • A:内联函数编译期间将调用之处用被调函数来代替,而虚函数运行时才能确定调用哪个函数,所以虚函数声明为内联不能提高效率,不是虚函数不能被声明为内联,这个我们稍后详细的说。
  • B:类里面存着相同函数名和参数的函数时,在调用时都会出现冲突,不知调用哪一个。
  • C:delete子类对象是一定会调用父类的析构函数的,先调用子类的析构函数然后调用父类的析构函数;如果要调用父类指向子类的对象的指针,此时才需要父类的析构函数是虚的。

内联函数(inline)

  • 内联函数的目的是为了减少函数调用时间。它是把内联函数的函数体在编译器预处理的时候替换到函数调用处,这样代码运行到这里时候就不需要花时间去调用函数。但内联函数有个缺点是它会增加执行文件大小。所以如果不适当的使用内联函数会造成执行文件特别大。
  • 系统可以忽略用户定义的内联函数,若是用户将一个很复杂的函数定义为内联时,此时程序效率不仅不能提高反而更慢时,系统就可以忽略关键字inline,按照正常函数调用。

而使用内联函数有以下几点需要注意:

  • 头文件中不仅要包含inline函数的声明,还要包含inline函数的定义
  • 编译器需要把inline函数体替换到函数调用处,所以编译器必须要知道inline函数的函数体是啥,所以要将inline函数的函数定义和函数声明一起写在头文件中,便与编译器查找替换。
  • 可以在同一个项目的不同源文件内定义函数名相同,实现相同的inline函数。
  • 同一个inline函数可以多处声明和定义,但是必须要完全相同。
  • 定义在class声明内的成员函数默认是inline函数。

虚函数(virtual)

  • 虚函数是为了实现多态特性的。虚函数的调用只有在程序运行的时候才能知道到底调用的是哪个函数。

其是有有如下几点需要注意:

  • 类的构造函数不能是虚函数,构造函数是为了构造对象的,所以在调用构造函数时候必然知道是哪个对象调用了构造函数,所以构造函数不能为虚函数
  • 类的静态成员函数是虚函数,类的静态成员函数是该类共用的,与该类的对象无关,静态函数里没有this指针,所以不能为虚函数
  • 类的析构函数最好定义为虚函数,因为在析构一个指向子类对象的父类指针时,若是析构函数不为虚函数,此时释放该指针时只调用父类析构函数,这样子类的资源不会被释放就会造成内存泄漏的情况。详细解释可参见博客 https://blog.csdn.net/chenxiyuehh/article/details/88775057

《Effective C++》的第33款:

即使是最简单的虚函数调用,编译器的内联处理程序对它也爱莫能助。(这一点也不奇怪。virtual的意思是"等到运行时再决定调用哪个函数",inline的意思是"在编译期间将调用之处用被调函数来代替",如果编译器甚至还不知道哪个函数将被调用,当然就不能责怪它拒绝生成内联调用了)。

虚函数内联函数

  • 虚函数用于实现运行时的多态,或者称为晚绑定或动态绑定。而内联函数用于提高效率。内联函数的原理是,在编译期间,对调用内联函数的地方的代码替换成函数代码。内联函数对于程序中需要频繁使用和调用的小函数非常有用。
  • 默认地,类中定义的所有函数,除了虚函数之外,会隐式地或自动地当成内联函数(注意:内联只是对于编译器的一个请求,编译器可以自己决定是否进行内联).
  • 无论何时,使用基类指针或引用来调用虚函数,它都不能为内联函数(因为调用发生在运行时,运行时才会确定具体调用哪一个函数)。但是,无论何时,使用类的对象(不是指针或引用)来调用时,可以当做是内联,因为编译器在编译时确切知道对象是哪个类的。

举个栗子看看

#include <iostream>
using namespace std;
class Base
{
public:
	virtual void who()
	{
		cout << "I am Base\n";
	}
};
class Derived : public Base
{
public:
	void who()
	{
		cout << "I am Derived\n";
	}
};

int main()
{
	// 此处的虚函数who(),是通过类的具体对象来调用的,编译期间就能确定了,所以它可以是内联的。
	Base b;
	b.who();

	// 此处的虚函数是通过指针调用的,需要在运行时期间才能确定,所以不能为内联。
	Base *ptr = new Derived();
	ptr->who();

	return 0;
}

<a class=虚函数" />
动态联编
通过这两幅图我们我们可以知道虚函数用指针或是引用调用时是在程序运行时确定是调用哪一个函数的,因此这种情况下是无法将虚函数声明为内联函数

若是想要了解更多关于内联函数什么情况下可以被声明为内联函数,可以参加博客,有详细的解释 https://blog.csdn.net/zy1691/article/details/3606128


http://www.niftyadmin.cn/n/1280751.html

相关文章

快速学习-Shell条件判断

第6章 条件判断 1&#xff0e;基本语法 [ condition ]&#xff08;注意condition前后要有空格&#xff09;注意&#xff1a;条件非空即为true&#xff0c;[ atguigu ]返回true&#xff0c;[] 返回false。 2. 常用判断条件 &#xff08;1&#xff09;两个整数之间比较 字符串比…

快速学习-Shell流程控制

第7章 流程控制&#xff08;重点&#xff09; 7.1 if 判断 1&#xff0e;基本语法 if [ 条件判断式 ];then 程序 fi 或者 if [ 条件判断式 ] then 程序 fi注意事项&#xff1a; &#xff08;1&#xff09;[ 条件判断式 ]&#xff0c;中括号和条件判断式之间必须有空格 &…

【LeetCode】—— 前k个高频单词和元素

一、前k个高频单词LeetCode692 1.1 题目描述 给一非空的单词列表&#xff0c;返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率&#xff0c;按字母顺序排序。 示例 1&#xff1a; 输入: [“i”, “love”, “leet…

【数据结构】—— 模拟实现二叉搜索树

二叉搜索树 这里先简单介绍一下什么是二叉搜索树模拟实现一个二叉搜索树了解其原理 二叉搜索树的概念 二叉搜索树又称为二叉排序树&#xff0c;它或者是一个空树&#xff0c;或者是拥有以下性质的二叉树&#xff1a; 若是它的左子树不为空&#xff0c;则左子树所有节点的值…

【C++】—— STL关联式容器map/set

一、关联式容器 首先我们先介绍一下什么是关联式容器 序列式容器vector、list、deque、forward_list(C11)因为其底层为线性序列的数据结构&#xff0c;里面存储的是元素本身。关联式容器也是用来存储数据的&#xff0c;与序列式容器不同的是&#xff0c;map其里面存储的是<…

【数据结构】—— 浅析AVL树及模拟实现

AVL树 AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下。因此&#xff0c;两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一…

php绝对路径与相对路径之间关系的研究

php中好像不能像asp那样用“/”表示根目录&#xff0c;代之以$_SERVER[DOCUMENT_ROOT]&#xff0c;其它则相同&#xff1a;../表示向上一层。./表示当前层。假如现在a/b/c/s.php要调用根目录下的 /bb/s2.txt&#xff0c;则&#xff1a; $RootDir $_SERVER[DOCUMENT_ROOT]; $f…

两个反汇编引擎

2019独角兽企业重金招聘Python工程师标准>>> http://www.pintool.org/ http://beatrix2004.free.fr/BeaEngine/ 转载于:https://my.oschina.net/sincoder/blog/117340