1,重載與指針:編程
1,下面的函數指針將保存哪一個函數的地址? ide
1 int func(int x) 2 { 3 return x; 4 } 5 6 int func(int a, int b) 7 { 8 return a + b; 9 } 10 11 int func(const char* s) 12 { 13 return strlen(s); 14 } 15 16 typedef int(*PFUNC)(int a); 17 int c = 0; 18 PFUNC p = func; 19 c = p(1); // which function to call ?
2,重載函數的函數名不表明函數的入口地址,要加入相應的函數類型方可;函數
2,函數重載趕上函數指針:測試
1,將重載函數名賦值給函數指針時:spa
1,根據重載規則挑選與函數指針參數列表一致的候選者;指針
2,嚴格匹配候選者的函數類型與函數指針的函數類型;code
1,比重載更加嚴格,也要加上返回值類型的匹配;blog
2,不進行任何形式的默認類型轉換;作用域
3,函數重載 VS 函數指針編程實驗:編譯器
1,main.cpp 文件:
1 #include <stdio.h> 2 #include <string.h> 3 4 int func(int x) 5 { 6 return x; 7 } 8 9 int func(int a, int b) 10 { 11 return a + b; 12 } 13 14 int func(const char* s) 15 { 16 return strlen(s); 17 } 18 19 typedef int(*PFUNC)(int a); //typedef double (*PFUNC)(int a) 時錯誤; 20 21 int main(int argc, char *argv[]) 22 { 23 int c = 0; 24 25 PFUNC p = func; 26 27 c = p(1); 28 29 printf("c = %d\n", c); 30 31 return 0; 32 }
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 文件:
1 int add(int a, int b);
2,add.c 文件:
1 #include "add.h" //不能用 #include <add.h>,不然找不到 add.h 文件,這裏不用包含這個文件以及定義 1 中的 add.h 頭文件也能夠編譯經過,可是後續的使用這個函數就只能包含源碼,因此仍是要調用頭文件; 2 3 int add(int a, int b) 4 { 5 return a + b; 6 }
3,用 gcc -c add.c -o add.o 編譯生成 add.o 文件;
4,在 main.c 文件中調用:
1 #include <stdio.h> 2 #include "add.h" 3 4 int main() 5 { 6 int c = add(1, 2); 7 8 printf("c = %d\n", c); 9 10 return 0; 11 }
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,代碼示例:
1 extern "C" // 告訴編譯器大括號中的代碼以 C 方式編譯; 2 { 3 // do C-style compilation here,能夠有不一樣的多個函數; 4 }
2,更改 main.cpp 文件以下:
1 #include <stdio.h> 2 3 extern "C" 4 { 5 #include "add.h" 6 } 7 8 int main() 9 { 10 int c = add(1, 2); 11 12 printf("c = %d\n", c); 13 14 return 0; 15 }
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++ 編譯器;
1 #ifdef _cplusplus // 判斷是否爲 C++ 編譯器; 2 extern "C" { // 保存這一行代碼; 3 #endif 4 5 // C-style Compilation here 6 7 #ifdef _cplusplus // 判斷是否爲 C++ 編譯器; 8 } // 保存這一行代碼; 9 #endif
9,注意事項:
1,C++ 編譯器不能以 C 的方式編譯重載函數;
1,編譯方式可以決定函數名被編譯後的目標名是什麼;
2,編譯方式決定函數名被編譯後的目標名:
1,C++ 編譯方式將函數名和參數列表編譯成目標名;
2,C 編譯方式只將函數名做爲目標名進行編譯;
10,小結:
1,函數重載是 C++ 對 C 的一個重要升級;
2,函數重載經過函數參數列表區分不一樣的同名函數;
3,extern 關鍵字可以實現 C 和 C++ 的相互調用;
1,extern "C" 代碼塊中不能出現重載函數;
4,編譯方式決定符號表中的函數名的最終目標名;