1,重载与指针:

1,下面的函数指针将保存哪个函数的地址?

 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 c = ;
PFUNC p = func;
c = p(); // which function to call ?

2,重载函数的函数名不代表函数的入口地址,要加入相应的函数类型方可;

2,函数重载遇上函数指针:

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

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

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

1,比重载更加严格,也要加上返回值类型的匹配;

2,不进行任何形式的默认类型转换;

3,函数重载 VS 函数指针编程实验:

1,main.cpp 文件:

 #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); //typedef double (*PFUNC)(int a) 时错误; int main(int argc, char *argv[])
{
int c = ; PFUNC p = func; c = p(); printf("c = %d\n", c); return ;
}

2,输出结果:

  1

4,注意:

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

1,C++ 中不止一个作用域,还有类作用域等;

2,C 只有一个全局作用域;

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

1,重载时,如果不碰到指针,则用参数列表选择,如果碰到指针,则用函数类型来选择;

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

1,强制类型转换为函数指针可以;

5,C++ 和 C 相互调用:

1,实际工程中 C++ 和 C 代码相互调用是不可避免的;

 1,项目中决定采用 C++ 的时候,也很可能会调用旧的用 C 代码编写的代码,这时就涉及到 C++ 调用 C 代码;

 2,C++ 编译器编译 C 的源码可以直接通过,但是工程中有一些 C 代码被编译成目标文件,相当于在 C++ 中会用到用 C 语言编写和编译的第三 方的库,这些第三方库还是要收费的,既然收费了,就要合理的利用;

 3,见如下示例:

 1,add.h 文件: 

 int add(int a, int b);

 2,add.c 文件:

 #include "add.h" //不能用 #include <add.h>,否则找不到 add.h 文件,这里不用包含这个文件以及定义 1 中的 add.h 头文件也可以编译通过,但是后续的使用这个函数就只能包含源码,所以还是要调用头文件;

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

    3,用 gcc -c add.c -o add.o 编译生成 add.o 文件;

    4,在 main.c 文件中调用:

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

  5,通过 g++ main.cpp add.o(第三方库不提供源代码,只提供头文件和编译生成的目标文件) 命令编译器显示:undefin dreference    to 'add(int, int)';

  6,通过符号表命令 nm 查阅 nm add.o 得到: 00000000 T add,说明符号表中已经有 add 函数了;

  7,因为用 C++ 编译器调用 C 编译器编译的代码,不能成功;

2,C++ 编译器能够兼容 C 语言的编译方式;

 1,C++ 天生需要兼容 C;

 2,C++ 和 C 编译方式是不同的,C++ 编译器能够兼容 C 语言编译方式, 但是有优先级问题;

3,C++ 编译器会优先使用 C++ 编译的方式;

4,extern 关键字能强制让 C++ 编译器进行 C 方式的编译;

 1,代码示例:

 extern "C"  // 告诉编译器大括号中的代码以 C 方式编译;
{
// do C-style compilation here,可以有不同的多个函数;
}

 2,更改 main.cpp 文件如下:

 #include <stdio.h>

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

6,C++ 调用 C 函数编程实验:

1,见本博客 5.4.2内容;

7,问题:

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

1,不能直接调用 extern "C",因为这是 C++ 中才有的,C 语言中不支持这样的写法,此处是一段 C 代码不管在 C 编译器还是 C++ 编译器都只以 C 方式编译,所以就要在 C 代码中来入手;

2,如果在 C 编译器中编译带有 extern "C" 的代码,则会报错,在 C++中不会,报错的内容为“expected identifier(标识符) or '(' before          string constant”;

8,解决方案:

1,_cplusplus 是 C++ 编译器内置的标准宏定义;

1,测试当前的编译器是否为 C++ 编译器,因为在 C 编译器内部不含有这个宏;

2,_cplusplus 的意义:

1,确保 C 代码以统一的 C 方式被编译成目标文件;

2,#ifdef _cplusplus  // 判断是否为 C++ 编译器;

 #ifdef _cplusplus  // 判断是否为 C++ 编译器;
extern "C" { // 保存这一行代码;
#endif // C-style Compilation here #ifdef _cplusplus // 判断是否为 C++ 编译器;
} // 保存这一行代码;
#endif

9,注意事项:

1,C++ 编译器不能以 C 的方式编译重载函数;

1,编译方式能够决定函数名被编译后的目标名是什么;

2,编译方式决定函数名被编译后的目标名:

1,C++ 编译方式将函数名和参数列表编译成目标名;

2,C 编译方式只将函数名作为目标名进行编译;

10,小结:

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

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

3,extern 关键字能够实现 C 和 C++ 的相互调用;

1,extern "C" 代码块中不能出现重载函数;

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

C++中的函数重载分析(二)的更多相关文章

  1. C++中的函数重载分析(一)

    1,重载是 C 语言到 C++ 语言的一个飞跃,C 语言中没有重载的概念,所有的函数 名是不允许有重复的,在 C++ 中因为引进了重载,所以函数名可以重复: 2,自然语言中的上下文: 1,你知道上面词 ...

  2. Linux中文件函数(二)

    一.link.linkat.unlink.unlinkat.remove函数 创建一个指向现有文件的链接的方法是使用link函数或linkat函数.函数的原型为: #include <unist ...

  3. EmguCV Image类中的函数(二)使用MorphologyEx进行更多的变换

    MorphologyEx中所有的变换如下图所示 调用方法: Mat aaa = CvInvoke.GetStructuringElement(Emgu.CV.CvEnum.ElementShape.R ...

  4. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  5. 一、MySQL中的索引 二、MySQL中的函数 三、MySQL数据库的备份和恢复 四、数据库设计和优化(重点)

    一.MySQL中的索引###<1>索引的概念 索引就是一种数据结构(高效获取数据),在mysql中以文件的方式存在.存储建立了索引列的地址或者指向. 文件 :(以某种数据 结构存放) 存放 ...

  6. C#中的函数式编程:递归与纯函数(二) 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面

    C#中的函数式编程:递归与纯函数(二)   在序言中,我们提到函数式编程的两大特征:无副作用.函数是第一公民.现在,我们先来深入第一个特征:无副作用. 无副作用是通过引用透明(Referential ...

  7. C#中的函数(二) 有参有返回值的函数

    接上一篇 C#中的函数(-) 无参无返回值的函数 http://www.cnblogs.com/fzxiaoyi/p/8502613.html 这次研究下C#中的函数(二) 有参有返回值的函数 依然写 ...

  8. 理解函数式编程中的函数组合--Monoids(二)

    使用函数式语言来建立领域模型--类型组合 理解函数式编程语言中的组合--前言(一) 理解函数式编程中的函数组合--Monoids(二) 继上篇文章引出<范畴论>之后,我准备通过几篇文章,来 ...

  9. PHP中的文件系统函数(二)

    这次我们来学习的是一些不是太常用,但却也非常有用的一些函数.它们中有些大家可能见过或者使用过,有一些可能就真的没什么印象了.它们都是 PHP 中文件系统相关操作函数的一部分.存在即合理,或许只是我们的 ...

随机推荐

  1. Solr的学习使用之(二)schema.xml等配置文件的解析

    上一篇文章已经讲解了如何部署Solr,部署是部署完了,可是总觉得心里空空的,没底,里面有N多配置文件,比如schema.xml.solrConfig.xml.solr.xml and so on……都 ...

  2. Kvm --01 虚拟化基础概念

    目录 1. 虚拟化基础概念 01. 什么是虚拟化? 02. 为什么要用虚拟化? 03. 虚拟化在企业中的应用场景? 04. 虚拟化软件介绍 05. Kvm介绍 2. 安装部署Kvm 3. Kvm虚拟机 ...

  3. MySQL06-- mysql索引

    目录 一.索引介绍 1.什么是索引 2.索引类型介绍 3.索引管理 5.索引操作 6.前缀索引 7.联合索引 8.创建索引总结: 一.索引介绍 1.什么是索引 1)索引就好比一本书的目录,它能让你更快 ...

  4. Polish orthography

    Computer encoding[edit] There are several different systems for encoding the Polish alphabet for com ...

  5. CSS实现三级菜单[转]

    头部导航条布局 html代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"&g ...

  6. java ArrayList存储基本类型

    package java06; /* 如果希望像集合ArrayList中存储基本数据类型数据,必须使用基本数据类型对应的“包装类” 基本数据类型 包装类(引用类型,包装类都位于java.lang包下 ...

  7. sqlserver 之 将查询结果变为json字符串

    GO /****** Object: StoredProcedure [dbo].[SerializeJSON] Script Date: 6/4/2019 3:58:23 PM 将查询结果变为jso ...

  8. MySQL MHA之 master_ip_failover.sh脚本

    master_ip_failover.sh脚本是用perl编写的,可以在mha-manager源码包中可以找到,下面给出的结合keepalived进行自动切换的脚本: [root@mha script ...

  9. AGC001[BCDE] 题解

    A没意思 F太难 所以大概近期的AGC题解都是BCDE的 然后特殊情况再说 开始刷AGC的原因就是计数太差 没有脑子 好几个学长都推荐的AGC所以就开始刷了 = = 大概两天三篇的速度?[可能也就最开 ...

  10. Java字节数组流学习

    字节数组流 基于内存操作,内部维护着一个字节数组,我们可以利用流的读取机制来处理字符串.无需关闭,不会报IOException. ByteArrayInputStream 包含一个内部缓冲区,该缓冲区 ...