2012-11-28 164 views
1

我有一個類的方法派生類,說A我做了什麼?需要實例化一個模板類

template <typename T> class A 
{ 
} ; 

A<T>派生的類,(保留型通用性)

template <typename T> class B : public A<T> 
{ 
} ; 

情況出現我需要在A<T>中聲明的方法中實例化B<T>。呃哦。

template <typename T> class A 
{ 
    void go() 
    { 
     B<T> * newB = new B<T>() ; // oh boy, not working.. 
    } 
} ; 

我應該怎麼做,我該如何解決這個問題?

+0

哇,什麼頭微調! –

回答

2

你需要打破兩個類之間的循環依賴關係。平凡在這種情況下:剛纔定義go()功能脫節:

template <typename T> class A 
{ 
public: 
    void go(); 
} ; 

template <typename T> class B : public A<T> 
{ 
} ; 

template <typename T> 
void A<T>::go() 
{ 
    B<T> * newB = new B<T>() ; 
} 

我喜歡脫節的定義,即使內聯函數時,無論如何,因爲它避免了混亂與不必要的細節的接口。我也更喜歡沒有循環依賴(當然不在基礎和派生之間),但它不總是可以避免的。

+0

每當我嘗試這個而不指定'T'的具體類型(如模板專業化)時,我傾向於獲得鏈接器錯誤 – bobobobo

+1

那麼你似乎有一種傾向,以某種形式做錯了......只要定義是在需要隱式實例化(即它在一個頭文件中)並正確寫入的位置,它可以工作。 –

+0

哦,好的。所以'template void A :: go()'仍然在標題中,它只是在'template class B:public A '之後。被我耍到了。 – bobobobo

1

你可以從它繼承之前前瞻性聲明類模板A - 只是一定要遵循B類的定義,在同一標題的類A模板的定義:

template <typename T> class A; 

template <typename T> class B : public A<T> {}; 

template <typename T> class A 
{ 
    void go() 
    { 
     B<T> * newB = new B<T>(); 
    } 
}; 
+1

你所做的陳述是錯誤的:你**不能**從一個前向聲明的類繼承* class *。然而,只要基類是在實例化點定義的,你就可以從一個前向聲明的類模板繼承一個*類模板*。原因是無論如何基類實際上可能是專業化的。 –

+0

@DietmarKühl:謝謝你的評論。班級模板確實是我想到的,但術語卻沒有了。 – Jon

0

另一種方式來做到這一點的是寫一個全局函數,每個templatedeclare friend

void go(A<T> *a) 
{ 
    // Can now make a B<T> 
    B<T> *b = new B<T>() ; 
    // access b's and a's privates if this function 
    // is friend to A<T> and B<T> 
} 
相關問題