2013-01-15 85 views
2

我正在圍繞這個問題進行包裝。我認爲這實際上是不可能的,但只是爲了確定我想問問在這裏是否真的有解決方案。 考慮下面的代碼。有2個模板類A和B以及兩個分別來自A和B的非模板類C和D.模板類有兩種類型,繼承和前向聲明

// definition of class A 
template <class DerivedA, class DerivedB> class A { 
private: 
    DerivedB data; 
public: 
    A(const DerivedB& data) : data(data) {} 
    virtual ~A() {} 
    DerivedB get() const { return data; } 
}; 

// definition of class B 
template <class DerivedA, class DerivedB> class B { 
private: 
    DerivedA data; 
public: 
    B(const DerivedA& data) : data(data) {} 
    virtual ~B() {} 
    DerivedA get() const { return data; } 
}; 

// forward declaration of D 
class D; 

// definition of class C, derives from A<C, D> 
class C : public A<C, D> { 
private: 
    int extraInfo; 
public: 
    C(const D& d) : A(d) {} 
    virtual ~C() {} 
    int getExtraInfo() const { return extraInfo; } 
}; 

// definition of class D, derives from B<C, D> 
class D : public B<C, D> { 
private: 
    int extraInfo; 
public: 
    D(const C& c) : B(c) {} 
    virtual ~D() {} 
    int getExtraInfo() const { return extraInfo; } 
}; 

這裏的問題是,類C不能被定義,因爲類D只是前向聲明。因此,當模板A被寫出時,它不知道它的私有成員的類型是什麼。請注意,我無法使用指針,我需要一些已知的功能。是否有可能編譯這樣我有我的課程C和D?

+0

什麼阻止你使用指針? – Henrik

+0

你想達到什麼目的? –

+0

@YochaiTimmer我試圖實現一個有向圖。類A代表節點,類B代表弧。爲了實際使用具有有用屬性的有向圖,節點和邊必須從節點類和邊類中派生出來。爲了避開'dynamic_cast',我嘗試使用這種模板化方法。 – rwols

回答

1

有解決這個問題沒辦法,你解釋它,不應該有。當你擁有它現在:

class C : public A<C, D> 

意味着C將繼承D類型的數據成員。依次爲:

class D : public B<C, D> 

意味着D將繼承C類型的數據成員。

如果CD,其中有一個C,其中有一個D ...你有一個很好的無限遞歸,在這種情況下,任何CD對象的大小將是無窮的意蘊。因此,除非您使用指針(您可以在插入適當的空指針的任何點處剪切無限長鏈)或引用(您可以引用先前使用的對象),否則您不能也不應該擁有這種類。

1

C繼承D類型的成員,D繼承C類型的成員。所以,不,這是不可能的。

0

您可以通過讓C和D實現一個純虛擬類,以及您需要的功能(包括getters),並使它們作爲模板參數傳遞該類來擺脫這種困境。然後在A和B中實際使用指向它的指針,但是保留了所有功能。

像這樣的東西(使自己適應)

// definition of class A 
template <class DerivedA, class DerivedB> class A { 
private: 
    const DerivedB& _data; 
public: 
    A(const DerivedB& data) : _data(data) {} 
    virtual ~A() {} 
    DerivedB& get() const { return data; } 
}; 

// definition of class B 
template <class DerivedA, class DerivedB> class B { 
private: 
    DerivedA data; 
public: 
    B(const DerivedA& data) : data(data) {} 
    virtual ~B() {} 
    DerivedA get() const { return data; } 
}; 

class TheInterface { 
public: 
    virtual int getExtraInfo() const = 0; 
virtual ~TheInterface() = 0; 
}; 

// definition of class C, derives from A<C, D> 
class C : public TheInterface, public A<C, TheInterface> { 
private: 
    int extraInfo; 
public: 
    C(const TheInterface& d) : A(d) {} 
    virtual ~C() {} 
    int getExtraInfo() const { return extraInfo; } 
}; 

// definition of class D, derives from B<C, D> 
class D : public TheInterface, public B<C, D> { 
private: 
    int extraInfo; 
public: 
    D(const C& c) : B(c) {} 
    virtual ~D() {} 
    int getExtraInfo() const { return extraInfo; } 
};