(2020.11.15 Sun)
C++命名空間namespace(ns)
命名空間的引入是為了避免變量或函數(shù)重名的問題睡毒。
C++中的名稱(name)可以是符號常量力惯、變量舌厨、宏刨疼、函數(shù)专缠、結(jié)構(gòu)狰挡、枚等捂龄。大規(guī)模程序設(shè)計(jì)中可能會出現(xiàn)標(biāo)識符的命名發(fā)生沖突。解決辦法是將變量定義在一個(gè)不同名字的命名空間中加叁。
命名空間有兩種:有名與無名跺讯,他們的定義格式如下
namespace 命名空間名
{聲明序列}
//有名
namespace
{聲明序列}
//無名
命名空間的成員可以在命名空間的定義內(nèi)為其命名(內(nèi)部定義),也可在命名空間外定義成員(外部定義)殉农。但是不能再外部定義子命名空間刀脏。
namespace outer
{
int i;
namespace inner //子命名空間
{
void f() {i++;}
}
void f();
}
void outer::f() //在命名空間外部定義成員
{
i++;
}
- 命名空間只能定義在頭文件中head file
- 命名空間開放,可以隨時(shí)更新加入新的成員
//前面已經(jīng)定義了outer
namespace outer // 給命名空間outer加入新的成員
{
int k;
void g() {
printf('g');
}
}
- 引用命名空間中的成員超凳,使用作用域運(yùn)算符::
outer::k = 1; //引用命名空間的成員并賦值時(shí)不需要指定數(shù)據(jù)類型
- 在預(yù)編譯部分中會出現(xiàn)include <iostream>和include <iostream.h>愈污。在新的C++標(biāo)準(zhǔn)中,生成頭文件的方法僅僅是將現(xiàn)有頭文件名中的.h去掉轮傍。以前的C++頭文件名.h會繼續(xù)支持暂雹,但頭文件的內(nèi)容不在命名空間std中。新的頭文件和舊文件相同创夜,但是頭文件的內(nèi)容在命名空間std(一個(gè)類)中杭跪。因此調(diào)用std,即using namespace std前需要做預(yù)處理驰吓,即#include <iostream>涧尿,才可以使用std內(nèi)的函數(shù)等內(nèi)容。如果不調(diào)用std檬贰,not using namespace std姑廉,則在調(diào)用cin/cout時(shí)需要使用std::cin/cout。
#include <iostream>
using namespace std; //using編譯指令
int main() {
cout << 'this is a C++ p.' << endl;
return 0;
}
//or
#include <iostream>
int main() {
std::cout <<' this is also a C++ p.' << endl;
return 0;
}
//或只使用命名空間的某個(gè)成員
#include <iostream>
using outer::g; //using聲明翁涤,針對命名空間中名稱的使用
void main () {
g(); //調(diào)用outer的g成員
}
- 上面的例子中有using namespace outer和using outer::g兩種用法桥言,前一種稱為using編譯指令,后一種稱為using聲明葵礼。聲明只把ns中特定成員的名稱添加到所在的區(qū)域号阿,使得該成員可以不需要采用命名空間的作用域解析運(yùn)算符來定位,而直接被使用鸳粉。但是使用using聲明更安全扔涧,因其只會導(dǎo)入指定的名稱。如果該名稱與局部名稱發(fā)生沖突赁严,則編譯器會報(bào)錯(cuò)扰柠。而using指令導(dǎo)入整個(gè)ns中所有成員的名稱粉铐,如果其中有名稱與局部名稱發(fā)生沖突,編譯器不會報(bào)錯(cuò)卤档,只是用局部名稱自動覆蓋ns中的同名成員蝙泼。當(dāng)需要反復(fù)使用一個(gè)ns中的多個(gè)函數(shù)時(shí),使用using編譯指令劝枣;當(dāng)只需要使用一個(gè)ns中的特定幾個(gè)函數(shù)時(shí)汤踏,建議使用ns聲明。
(2020.11.17 Tues)
命名空間和類的區(qū)別
一般程序的開發(fā)都由多人完成舔腾,為防止不同模塊的類和函數(shù)重名溪胶,采用命名空間來區(qū)分避免混淆。
只要兩個(gè)類在不同的命名空間中稳诚,他們就可以擁有相同的類名稱哗脖。把類封裝進(jìn)命名空間的優(yōu)勢在于方便調(diào)用甚至其他應(yīng)用程序的調(diào)用。
#include <iostream>
using namespace std;
namespace s1
{
class S_Class
{
public:
void show()
{
cout << '調(diào)用命名空間S1中類S_Class的函數(shù)show().' << endl;
}
};
}
namespace s2
{
class S_Class
{
public:
void show()
{
cout << '調(diào)用命名空間s2的類S_Class的函數(shù)show()' << endl;
}
};
}
int main() {
s1::S_Class x; //聲明一個(gè)s1中類S_Class的實(shí)例x
x.show(); //調(diào)用類實(shí)例x中的show()扳还,輸出結(jié)果
s2::S_Class y; //聲明一個(gè)s2中類S_Class的實(shí)例y
y.show(); //調(diào)用類實(shí)例y中的show()才避,輸出結(jié)果
return 0;
}
作用域限定符Scope resolution operator ::
在三種情況中使用作用域限定符
- 在命名空間的使用過程中,使用::來引用指定命名空間中的成員氨距。另一種引用方法是使用using指令桑逝。
- 在不同作用域內(nèi)聲明的變量可以重名,但如果局部變量和全局變量重名俏让,在局部變量的作用域內(nèi)可以使用::來引用全局變量楞遏。
#include <iostream>
using namespace std;
int x = 100; //定義全局變量
int main ()
{
int x = 150;
cout << '全局變量x=' << ::x << endl; //輸出全局變量
cout << '局部變量x=' << x << endl; //輸出局部變量
::x = 750;
cout << '全局變量x=' << ::x << endl; //輸出全局變量
cout << '局部變量x=' << x << endl; //輸出局部變量
return 0;
}
另外,::只能用來訪問全局變量首昔,不能訪問一個(gè)在語句塊外生命的同名局部變量寡喝。下面是一個(gè)錯(cuò)誤的使用方式。
//這是一個(gè)錯(cuò)誤的使用方式
void main() {
int x = 11; //x是局部變量
{
int x = 22;
::x = 33; //錯(cuò)誤的修改方式沙廉,因x也是局部變量
}
}
- 在類外定義類成員函數(shù)時(shí)拘荡,需要使用scope resolution operator。比如聲明一個(gè)類A撬陵,里面聲明了一個(gè)成員函數(shù)void fun();,如果類中沒有給出該成員定義网缝,在類外定義該成員時(shí)巨税,要寫成void A::fun(),表示函數(shù)fun()是類A的成員函數(shù)粉臊。
#include <iostream>
#include <string.h>
class cbook
{
private:
char * m_pczname;
int m_npages;
int m_nedition;
public:
void getbookname(char *pname);
int getbookedition();
private:
void setbookname(char * pname);
void settotalpages(int npages);
public:
cbook();
}; //定義一個(gè)類和結(jié)構(gòu)體的結(jié)尾處的大括號后面有個(gè)分號
void cbook::getbookname(char * pname)
{
strcpy(pname, m_pczname); //定義成員函數(shù)
}
int cbook::getbookedition()
{
return m_nedition; //成員函數(shù)中引用類成員變量草添,直接寫名字,不需要加self
}
void cbook::setbookname(char * pname)
{
if (m_pczname != 0)
delete[] p_pczname;
m_pczname = new char[strlen(pname)+1]; //重新分配存儲空間
strcpy(m_pczname,pname); //復(fù)制字符串
}
void cbook::settotalpages(int npages)
{
m_npages = npages; //成員函數(shù)中引用類成員變量扼仲,直接寫名字远寸,不需要加self
}
void main ()
{
cbook op1; //聲明該類的對象
int i;
i = op1.getbookedition();
cout << i << endl;
}
這里注意到抄淑,類說明的程序內(nèi)容較多,應(yīng)該放在獨(dú)立的文件中驰后。例如cbook的類說明可以放在頭文件xxx.h中肆资,類的定義放在以.cpp為擴(kuò)展名的文件中,稱為類的實(shí)現(xiàn)文件灶芝。在文件開始部分應(yīng)該用include將類說明文件包含進(jìn)來(類實(shí)現(xiàn)可以不include?)
Reference
1 劉蕾編著郑原,21天學(xué)通C++,中國工信出版集團(tuán)夜涕,電子工業(yè)出版社
2 聚慕課教育研發(fā)中心編著犯犁,C++從入門到項(xiàng)目實(shí)踐(超值版),清華大學(xué)出版社