㈠ C++ 包括類的聲明、成員函數的實現
雖然很多程序員都熟悉名字空間的概念,但他們常常都是被動地使用名字空間。也就是說他們使用的是第三方定義的成員(如標准庫的類和函數),而不是在名字空間中聲明自己的類和函數。本文擬討論如何在名字空間中聲明自己的類和函數,以及如何在程序中使用它們。
名字空間是一個范疇,它包含類聲明,函數聲明,常量聲明和模板聲明等名字空間成員。例如:
namespace proj_alpha
{
//下面是名字空間 proj_alpha 的成員
class Spy {/*..*/};
void encrypt (char *msg);
const int MAX_SPIES = 8;
}
在上面的例子中,類Spy在一個單獨的文件中實現。通常,你是在一個專門的頭文件中聲明一個類並在不同的源文件中獨立地定義其成員函數。那麼如何將名字空間成員類分離成多個源文件呢?
下面是名為 Foo.hpp 的頭文件,其中定義了一個名為NS的名字空間,它包含類Foo的聲明:
//Foo.hpp
namespace NS
{
class Foo
{
public:
void f();
void g();
};
}//close NS
另外,在一個單獨的源文件Foo.cpp中,首先包含頭文件Foo.hpp以便實現類Foo的成員函數f()和g():
//Foo.cpp
#include "Foo.hpp"
void NS::Foo::f()
{ /*..*/ }
void NS::Foo::g()
{ /*..*/ }
為了使用名字空間成員,必須使用成員的全路徑名,它由名字空間後跟::合成原名組成。因此,類Foo的全路徑名是NS::Foo。這樣編譯器便可以知道NS是一個名字空間名,頭文件Foo.hpp必須在引用NS之前被包含。
名字空間是可以擴展的。也就是說可以聲明類,而且所聲明的類在其它的.cpp文件中是相同的名字空間成員:
//Bar.hpp
namespace NS //擴展 NS
{
class Bar
{
public:
void a();
void b();
};
}
在Bar.cpp文件中:
#include "Bar.hpp"
void NS::Bar::a()
{/*..*/}
void NS::Bar::b()
{/*..*/}
可以看出,雖然Foo和Bar這兩個類在不同的頭文件中聲明,但它們都是名字空間NS的成員。並且編譯器和鏈接器將這兩個類看成是同一名字空間的成員。那麼,如何在應用程序中使用這些類呢?
在文件main.cpp中,必須要包含聲明類Foo和Bar的頭文件並加上相應的名字空間引用聲明-using:
#include "Bar.hpp"
#include "Foo.hpp"
int main()
{
using NS::Bar; //使用名字空間
using NS::Foo; //同上
Bar b;
Foo f;
f.f();
//...
}
using聲明由關鍵字using後跟名字空間成員的全路徑。這樣就使你在using聲明範圍內使用成員時不用再加路徑。上面的例子中,可以直接使用Foo和Bar,因為在main()的開始使用了using聲明。如果沒有using聲明就必須使用全路徑成員名。
int main()
{
NS::Bar b; //全路徑名
NS::Foo f; //同上
//?
}
另外,還有一種引用名字空間成員的方法是使用using指令:
#include "Bar.hpp"
#include "Foo.hpp"
int main()
{
using namespace NS; // using 指令
Bar b;
Foo f;
f.f();
//...
}
using指令由關鍵字「using namespace」後跟名字空間名構成。在訪問名字空間成員時它是使用最少的一種方法,原因是這種方法將所有名字空間成員注入當前的范圍,從而增加了潛在的名字沖突。