本章主要內容:
- 1)函數重載
- 2)C++調用C代碼
- 3)new/delete關鍵字實現動態內存分配
- 4)namespace命名空間
大家都知道,在生活中,動詞和不同的名詞搭配一起,意義都會大有不同,比如”玩”:
- 玩游戲
- 玩卡牌
- 玩足球
所以在C++中,便出現了函數重載(JAVA,c#等語言都有函數重載)
1.函數重載(overload)
表示有多個相同的函數名(類似上面的”玩”),但是參數表不同(類似上面的名詞)
參數表不同主要有以下幾種
- 1) 參數個數不同
- 2) 參數類型不同
- 3) 參數順序不同
1.1舉個栗子
#include <stdio.h> int func(char *str) //func1 { printf("str=%s\n",str); } int func(int a) //func2 { printf("a=%d\n",a); } int func(int a,int b) //func3 { printf("a*b =%d\n",a*b); } int main() { char s[10]="hello"; func(s); func(10); func(5,5); }
輸出結果:
str=hello a=10 a*b =25
通過上個栗子可以看到,函數名相同,參數不同,而意義卻大有不同.
1.2那這些重載函數的入口地址是否相同
修改上面栗子的main()函數,如下圖所示:

可以看到輸出結果,每個函數的入口地址都不一樣(重載函數的入口地址,必須使用強制轉換來獲取)
也可以通過nm命令來查看符號表,如下圖所示:

注意:
- 重載函數需要避免使用參數默認值
- 調用重載函數時,只會匹配函數參數表,與函數返回值無關
- 函數重載必須發生在同一個作用域中
- 重載函數的入口地址,不能直接通過函數名來獲取
2.C++與C代碼相互調用
當C++想調用C里的某個函數時,則使用extern “C”
還是舉個栗子,通過C++調用C里面的add()函數
1) 首先創建3個文件

add.c代碼如下:
#include "add.h" int add(int a,int b) { return a+b; }
add.h代碼如下:
int add(int a,int b);
main.cpp代碼如下:
#include <stdio.h> #ifdef __cplusplus extern "C" //通過C方式來編譯add.h,也就是add()函數 { #include "add.h" } #endif int main() { printf("%d \n",add(1,3)); return 0; }
main.cpp里的__cplusplus宏是C++編譯器自帶的,而extern "C"只有C++里才有定義.
所以通過__cplusplus宏判斷,可以使main.cpp在C或C++編譯器下都能編譯運行.
2)編譯運行:
gcc -c add.c //生成add.o文件 g++ -o main main.cpp add.o //生成main可執行文件 ./main
3)輸出結果:

3. C++中的動態內存分配
3.1 回顧C:
在C語言中,大家都知道使用malloc()和free(),比如:
int *p = malloc(10*sizeof(int)); //申請10個int型空間 if(p) { ... ... free(p); }
從上面栗子,可以看到C是通過庫函數完成內存分配的
3.2而在C++中,則通過new關鍵字進行內存申請,delete關鍵字進行內存釋放,比如:

- Type: 指數據類型,比如int,char,float等
- N: 指申請的數組個數大小
除了上圖例子外,new關鍵字還可以通過分配並初始化(類似calloc()函數)
例如:
int *p1= new int(1); //動態分配一個int空間給p1,並賦值為1 float *p2=new float(2.0f); //2.0后面加f,表示2.0是個float類型 char *p3=new char('c');
注意:
- 釋放數組的空間時,必須使用delete[],而不是delete,避免內存泄漏
- 使用new時,默認值為隨機值,而對於new()時,則為0,比如: int *p = new int(); //默認值為0
3.3 以string為例,創建string數組
#include <iostream> #include <string> using namespace std; int main() { string *p = new string[10]; for(int i=0;i<10;i++) p[i] = "123"; for(int i=0;i<10;i++) cout<<p[i]<<endl; delete[] p; }
3.3 二維指針示例
以string二維指針為例:
#include <iostream> #include <string> using namespace std; int main() { string **p = new string*[4]; //創建行數 for(int i=0;i<4;i++) p[i] = new string[3]; //創建列數 for(int i=0;i<4;i++) for(int j=0;j<3;j++) { p[i][j]="123"; cout<<p[i][j] <<endl; } for(int i=0;i<4;i++) delete[] p[i] ; delete[] p; }
4.C++中的命名空間(namespace)
4.1回顧C:
大家都知道,在C語言中,當編譯多個C文件時,可能會遇到同名全局標識符的錯誤,這是因為C語言中的所有全局標識符都是共享同一個作用域
4.2所以C++中便提出命名空間(namespace)的概念
- 命名空間會將全局作用域分成不同部分的命令空間,可以將類,對象,函數等聚集在一個namespace里
- 不同命名空間中的標識符可以同名
- 命名空間可以相互嵌套,也就是說A命令空間里可以再次定義B命令空間
- 在C++中,全局作用域也叫默認命名空間
4.3命名空間(namespace)的使用
1)定義一個命名空間:
namespace name //定義一個命名空間,名為name { int varialbe; //... ... }
2)使用整個命名空間name,並將該空間設為當前默認命名空間:
using namespace name;
3)使用全局命名空間中的變量:
::varialbe; //由於::前面沒有命名空間名字,所以使用全局變量
4)使用某個命名空間中的變量:
using name::variable //使用name空間里的variable變量
4.4 舉個栗子
#include <stdio.h> namespace First //定義First命名空間 { int i = 0; } namespace Second //定義Second命名空間 { int i = 1;namespace Internal //在Second里,再次定義一個Internal空間(實現嵌套) { struct Position { int x; int y; }; } } int main() { using namespace First; //使用First整個命名空間,成為該main()的默認空間 using Second::Internal::Position; //使用Second->Internal空間里的Position結構體 printf("First::i = %d\n", i); printf("Second::i = %d\n", Second::i); Position p = {2, 3}; printf("p.x = %d\n", p.x); printf("p.y = %d\n", p.y); return 0; }
輸出結果:
First::i = 0 Second::i = 1 p.x = 2 p.y = 3
下章接着來學習: 5.C++里的4種新型類型轉換
