【C++】 9_函数重载分析 (下)

news/2023/12/9 16:27:27 标签: c/c++

重载与指针

  • 函数重载遇上函数指针

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

      • 根据重载规则挑选与函数指针参数列表一致的候选者
      • 严格匹配候选者的函数类型与函数指针的函数类型

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

#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 c);

int main(int argc, char* argv[])
{
    int c = 0;
    
    PFUNC p = func;
    
    c = p(1);
    
    printf("c = %d\n", c);

    return 0;
}
输出:
c = 1
  • 注意

    • 函数重载必然发生在同一个作用域
    • 编译器需要用参数列表函数类型进行函数选择
    • 无法直接通过函数名得到重载函数的入口

应该怎样获得某一个重载函数的地址呢?

#include <stdio.h>

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

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

int main()
{
    printf("%p\n", (int(*)(int, int))add);        // 通过类型转换得到函数指针 
    printf("%p\n", (int(*)(int, int, int))add);

    return 0;
}

C++ 和 C 相互调用

  • 实际工程中 C++ 和 C 代码相互调用是不可避免的(尤其在已经存在的C源码或C库)
  • C++ 编译器能够兼容 C 语言的编译方式
  • C++ 编译器会优先使用 C++ 编译的方式
  • extern 关键字能强制让 C++ 编译器进行 C 方式的编译
extern "C"
{
    // do C-style compilation here
}

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

add.h

int add(int a, int b);

add.c

#include "add.h"

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

main_1.cpp

#include <stdio.h>
#include "add.h"

int main()
{
    int c = add(1, 2);
    
    printf("c = %d\n", c);
    
    return 0;
}
gcc -c add.c -o add.oo
g++ add.h add.oo main.cpp 
 
输出:
main_1.cpp:(.text+0x19): undefined reference to `add(int, int)'
collect2: ld returned 1 exit status

main_2.c

#include <stdio.h>
extern "C"
{

#include "add.h"

}

int main()
{
    int c = add(1, 2);
    
    printf("c = %d\n", c);
    
    return 0;
}
输出:
c = 3

分析:【不同的编译方式导致不同的编译结果】
gcc 编译 add.c add.h 生成 add.oo 中的符号表
00000000 T add

g++ 编译 add.c add.h 生成 add.oo 中的符号表
00000000 T _Z3addii
     U __gxx_personality_v0

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

  • __cplusplus 是 C++ 编译器内置的标准宏定义
  • __cplusplus 的意义:确保 C 代码以统一的 C 方式被编译成目标文件
#ifdef __cpusplus
extern "C" {
#endif

// C-Style Compilation

#ifdef __cpluscplus
}
#endif

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

add.h

int add(int a, int b);

add.c

#include "add.h"

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

main.c

#include <stdio.h>

#ifdef __cplusplus
extern "C"
{
#endif

#include "add.h"

#ifdef __cplusplus
}
#endif

int main()
{
    int c = add(1, 2);
    
    printf("c = %d\n", c);
    
    return 0;
}
输出:
c = 3

注意事项:

  • C++ 编译器不能以 C 的方式编译重载函数
  • 编译方式决定函数名被编译后的目标名
  • C++ 编译方式将函数名和参数列表编译成目标名
  • C 编译方式只将函数名作为目标名进行编译

小结

  • 函数重载是 C++ 对 C 的一个重要升级
  • 函数重载通过函数参数列表区分不同的同名函数
  • extern 关键字能够实现 C 和 C++ 的相互调用
  • 编译方式决定符号表中的函数名的最终目标名

以上内容参考狄泰软件学院系列课程,请大家保护原创!


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

相关文章

Shell:命令别名

alias命令设置别名&#xff1a; alias cls"clear"设置的别名会在当前bash退出时失效&#xff0c;可以将命令写入~/.bashrc&#xff1a; echo alias cls"clear" >> ~/.bashrc若想跳过使用别名而使用原始命令&#xff0c;可在命令前加\符号&#xff1a…

Arrays工具类十大常用方法

翻译人员: 铁锚 翻译日期: 2013年11月19日 原文链接: Top 10 Methods for Java Arrays 以下是由 stackoverflow 网站 投票决出的Java数组最常用的十个方法, 0. 声明数组 String[] aArray new String[5]; String[] bArray {"a","b","c", &q…

Java和计算机科学课程的关系

翻译人员: 铁锚 翻译时间: 2013年11月20日 原文链接: Java and Computer Science Courses 一个好程序员不仅要知道如何编程来完成特定任务,还要了解为什么要这样编程,以及掌握如何高效地实现。 事实上,我们通过Google几乎可以找到任意代码.所以了解为什么这样做比起实现功能…

ThinkPHP pdo连接Oracle的配置写法,提示报错

DB_TYPE > pdo, // 数据库类型DB_USER > user101, // usernameDB_PWD > zb~!#$%, // passwordDB_PREFIX > TB_, // 数据库表前缀DB_DSN > oci:dbname127.0.0.1:1158/orcl;charsetutf8, ThinkPHP 3.2.2 …

PO VO BO DTO POJO DAO

2019独角兽企业重金招聘Python工程师标准>>> PO VO BO DTO POJO DAO 总体一览&#xff1a; 1.DAO[data access object]数据访问对象 用于数据访问的 java 类&#xff0c;对数据访问不仅仅指的是对数据库的访问。 假如A系统调用B系统的服务获取数据&#xff0c;这时候…

Java之谜 —— 来自Neal Gafter的演讲

翻译人员: 铁锚 翻译日期: 2013年11月20日 原文链接: A Puzzle from “A Brief History of the (Java) World and a Peek Forward” Presented by Neal Gafter 以下是来自Neal Gafter 演讲中的一个Java谜题: import java.util.Random; // Rhymes,押韵 public class Rhymes {…

erlang调试方法

第一种方式&#xff0c;加打印记录%%-define(debug, ok).-ifdef(debug). -define(LOG(X), io:format("pid:~p , {~p,~p}: ~p~n", [self(), ?MODULE, ?LINE, X])). -else. -define(LOG(X), true). -endif.设置LOG的宏定义&#xff0c;调试只要在代码中加入?LOG(Val…

Oracle Cloud Native Framework推出云原生解决方案

摘要&#xff1a;Oracle Cloud Native Framework云原生平台提供托管云服务和本地软件&#xff0c;同时在现Oracle云基础架构上跨应用程序配置和分析大量服务。developer relations for Oracle Cloud Infrastructure副总裁Bob Quillin讨论了该框架的优势以及对2019年云原生市场的…

Java异常处理示例

翻译人员: 铁锚 翻译日期: 2013年11月22日 原文链接: Java Exception Handling Example 本文中有两个示例, 第一个演示了所有调用其他方法的地方&#xff0c;都必须处理被调用函数抛出的异常.第二个示例演示了捕获父类异常也可以用来捕获子类异常。 1 调用函数必须处理被调…

一、OSI七层参考模型摘要

一、&#xff08;Open systems interconnection&#xff09;OSI参考模型1、网络&#xff1a;就是将分布在不同地理位置&#xff0c;具有独立功能的终端&#xff0c;通过通信线路和通信设备相互连接起来&#xff0c;进行数据通信&#xff0c;实现资源共享。2、LAN&#xff08;Lo…

从length与length()开始谈Java

翻译人员: 铁锚 翻译时间: 2013年11月23日 原文链接: Start from length & length() in Java 首先请看下面的问题,你能快速地回答上来吗? 假设没有任何集成开发环境和自动补全功能,如何获取数组的长度?如何取得字符串的长度? 我将为 新手以及中等水平这个水平之间的开…

【Bugly 技术干货】Android开发必备知识:为什么说Kotlin值得一试

1、Hello, Kotlin Bugly 技术干货系列内容主要涉及移动开发方向&#xff0c;是由 Bugly 邀请腾讯内部各位技术大咖&#xff0c;通过日常工作经验的总结以及感悟撰写而成&#xff0c;内容均属原创&#xff0c;转载请标明出处。 1.1 Kotlin的身世 写了许久Java&#xff0c;有没有…

My sql 8.0.13 安装填坑

会报错的写法&#xff1a; GRANT ALL PRIVILEGES ON *.* root% identified by 123123 WITH GRANT OPTION; 以下是正确的写法&#xff1a; grant all privileges on *.* to root’%’ ;转载于:https://www.cnblogs.com/yuanhang/p/10160849.html

比较ArrayList、LinkedList、Vector

翻译人员: 铁锚翻译时间: 2013年12月2日原文链接: ArrayList vs. LinkedList vs. Vector1. List概述 List,就如图名字所示一样,是元素的有序列表。当我们讨论List时&#xff0c;将其与Set作对比是一个很好的办法,Set集合中的元素是无序且唯一的。下图是Collection的类继承图,从…

对比常量存储与堆栈

翻译人员: 铁锚 翻译时间: 2013年12月3日 原文链接: Static Storage vs Heap vs Stack 下面是对编译器内存分配的总结: 1. 静态分配 vs 动态分配 静态分配: 编译器只依赖于程序代码中的字面量就可以进行分配的部分。静态分配尽可能多地分配数据对象,原因之一是这些对象的…

在Linux(ubuntu server)上面安装NodeJS的正确姿势

上一篇文章&#xff0c;我介绍了 在Windows中安装NodeJS的正确姿势&#xff0c;这一篇&#xff0c;我们继续来看一下在Linux上面安装和配置NodeJS。 为了保持一致&#xff0c;这里也列举三个方法 第一个方法&#xff1a;通过官网下载安装 https://nodejs.org/en/download/ 这种…
最新文章