2009-09-30 23 views
5

我想從一個普通到另一個投,說:C++模板類型轉換與衍生物

myClass<MoreAbstract> anItem = myclass<DerivateFromMoreAbstract> anotherObject; 

或者做類似

aFunction(anotherObject); // myclass<DerivateFromMoreAbstract> anotherObject 

其中機能缺失簽名

aFunction(myClass<MoreAbstract> item); 

實際上,myClass實際上是我在網上找到的shared_ptr的簡化實現。我想知道是否有任何方法可以從一種指針類型切換到另一種指針封裝類型。

有沒有辦法做這樣的鑄造?如果是這樣,那麼執行它的正確方法是什麼?

如果有幫助的人,VC++給了我這個錯誤:

Error 1 error C2440: 'type cast' : cannot convert from 'myClass<T>' to 'myClass<T>' 
+1

難道這是C++。NET。泛型或c + +模板的問題? –

+0

@Yannick:C++模板。 – tomzx

回答

10

你不能靜態轉換,因爲它們是不兼容的類型。有時你可以創建一個操作員把該類型而不是

#include <iostream> 

class A { }; 

class B : public A { }; 


template<typename T> 
struct holder { 
    T* value; 

    holder (T*value) : value (value) { } 

    template < typename U > // class T : public U 
    operator holder<U>() const 
    { 
     return holder<U>(value); 
    } 
}; 


int main() 
{ 
    using namespace std; 

    B b; 

    holder<B> hb (&b); 
    holder<A> ha = hb; 

    cout << boolalpha; 

    cout << (hb.value == ha.value) << endl; 

    return 0; 
} 

這是否是一個有意義的操作,而依賴於語義模板類的 - 如果aFunction可以把任何東西進入處理程序,您不希望更具體的對象被突變。因此,不管怎樣,你都要用強制操作符或模板拷貝構造函數和賦值來複制。 (強制代碼較少,但如果不使用參考參數,可能會導致創建更多對象)

+2

我寧願將轉換構造函數轉換爲轉換運算符,因爲後者無法啓用或禁用 –

+0

@Pete Kirkham:我需要你的幫助。爲什麼你在struct holder裏面使用template ?它的目的是什麼?在您寫下的評論中,// T類:public U.這是什麼意思? – Destructor

3

對不起,那是不可能的。 (好吧,除非你做了討厭的reinterpret_cast黑客,但你不想這麼做 - 最終的結果不會很好)。

T<Base>T<Derived>是無關的。編譯器不能假設 - 記住T完全有可能專門用於Derived是完全不同的東西。

1

C++中的模板以及C++。net中的泛型不是協變的。

檢查this問題,可能會給你一個解決方法的想法。

6

類型不是默認以這種方式轉換的(因爲您可能不希望對象這樣做)。一般來說,您可以採取兩種方法:

實施顯式轉換函數,這對於運行時轉換可能很有用,如boost's shared_ptr dynamic_pointer_cast。你最終的東西,如:

template <typename To, typename From> 
myclass<To> myclass_cast(const myclass<From>&) 
{ /* do a runtime cast, possibly with exceptions */ } 

第二種方法是轉換構造函數,這是很好的,如果它是在編譯時可判定它們是否可轉換。例如,如果所有的類都是可轉換從模板上派生到模板上的基地,這裏有一個構造函數時這是真的(使用enable_if和boost :: type_traits)只會工作:

template <typename To> 
class myclass { 
    //converting constructor 
    template <typename From> 
    myclass(const myclass<From>&, 
      typename enable_if<boost::type_traits::is_base_of<To, From> >::type* dummy = 0) 
    { } 
};