最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析C++中前置聲明的應(yīng)用與陷阱

 更新時(shí)間:2013年07月20日 16:18:20   作者:  
以下是對(duì)C++中前置聲明的應(yīng)用與陷阱進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下

前置聲明的使用
有一定C++開發(fā)經(jīng)驗(yàn)的朋友可能會(huì)遇到這樣的場(chǎng)景:兩個(gè)類A與B是強(qiáng)耦合關(guān)系,類A要引用B的對(duì)象,類B也要引用類A的對(duì)象。好的,不難,我的第一直覺讓我寫出這樣的代碼:

復(fù)制代碼 代碼如下:

// A.h
#include "B.h"
class A
{

public:
    A(void);
    virtual ~A(void);
};
//A.cpp
#include "A.h"
A::A(void)
{
}
A::~A(void)
{
}
// B.h
#include "A.h"
class B
{
    A a;
public:
    B(void);
    ~B(void);
};
// B.cpp
#include "B.h"
B::B(void)
{
}
B::~B(void)
{
}

好的,完成,編譯一下A.cpp,不通過(guò)。再編譯B.cpp,還是不通過(guò)。編譯器都被搞暈了,編譯器去編譯A.h,發(fā)現(xiàn)包含了B.h,就去編譯B.h。編譯B.h的時(shí)候發(fā)現(xiàn)包含了A.h,但是A.h已經(jīng)編譯過(guò)了(其實(shí)沒有編譯完成,可能編譯器做了記錄,A.h已經(jīng)被編譯了,這樣可以避免陷入死循環(huán)。編譯出錯(cuò)總比死循環(huán)強(qiáng)點(diǎn)),就沒有再次編譯A.h就繼續(xù)編譯。后面發(fā)現(xiàn)用到了A的定義,這下好了,A的定義并沒有編譯完成,所以找不到A的定義,就編譯出錯(cuò)了。提示信息如下:
1>d:/vs2010/test/test/a.h(5): error C2146: syntax error : missing ';' before identifier 'b'
1>d:/vs2010/test/test/a.h(5): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:/vs2010/test/test/a.h(5): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
那怎么辦?有辦法,C++為我們提供了前置聲明。前置聲明是什么?舉個(gè)形象點(diǎn)的例子,就是我要蓋一個(gè)屋子(CHOuse),光有屋子還不行啊,我還得有床(CBed)。但是屋子還沒蓋好,總不能先買床吧,床的大小我定了,改天買。先得把房子蓋好,蓋房子的時(shí)候我先給床留個(gè)位置,等房子蓋好了,我再?zèng)Q定買什么樣的床。前置聲明就是我在聲明一個(gè)類(CHouse)的時(shí)候,用到了另外一個(gè)類的定義(CBed),但是CBed還沒有定義呢,而且我還先不需要CBed的定義,只要知道CBed是一個(gè)類就夠了。那好,我就先聲明類CBed,告訴編譯器CBed是一個(gè)類(不用包含CBed的頭文件):
復(fù)制代碼 代碼如下:

class CBed;

然后在CHouse中用到CBed的,都用CBed的指針類型代(因?yàn)橹羔橆愋凸潭ù笮〉模荂Bed的大小只用知道了CBed定義才能確定)。等到要實(shí)現(xiàn)CHouse定義的時(shí)候,就必須要知道CBed的定義了,那是再包好CBed的頭文件就行了。

前置聲明有時(shí)候很有用,比如說(shuō)兩個(gè)類相互依賴的時(shí)候要。還有前置聲明可以減少頭文件的包含層次,減少出錯(cuò)可能。上面說(shuō)的例子。

復(fù)制代碼 代碼如下:

// House.h
class CBed; // 蓋房子時(shí):現(xiàn)在先不買,肯定要買床的
class CHouse
{
    CBed* bed; // 我先給床留個(gè)位置
public:
    CHouse(void);
    virtual ~CHouse(void);
    void GoToBed();
};
// House.cpp
#include "Bed.h"
#include "House.h" // 等房子開始裝修了,要買床了
CHouse::CHouse(void)
{
    bed = new CBed(); // 把床放進(jìn)房子
}
CHouse::~CHouse(void)
{
}
void CHouse::GoToBed()
{
    bed->Sleep();
}
// Bed.h
class CBed
{
public:
    CBed(void);
    ~CBed(void);
    void Sleep();
};
// Bed.cpp
#include "Bed.h"
CBed::CBed(void)
{
}
CBed::~CBed(void)
{
}
void CBed::Sleep()
{
}

前置聲明中的陷阱
注意這里有陷阱:
1、CBed* bed;必須用指針或引用
引用版本:
復(fù)制代碼 代碼如下:

// House.h
class CBed; // 蓋房子時(shí):現(xiàn)在先不買,肯定要買床的
class CHouse
{
    CBed& bed; // 我先給床留個(gè)位置
    // CBed bed; // 編譯出錯(cuò)
public:
    CHouse(void);
    CHouse(CBed& bedTmp);
    virtual ~CHouse(void);
    void GoToBed();
};
// House.cpp
#include "Bed.h"
#include "House.h" // 等房子開始裝修了,要買床了
CHouse::CHouse(void)
    : bed(*new CBed())
{
    CBed* bedTmp = new CBed(); // 把床放進(jìn)房子
    bed = *bedTmp;
}
CHouse::CHouse(CBed& bedTmp)
    : bed(bedTmp)
{
}
CHouse::~CHouse(void)
{
    delete &bed;
}
void CHouse::GoToBed()
{
    bed.Sleep();
}

2、不能在CHouse的聲明中使用CBed的方法
使用了未定義的類型CBed;
bed->Sleep的左邊必須指向類/結(jié)構(gòu)/聯(lián)合/泛型類型
復(fù)制代碼 代碼如下:

class CBed; // 蓋房子時(shí):現(xiàn)在先不買,肯定要買床的
class CHouse
{
    CBed* bed; // 我先給床留個(gè)位置
    // CBed bed; // 編譯出錯(cuò)
public:
    CHouse(void);
    virtual ~CHouse(void);
    void GoToBed()
    {
        bed->Sleep();  // 編譯出錯(cuò),床都沒買,怎么能睡
    }
};

3、在CBed定義之前調(diào)用CBed的析構(gòu)函數(shù)
復(fù)制代碼 代碼如下:

// House.h
class CBed; // 蓋房子時(shí):現(xiàn)在先不買,肯定要買床的
class CHouse
{
    CBed* bed; // 我先給床留個(gè)位置
    // CBed bed; // 編譯出錯(cuò)
public:
    CHouse(void);
    virtual ~CHouse(void);
    void GoToBed();
    void RemoveBed()
    {
        delete bed; // 我不需要床了,我要把床拆掉。還沒買怎么拆?
    }
};
// House.cpp
#include "Bed.h"
#include "House.h" // 等房子開始裝修了,要買床了
CHouse::CHouse(void)
{
    bed = new CBed(); // 把床放進(jìn)房子
}
CHouse::~CHouse(void)
{
    int i = 1;
}
void CHouse::GoToBed()
{
    bed->Sleep();
}
// Bed.h
class CBed
{
    int* num;
public:
    CBed(void);
    ~CBed(void);
    void Sleep();
};
// Bed.cpp
#include "Bed.h"
CBed::CBed(void)
{
    num = new int(1);
}
CBed::~CBed(void)
{
    delete num; // 調(diào)用不到
}
void CBed::Sleep()
{
}
//main.cpp
#include "House.h"
int main()
{
    CHouse house;
    house.RemoveBed();
}

前置聲明解決兩個(gè)類的互相依賴
接下來(lái),給出開篇第一個(gè)問(wèn)題的答案:
復(fù)制代碼 代碼如下:

// A.h
class B;
class A
{
    B* b;
public:
    A(void);
    virtual ~A(void);
};
//A.cpp
#include "B.h"
#include "A.h"
A::A(void)
{
    b = new B;
}
A::~A(void)
{
}
// B.h
class A;
class B
{
    A a;
public:
    B(void);
    ~B(void);
};
// B.cpp
#include "A.h"
#include "B.h"
B::B(void)
{
    a = New A;
}
B::~B(void)
{
}

前置聲明在友元類方法中的應(yīng)用
《C++ Primer 4Edition》在類的友元一章節(jié)中說(shuō)到,如果在一個(gè)類A的聲明中將另一個(gè)類B的成員函數(shù)聲明為友元函數(shù)F,那么類A必須事先知道類B的定義;類B的成員函數(shù)F聲明如果使用類A作為形參,那么也必須知道類A的定義,那么兩個(gè)類就互相依賴了。要解決這個(gè)問(wèn)題必須使用類的前置聲明。例如:
復(fù)制代碼 代碼如下:

// House.h
#include "Bed.h"
class CHouse
{
    friend void CBed::Sleep(CHouse&);
public:
    CHouse(void);
    virtual ~CHouse(void);
    void GoToBed();
    void RemoveBed()
    {
    }
};
// House.cpp
#include "House.h"
CHouse::CHouse(void)
{
}
CHouse::~CHouse(void)
{
    int i = 1;
}
void CHouse::GoToBed()
{
}
// Bed.h
class CHouse;
class CBed
{
    int* num;
public:
    CBed(void);
    ~CBed(void);
    void Sleep(CHouse&);
};
// Bed.cpp
#include "House.h"
CBed::CBed(void)
{
    num = new int(1);
}
CBed::~CBed(void)
{
    delete num;
}
void CBed::Sleep(CHouse& h)
{
}

相關(guān)文章

  • C++控制臺(tái)實(shí)現(xiàn)簡(jiǎn)單注冊(cè)登錄

    C++控制臺(tái)實(shí)現(xiàn)簡(jiǎn)單注冊(cè)登錄

    這篇文章主要為大家詳細(xì)介紹了C++控制臺(tái)實(shí)現(xiàn)簡(jiǎn)單注冊(cè)登錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • 詳解C++中四種類型的轉(zhuǎn)換

    詳解C++中四種類型的轉(zhuǎn)換

    這篇文章主要是想和大家一起聊聊來(lái)C++中的四種類型轉(zhuǎn)換?:const_cast、static_cast、reinterpret_cast和dynamic_cast,感興趣的可以了解一下
    2022-12-12
  • C++單例模式應(yīng)用實(shí)例

    C++單例模式應(yīng)用實(shí)例

    這篇文章主要介紹了C++單例模式應(yīng)用實(shí)例,詳細(xì)講述了單例模式的原理與結(jié)構(gòu),及相關(guān)的打印機(jī)應(yīng)用實(shí)例,需要的朋友可以參考下
    2014-10-10
  • C++獲取GPU顯卡信息的示例代碼

    C++獲取GPU顯卡信息的示例代碼

    這篇文章主要為大家詳細(xì)介紹了如何使用C++獲取GPU顯卡信息,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,有需要的小伙伴可以參考一下
    2024-02-02
  • 關(guān)于C++函數(shù)模版的實(shí)現(xiàn)講解

    關(guān)于C++函數(shù)模版的實(shí)現(xiàn)講解

    今天小編就為大家分享一篇關(guān)于關(guān)于C++函數(shù)模版的實(shí)現(xiàn)講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • C++中關(guān)鍵字const的詳細(xì)說(shuō)明和使用介紹(最全)

    C++中關(guān)鍵字const的詳細(xì)說(shuō)明和使用介紹(最全)

    const在C/C++中是十分重要的,如果單純理解為“常量”那么你的格局就小了,今天在這里給大家介紹一下const在C++中具體詳細(xì)的用法,需要的朋友可以參考下
    2025-03-03
  • 關(guān)于C++中定義比較函數(shù)的三種方法小結(jié)

    關(guān)于C++中定義比較函數(shù)的三種方法小結(jié)

    下面小編就為大家?guī)?lái)一篇關(guān)于C++中定義比較函數(shù)的三種方法小結(jié)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-10-10
  • 利用Qt實(shí)現(xiàn)可擴(kuò)展對(duì)話框的示例代碼

    利用Qt實(shí)現(xiàn)可擴(kuò)展對(duì)話框的示例代碼

    可擴(kuò)展對(duì)話框通常用于用戶對(duì)界面有不同要求的場(chǎng)合。當(dāng)供高級(jí)用戶使用或需要更多信息時(shí),可通過(guò)某種方式的切換顯示完整對(duì)話窗體(擴(kuò)展窗體)。本文將用Qt實(shí)現(xiàn)可擴(kuò)展對(duì)話框,需要的可以參考一下
    2022-06-06
  • C++多繼承多態(tài)的實(shí)例詳解

    C++多繼承多態(tài)的實(shí)例詳解

    這篇文章主要介紹了C++多繼承多態(tài)的實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • vscode+platformIO開發(fā)stm32f4的實(shí)現(xiàn)

    vscode+platformIO開發(fā)stm32f4的實(shí)現(xiàn)

    這篇文章主要介紹了vscode+platformIO開發(fā)stm32f4的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05

最新評(píng)論

永仁县| 汝南县| 黄陵县| 阿坝县| 广饶县| 峨眉山市| 六安市| 大姚县| 桦南县| 黄石市| 宜宾县| 莎车县| 白银市| 余干县| 遂平县| 莱阳市| 宜春市| 上蔡县| 东阳市| 商河县| 南昌县| 肥东县| 和平县| 河源市| 博罗县| 邹平县| 平江县| 海林市| 吴堡县| 衡南县| 临猗县| 镇康县| 驻马店市| 龙江县| 闻喜县| 广南县| 长丰县| 卓尼县| 达州市| 萝北县| 蒙山县|