淺析C++中前置聲明的運用與圈套。本站提示廣大學習愛好者:(淺析C++中前置聲明的運用與圈套)文章只能為提供參考,不一定能成為您想要的結果。以下是淺析C++中前置聲明的運用與圈套正文
前置聲明的應用
有必定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)
{
}