聲明和定義的區別(深刻理解)

###問題 聲明和定義區別 definition declared 先看一下html

  • 例子1 編譯有沒有問題
class B
{
private:
  A* m_pData;
};

編譯很明顯出現錯誤::沒有 聲明 error: ‘A’ has not been declared error: 'A' does not name a typec++

  • 例子2 編譯有沒有問題
class A;
class B
{
private:
  A* m_pData;
};

編譯沒有報錯 class A 屬於前置聲明 告訴編譯器 能夠識別這個符號聲明不會分配存儲空間 具體這符號能夠作什麼操做不清楚 The forward declaration tells the compiler that the said type exists and nothing more about the particular type 用處: 前置聲明用於指針和引用 由於指針是固定大小 不會由於類A的變更 引發類B從新編譯面試

  • 例子3 編譯有沒有問題
class A;//這是前置聲明(Forward declaration)
class B
{
private:
  A* m_pData;
  void test()
  {
	  m_pData->test();//error以前沒有定義
  }
};
//自後定義了太晚啦
class A
{
public:
	void test();
};

編譯出現錯誤: 前置聲明不能被使用 a.cpp: In member function 'void B::test()': a.cpp:24:11: error: invalid use of incomplete type 'class A' m_pData->test(); ^ a.cpp:17:7: error: forward declaration of 'class A' why You cannot forward declare if you need to deference the structure members微信

class a 是作了聲明 並未定義(在使用以前)session

  • 例子4 只聲明不定義
A.CPP:
extern"C" long ABC( long a, long b );
//是聲明(不是定義 沒有給出 ABC實現的)
 void main()
 {
    long c = ABC( 10, 20 ); 
 }

編譯沒有問題 運行期間出錯:函數

undefined symbol xxx工具

問題定位: nm a.out||grep xx |c++filt U AAA::BBB(int)ui

運行期間出錯: U 該符號未定義過,須要自其餘對象文件中連接進來.net

上面代碼在a.cpp中書寫,編譯生成文件a.obj,沒有問題。但按照以前的說明,鏈接時將錯誤,由於找不到符號_ABC。由於名字_ABC對應的地址欄還空着unix

緣由:對象(函數 類)沒有定義

通常緣由 1 該符號 沒有在當前cpp文件中實現 2 沒有引入其餘cpp文件(庫)

###回答:聲明和定義區別

聲明:定義一個符號 不佔用存儲空間
定義:對這這符號進行完整描述 
具體到函數, class, 和基本數據類型
出現 {} 就是定義 
定義的做用很明顯了,有意義的映射(名字 對地址)佔用存儲空間

A a;//屬於實例化 class A{}//聲明和定義合併在一塊兒了

聲明是告訴編譯器一些信息,以協助編譯器進行語法分析,避免編譯器報錯。而定義是告訴編譯器生成一些代碼,而且這些代碼將由鏈接器使用。即:聲明是給編譯器用的,定義是給鏈接器用的

用類來舉例

> class A
 {
   long ABC( long a, long b );
    //只聲明,沒有定義 在cpp中實現
 long get_session_( long a, long b    ) 
 {  xxxx;} //定義 多了 {} 實現

 };

####擴容:c++和c 對函數符號規則同樣嗎

說明 a.c 和a.cpp內容相同
代碼1

void test(); void test(int); void main() { }

代碼2

void test(){};
void test(int){};
void main()
{
}

1 gcc a.c 編譯代碼1沒有問題 由於聲明是符號

2 gcc a.c 編譯代碼2 有問題 輸入圖片說明

3 g++ a.cpp: 代碼1和代碼2 編譯都沒有問題

c語言不支持函數的重載 由於函數名稱就是符號

知識補充 如何查找一個符號

**1 如何查看一個動態庫信息 **

1.nm -D libxxx.so 打印出符號信息。 我通常這樣用:nm -D libxxx.so |grep T 2.ldd libxxx.so 查看依賴關係 3.readelf -a libxxxx.so 用來讀取elf信息 我通常這樣用:readelf libxxx.so |grep NEEDED 這樣也能夠讀取依賴關係 4.objdump -d libxxxx.so 5.rmp -qfl libxxx.so 這樣能夠查看so庫裏面包含的內容,頭文件等 6.file libxxx.so 這樣能夠查看so庫的屬性 2 如何判斷動態庫a.so 是否load一個靜態庫b.a?

說明 1 ldd動態庫是不顯示靜態庫的名稱的

2 靜態庫的代碼在編譯過程當中已經被載入可執行程序 s

1 nm工具能夠打印出庫中的涉及到的全部符號,這裏的庫既能夠是靜態的也能夠是動態的。 2 可使用 ar -t libname.a 來查看一個靜態庫由那些.o文件構成 Alt text

Alt text

參考 1 http://stackoverflow.com/questions/10894804/forward-declaration-of-struct

2http://blog.chinaunix.net/uid-23381466-id-3464666.html


###想要了解更多c++面試考察基礎知識 歡迎關注
這裏輸入引用文本

相關文章
相關標籤/搜索