c/c++關於定義和聲明的原則是一次定義,多次聲明。定義分配了變量以及函數的內存,而聲明則為這些變量和函數指定了一個引用標簽,用來使用這些內存,也就是名字。定義的使用是通過聲明(名字)來調用的。每個定義都有作用域(scope),潛在作用域(declaration region),鏈接性(linkage)和生存時間,據定義的實現而不同。重復定義錯誤往往是因為潛在作用域的交叉而引起的。
生存時間是指定義的存活時間,有動態,靜態和局部三種情況。聲明(名字)存活時間依附於定義。動態的指在運行時從堆裡動態申請內存的變量(不包括函數類型,函數運行前已經根據實現而決定了棧的大小);需要手動釋放,否則至死方休。靜態的指全局變量,函數,和函數內部用static限制的變量;存活時間為整個程序運行過程。局部指在函數運行時壓棧和彈棧的變量;在函數運行時存在。
作用域(scope)指定義的聲明(名字)可以被使用的區域。在這個區域裡面聲明(名字)必須唯一且准確的指向定義的內存。否則會出現重定義錯誤。
潛在作用域(declaration region)指定義的聲明(名字)可以被編譯器識別的區域,區域會因定義的鏈接性而不同,范圍覆蓋了作用域。在這個區域內有些地方會因同名聲明被隱藏起來,內鏈接定義的聲明會隱藏外鏈接定義的聲明,局部定義的聲明會隱藏內鏈接定義的聲明和外鏈接定義的聲明。沒有隱藏的同名聲明會引發重定義錯誤。
鏈接性指定義被其它單元(c++文件)識別(使用)的屬性。可以有外鏈接性,內鏈接性和無鏈接性。外部鏈接性說明定義可以被其它單元識別,並可以通過extern在外部引用聲明,然後使用;此時定義的潛在作用域是全局的。內鏈接性說明定義只能在本單元(一個C++文件)內被識別;潛在作用域是本單元。無鏈接性是指定義在函數內部的靜態變量和局域變量的屬性;潛在作用域是本代碼塊。
避免潛在作用域的同名聲明的沖突,有兩種辦法:1、定義的鏈接屬性改成內部的,可用static限定,或者空namespace限定。2、使用命名空間,對聲明進行限定。
另:const變量的默認鏈接性為內部的,函數和全局變量的默認鏈接性為外部的。