1. 程式人生 > >【C++】淺析「namespace/過載/引用」

【C++】淺析「namespace/過載/引用」

前言

大一第一次接觸C++時,不理解 using namespace std; 故整理 C++ 中的「namespace/過載/引用」的概念如下


//名稱空間問題
using namespace std;//使用標準庫名稱空間

//函式過載
int add(int i, int j);
int add(int i, int j, int k);//對add函式過載

//指標&引用
int add(int* i ,int* j);//指標
int add(int &i ,int &k);//引用

如何理解名稱空間

  • 為什麼要設計名稱空間

    1.大型工程多開發者時會出現命名衝突: 大型工程常由多個開發者共同編寫,在主程式include多個頭檔案時,多個頭檔案可能包含名字相同的變數,此時這一組變數處於同一個作用域,產生了命名衝突。 2.使用者自定義的變數名與使用者使用的標準庫中的名字衝突:

    如程式設計師定義函式cout,cout非語言識別符號,但在include時,會與標準庫命名衝突。

  • 解決方案:引入名稱空間,常見用法:

    using namespace std;

    使用標準庫名稱空間,此時所有std中出現的命名(如cout)全部指向std中的定義。

    using std::cout;

    使用std中的cout,其它同上

    在以下條件下:

namespace name1
{
    int age=18;
}
namespace name2
{
    int age=21;
}

我們可以同時

cout<<name1::age<<endl;
cout<<
name1::age<<endl;

此外,我們可以同時使用using namespace std& using std::cout,再對部分變數指定名稱空間

 //在上述程式碼基礎上 
using namespace name1; 
cout<<age<<endl;//18
cout<<name1::age<<endl;//18
cout<<name2::age<<endl;//21

過載(C++為什麼支援過載?)

使用方法:

    int add(int i, int j)
    {
        return
i+j; } int add(int i, int j, int k)//對add函式過載 { return i+j+k; }

在主程式中我們可以

int i, j, k;
i=j=k=1;
cout<<add(i,j)<<endl;//2
cout<<add(i,j,k)<<endl;//3

對從C語言過來的人來說,這種方法簡直不可思議。事實上形參不同時,C++允許同名函式的出現。

  • 為什麼C不可以?

(知識回顧,可跳過) 易知,從碼完程式碼到執行,編譯器需要進行 預處理(包含標頭檔案、註釋的刪除、識別符號與巨集的替換) 編譯(語法、語義、符號的分析,並對符號進行彙總) 彙編(生成符號表,同時彙編生成二進位制程式碼) 連結(符號表合併、重定位、合併段表)

c++對函式名的儲存通過新增形參型別的字尾實現對同名函式的區分(過載)

  int add(int i, int j);//儲存為_add_int_int
  int add(int i, int j, int k);//儲存為_add_int_int_int

由於C未對函式名的儲存作區分,因此C不能出現同名函式。

引用的簡析

1.指標和引用(概念、使用方法、做引數、做返回值的作用,指標和引用的區別)

  • 概念&使用方法:

我們知道,形參是實參的拷貝,因此在C語言為了改變實參的值我們常使用指標的形式傳遞引數

int add(int* i ,int* j);//指標

C++引入新的語法:引用

int add(int &i ,int &k);//引用

2.有別於指標的是:

指標變數儲存原變數的地址 引用是建立原變數的別名,此過程中不建立一個特殊變數去儲存地址

引用的出現,可以替代部分原指標的使用,使程式更安全(指標危險)、效率高(減小記憶體開銷),更能解決部分原來指標無法解決的問題,如拷貝建構函式

引用解決的問題例項: 對如下程式碼

class time
{
    time(time t)//目標為實現一個“拷貝建構函式”
    {
        ······
    }
}//但事實上形參t的建立又會觸發“拷貝建構函式”,最終無限迴圈,使用引用可解決此問題。

class time
{
    time(time &t)//目標為實現一個“拷貝建構函式”//t只是一個別名,不會建立新的物件
     {
        ······
     }
}