騰訊面試題竟然只是“Hello World”,深度理解命名空間與函數重載的原理(C++入門)

命名空間

無論學習編程語言,開始入門的“Hello World”是必不可少的。

#include<iostream>
using namespace std;
int main()
{
   
   
count<<"hello world"<<endl;
return 0;
}

看起來很簡單,但是深究起來卻有很大的學問。沒錯這其實是一位學長的騰訊面試題。是不是有點懷疑人生,其實面試官只是藉助着一個簡單的程序深挖了背後的底層原理。

命名空間概念

先來看一個概念叫做命名空間。

#include<stdio.h>
//命名空間
int scanf=0;//c不能用關鍵字作爲變量名,但是函數沒有規定,所以按理來說應該是可以的
int main()
{
   
   
printf("%d",scanf);
return 0;
}

但是卻有這麼一個錯誤。
在這裏插入圖片描述
我們知道在預處理的時候會展開頭文件,scanf函數在裏面,所以這裏是有歧義,在我們寫項目的時候會出現同樣的問題,假如出現了同樣的命名,在鏈接合成同一個文件的時候,那聲明成static可以解決嗎,static是解決一個全局變量在多個文件進行編譯衝突問題,解決不了命名的這個問題,顯然C語言對這個問題沒有辦法,Cpp通過命名空間來改變來解決這個問題。

#include<stdio.h>
//命名空間,域
namespace bit
{
   
   
int scanf=0;
}
int main()
{
   
   
printf("%d",scanf);
return 0;
}

編譯成功
在這裏插入圖片描述
輸出竟然是這麼大,爲什麼呢?
在這裏插入圖片描述
我們在代碼裏寫的命名空間域還沒有使用他,將它隔離起來,頭文件展開的時候跳過,所以這裏打印的是scanf的地址,嚴格來說應該打印%p,就打印了他的地址



namespace bit
{
   
   
int scanf=0;
}

命名空間應用

他本質還是一個全局變量,要訪問它有三種方法。
第一種是通過域作用限定符直接用。

printf("%d",bit::scanf);

第二種是單獨展開特定的變量

namespace bit
{
   
   
int a=0;
int b=0;
int c=0
}
using bit::b;
int main()
{
   
   
printf("%d",b);
return 0;
}

第三種很粗暴,也就出現了文章開始的,我們經常用的那一種格式

namespace bit
{
   
   
int a=0;
int b=0;
int c=0
}
using namespace bit;
int main()
{
   
   
printf("%d",a);
printf("%d",b);
printf("%d",c);
return 0;
}

在寫大型項目時,我們用第一種或者第二種進行展開。
在Cpp訓練時,我們所需要所有的庫便是在這個std中,通常選擇全部展開。

using namespace std;

命名空間嵌套

在這裏插入圖片描述
在這裏插入圖片描述
不同文件也可以有同名命名空間,鏈接時會合成一個。

io流

iostream

要使用cin(鍵盤),cout(控制檯)。首先便是要包含頭文件

include<iostream>

然後便是展開std命名空間,三種方式。
語法格式:

//可以認爲字符串的東西流向cout
cout<<"hello";
//想要換行
cout<<"hello"<<endl;

自動識別內容,無需c語言一樣指定格式
<< 和>>是運算符,cin和cout是對象

int i=0;
cin>>i;

當有不同類型變量的時候,用cin,cout

int main()
{
   
   
int i;
double d;
cin>>i>>d;
cout<<i<<d<<endl;
}

當這種情況,我們想要輸出一些格式做一些說明,或者想讓他有序一點,用printf更合適

struct Student
{
   
   
   char name[10];
   int age;
};
int main()
{
   
   
int i;
double d;
cin>>i>>d;
cout<<i<<d<<endl;
struct Student s={
   
   "peter",18};
printf("name:%s age:%d\n",s.name,s.age);
}

這種挺複雜的
在這裏插入圖片描述

函數重載

缺省

先來看個概念
缺省:聲明或定義的時候爲函數的參數制定一個默認的值。
在這裏插入圖片描述
缺省還分爲全缺省和半缺省

全缺省意思就是形參全部指定。
半缺省部分指定必需要從右向左給值。




缺省參數不能再函數聲明和定義中同時出現。
就算缺省值一樣也不行,必須在聲明時給好





在這裏插入圖片描述

函數重載概念

函數的一種特殊情況,Cpp允許在同一作用域種聲明功能類似的同名函數,這些同名函數的形參列表
(參數個數或類型或順序)必須不同。

c++函數重載實現原理

假設當前有這麼幾個文件 test.h , test.cpp , main.cpp
經過這麼幾個過程

預處理:頭文件展開,宏替換,條件編譯

test.cpp->test.i      main.cpp->main.i

編譯:檢查語法,生成彙編代碼

test.i->test.s    main.i->main.s

彙編把彙編代碼轉換成二進制機器碼

test.s->test.o          main.s->main.o

鏈接

-o形成可執行文件

彙編的時候通過call 函數地址,他不知道自己找的是什麼(call_(?)),只能找到函數聲明,
只有在鏈接時會在其他文件的符號表中通過函數名找,拿到地址。

windows查看底層原理太複雜,我們在Linux環境下查看。
先簡單編一個c語言文件
在這裏插入圖片描述
通過objdump指令查看
我們可以看到c語言在調用時直接調用的函數名,多個相同的文件
在這裏插入圖片描述
再來看c++
在這裏插入圖片描述
查看obj文件
在這裏插入圖片描述
可以明顯的看到c++與c語言的不同,c++使用了一個東西叫函數修飾規則。
通過_z[]+函數名+類型首字母,c++的重載函數只要參數不同修飾的名字就不同,這樣鏈接的時候就會找到。
C語言沒有修飾規則,所以直接通過名字去找,有同名就衝突了。











發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章