2009-10-14 29 views
8

下面的代碼是合法的C++嗎?聲明但不定義內部結構/類 - 合法的C++或不?

class Foo 
{ 
    class Bar; 

    void HaveADrink(Bar &bar); 
    void PayForDrinks(Bar &bar); 

    public: 
    void VisitABar(int drinks); 
}; 

class Foo::Bar 
{ 
    public: 
    int countDrinks; 
}; 

void Foo::HaveADrink(Bar &bar) 
{ 
    bar.countDrinks++; 
} 
void Foo::PayForDrinks(Bar &bar) 
{ 
    bar.countDrinks = 0; 
} 
void Foo::VisitABar(int drinks) 
{ 
    Bar bar; 
    for (int i=0; i<drinks; i++) HaveADrink(bar); 
    PayForDrinks(bar); 
} 

兩個Visual C++和GCC接受它,但是代碼似乎有些奇怪,我和我不想把它拒絕了一些未來的編譯器。

儘管如此,該模式似乎對減少編譯時依賴性很有用 - 我經常用它來聲明用於傳遞一些「上下文」(一堆變量)的結構,這些結構在幾個函數之間共享在同一個cpp文件中,這樣我就不必在公共接口中引入「上下文」定義。

+0

我只是在製作幾個上下文類的過程中,所以我也很感興趣。順便說一下,使countDrinks公共訪問。 – stefaanv 2009-10-14 07:50:32

+0

我是否認爲你指的是Foo :: Bar類定義? – MSalters 2009-10-14 07:59:29

回答

10

合法的,確實有用的實現細節隱藏到外面的世界。

9

我原來說這是「pimpl成語」:http://c2.com/cgi/wiki?PimplIdiom 但我同意這只是pimpl的一部分。這項技術由pimpl使用。

您正在轉發Foo類中的class Bar。只要你在Foo的definigino裏面做任何事情都不需要做任何事情,那就需要Bar的尺寸。您可以使用指針或引用(Bar *或Bar &)來引用Bar,但是如果您在Foo中聲明瞭這樣的數據成員,例如:

private: Bar _bar;

這是行不通的。原因是因爲Foo的定義必須足以確定Foo的大小。由於Bar的大小在Foo的定義內部是未知的,所以它會使Foo的大小不確定。但使用指針將工作:

私人: 酒吧* _bar;

由於指針的sizeof是相同的,因此已知,無論Bar將在以後如何定義。

+2

嗯,它不是_exactly_ pimpl成語(他的代碼中沒有pimpl),但你是對的 - 本質上是這樣。 +1 – sbi 2009-10-14 08:18:03

+1

它只與pimpl相關,因爲它更多地涉及某個上下文的範圍,pimpl是您的類的完整實現。但是你是對的:你只能在做這個時聲明一個指針。幫你一個忙,並使用適當的智能指針。 – stefaanv 2009-10-14 08:40:07

+0

這絕對不是PIMPL。 Bar中沒有實現。 – 2009-10-14 13:59:53