C++ 類的前向聲明的用法


我們知道C++的類應當是先定義,然后使用。但在處理相對復雜的問題、考慮類的組合時,很可能遇到倆個類相互引用的情況,這種情況稱為循環依賴。

例如:

class A
{
public:
    void f(B b);//以B類對象b為形參的成員函數
                //這里編譯錯位,因為'B'為為止符號
};

class B
{
public:
    void g(A a);
};

這里類A的公有成員函數f的形參是類B的對象,同時類B的公有成員函數g也以類A的對象為形參。由於在使用一個類之前,必須首先定義該類,因此無論將哪一個類的定義放在前面,都會引起編譯錯誤。結局這個問題的方法,就是使用前向引用聲明。前向引用聲明,是在引用未定義的類之前,將該類的名字告訴編譯器,試編譯器知道那是一個類名。這樣,當程序中使用這個類名時,編譯器就不會認為是錯誤,而類的完整定義可以在程序的其他地方。在上述程序加上下面的前向引用聲明,問題就解決了。

class B; //前向引用聲明
class A//A類的定義
{
public://外部接口
    void f(B b);//以B類對象b為形參的成員函數
               
};

class B//B類的定義
{
public://外部接口
    void g(A a);//以A類對象a為形參的成員函數
};
 
 
使用前向引用聲明雖然可以解決一些問題,但它並不是萬能的。需要注意的是,盡管使用了前向引用聲明, 但是在提供一個完整的類聲明之前,不能定義該類的對象,也不能在內聯成員函數中使用該類的對象。請看下面的程序段:
class Fred;    //前向引用聲明
class Barney
{
    Fred x;    //錯誤:類Fred的聲明尚不完善
};
class Fred
{
    Barney y;
};

編譯出錯的原因是對此類Fred的前向引用聲明只能說明Fred是一個類名,而不能給出該類的完整定義,因此在類Barney中不能定義類Fred的數據成員。

 

再看下面這一段程序:

class Fred;    //前向引用聲明

class Barney
{
public:
    void method()
    {
        x->yabbaDabbaDo();    //錯誤:Fred類的對象在定義之前被使用
    }
private:
    Fred* x;   //正確,經過前向引用聲明,可以聲明Fred類的對象指針
};

class Fred
{
public:
    void yabbaDabbaDo();
private:
    Barney* y;
};

出錯原因:類Barney的內聯函數中使用了由x所指向、Fred類的對象,而此時Fred類尚未完整地定義。

應該記住:當你使用前向引用聲明時,你只能使用被聲明的符號,而不能涉及類的任何細節。

 
C++的類可以進行前向聲明。但是,僅僅進行前向聲明而沒有定義的類是不完整的,這樣的類, 只能用於定義指針、引用、以及用於函數形參的指針和引用。
而不能定義對象(因為此時編譯器只知道這是個類,還不知道這個類的大小有多大),也不能訪問類的對象,任何形式的訪問都不允許(因為此時根本不知道有些什么成員)。等到類正式定義以后,就可以以各種方式使用該類了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM