重载与指针

下面的函数指针将保存哪个函数的地址:

在给p赋值的时候,我们使用了func,但是这里并没有指明参数,编译器是怎么知道这个func函数指的是第一个func函数呢?

函数重载遇上指针:

  将重载函数名赋值给函数指针时

    1、根据重载规则挑选与函数指针参数列表一致的候选者

    2、严格匹配候选者的函数类型与函数指针的函数类型

测试程序如下:

 #include <stdio.h>
#include <string.h> int func(int x)
{
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 main(int argc, char *argv[])
{
int c = ; PFUNC p = func; c = p(); printf("c = %d\n", c); return ;
}

编译运行结果如下:

将19行的返回类型由int改为void或者double,再次编译,结果如下:

三个候选函数都无法匹配p的类型。因为当函数重载遇上函数指针时,编译器会严格匹配函数类型,函数类型包括返回值类型和参数类型。

重载与指针

注意:

  1、函数重载必然发生在同一个作用域中

  2、编译器需要用参数列表或函数类型进行函数选择

  3、无法直接通过函数名得到重载函数的入口地址

在上一节中,我们直接通过函数名打印了函数地址,这样的话和这里的第三条不就矛盾了吗?

上一节我们对函数名进行了一些转换,如果不转换的话,编译会报错,如下:

编译错误提示我们函数指针没有上下文类型信息。

写上类型转换信息,再次编译,如下:

因为有了明确的类型转换信息,编译器就会根据要转换的目标类型,严格的去匹配函数。严格的匹配就是根据函数的返回值类型和参数类型去匹配,这两个合起来就叫做函数类型。我们也可以说严格的按照函数类型去匹配。

C和C++相互调用:

C++调用C语言写的库:

C++编译器直接编译C语言源码可以直接通过,但是这里我们解决的不是源码编译问题,而是,我们要在C++中利用以前别人别写好的C库函数,这些函数是看不到源码的,它们被编译成了目标文件,我们只能调用。

示例:

编写add.h文件:

 int add(int a, int b);

编写add.c文件:

 #include "add.h"

 int add(int a, int b)

 {

     return a + b;

 }

通过命令gcc -c add.c -o add.o将add.c编译成add.o中间文件。

在main函数中编写C++程序调用add函数(C语言编写的),如下所示:

报错提示我们符号找不到。

通过执行nm  add.o,我们发现add.o文件中确实有add符号。

为了解决这种问题,我们需要强制C++编译器使用C语言的编译方式。

通过extern(extern  "C")关键字可以达到这种目的。

我们将#include "add.h"放进extern "C"中,再次编译运行,结果如下:

如何保证一段C代码只会以C的方式被编译?

我们第一个想到的是加上extern "C",但是这个关键字是C++中才有的,C语言中没有这个用法,如果我们在源程序中写上extern "C",然后用C语言编译器编译就会报错。

解决方案如下:

__cplusplus是所有的C++编译器都支持的,标准的宏定义。

实验如下:编写C版本的main函数

用C语言编译器可以编译成功。

注意事项:

示例如下:

可以看到g++编译器编译后目标名里面有参数类型信息。

上述函数以C方式编译的话会直接报错,因为这两个函数得到相同的目标名,因为C语言中没有重载的概念。

小结:

  函数重载是C++对C的一个重要升级

  函数重载通过函数参数列表区分不同的同名函数

  extern关键字能够实现C和C++的相互调用,但是extern “C”代码块中绝对不能有重载函数

  编译方式决定符号表中的函数名的最终目标名

第9课 函数重载分析(下)与C、C++相互调用的更多相关文章

  1. 第七课 GDB调试 (下)

    1序言: 通过前面一节第六课 GDB调试 (下)文章,可以掌握理解了gdb调试:怎么启动.运行,打断点.查看变量.甚至改变变量等的知识,今天来大概讲解下调试bug的类型. 2知识点: 2.1 就像之前 ...

  2. C++基础学习笔记----第四课(函数的重载、C和C++的相互调用)

    本节主要讲了函数重载的主要概念以及使用方法,还有C和C++的相互调用的准则和具体的工程中的使用技巧. 函数重载 1.基本概念 函数重载就是用同一个函数名来定义不同的函数.使用不同的函数参数来搭配同一个 ...

  3. Swift 中的函数(下)

    学习来自<极客学院:Swift中的函数> 工具:Xcode6.4 直接上基础的示例代码,多敲多体会就会有收获:百看不如一敲,一敲就会 import Foundation /******** ...

  4. C++解析(7):函数重载分析

    0.目录 1.重载的概念 2.C++中的函数重载 3.函数默认参数遇上函数重载 4.编译器调用重载函数的准则 5.重载与指针 6.C++和C相互调用 7.小结 1.重载的概念 自然语言中的上下文--你 ...

  5. C++中的函数重载分析(二)

    1,重载与指针: 1,下面的函数指针将保存哪个函数的地址? int func(int x) { return x; } int func(int a, int b) { return a + b; } ...

  6. Linux下进程的同步相互排斥实例——生产者消费者

    linux下的同步和相互排斥 Linux sync_mutex 看的更舒服点的版本号= = https://github.com/Svtter/MyBlog/blob/master/Linux/pth ...

  7. .Net 环境下C# 通过托管C++调用本地C++ Dll文件

     综述 : 本文章介绍.Net 环境下C# 通过托管C++调用本地C++ Dll文件, 示例环境为:VS2010, .Net4.0, Win7. 具体事例为测试C++, C#, 及C#调用本地C++D ...

  8. C&C++——C函数与C++函数相互调用问题

    C C++相互调用 在项目中融合C和C++有时是不可避免的,在调用对方的功能函数的时候,或许会出现这样那样的问题,但只要我的C代码和我的C++代码分别都能成功编译,那其他就不是问题.近来在主程序是C语 ...

  9. .netcore在linux下使用P/invoke方式调用linux动态库

    http://www.mamicode.com/info-detail-2358309.html   .netcore下已经实现了通过p/invoke方式调用linux的动态链接库(*.so)文件 1 ...

随机推荐

  1. PAT 1075 PAT Judge[比较]

    1075 PAT Judge (25 分) The ranklist of PAT is generated from the status list, which shows the scores ...

  2. docker——核心实现技术

    作为一种容器虚拟化技术,Docker深度应用了操作系统的多项底层支持技术. 早期版本的Docker是基于已经成熟的Linux Container(LXC)技术实现的.自从0.9版本起,Docker逐渐 ...

  3. NodeJS学习笔记二

    类声明和类表达式 ES6 中的类实际上就是个函数,而且正如函数的定义方式有函数声明和函数表达式两种一样,类的定义方式也有两种,分别是:类声明.类表达式. 类声明 类声明是定义类的一种方式,就像下面这样 ...

  4. SQL语句中case函数

    case函数,严格的意义上来讲case函数已经试流程控制语句了,不是简单意义上的函数,不过为了方便,很多人将case函数称为流程控制函数. case函数的一般有两种用法:1.case expressi ...

  5. MD5—加密,加盐

    MD5的参考盐值:String salt = "212*)()()**()^&UYGbakdkj " ; MD5—加密工具类 package com.demo.tools; ...

  6. Ubuntu 系统下暴力卸载 MySQL

    一.概述 MySQL 出问题了,正常的 start.stop 不起作用. apt-get remove mysql-server apt-get remove mysql-client 上面这些命令不 ...

  7. 【android】如何让WebView对Video标签的支持更强力

    先说结论:各个产商对HTML5特性支持的程度不一样,用默认的WebChromeClient不能普遍适用. 因此咱基于GITHUB上一个VideoEnabledWebView库做了自己的封装,在魅族.华 ...

  8. 20145325张梓靖 实验四 "Andoid开发基础"

    20145325张梓靖 实验四 "Andoid开发基础" 实验内容 使用 Android Studio 设计"Hello" 设计过程 创建项目 选择.xml中的 ...

  9. git中Untracked files如何清除

    $ git status # On branch test # Untracked files: # (use "git add <file>..." to inclu ...

  10. Java 面试题收集

    1.java有哪些常用的包 java.langjava.utiljava.iojava.netjava.sqljava.awtjava.text java.math 2.Java接口修饰符final ...