详解C++中的内联函数和函数重载

内联函数(内嵌函数,内置函数)

调用函数时需要一定的时间和空间的开销。C++提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开。这种在函数调用处直接嵌入函数体的函数称为内联函数(inline function),又称内嵌函数或内嵌函数。

指定内联函数的方法很简单,只需要在定义函数时增加 inline 关键字。

注意:是在函数定义时增加 inline 关键字,而不是在函数声明时。在函数声明时增加 inline 关键虽然没有错误,但是也没有任何效果

inline 关键字放在函数声明处不会起作用:

inline void swap(int &a, int &b);
void swap(int &a, int &b)
{
  int temp = a;
  a = b;
  b = temp;
}
inline 关键字应该与函数体放在一起:
void swap(int &a, int &b);
inline void swap(int &a, int &b)
{
  int temp = a;
  a = b;
  b = temp;
}

采用内联函数可以有效避免函数调用的开销,程序执行效率更高。使用内联函数的缺点就是,如果被声明为内联函数的函数体非常大,则编译器编译后程序的可执行码将会变得很大。

另外,如果函数体内出现循环或者其它复杂的控制结构的时候,这个时候处理这些复杂控制结构所花费的时间远大于函数调用所花的时间,因此如果将这类函数声明为内联函数意义不大,反而会使得编译后可执行代码变长。

通常在程序设计过程中,我们会将一些频繁被调用的短小函数声明为内联函数。

应当说明:对函数作inline声明,只是程序员对编译系统提出的一个建议,也就是说它是建议性的,而不是指令性的。并非一经指定为inline,编译系统就必须这样做。编译系统会根据具体情况决定是否这样做。

一个完整的示例:

#include <iostream>
using namespace std;
int max(int, int, int); //函数声明,左端也可以加inline
int main( )
{
  int i=10, j=20, k=30, m;
  m = max(i, j, k);
  cout<<"max="<<m<<endl;
  return 0;
}
inline int max(int a, int b, int c) //定义max为内联函数
{
  if(b>a) a=b;
  if(c>a) a=c;
  return a;
}

运行结果:

max=30

由于在定义函数时指定它为内置函数,因此编译系统在遇到函数调用“max(i, j, k)”时,就用max函数体的代码代替“max(i,j, k)”,同时将实参代替形参。这样,程序第6行 “m=max(i, j, k);”就被置换成:

  if (j>i) i=j;
  if(k>i) i=k;
  m=i;

函数重载

在编程时,有时我们要实现的是同一类的功能,只是有些细节不同。例如希望从3个数中找出其中的最大者,而每次求最大数时数据的类型不同,可能是3个整数、3个双精度数或3个长整数。程序设计者往往会分别设计出3个不同名的函数,其函数原型为:

  int max1(int a, int b, int c); //求3个整数中的最大者
  double max2(double a, double b, double c); //求3个双精度数中最大者
  long max3(long a, long b, long c); //求3个长整数中的最大者

C++允许用同一函数名定义多个函数,这些函数的参数个数和参数类型不同。这就是函数的重载(function overloading)。即对一个函数名重新赋予它新的含义,使一个函数名可以多用。

对上面求最大数的问题可以编写如下的C++程序。

【例】求3个数中最大的数(分别考虑整数、双精度数、长整数的情况)。

#include <iostream>
using namespace std;
int main( )
{
  int max(int a,int b,int c); //函数声明
  double max(double a,double b,double c); //函数声明
  long max(long a,long b,long c);//函数声明
  int i1,i2,i3,i;
  cin>>i1>>i2>>i3; //输入3个整数
  i=max(i1,i2,i3); //求3个整数中的最大者
  cout<<"i_max="<<i<<endl;
  double d1,d2,d3,d;
  cin>>d1>>d2>>d3; //输入3个双精度数
  d=max(d1,d2,d3); //求3个双精度数中的最大者
  cout<<"d_max="<<d<<endl;
  long g1,g2,g3,g;
  cin>>g1>>g2>>g3; //输入3个长整数
  g=max(g1,g2,g3); //求3个长整数中的最大者
  cout<<"g_max="<<g<<endl;
}
int max(int a,int b,int c) //定义求3个整数中的最大者的函数
{
  if(b>a) a=b;
  if(c>a) a=c;
  return a;
}
double max(double a,double b,double c)//定义求3个双精度数中的最大者的函数
{
  if(b>a) a=b;
  if(c>a) a=c;
  return a;
}
long max(long a,long b,long c) //定义求3个长整数中的最大者的函数
{
  if(b>a) a=b;
  if(c>a) a=c;
  return a;
}

运行情况如下:

185-76567 (输入3个整数)
56.87 90.23 -3214.78 (输入3个实数)
67854 -912456 673456 (输入3个长整数)
i_max=567 (输出3个整数的最大值)
d_max=90.23 (输出3个双精度数的最大值)
g_max=673456 (输出3个长整数的最大值)

上例3个max函数的函数体是相同的。

其实重载函数并不要求函数体相同;除了允许参数类型不同以外,还允许参数的个数不同。

【例】编写一个程序,用来求两个整数或3个整数中的最大数。如果输入两个整数,程序就输出这两个整数中的最大数,如果输入3个整数,程序就输出这3个整数中的最大数。

#include <iostream>
using namespace std;
int main( )
{
  int max(int a,int b,int c); //函数声明
  int max(int a,int b); //函数声明
  int a=8,b=-12,c=27;
  cout<<"max(a,b,c)="<<max(a,b,c)<<endl;//输出3个整数中的最大者
  cout<<"max(a,b)="<<max(a,b)<<endl; //输出两个整数中的最大者
}
int max(int a,int b,int c)//此max函数的作用是求3个整数中的最大者
{
  if(b>a) a=b;
  if(c>a) a=c;
  return a;
}
int max(int a,int b)//此max函数的作用是求两个整数中的最大者
{
  if(a>b) return a;
  else return b;
}

运行情况如下:

max(a, b, c)=27
max(a, b)=8

两次调用max函数的参数个数不同,系统就根据参数的个数找到与之匹配的函数并调用它。

参数的个数和类型可以都不同。但不能只有函数的类型不同而参数的个数和类型相同。例如:

  int f(int); //函数返回值为整型
  long f(int); //函数返回值为长整型
  void f(int); //函数无返回值

在函数调用时都是同一形式,如“f(10)”。编译系统无法判别应该调用哪一个函数。重载函数的参数个数、参数类型或参数顺序3者中必须至少有一种不同,函数返回值类型可以相同也可以不同。

在使用重载函数时,同名函数的功能应当相同或相近,不要用同一函数名去实现完全不相干的功能,虽然程序也能运行,但可读性不好,使人莫名其妙。

(0)

相关推荐

  • C++中构造函数重载

    #include<stdio.h> class Test { private: int i; int j; int k; public: Test() { i=j=k=0; } Test(int v) { i=j=k=v; } void print() { printf("i= %d, j=%d, k=%d \n",i,j,k); } }; int main() { Test t1(1); Test t2=2; Test t3=Test(3); t1.print(); t2

  • C++中函数重载实例详解

    C++中函数重载实例详解 函数重载: 1.具有相同的名称,执行基本相同的操作,但是使用不同的参数列表. 2.函数具有多态性. 3.编译器通过调用时参数的个数和类型确定调用重载函数的哪个定义. 4.只有对不同的数据集完成基本相同任务的函数才应重载. 函数重载的优 点 1.不必使用不同的函数名 2.有助于理解和调试代码 3.易于维护代码 接下来直接上代码: #include <iostream> using namespace std ; void say_hello(void) { cout &

  • C++函数重载详解及实例代码

    C++函数的重载 定义 在同一个作用域中,函数名相同,函数的参数列表不同的函数之间构成重载关系,在不同作用域中的同名函数遵循标识符隐藏的原则 ATTENTION:重载与函数的返回值类型无关,因为声明一个函数不需要返回类型,所以无法用来区分哪个函数 常函数和普通成员函数之间构成重载,重载时常对象调用常成员函数,一般对象调用一般成员函数 class A{ - public: void getVal()const{-} void getVal(){-} }; int main(){ const A a

  • C++函数重载的深入解析

    我们在开瓶瓶罐罐的时候,经常会遭遇因各种瓶口规格不同而找不到合适的工具的尴尬.所以有时候就为了开个瓶,家里要备多种规格的开瓶器.同样是开个瓶子嘛,何必这么麻烦?于是有人发明了多功能开瓶器,不管啤酒瓶汽水瓶还是软木塞的红酒瓶都能轻松打开. 然而开瓶器的问题也会发生到程序设计中.比如我们要编写一个函数来求一个数的绝对值,然而整数.浮点型数.双精度型数都有绝对值,但为它们编写的函数返回值类型却是各不相同的.比如: 复制代码 代码如下: int iabs(int a);float fabs(float

  • 深度探究C++中的函数重载的用法

    C++ 允许同一范围内具有相同名称的多个函数的规范.这些函数称为重载函数,"重载"中对其进行了详细介绍.利用重载函数,程序员可以根据参数的类型和数量为函数提供不同的语义. 例如,采用字符串(或 char *)参数的 print 函数执行的任务与采用"双精度"类型的参数的函数执行的任务截然不同.重载允许通用命名并使程序员无需创建名称,例如 print_sz 或 print_d.下表显示了 C++ 使用函数声明的哪些部分来区分同一范围内具有相同名称的函数组. 重载注意事

  • 详解C++中的内联函数和函数重载

    内联函数(内嵌函数,内置函数) 调用函数时需要一定的时间和空间的开销.C++提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开.这种在函数调用处直接嵌入函数体的函数称为内联函数(inline function),又称内嵌函数或内嵌函数. 指定内联函数的方法很简单,只需要在定义函数时增加 inline 关键字. 注意:是在函数定义时增加 inline 关键字,而不是在函数声明时.在函数声明时增加 inline 关键虽然没有错误,但是也没有任何效果 inline 关键

  • 一文详解Python中的Map,Filter和Reduce函数

    目录 1. 引言 2. 高阶函数 3. Lambda表达式 4. Map函数 5. Filter函数 6. Reduce函数 7. 总结 1. 引言 本文重点介绍Python中的三个特殊函数Map,Filter和Reduce,以及如何使用它们进行代码编程.在开始介绍之前,我们先来理解两个简单的概念高阶函数和Lambda函数. 2. 高阶函数 把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式. 举例如下: def higher(your_function, som

  • 详解Django中views数据查询使用locals()函数进行优化

    优化场景 利用视图函数(views)查询数据之后可以通过上下文context.字典.列表等方式将数据传递给HTML模板,由template引擎接收数据并完成解析.但是通过context传递数据可能就存在在不同的视图函数中使用重复的查询语句,所以可以通过将重复查询语句设置全局变量,配合locals()函数进行数据查询与传递. 优化前 def index(request): threatname = '威胁情报展示' url = 'www.testtip.com' allthreat = Threa

  • 详解WordPress中用于合成数组的wp_parse_args()函数

    wp_parse_args() 函数是 WordPress 核心经常用到的函数,它的用途很多,但最主要用来给一个数组参数(args)绑定默认值. 因为 wp_parse_args() 函数返回的一定是一个数组,所以他会把传入查询字符串和对象(object)自动转换成数组,给了使用者更加方便的条件,也增加了兼容性. 常见的 query_posts().wp_list_comments() 和 get_terms() 函数都使用了 wp_parse_args() 函数来帮它给数组参数添加默认值. 用

  • 图文详解Python中最神秘的一个魔法函数

    目录 前言 1.有点价值的missing() 2.神出鬼没的missing() 3.被施魔法的missing() 4.小结 五.总结 前言 一个非常神秘的魔术方法. 这个方法非常不起眼,用途狭窄,我几乎从未注意过它,然而,当发现它可能是上述"定律"的唯一例外情况时,我认为值得再写一篇文章来详细审视一下它. 本文主要关注的问题有:(1) missing()到底是何方神圣?(2) missing()有什么特别之处?擅长"大变活人"魔术? (3) missing()是否真

  • 详解linux中fork、vfork、clone函数的区别

    在linux系统中,fork(),vfork()和clone函数都可以创建一个进程,但是它们的区别是什么呢???本文就这三者做一个较深入的分析!!! 1.fork() fork()函数的作用是创建一个新进程,由fork创建的进程称为子进程,fork函数调用一次返回两次,子进程返回值为0,父进程返回子进程的进程ID.我们知道,一个进程的地 址空间主要由代码段,数据段,堆和栈构成,那么p2就要复制相关的段到物理内存.原始的unix系统的实现的是一种傻 瓜式的进程创建,这些复制包括: (1) 为子进程

  • 实例详解Python中的numpy.abs和abs函数

    目录 说在最前 先看示例程序-abs()函数 再看示例程序-numpy.abs()函数 观察两个程序的结果 分析解释 拓展 补充:numpy abs()报错 总结 说在最前 不知道小伙伴们在写代码的时候有没有区分开numpy.abs和abs函数,别小看这两个函数,如果在写程序的时候正确区分使用这两个函数可以使自己的程序运行效率大大提升. 别看这两个函数都能对整数求绝对值,但他们俩的返回值类型完全不一样,如果傻傻地混为一谈,将会使你的程序运行时间被大大拖累! 今天笔者就带小伙伴们看看,这两个函数究

  • 详解C#中通过委托来实现回调函数功能的方法

    委托(delegate)是一种可以把引用存储为函数的类型,这类似于c++中的函数指针. 回调函数 c++中的回调函数,就是用函数指针来实现的.类似的,c#中用委托,来实现回调函数的功能. 回调函数为什么被称为回调函数?比如你调用了一个函数,那么就叫调用,但是如果你在调用一个函数的时候,还需要把一个函数提供给该函数,让这个函数来调用你的函数,那么你提供的这个函数就被称为回调函数(callback). 对于python这样的动态语言而言,就没有c#,c++提供特殊的语法实现回调函数,因为在pytho

  • 详解C#中委托,事件与回调函数讲解

    .Net编程中最经常用的元素,事件必然是其中之一.无论在ASP.NET还是WINFrom开发中,窗体加载(Load),绘制(Paint),初始化(Init)等等. "protected void Page_Load(object sender, EventArgs e)"这段代码相信没有人不熟悉的.细心一点一定会发现,非常多的事件方法都是带了"object sender, EventArgs e"这两个参数.这是不是和委托非常相似呢? 一.委托(有些书中也称为委派)

  • 详解WordPress中添加和执行动作的函数使用方法

    add_action()(添加动作) add_action() 函数用来挂载一个函数到动作钩子上. 用法 add_action( $tag, $function_to_add, $priority, $accepted_args ); 参数 $hook (字符串)(必须)挂载函数的动作名称. 默认值:None $function_to_add (回调函数)(必须)挂载的函数,直接填写字符串形式的函数名即可. 默认值:None $priority (整数)(可选)动作执行的优先级,数值越小越先被执

随机推荐