本节主要讲了函数重载的主要概念以及使用方法,还有C和C++的相互调用的准则和具体的工程中的使用技巧。

函数重载

1.基本概念

函数重载就是用同一个函数名来定义不同的函数。使用不同的函数参数来搭配同一个函数名。基本例程如下:

#include <stdio.h>
#include <string.h> int func(int a)
{
return a;
} int func(int x, int y)
{
return x*y;
} int func(int a, int b, int c)
{
return a + b + c;
} int func(char *p)
{
return strlen(p);
} int main()
{
printf ("func(1) = %d\n", func(1));
printf ("func(1,2) = %d\n", func(1,2));
printf ("func(1,2,3) = %d\n", func(1,2,3));
printf ("func(abcdef) = %d\n", func("abcdef"));
}

2.重载条件

①参数个数不同。

②参数类型不同。

③参数顺序不同。
课程里的老师说这三个条件是不按住顺序的,也就是只要有一个条件满足就可以判断对哪个函数进行重载,但是我觉得有问题存在。

例程:

#include <stdio.h>
#include <string.h> int func(const char *p, int b)
{
return strlen(p);
} int func(int b, const char *p)
{
return b ;
} int main()
{
printf ("func(1,ac) = %d\n", func(1,"ac"));
printf ("func(ac, 1) = %d\n", func("ac", 1));
}

从上面的程序证明了条件③,函数的参数顺序不同函数可以进行重载。 在C++中可以将功能类似的函数都重载起来,仅仅让编译根据参数的不同来实现不同的编译,从而实现重载函数的识别和调用。

3.函数的重载与函数默认参数的冲突

例程:

#include <stdio.h>
#include <string.h> int func(int a, int b, int c = 0)
{
return a * b * c;
} int func(int a, int b)
{
return a + b;
} int main()
{
printf ("func(1,2) = %d\n", func(1,2));
}

这个时候编译器会承认两个函数func是重载函数,但是编译器会报错,错误报告是:对重载函数的调用不明确。这个叫做程序的二义性。当我们使用函数重载的时候就不要使用函数的默认参数,当我们使用函数的默认参数的时候就不要进行函数的重载。

4.C++编译器调用重载函数的准则

我们在进行函数重载的时候会有很多个同名的函数,这些同名函数最后是怎么被编译成为可执行程序的,这些事依赖于C++编译器的编译准则的。

在匹配成功的前两准则中前面的小例子都可以体现出来,下面的历程是针对通过默认类型转换匹配实参的准则。历程如下:

#include <stdio.h>
#include <string.h> int func(int a, int b)
{
return a + b;
} int func(int b)
{
return 1;
} int main()
{
printf ("func(1,2) = %d\n", func('a',2));
}

这里将‘a’转化为ASII码来与函数的参数进行匹配。

问题:老师说函数的重载三个准则是没有顺序的,但是当出现第二条和第三条冲突的时候在VS2008的C++编译环境下还是有顺序的,函数还是会先对完全匹配的进行重载。例程如下:

#include <stdio.h>
#include <string.h> int func(int a, int b)
{
return a + b;
} int func(char a, int b)
{
return 1;
} int main()
{
printf ("func(1,2) = %d\n", func('a',2));
}

上述程序的打印结果是1

5.重载函数的注意事项

①重载函数在本质上是相互独立的不同函数。

②重载函数的类型是不同的。

③函数的返回值不能作为重载函数的依据。

④重载函数是由函数名和参数列表决定的。

6.函数重载与函数指针

当使用重载函数名对函数指针进行赋值时,根据重载规则与函数指针参数列表一样的函数定为重载函数,同时函数类型和函数指针的类型要求十分严格。

例程:

#include <stdio.h>
#include <string.h> int func(int x) // int(int a)
{
return x;
} int func(int a, int b)
{
return a + b;
} int func(const char* s)
{
return strlen(s);
} typedef int(*PFUNC)(int a); // int(int a) int main(int argc, char *argv[])
{
int c = 0;
PFUNC p = func; c = p(1); printf("c = %d\n", c); printf("Press enter to continue ...");
getchar();
return 0;
}

C和C++的相互调用

1.在实际的项目中融合C和C++代码是不可避免的(想起了学习嵌入式的岁月,尽管是菜鸟)。虽然C++编译器能够兼容C语言的编译方式,但C++编译器会优先使用C++的方式进行编译利用extern关键字强制让C++编译器对代码进行C方式编译。C++和C的编译方式是不同的,因为语言是不同的,这些方式主要包括一些规则和一些约束等。

2.C++(main.cpp)调用C语言(add.c)编写的函数

代码如下:

main.cpp

#include <stdio.h>

extern "C"
{
#include "add.h"
} int main()
{
printf("1 + 2 = %d\n", add(1, 2)); return 0;
}

add.c

#include "add.h"

int add(int a, int b)
{
return a + b;
}

编译流程:① gcc add.c -o add.o 或 gcc -c add.c ②g++ main.cpp add.o就可以了

3.C语言(main.c)调用C++(add.cpp)编写的函数
代码如下:

main.c

#include <stdio.h>
#include "add.h" int main()
{
printf("1 + 2 = %d\n", add(1, 2)); return 0;
}

add.cpp

extern "C"
{ #include "add.h" int add(int a, int b)
{
return a + b;
} }

编译流程:① g++ -c add.cpp②gcc main.c -lstdc++ add.o 

问题:这里相互编译的过程是调用了两个不同的编译器gcc和g++,但是里面的标准以及函数链接库肯定会存在差异,也就是说虽然C++是C的发展,但是仍然会产生问题,不过这个问题是由编译器来掩盖的?还是这就是C++的先进所在?两个编译器的差别以及这两种标准的融合?

4.C++和C相互调用的同意解决方案

_cplusplus是c++编译器内置的标准宏定义,让c代码既可以通过c编译器的编译,又可以在c++编译器中以c的方式进行编译(使用条件编译),代码如下:

#include <stdio.h>
#include <string.h> #ifdef __cplusplus
extern "C" {
#endif int func(int a, int b)
{
return a + b;
} int func(const char* s)
{
return strlen(s);
} #ifdef __cplusplus
}
#endif int main(int argc, char *argv[])
{
printf("Press enter to continue ...");
getchar();
return 0;
}

注意:在extern “C”的两个大括号之间可以放函数的定义或者函数的声明,不单单是函数的定义。
5.
C++编译器不能以C语言的方式编译多个重载函数

错误代码示例:

#ifdef __cplusplus
extern "C"{
#endif void f()
{ } void f(int i)
{ }
#ifdef __cplusplus
}
#endif int main()
{
return 0;
}

C++基础学习笔记----第四课(函数的重载、C和C++的相互调用)的更多相关文章

  1. C++基础学习笔记----第十三课(操作符重载-下)

    本节主要讲使用成员函数重载操作符,包括[],=,(),->四种操作符的重载以及&&和||的问题. 类的成员函数进行操作符重载 基本概念 类的成员函数也可以进行操作符的重载.类的普 ...

  2. Java中执行存储过程和函数(web基础学习笔记十四)

    一.概述 如果想要执行存储过程,我们应该使用 CallableStatement 接口. CallableStatement 接口继承自PreparedStatement 接口.所以CallableS ...

  3. python 基础学习笔记(6)--函数(2)

                                                                                                        ...

  4. python 基础学习笔记(6)--函数(1)

    ## **函数(1)** **函数的定义:** 1. [ ] 小时候大家应该都玩过乐高积木,只要通过想象和创意,可以用它怕拼凑出很多神奇的东西.随着学习的深入,编写的代码日益增加并且越来越复杂,所以需 ...

  5. Python基础学习笔记(十一)函数、模块与包

    参考资料: 1. <Python基础教程> 2. http://www.runoob.com/python/python-functions.html 3. http://www.liao ...

  6. python学习笔记(四)— 函数

    一.函数是什么? 函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,编程中的函数在英文中也有很多不同的叫法.在BASIC中叫做subroutine(子过程或子程序),在Pasc ...

  7. ASP.Net MVC开发基础学习笔记:四、校验、AJAX与过滤器

    一.校验 — 表单不是你想提想提就能提 1.1 DataAnnotations(数据注解) 位于 System.ComponentModel.DataAnnotations 命名空间中的特性指定对数据 ...

  8. Python基础学习笔记(四)语句

    参考资料: 1. <Python基础教程> 2. http://www.runoob.com/python/python-chinese-encoding.html 3. http://w ...

  9. python基础学习笔记第四天 list 元祖 字典

    一 LIST方法 列表操作包含以下函数:1.cmp(list1, list2):比较两个列表的元素 2.len(list):列表元素个数 3.max(list):返回列表元素最大值 4.min(lis ...

随机推荐

  1. 数据结构——二叉搜索树(Binary Search Tree)

    二叉树(Binary Tree)的基础下 每个父节点下 左节点小,右节点大. 节点的插入: 若root==NULL则root=newnode 否则不断与节点值比较,较小则向左比较,较大则向右比较. 完 ...

  2. JQuery实现表格的相同单元格合并的三种方法

    代码: <!DOCTYPE html> <html> <head> <title>merge.html</title> <meta h ...

  3. gdal库的三个使用心得

    作者:朱金灿 来源:http://blog.csdn.net/clever101 最近使用gdal库比较多,就谈谈gdal库的一些使用心得. 第一个是GDALOpen的访问权限参数会影响图像的创建金字 ...

  4. Java 输出通过 InetAddress 获得的 IP 地址数组

    使用 InetAddress 获取 IP 地址会得到一个 byte 数组 如果你直接输出这个数组,你会发现 IP 地址中的某些位变成了负数 比如 61.135.169.105 会输出成 61.-121 ...

  5. IBATIS动态SQL

    转自:http://www.cnblogs.com/phoebus0501/archive/2011/05/16/2048126.html 直接使用JDBC一个非常普遍的问题就是动态SQL.使用参数值 ...

  6. Android短信拦截和电话拦截

    MainActivity: package com.wyl.bctest; import android.support.v7.app.ActionBarActivity; import androi ...

  7. 【 D3.js 入门系列 — 3 】 做一个简单的图表!

    图1. 柱形图 1. 柱形图 前几章的例子,都是对文字进行处理.本章中将用 D3 做一个简单的柱形图.制作柱形图有很多种方法,比如用 HTML 的 <div> 标签,或在 SVG 上绘制 ...

  8. ASP.NET MVC 5 学习教程:通过控制器访问模型的数据

    原文 ASP.NET MVC 5 学习教程:通过控制器访问模型的数据 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连 ...

  9. mysql HA方案: MHA

    mysql-master-ha mysql 做热备和高可用的方法有很多种, 比如: mmm: http://mysql-mmm.org/ mha: https://code.google.com/p/ ...

  10. Shell之sed命令

    sed用于一次性处理所有的编辑任务,尤为高效,为用户节省了大量的时间,sed适用于以下三种场合: 1.编辑相对交互文本编辑器而言太大的文件: 2.编辑命令太复杂,在交互式文本编辑器中难以输入的情况: ...