關於C++中的前置聲明

來源:互聯網
上載者:User

今天一朋友問及C++中的前置聲明問題,下面是我給出的回答。

 

在編寫C++程式的時候,偶爾需要用到前置聲明(Forward declaration)。下面的程式中,帶注釋的那行就是類B的前置說明。這是必須的,因為類A中用到了類B,而類B的聲明出現在類A的後面。如果沒有類B的前置說明,下面的程式將不同通過編譯,編譯器將會給出類似“缺少類型說明符”這樣的出錯提示。

代碼一:

// ForwardDeclaration.h

#include
<iostream>

using namespace std;

 

class B;            
// 這是前置聲明(Forward declaration)

class A

{

private:

         B* b;

public:

         A(B* b):b(b)

         {

         }

         …

};

 

class B

{

         …

};

 

// Main.cpp

#include "ForwardDeclaration.h"

int main(int argc,
char** argv)

{

         B* b = new B();

         A* a = new A(b);

 

         delete a;

         delete b;

 

         return 0;

}

上面程式可以順利編譯和運行(幾乎沒有做什麼,也沒有輸出)。

 

是不是有了前置說明就萬事大吉了呢?我們看看下面的代碼(帶陰影部分的代碼是新增加的):

代碼二:

// ForwardDeclaration.h

#include
<iostream>

using namespace std;

 

class B;            
// 這是前置聲明(Forward declaration)

 

class A

{

private:

         B* b;

public:

         A(B* b):b(b)

         {

         }

 

         void someMethod()

         {

                   b->someMethod();                                                 
// (1)

         }

};

 

class B

{

private:

public:

         void someMethod()

         {

                   cout <<
"something happened..." << endl;

         }

};

 

// Main.cpp

#include
"ForwardDeclaration.h"

 

int main(int argc,
char** argv)

{

         B* b = new B();

         A* a = new A(b);

 

         a->someMethod();

 

         delete a;

         delete b;

 

         return 0;

}

 

一編譯,發現代碼(1)處出錯。出錯提示往往包括(不同的編譯器給出的提示會有所不同):

1.       使用了未定義的類型B;

2.       “->somemethod”的左邊必須指向類/結構/聯合/泛型型別

 

原因:

1.       (1)處使用了類型B的定義,因為調用了類B中的一個成員函數。前置聲明class B;僅僅聲明了有一個B這樣的類型,而並沒有給出相關的定義,類B的相關定義,是在類A後面出現的,因此出現了編譯錯誤;

2.       代碼一之所以能夠通過編譯,是因為其中僅僅用到B這個類型,並沒有用到類B的定義。

 

解決辦法是什嗎?

將類的聲明和類的實現(即類的定義)分離。如下所示:

// ForwardDeclaration.h   類的聲明

#include
<iostream>

using namespace std;

 

class B;            
// 這是前置聲明(Forward declaration)

 

class A

{

private:

         B* b;

public:

         A(B* b);

         void someMethod();

};

 

class B

{

private:

public:

         void someMethod();

};

 

// ForwardDeclaration.cpp        類的實現

#include
"ForwardDeclaration.h"

 

A::A(B* b):b(b)

{

}

 

void A::someMethod()

{

         b->someMethod();

}

 

 

void B::someMethod()

{

         cout << "something happened..." << endl;

}

 

// Main.cpp

#include
"ForwardDeclaration.h"

 

int main(int argc,
char** argv)

{

         B* b = new B();

         A* a = new A(b);

 

         a->someMethod();

 

         delete a;

         delete b;

 

         return 0;

}

 

結論:

前置聲明只能作為指標或引用,不能定義類的對象,自然也就不能調用對象中的方法了。

 

而且需要注意,如果將類A的成員變數B* b;改寫成B& b;的話,必須要將b在A類的建構函式中,採用初始化列表的方式初始化,否則也會出錯。關於這點,詳見:特殊資料類型成員變數的初始化

轉自:http://patmusing.blog.163.com/blog/static/135834960201038113714199/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.