亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

淺析C++中前置聲明的應用與陷阱

2020-01-26 15:58:55
字體:
來源:轉載
供稿:網友

前置聲明的使用
有一定C++開發經驗的朋友可能會遇到這樣的場景:兩個類A與B是強耦合關系,類A要引用B的對象,類B也要引用類A的對象。好的,不難,我的第一直覺讓我寫出這樣的代碼:

復制代碼 代碼如下:

// 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,不通過。再編譯B.cpp,還是不通過。編譯器都被搞暈了,編譯器去編譯A.h,發現包含了B.h,就去編譯B.h。編譯B.h的時候發現包含了A.h,但是A.h已經編譯過了(其實沒有編譯完成,可能編譯器做了記錄,A.h已經被編譯了,這樣可以避免陷入死循環。編譯出錯總比死循環強點),就沒有再次編譯A.h就繼續編譯。后面發現用到了A的定義,這下好了,A的定義并沒有編譯完成,所以找不到A的定義,就編譯出錯了。提示信息如下:
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++為我們提供了前置聲明。前置聲明是什么?舉個形象點的例子,就是我要蓋一個屋子(CHOuse),光有屋子還不行啊,我還得有床(CBed)。但是屋子還沒蓋好,總不能先買床吧,床的大小我定了,改天買。先得把房子蓋好,蓋房子的時候我先給床留個位置,等房子蓋好了,我再決定買什么樣的床。前置聲明就是我在聲明一個類(CHouse)的時候,用到了另外一個類的定義(CBed),但是CBed還沒有定義呢,而且我還先不需要CBed的定義,只要知道CBed是一個類就夠了。那好,我就先聲明類CBed,告訴編譯器CBed是一個類(不用包含CBed的頭文件):
復制代碼 代碼如下:

class CBed;

然后在CHouse中用到CBed的,都用CBed的指針類型代(因為指針類型固定大小的,但是CBed的大小只用知道了CBed定義才能確定)。等到要實現CHouse定義的時候,就必須要知道CBed的定義了,那是再包好CBed的頭文件就行了。

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

復制代碼 代碼如下:

// House.h
class CBed; // 蓋房子時:現在先不買,肯定要買床的
class CHouse
{
    CBed* bed; // 我先給床留個位置
public:
    CHouse(void);
    virtual ~CHouse(void);
    void GoToBed();
};
// House.cpp
#include "Bed.h"
#include "House.h" // 等房子開始裝修了,要買床了
CHouse::CHouse(void)
{
    bed = new CBed(); // 把床放進房子
}
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;必須用指針或引用
引用版本:
復制代碼 代碼如下:

// House.h
class CBed; // 蓋房子時:現在先不買,肯定要買床的
class CHouse
{
    CBed& bed; // 我先給床留個位置
    // CBed bed; // 編譯出錯
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(); // 把床放進房子
    bed = *bedTmp;
}
CHouse::CHouse(CBed& bedTmp)
    : bed(bedTmp)
{
}
CHouse::~CHouse(void)
{
    delete &bed;
}
void CHouse::GoToBed()
{
    bed.Sleep();
}

2、不能在CHouse的聲明中使用CBed的方法
使用了未定義的類型CBed;
bed->Sleep的左邊必須指向類/結構/聯合/泛型類型
復制代碼 代碼如下:

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

3、在CBed定義之前調用CBed的析構函數
復制代碼 代碼如下:

// House.h
class CBed; // 蓋房子時:現在先不買,肯定要買床的
class CHouse
{
    CBed* bed; // 我先給床留個位置
    // CBed bed; // 編譯出錯
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(); // 把床放進房子
}
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; // 調用不到
}
void CBed::Sleep()
{
}
//main.cpp
#include "House.h"
int main()
{
    CHouse house;
    house.RemoveBed();
}

前置聲明解決兩個類的互相依賴
接下來,給出開篇第一個問題的答案:
復制代碼 代碼如下:

// 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)
{
}

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

// 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)
{
}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
www.日韩欧美| 精品国产1区2区| 欧美激情第1页| 国产精品99久久99久久久二8| 欧美激情奇米色| 91精品在线播放| 国产一区二区三区日韩欧美| 国产啪精品视频网站| 亚洲国产三级网| 国产精品美女久久久久av超清| 亚洲精品久久久一区二区三区| 欧美精品videossex性护士| 欧美色xxxx| 亚洲国产高清高潮精品美女| 国产在线不卡精品| 亚洲国产一区二区三区四区| 欧美激情视频网址| 粉嫩老牛aⅴ一区二区三区| 欧美视频在线观看 亚洲欧| 日韩在线观看成人| 日本乱人伦a精品| 成人xxxxx| 中文字幕久久亚洲| 91精品国产高清自在线看超| 亚洲欧美制服另类日韩| 国产精品久久久久久av下载红粉| 亚洲精品久久久久国产| 久久成人精品电影| 欧美成人精品xxx| 国产精品一区二区三区在线播放| 欧美国产日韩精品| 久久黄色av网站| 欧美日韩亚洲成人| 亚洲桃花岛网站| 久久久免费在线观看| 久久久久久久久网站| 国产丝袜一区二区三区| 狠狠操狠狠色综合网| 日韩精品有码在线观看| 久久亚洲国产精品| 国产精品久久久久久久久男| 国产一区在线播放| 中文字幕不卡在线视频极品| 亚洲国产精品久久精品怡红院| 欧美孕妇与黑人孕交| 日韩欧美中文免费| 亚洲欧美日韩区| 亚洲色图综合网| 久久亚洲国产成人| 日本国产欧美一区二区三区| 国产精品青青在线观看爽香蕉| 国产91ⅴ在线精品免费观看| 欧美日韩成人精品| 久久伊人色综合| 国产精品一香蕉国产线看观看| 欧美成人午夜影院| 午夜免费在线观看精品视频| 国产情人节一区| 欧美有码在线视频| 精品视频偷偷看在线观看| 亚洲欧美视频在线| 欧美日韩国产精品一区二区不卡中文| 欧美一区二区三区免费观看| 欧美成人精品一区二区| 色妞欧美日韩在线| 亚洲人午夜精品免费| 亚洲另类欧美自拍| 日韩理论片久久| 亚洲2020天天堂在线观看| 中文字幕国产日韩| 亚洲精品第一国产综合精品| 国产成人av在线播放| 91久久精品在线| 成人免费xxxxx在线观看| www国产精品com| 日韩精品在线免费观看视频| 欧美极品在线视频| 久久大大胆人体| 亚洲欧美日韩第一区| 日韩免费在线视频| 欧美激情a在线| 日韩av一卡二卡| 欧美亚洲国产精品| 久久久av电影| 98精品国产高清在线xxxx天堂| 久久久久九九九九| 久久久亚洲精品视频| 久久久久久久色| 欧美在线免费看| 久久精品国产久精国产一老狼| 欧美性xxxx极品高清hd直播| 国产美女搞久久| 正在播放欧美视频| 2019日本中文字幕| 亚洲黄色成人网| 日韩av在线一区二区| 亚洲精品aⅴ中文字幕乱码| 国产日韩欧美电影在线观看| 尤物tv国产一区| 91国内在线视频| 在线观看视频亚洲| 91在线观看免费网站| 亚洲欧美一区二区三区情侣bbw| 91影视免费在线观看| 亚洲码在线观看| 久久久这里只有精品视频| 久久人人97超碰精品888| 欧美国产高跟鞋裸体秀xxxhd| 欧美日韩一区二区三区在线免费观看| 久久精品成人欧美大片| 精品国产一区二区在线| 久久天天躁狠狠躁夜夜躁2014| 日韩性xxxx爱| 一区三区二区视频| 久久精品91久久久久久再现| 国产精品观看在线亚洲人成网| 国产欧美日韩91| 亚洲国产精品成人精品| 中文字幕一精品亚洲无线一区| www.xxxx欧美| 91免费视频网站| 国产一区二区久久精品| 91免费综合在线| 欧美精品中文字幕一区| 一区二区中文字幕| 欧美精品videosex极品1| 91色中文字幕| 97激碰免费视频| 日韩国产欧美精品一区二区三区| 亚洲sss综合天堂久久| 国产裸体写真av一区二区| 国产成人精品在线| 在线观看中文字幕亚洲| 456亚洲影院| 久久久www成人免费精品张筱雨| 久久精品成人一区二区三区| 亚洲国产日韩精品在线| 国产美女直播视频一区| 欧美乱大交xxxxx另类电影| 欧美性xxxxx极品| 色婷婷综合久久久久中文字幕1| 国产午夜精品一区二区三区| 国产高清视频一区三区| 日韩欧美中文在线| 欧美日韩激情视频| 国产精品丝袜一区二区三区| 国产精品综合不卡av| 91大神在线播放精品| 国产精品h片在线播放| 国产成人精品在线播放| 91经典在线视频| 国产精品揄拍500视频| 成人日韩av在线| 成人性生交大片免费看视频直播| 日本精品一区二区三区在线| 欧美伦理91i| 欧美另类暴力丝袜| 国产精品一久久香蕉国产线看观看| 国产精品视频免费观看www| 欧美性猛交xxxx乱大交| 久久久久亚洲精品国产| 92看片淫黄大片看国产片| 在线激情影院一区| 久久久久国色av免费观看性色|