const、static、extern用法

const的用法:

1、在C語言中,const修飾的變量是"常變量",在編譯階段檢查常變量有沒有做左值(不可以爲左值),其他處理和普通變量相同。

2、在C++中,const修飾的變量爲"常量",在編譯階段,把用到常量的地方替換成常量初始化的值(常量:(1)常量一定要初始化;(2)不可以做左值;(3)不能間接修改常量的值;);

3、在C++中,const修飾的成員變量也不能在類定義處初始化,只能通過構造函數初始化列表進行,並且必須有構造函數(const數據成員只在某個對象生存期內是常量,而對於整個類而言卻是可變的。因爲類可以創建多個對象,不同的對象其const數據成員的值可以不同。所以不能在類的聲明中初始化const數據成員,因爲類的對象沒被創建時並且編譯器不知道const數據成員的值);

4、在C++中,cosnt成員方法主要目的是防止成員函數修改對象的內容。即const成員函數不能修改成員變量的值,但可以訪問成員變量。

static的用法:

修飾變量:

1、靜態全局變量:在全局變量前,加上關鍵字static,該變量就被定義成爲一個靜態全局變量。                                                       特點:(1)該變量在全局數據區分配內存;(2)未經初始化的靜態全局變量會被程序自動初始化爲0(自動變量的值是隨機的,除非它被顯式初始化);(3)靜態全局變量在聲明它的整個文件都是可見的(golbal轉變爲local),而在文件之外(extern)是不可見的;(4)定義全局變量就可以實現變量在文件中的共享;(5)靜態全局變量不能被其它文件所用; (6)其它文件中可以定義相同名字的變量,不會發生衝突;

2、靜態局部變量: 在局部變量前,加上關鍵字static,該變量就被定義成爲一個靜態局部變量。在函數體內定義了一個變量,每當程序運行到該語句時都會給該局部變量分配棧內存。但程序結束時,系統就會收回棧內存,局部變量也相應失效。但如果想對變量的值進行保存,想法是定義一個全局變量來實現。但這樣變量已經不再屬於函數本身了,不再僅受函數的控制,給程序的維護帶來不便。靜態局部變量正好可以解決這個問題。靜態局部變量保存在全局數據區,而不是保存在棧中,每次的值保持到下一次調用,直到下次賦新值。(1)該變量在全局數據區分配內存(棧到數據存儲區);(2)靜態局部變量在程序執行到該對象的聲明處時被首次初始化,即以後的函數調用不再進行初始化;(3)靜態局部變量一般在聲明處初始化,如果沒有顯式初始化,會被程序自動初始化爲0;(4)它始終駐留在全局數據區,直到程序運行結束。但其作用域爲局部作用域,當定義它的函數或語句塊結束時,其作用域隨之結束;

3、2靜態成員變量:在類內數據成員的聲明前加上關鍵字static,該數據成員就是類內的靜態數據成員。                                             特點:(1)而靜態數據成員被當作是類的成員。無論這個類的對象被定義了多少個,靜態數據成員在程序中也只有一份拷貝,由該類型的所有對象共享訪問。(2)靜態數據成員存儲在全局數據區,屬於本類的所有對象共享,所以,它不屬於特定的類對象,在沒有產生類對象時其作用域就可見,即在沒有產生類的實例時,我們就可以操作它; (3)由於它不屬於特定的類對象,在沒有產生類對象時其作用域就可見,所以要在類外初始化(類作用域);(4)靜態成員變量沒有進入程序的全局名字空間,因此不存在與程序中其它全局名字衝突的可能性;(5)可以實現信息隱藏。靜態數據成員可以是private成員,而全局變量不能;

修飾函數:

1、普通全局方法:靜態函數,在函數的返回類型前加上static關鍵字,函數即被定義爲靜態函數。靜態函數與普通函數不同,它只能在聲明它的文件當中可見(golbal轉變爲local),不能被其它文件使用。(1)靜態函數不能被其它文件所用;(1)其它文件中可以定義相同名字的函數,不會發生衝突;

2、靜態成員方法:靜態成員方法爲類的全部服務而不是爲某一個類的具體對象服務。thiscall調用約定轉變爲cdcall調用約定,與普通函數相比,靜態成員函數由於不是與任何的對象相聯繫,因此它不具有this指針(不依賴對象調動)。它無法訪問屬於類對象的非靜態數據成員,也無法訪問非靜態成員函數,它只能調用其餘的靜態成員函數。 (1)出現在類體外的函數定義不能指定關鍵字static;(2)靜態成員之間可以相互訪問,包括靜態成員方法訪問靜態成員變量和訪問靜態成員方法;(3)非靜態成員函數可以任意地訪問靜態成員函數和靜態數據成員;(4)靜態成員函數不能訪問非靜態成員函數和非靜態數據成員;(5)靜態成員方法在類外定義實現;

C和C++的相互調用:"extern C"

extern 基本解釋:extern可以置於變量或者函數前,以標示變量或者函數的定義在別的文件中,提示編譯器遇到此變量和函數時在其他模塊中尋找其定義。通過這種行爲它告訴編譯器:該變量/函數的定義已經存在在某個地方了,讓編譯器到其他的模塊去尋找它的定義。另外,extern也可用來進行鏈接指定。

1、C++調用C,在C++中寫入extern   “C“。使用extern“C”主要是因爲C++語言在編譯的時候爲了實現多態,會將函數名和函數結合起來形成另外一種函數名(總之就是說編譯後的函數名與你之前自己聲明時的函數名會不一樣),而C語言中無多態的概念當然也就不會有這種奇異的名字變化問題。這是問題就出現了,當你要在C++中調用C函數時,由於名字的不同,所以它會找不到所調用的這個函數的定義,因而會出錯。     爲了解決這一C與C++的矛盾衝突,就有了extern "C'。

2、C調用C++:使用extern "C"則是告訴編譯器依照C的方式來編譯封裝接口,當然接口函數裏面的C++語法還是按C++方式編譯。

//普通函數 
// C++ Code
extern "C" int foo( int x );
int foo( int x )
{
   //...
}
/*
這樣,編譯器會將foo函數編譯成類似_foo符號,而不會編譯成類似_foo_int符號
則C可以這樣調用C++函數
*/
// C Code
int foo( int x );
void cc( int x )
{
    foo( x );
    //...
}
//**************************************************************************************
/*
如果想調用重載的C++函數,則須封裝單獨的接口共C調用。
*/
// C++ Code
void foo( int x );
void foo( float x );

extern "C" void foo_i( int x )
{
    foo( x );
}
extern "C" void foo_f( float x )
{
    foo( x );
}
/*
則C中可這樣調用
*/
// C Code
void foo_i( int x );
void foo_f( float x );
void ccc( int x1, float x2 )
{
    foo_i( x1 );
    foo_f( x2 );
    // ...
} 
//**************************************************************************************
/*
C中想調用C++中的成員函數(包括虛函數),則需要提供一個簡單的包裝(wrapper)。
*/
// C++ code:
class C
{
  ...
  virtual double f(int);
};
extern "C" double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}
/*
然後,你就可以這樣調用 C::f():
*/
//C code
double call_C_f(struct C* p, int i);//聲明
void ccc(struct C* p, int i)
{
   double d=call_C_f(p,i);
 ...
}

3、C(不清楚是那種編譯器(C/C++)):#ifdef_cplusplus

在cpp的代碼之中會看到這樣的代碼: 特別是C++中引入C的頭文件,這些C頭文件中出現很多如下代碼。

#ifdef __cplusplus extern "C" { #endif
/*
一段代碼
*****************************
*****************************
*****************************
*****************************
*/
#ifdef __cplusplus } #endif  

其中__cplusplus是C++編譯器的保留宏定義.就是說C++編譯器認爲這個宏已經定義了。所以關鍵是extern "C" {},extern "C"是告訴C++編譯器件括號裏的東東是按照C的obj文件格式編譯的,要連接的話按照C的命名規則去找.

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章