2012-07-06 52 views
6

我正在設計一個簡單的Array類,可以容納任何類型的對象,就像一個可以在一個對象中容納多種類型數據的向量。 (這是一個學習的目的。)如何在運行時使用C++獲取給定元素的模板類型?

我有一個名爲Container空基類:

class Container {}; 

和被叫Object模板化的子類:

template <class T> 
class Object : public Container { 
    T& object; 
public: 
    Object(T& obj = nullptr) : object(obj) {} 
}; 

我有一個Array類持有vector指針Container s我用來保存Object s:

class Array { 
    std::vector<Container *> vec; 
public: 
    template <class T> 
    void add_element(const T&); 
    auto get_element(int); 
}; 

add_element存儲元件到Object S和將其放入vec

template <class T> 
void Array::add_element(const T& element) 
{ 
    vec.push_back(new Object<T>(element)); 
} 

get_element移除元件從它的Object並將其傳遞迴給調用者。這是我的問題所在。爲了從Object刪除元素,我需要知道它是什麼類型的Object

auto Array::get_element(int i) 
{ 
    return (Object</* ??? */> *)vec[i])->object; 
} 

是否有某種方式爲我找出我存儲什麼樣的目標?

編輯:因爲人們聲稱這是不可能的,這個怎麼樣。是否有某種方式實際存儲類內部的類信息? (我知道你可以用紅寶石來做到這一點)。如果我能這樣做,我可以在每個Object中存儲返回類型get_element

+0

@ildjarn:由於OP中的問題使用'auto',我認爲它是安全的假設。 – 2012-07-06 22:19:20

+0

@ user315052,因爲使用這種方式會更困難。 @ildjarn是的,但是如果我'decltype(vec [i])'我只會得到一個'Container *'。我需要知道它是什麼子類。 – anthropomorphic 2012-07-06 22:19:36

+0

@Jesse:啊,好點。 :-P – ildjarn 2012-07-06 22:21:42

回答

2

我在想這個模板的行。

template <class T> 
T& Array::get_element(int i, T &t) 
{ 
    Object<T> *o = dynamic_cast<Object<T> *>(vec[i]); 
    if (o == 0) throw std::invalid_argument; 
    return t = o->object; 
} 

Array arr; 
double f; 
int c; 

arr.get_element(0, f); 
arr.get_element(1, c); 

但或者,你可以這樣做:

template <class T> 
T& Array::get_element(int i) 
{ 
    Object<T> *o = dynamic_cast<Object<T> *>(vec[i]); 
    if (o == 0) throw std::invalid_argument; 
    return o->object; 
} 

f = arr.get_element<double>(0); 
c = arr.get_element<int>(1); 
+0

你知道,我認爲這可能是最好的方法,謝謝 – anthropomorphic 2012-07-06 22:54:31

+0

我不太喜歡你的throw語句,通常我會拋出一個'std :: exception',但你的基本思想是好的。沒有prb - thx =) – anthropomorphic 2012-07-06 22:57:02

+1

@MichaelDorst:編輯提出,問候 – jxh 2012-07-06 23:01:44

1

函數返回類型如Array::get_element必須在編譯時確定。由於類Array不知道它在編譯時存儲了哪些類型的容器,唯一的選擇是返回基址Container*指針。然後,該代碼的用戶可以使用虛擬功能和/或處理這些通用容器。

+0

這個類的全部內容都是爲了讓我在每次訪問元素時都不必使用所有的語法。 '((對象 *)vec [num] .-> object'太亂了 – anthropomorphic 2012-07-06 22:23:49

+1

如果'Container'有足夠的虛函數,就不需要任何強制轉換 – aschepler 2012-07-06 23:28:46

1

dynamic_cast <>()當在指針上使用時,可用於檢查轉換是否真的可行,因爲當類型不匹配時它會返回NULL。

但是,您可能需要重新考慮您的設置; dynamic_cast是不是你想要使用,如果你可以避免它,並有級聯的「if object-is-type1然後做到這一點;否則,如果object-is-type2那麼做;否則,如果object-is-type3 ......「幾乎總是設計不好的肯定標誌。

在你的get_element中使用auto可能是你解決問題的技巧,你不知道類型是什麼 - 但這不起作用。編譯器仍然需要知道返回類型;它在運行時不能改變。

編輯:你也可以退後一步,問自己你是否真的需要一個可以存儲「任何東西」的數組。我已經使用了Objective-C很長一段時間,它基本上是圍繞着一切都只是一個「對象」的概念而構建的,人們可以根據任何事情調用任何東西,這些都是在運行時完成的。但是,我發現這種實際使用很少見...特別是對於容器,我發現我使用的每個NSArray都只有一種類型的對象,或者可能是一個普通的基類,但實際上並不是獨立的,不相關的類。

+0

這種用法很少見,但仍然有必要我最初的想法是創建一個我可以用作Obj-C對象的包裝的類(爲了最小化Obj-C++代碼,因爲它很難維護)。如果我使用一個向量,我無法處理每個場景,這是有問題的 – anthropomorphic 2012-07-06 22:31:40

相關問題