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


    本节主要讲了函数重载的主要概念以及使用方法,还有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
    ", func(1));
    	printf ("func(1,2) = %d
    ", func(1,2));
    	printf ("func(1,2,3) = %d
    ", func(1,2,3));
    	printf ("func(abcdef) = %d
    ", 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
    ", func(1,"ac"));
    	printf ("func(ac, 1) = %d
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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;
    }
  • 相关阅读:
    数据结构与算法JavaScript (一) 栈
    js架构设计模式——前端MVVM框架设计及实现(二)
    js架构设计模式——前端MVVM框架设计及实现(一)
    js架构设计模式——MVC,MVP 和 MVVM 的图示及简单明了的区别说明
    js架构设计模式——你对MVC、MVP、MVVM 三种组合模式分别有什么样的理解?
    js面向对象oop编程
    js模块化开发——前端模块化
    SPRING 集成 activemq 的 topic 模式
    linux yum 本地源配置
    ORACLE 导入的问题
  • 原文地址:https://www.cnblogs.com/riasky/p/3455584.html
Copyright © 2020-2023  润新知