2010-08-19 106 views
1

我想爲一個數據庫類寫一個函數,它基本上只是一個包圍對象(比如形狀)的hash_map的包裝,它由ID號索引,它將查找一個ID並將其轉換爲適當的指針類型。在函數中是否可以將類型作爲參數?

例如我希望能夠做到這樣的事情:

Circle* shapeToLookup = NULL; 
int idNum = 12; 
database.lookup(idNum, circleToLookup); 
if(circleToLookup != NULL) 
{ 
    // Do stuff with the circle. 
} 

並讓數據庫知道它的參數的類型。有沒有辦法做到這一點,而不是超載功能(lookup(int, Circle*),lookup(int, Rect*),廣告nauseum)?你能否聲明一個像lookup(int, Shape*)這樣的函數,並且知道它給出了哪種類型?

謝謝!

+0

IMO,這實際上是一個數據庫問題。你也不會說什麼數據庫。我會查看SQL關鍵字「LIKE」。 – JustBoo 2010-08-19 15:49:36

+0

你打算如何將類型信息傳遞給數據庫? (或者我應該說,數據庫將如何接收它?) – 2010-08-19 15:50:19

+0

如果您希望數據庫使用此信息*執行某些操作*,則必須編寫一些特定於圓的代碼,某些矩形特定的代碼等等令人厭惡。問題是*你想把這個代碼放在哪裏。你能告訴我們你想要數據庫做什麼嗎? – Beta 2010-08-19 15:51:50

回答

3

您可以使用模板來做到這一點。

編輯:基於額外信息的新實現。如果mymapstd::map<int, Shape*>

template <typename T> 
void lookup(int idNum, T* &ptr) { 
    auto it = mymap.find(idNum); 
    if (it == mymap.end()) { 
     ptr = 0; 
    } else { 
     ptr = dynamic_cast<T*>(*it); // Shape must have a virtual member function 
    } 
} 

或者你可能更喜歡:

template <typename T> 
T* lookup(int idNum) { 
    auto it = mymap.find(idNum); 
    if (it == mymap.end()) { 
     return 0; 
    } 
    return dynamic_cast<T*>(*it); 
} 

然後調用它像Circle *circle = database.lookup<Circle>(123);

顯然多態性容器的樂趣本身就是一個一大堆,但我會假設你已經排序。那裏可能有一個shared_ptr,我已經遺漏了。

舊的實現時,我想到了DB可以存儲POD的副本:

template <typename T> 
void lookup(int idNum, T* &ptr) { 
    void *theresult = // something based on idNum 

    // some check needed here that theresult really is the right type. 
    // how you do this depends on the database, but suppose that 
    // the database gives us some integer "type" which indicates the type 
    if (type != type_constant<T>::value) { 
     ptr = 0; 
    } else { 
     ptr = static_cast<T*>(theresult); 
    } 
} 

type_constant是 「型特徵」 的一個例子,你實現它想:

template <typename T> 
struct type_constant {}; 

template <> 
struct type_constant<Circle> { 
    static const int value = 1; 
}; 

template <> 
struct type_constant<Rectangle> { 
    static const int value = 2; 
}; 

// etc... 
+0

我們是否應該不使用dynamic_cast <>投向兒童類型。 (即從Shape *到Circle *)? – 2010-08-19 15:55:45

+0

也許吧。我不知道這個數據庫實際上是否返回 - 如果它是一個'Shape *',它的referand是一個子類,並且'Shape *'具有任何虛擬成員函數,那麼是的。如果數據庫本身不是基於對象的,或者某個地方的某個人必須根據指示類型的記錄來執行某些操作。我無法從「Shape *」是一個實際的基類的問題或者問題提及者認爲它可能是解決方案的一部分的問題中斷言。 – 2010-08-19 15:59:10

+0

我不知道'type_constant',我可能會像馬丁所說的那樣看着'dynamic_cast'。一個facepalm的位,不用馬上思考模板。 – spbots 2010-08-19 16:01:32

0

其他人已經解釋瞭如何將一個類型傳遞給一個函數(通過使用函數模板)。我想給另一種觀點:

這可能是更好的對Shape引入一個新的虛函數,然後Do stuff with the Circle部分移動到在Cricle類,虛函數的重新實現。

這樣,您就不需要知道類型。您只需從數據庫中獲取Shape對象,然後調用doStuff()函數 - 並且它根據Shape的實際類型執行正確的操作。虛擬函數的一個很好的用例。 :-)

當然,這可能或多或少簡單一些,具體取決於Do stuff的實際情況。

+0

不幸的是,這是遺留代碼中的一個重要的重構工作,其中「形狀」都嚴重依賴於其他形狀,因此查找實際上是在其他形狀內部發生的,doStuff()不一定是通用功能。感謝雖然:) – spbots 2010-08-19 15:55:56

4
template <T> 
Database::lookup(int idNum, T TobjectToLookup) 
{ 
    // inside here, T is the type of the object passed in/ 
} 
相關問題