在這一部分之前,書中介紹了基本類型的顯式初始化以及簡單的異常處理.
基本類型的顯式初始化是比較簡單的.就是說你在定義一個(gè)整型變量的時(shí)候,有兩種不同的情況:
int i1; // undefined value
int i2 = int(); // initialized with zero
如果按照前一種,會(huì)作"值未定義;如果按照后一種,則自動(dòng)被初始化為0.這樣也就確保了你的類在初始化的時(shí)候有一個(gè)確定的初始值.
至于異常的處理等問題,書中會(huì)在后面有比較詳細(xì)的描述.這里可以看到比較有意思的一點(diǎn),就是指定函數(shù)拋出的異常類型,這于Java很像:
void f() throw(bad_alloc);
下面轉(zhuǎn)入正題:命名空間.
有了命名空間,它將會(huì)取代函數(shù)和類作用于全局,并作為它所統(tǒng)領(lǐng)的那些類和函數(shù)的唯一標(biāo)識(shí)存在.這樣可以避免命名沖突情況的出現(xiàn).正如書中所說:
Unlike classes, namespaces are open for definitions and extensions in different modules. Thus
you can use namespaces to define modules, libraries, or components even by using multiple
files. A namespace defines logical modules instead of physical modules (in UML and other
modeling notations, a module is also called a package).
可以像這樣定義一個(gè)命名空間:
namespace MyNameSpace
{
class MyClass
{
private:
char * _classInfo;
public:
char* getClassInfo()
{
return _classInfo;
}
MyClass(const char* info)
{
_classInfo=new char[strlen(info)];
strcpy(_classInfo,info);
}
~MyClass()
{
if(_classInfo)
{
std::cout<<"free classinfo";
delete[] _classInfo;
}
}
};
void printMyClassInfo(MyClass &instance)
{
std::cout<<instance.getClassInfo();
}
}
從上面可以看出,這個(gè)命名空間里面包括了一個(gè)類和一個(gè)函數(shù).類中包含了char*類型的成員變量.函數(shù)printMyClassInfo 以一個(gè)MyClass類型的引用作為參數(shù).為什么要用引用呢?熟悉c++的人應(yīng)當(dāng)很清楚,我是通過實(shí)驗(yàn)才剛剛知道原因.這個(gè)原因我將會(huì)在后面說明.
好現(xiàn)在來看一下調(diào)用過程,通常的調(diào)用過程是這樣的:
int main()
{
MyNameSpace::MyClass instance("MyClass!\n");
MyNameSpace::printMyClassInfo(instance);
}
這沒有任何問題,但有意思的是,還可以這樣調(diào)用:
int main()
{
MyNameSpace::MyClass instance("MyClass!\n");
printMyClassInfo(instance);
}
看來c++中在使用一個(gè)命名空間的類或者函數(shù)的時(shí)候,這個(gè)命名空間就被"自動(dòng)"引入了.當(dāng)尋找函數(shù)printMyClassInfo的時(shí)候會(huì)在當(dāng)前的上下文中進(jìn)行尋找的同時(shí),還會(huì)到以前用到過的命名空間中去尋找.
當(dāng)然,通常情況下我們喜歡這樣做:
using namespace MyNameSpace;
int main()
{
MyClass instance("MyClass!\n");
printMyClassInfo(instance);
}
但是并不是在任何情況下都鼓勵(lì)using namespace這種做法的.在書中將得比較清楚:
Note that you should never use a using directive when the context is not clear (such as in header
files, modules, or libraries). The directive might change the scope of identifiers of a namespace,
so you might get different behavior than the one expected because you included or used your
code in another module. In fact, using directives in header files is really bad design.
上面這段話強(qiáng)調(diào)了當(dāng)上下文并不明確的情況下(比如在一個(gè)頭文件,組件或者庫里面),不要使用using這種寫法,這個(gè)指令會(huì)改變命名空間標(biāo)識(shí)符的作用域,這樣你就有可能引發(fā)和你預(yù)期不相同的行為,因?yàn)槟銜?huì)在另外一個(gè)組件中引用你的代碼或使用它.事實(shí)上,將using標(biāo)識(shí)符寫在頭文件里面是一種相當(dāng)不好的設(shè)計(jì).
在這里,我看了一下c++程序設(shè)計(jì)語言這本書,發(fā)現(xiàn)命名空間除了像上面這樣聲明以外,還可以像類一樣這樣來寫:
在命名空間中這樣定義
void printMyClassInfo(MyClass &);
然后在外面寫函數(shù)的主體
void MyNameSpace::printMyClassInfo(MyClass &instance)
{
std::cout<<instance.getClassInfo();
}
好了,寫了這么多,再來看看剛才留下來的那個(gè)問題.
其實(shí)很簡單,一個(gè)函數(shù)如果傳遞的是值,那么就會(huì)在內(nèi)存中產(chǎn)生一個(gè)一模一樣的"復(fù)本",而那個(gè)字符指針也會(huì)被復(fù)制一次.當(dāng)傳送的值超過它的作用域的時(shí)候 ,就會(huì)被釋放掉,而被復(fù)制的"本體"在程序運(yùn)行結(jié)束之后,又會(huì)被"釋放一次".這樣在運(yùn)行的時(shí)候,它會(huì)提示你這樣的錯(cuò)誤:
*** glibc detected *** double free or corruption (fasttop): 0x0804a008 ***
在我們的MyClassl類的析構(gòu)中,我們有一個(gè)輸出,所以這里就輸出了兩次:
free classinfofree classinfo
posted on 2007-06-14 22:06
littlegai 閱讀(284)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
我的讀書筆記