天天看點

C++深度解析 函數重載分析---函數指針,函數重載,C++和C互相調用(8)函數指針函數重載  VS  函數指針C++和C互相調用保證代碼,即被C的編譯器編譯過,也被C++的編譯器編譯過。 C++編譯方式将函數名和參數清單編譯成目标名注意事項小結:

C++深度解析 函數重載分析--函數指針,函數重載,C++和C互相調用(8)

函數指針

typedef  傳回類型(*新類型)(參數表)

typedef char (*PTRFUN)(int);   
PTRFUN pFun;   
char glFun(int a){ return;}   
void main()   
{   
    pFun = glFun;   
    (*pFun)(2);   
}   
           

typedef的功能是定義新的類型。第一句就是定義了一種PTRFUN的類型,并定義這種類型為指向某種函數的指針,這種函數以一個int為參數并傳回char類型。後面就可以像使用int,char一樣使用PTRFUN了。 第二行的代碼便使用這個新類型定義了變量pFun。

函數重載  VS  函數指針

函數重載遇上函數指針時:

将重載函數名指派給函數指針時

1、根據重載規則挑選與函數指針參數清單一緻的候選者

2、嚴格比對候選者的函數類型與函數指針的函數類型

示例程式:(函數重載 VS 函數指針)

#include <stdio.h>
#include <string.h>

int func(int x)
{
    return x;
}

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

int func(char* s)
{
    return strlen(s);
}

//函數指針類型PFUNC
typedef int(*PFUNC)(int a);

int main(int argc, char* argv[])
{
    int c = 0;
    
    //函數指針p
    PFUNC p = func;
    
    //根據函數指針p,所指向參數清單進行選擇:(int a)
    //嚴格比對函數類型:int
    c = p(1);
    
    printf("c = %d\n", c);
    
    return 0;
}
           

結果如下:

C++深度解析 函數重載分析---函數指針,函數重載,C++和C互相調用(8)函數指針函數重載  VS  函數指針C++和C互相調用保證代碼,即被C的編譯器編譯過,也被C++的編譯器編譯過。 C++編譯方式将函數名和參數清單編譯成目标名注意事項小結:

從上述例子,注意:

函數重載必然發生在同一個作用域中。

編譯器需要用參數清單或函數類型進行函數選擇。

無法直接通過函數名得到重載函數的入口位址(參考上一章節的最後一個例子!!!!)

C++和C互相調用

C++編譯器要相容C語言的編譯方式。

C++編譯器會優先使用C++編譯的方式

extern關鍵字能強制讓C++編譯器進行C方式的編譯

//告訴C++編譯器,下面的代碼是以C語言的方式編譯
extern "C"
{
    //do C-style compilation here
}
           

示例程式:(建立立一個檔案夾)

add.h

int add(int a, int b);
           

add.c

#include "add.h"

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

main.cpp(調用C函數)

#include <stdio.h>

//告訴C++編譯器,add.h包含的内容(C代碼)必須用C方式編譯
extern "C"
{
#include "add.h"
}

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

結果如下:(*.o 目标檔案)

C++深度解析 函數重載分析---函數指針,函數重載,C++和C互相調用(8)函數指針函數重載  VS  函數指針C++和C互相調用保證代碼,即被C的編譯器編譯過,也被C++的編譯器編譯過。 C++編譯方式将函數名和參數清單編譯成目标名注意事項小結:
C++深度解析 函數重載分析---函數指針,函數重載,C++和C互相調用(8)函數指針函數重載  VS  函數指針C++和C互相調用保證代碼,即被C的編譯器編譯過,也被C++的編譯器編譯過。 C++編譯方式将函數名和參數清單編譯成目标名注意事項小結:

通過nm指令,檢視add.o目标檔案(用C語言編譯器編譯的)的符号表資訊,檢視是否有add函數。

保證代碼,即被C的編譯器編譯過,也被C++的編譯器編譯過。

__cplusplus是C++編譯器内置的标準宏定義,可以測試目前的編譯器 是不是 C++編譯器

__cpluscplus:確定C代碼以統一的C方式被編譯成目标檔案

示例程式:

#include <stdio.h>

//兩個#ifdef #endif
#ifdef __cplusplus //如果是C++編譯器(__cplusplus測試目前的編譯器 是不是 C++編譯器)
extern "C" {
#endif

#incldue "add.h"

#ifdef __cplusplus
}
#endif

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

結果如下:

C++深度解析 函數重載分析---函數指針,函數重載,C++和C互相調用(8)函數指針函數重載  VS  函數指針C++和C互相調用保證代碼,即被C的編譯器編譯過,也被C++的編譯器編譯過。 C++編譯方式将函數名和參數清單編譯成目标名注意事項小結:

C++編譯方式将函數名和參數清單編譯成目标名

示例程式:

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

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

結果如下:

C++深度解析 函數重載分析---函數指針,函數重載,C++和C互相調用(8)函數指針函數重載  VS  函數指針C++和C互相調用保證代碼,即被C的編譯器編譯過,也被C++的編譯器編譯過。 C++編譯方式将函數名和參數清單編譯成目标名注意事項小結:

分析:從上圖可以知道test.oo的符号表,_Z3addii和_Z3addiii這兩個是被編譯後的目标函數名(附加資訊),ii和iii代表參數的個數,ii表明有兩個參數int,iii表明有三個參數int。

注意事項

C++編譯器不能以C的方式編譯重載函數。

編譯方式決定函數名被編譯後的目标名。

C++編譯方式将函數名和參數清單編譯成目标名

小結:

函數重載通過函數名和參數清單,來區分不同的同名函數。

在extern "C"代碼塊中,不能存在重載函數!!!

函數傳回值不能作為函數重載的依據。

繼續閱讀