1. 程式人生 > >C++中的名稱空間namespace詳解及細節參考

C++中的名稱空間namespace詳解及細節參考

名稱空間特性

c++中要求可以通過定義一種新的宣告區域來建立名稱空間,這樣目的之一就是提供一個宣告名稱的區域。一個名稱區域中的名稱不會與另外一個名稱空間的相同名稱發生衝突,同時允許程式中的其他部分使用該名稱訪問空間中宣告的東西

使用namespace建立名稱空間的栗子:

namespace Jack
{
    double a;
    void fetch();
    struct Hell
    {
    };
}
namespace Jill
{
    int Hell;
    char fetch;
    struct a
    {
    };
}

名稱空間中內容的訪問

訪問名稱空間中的名稱,可以通過域解析運算子::,使用名稱空間來限定該名稱

Jack::a = 1.2;
Jill::Hell = 5;

 我們還可以使用using,來簡化每次都要限定的操作,using分為兩種:using 宣告和using 編譯指令

using宣告

using Jack::a;
using Jill::Hell;

使用using宣告只能宣告名稱空間中的某一個變數或者函式,並且既可以將名稱宣告在區域性宣告區域也可以將名稱新增到全域性名稱空間中

using編譯指令

using namespace Jill;
using namespace Hill;

和using宣告不同的是:using編譯指令使名稱空間中的所有名稱都可用;和using宣告相同的是:using既可以將名稱宣告在區域性宣告區域也可以將名稱宣告在全域性宣告區域中 。

using宣告和using編譯指令區別

#include <iostream>

using namespace std;

namespace Jill
{
    double buckey(double n){}
    double fetch;
}
char fetch;       //全域性變數
int main()
{
    using namespace Jill;
    double fetch;        //區域性變數,使用using編譯指令時,如果出現命名衝突,則區域性版本內容將隱藏名稱空間內容
    cin >> fetch;         //區域性變數內容
    cin >> ::fetch;      //通過作用域解析符獲取全域性變數內容
    cin>>Jill::fetch;    //名稱空間中的數值

    using Jill::fetch;  
    //double fetch;       //如果using宣告,如果定義了相同的名稱,則兩個名稱會發生衝突,此時定義區域性變數將會報錯
    cin>>fetch;           //輸入為名稱空間中的數值     
    cin>>::fetch;         //全域性變數的數值
}

namespace中細節注意

首先需要知道,c++提供兩種變數宣告:一、定義,給變數分配儲存空間;二、宣告,不給變數分配儲存空間,引用已有變數,關鍵字為:extern

c++中只能有一個變數的定義,其餘的只能為變數的引用

當使用.cpp檔案對名稱空間.h檔案進行函式具體化時,如果.h檔案存在變數的定義,這裡會出現變數重定義:

解決方法以及產生原因均在程式註釋:

/*
namesp.h檔案
*/
#ifndef NAMESP_H_INCLUDED
#define NAMESP_H_INCLUDED

#include <string>

namespace per
{
	struct Person
	{
		std::string fname;
		std::string lname;
	};
	void getPersion(Person &);
	void showPerson(const Person &);
}

namespace debts
{
	using namespace per;
	struct Debt
	{
		Person name;
		double amount;
	};
	extern double fetch;            //這裡一定為引用,因為namesp.h檔案編譯時,會找到namesp.cpp檔案一起編譯,如果使用定義的話,會在namesp.cpp和main.cpp檔案中
	//各包含一次,產生名稱定義衝突,所以這裡要將變數的定義放在namesp.cpp檔案中,這樣只會包含變數一次
	void getDebt(Debt &);
	void showDebt(const Debt&);
	double sumDebts(const Debt ar[], int n);
}
#endif // NAMESP_H_INCLUDED
/*
namesp.cpp檔案
*/
#include <iostream>
#include "namesp.h"

namespace per
{
	using std::cout;
	using std::cin;
	void getPersion(Person & rp)
	{
		cout << "Enter first name";
		cin >> rp.fname;
		cout << "Enter last name";
		cin >> rp.lname;
	}
	void showPerson(const Person &rp)
	{
		std::cout << rp.lname << ", " << rp.fname;
	}
}
namespace debts
{
	double fetch;
	void getDebt(Debt &rd)
	{
		getPersion(rd.name);
		std::cout << "Enter debt: ";
		std::cin >> rd.amount;
	}
	void showDebt(const Debt &rd)
	{
		showPerson(rd.name);
		std::cout << ": $" << rd.amount << std::endl;
	}
	double sumDebts(const Debt ar[], int n)
	{
		double totle = 0;
		for (int i = 0; i < n; i++)
			totle += ar[i].amount;
		return totle;
	}

}
/*
main.cpp檔案
*/
#include <iostream>
#include "namesp.h"
void other(void);
void another(void);

int main()
{
	using debts::Debt;
	using debts::showDebt;


	Debt golf = { { "Benny","Goatsniff" },120.0 };
	showDebt(golf);
	other();
	another();
	return 0;
}

void other()
{
	using std::cout;
	using std::endl;
	using namespace debts; 
	double fetch = 0;
	cout << fetch << " " << &fetch << endl;
	cout << debts::fetch << " " << &debts::fetch << endl;
	//int repeat;        當名稱空間和生命區定義了相同的名稱,在使用using宣告將名稱空間的名稱匯入宣告區域,則這兩個名稱會發生衝突
	Person dg = { "Doodles","Gloster" };
	showPerson(dg);
	cout << endl;

	Debt zippy[3];
	for (int i = 0; i < 3; i++)
		getDebt(zippy[i]);

	for (int i = 0; i < 3; i++)
		showDebt(zippy[i]);

	cout << "Total debt:$" << sumDebts(zippy, 3) << endl;
	return;
}

void another()
{
	using per::Person;
	Person collector = { "Milo","Rightshift" };
	per::showPerson(collector);
	std::cout << std::endl;
}

參考書籍

《c++ primer plus 第六版》