簡介名稱空間


一個應用程式中會有多變數、常數、函式、類別彼此合作,也有可能由多個團隊共同分工,完成應用程式的某些功能塊,再組合在一起。

如果你的應用程式是多個團隊共同合作,如果沒有定義名稱空間,名稱預設都是位於全域名域空間,以類別定義來說,那麼若 A 部門寫了個 Account 類別,B 部門寫了個 Account 類別,當他們要將應用程式整合時,就會發生名稱衝突的問題。

C++ 可以使用 namespace 來定義名稱空間,例如,可以在 account.h 中定義 bank 名稱空間:

account.h

#include <string>

namespace bank {
    using namespace std; 

    class Account { 
    private:
        string id;  
        string name; 
        double balance;

    public: 
        Account(string id, string name, double balance);
        void deposit(double amount);
        void withdraw(double amount);
        string to_string() const;
    };
}

在 account.cpp 可以開啟 bank 名稱空間,並在其中實作類別定義:

...略
#include "account.h"

namespace bank {
    using namespace std;

    Account::Account(string id, string name, double balance) {
        this->id = id;
        this->name = name;
        this->balance = balance;
    }

    string Account::to_string() const {
        return string("Account(") + 
            this->id + ", " +
            this->name + ", " +
            std::to_string(this->balance) + ")";
    }

    ...略
}

或者是在實作時指定 bank 範疇:

...略
#include "account.h"

using namespace std;

bank::Account::Account(string id, string name, double balance) {
    this->id = id;
    this->name = name;
    this->balance = balance;
}

string bank::Account::to_string() const {
    return string("Account(") + 
           this->id + ", " +
           this->name + ", " +
           std::to_string(this->balance) + ")";
}
...略

名稱空間會是類別名稱的一部份,因此在使用時,必須包含 bank 前置:

bank::Account acct = {"123-456-789", "Justin Lin", 1000};
cout << acct.to_string() << endl;

try {
    acct.withdraw(10200);
    acct.deposit(-500);
}
catch(invalid_argument &ex) {
    cout << "引數錯誤:" << ex.what() << endl;
}
catch(bank::Insufficient &ex) {
    cout << "帳號錯誤:"  << endl
        << "\t" << ex.what() << endl
        << "\t餘額 " << ex.getBalance() << endl;
}

或者是使用 using 來指明使用哪個名稱空間,例如:

...略
using namespace std;
using namespace bank;

int main() {
    Account acct = {"123-456-789", "Justin Lin", 1000};
    cout << acct.to_string() << endl;

    try {
        acct.withdraw(10200);
        acct.deposit(-500);
    }
    catch(invalid_argument &ex) {
        cout << "引數錯誤:" << ex.what() << endl;
    }
    catch(Insufficient &ex) {
        cout << "帳號錯誤:"  << endl
            << "\t" << ex.what() << endl
            << "\t餘額 " << ex.getBalance() << endl;
    }
}

這也就是為何,至今在使用 coutstring 等名稱前,都會撰寫 using namespace std 的原因,這些名稱是定義在 std 名稱空間之中,當然,using 不可以濫用,不能名稱衝突也可能發生,C++ 其實並不建議使用 using,多半建議以 std::coutstd::string 來指明,這系列文件的範例基本上都很小,才會偷懶直接 using namespace std