2012-03-05 106 views
5

我有以下層次:從基指針溯造型到模板派生類型

class base 
{ 
public: 
    virtual ~base(){} 
    virtual void foo() {} 
}; 

template <typename T> 
class derived1 : public base 
{ 
    virtual void foo() {}; 
}; 

template <typename T> 
class derived2 : public base 
{ 
    virtual void foo() {}; 
}; 

現在給出一個指向基地,我想找出是否 底層或者是derived1或Derived2的。問題是 derived1和derived2可以專門用於許多不同的 類型,使用dynamic_cast測試downcast需要知道 模板類型。我已經結束了凌亂,不可靠和不完整的代碼位:

base* b = new derived1<int>(); 

if (dynamic_cast<derived1<int>*> || 
    dynamic_cast<derived1<unsigned int>*> || 
    dynamic_cast<derived1<double>*>) 
    std::cout << "is derived1"; 
else if (dynamic_cast<derived2<int>*> || 
    dynamic_cast<derived2<unsigned int>*> || 
    dynamic_cast<derived2<double>*>) 
    std::cout << "is derived2"; 

有沒有更好的方法,可以處理任何類型的專業化?

+2

一旦您知道該類型是派生模板之一的特化,您打算做什麼? – 2012-03-05 02:20:09

+0

@James:爲每一個函數調用一個特定的函數 - 順便說一句,有更多的derived1和derived2 – 2012-03-05 02:23:28

+6

需要動態地測試基類指針的具體類型的條件代碼是一個糟糕的代碼味道。有可能有一種方法來改變你的設計,以避免這種情況。 – 2012-03-05 02:24:45

回答

8

將依賴於類型的邏輯移入類型中。

相反的:

if (dynamic_cast<derived1<int>*>(b) || 
    dynamic_cast<derived1<unsigned int>*>(b) || 
    dynamic_cast<derived1<double>*>(b)) 
    std::cout << "is derived1"; 
else if (dynamic_cast<derived2<int>*>(b) || 
    dynamic_cast<derived2<unsigned int>*>(b) || 
    dynamic_cast<derived2<double>*>(b)) 
    std::cout << "is derived2"; 

添加virtual print_name() const功能base,然後執行:

void example() { 
    std::unique_ptr<base> b(new derived1<int>()); 
    b->print_name(); 
} 
class base 
{ 
public: 
    ~base(){} 
    virtual void foo() {} 
    virtual void print_name() const = 0; 
}; 

template <typename T> 
class derived1 : public base 
{ 
    virtual void foo() {} 
    virtual void print_name() const { 
     std::cout << "is derived1"; 
    } 
}; 

template <typename T> 
class derived2 : public base 
{ 
    virtual void foo() {} 
    virtual void print_name() const { 
     std::cout << "is derived2"; 
    } 
}; 
6

插入一個非模板類其間basederived1derived2

class base 
{ 
public: 
    virtual ~base() {} // **NOTE** Should be virtual 
    virtual void foo() {} 
}; 

class derived1_base : public base 
{ 
}; 

template <typename T> 
class derived1 : public derived1_base 
{ 
public: 
    virtual void foo() {} 
}; 

class derived2_base : public base 
{ 
}; 

template <typename T> 
class derived2 : public derived2_base 
{ 
public: 
    virtual void foo() {} 
}; 

在評論,你所提到的:

[我要]呼籲每一個特定的功能 - 順便說一句有不止 derived1和Derived2的

添加一個(虛擬)功能derived1_base,你甚至不需要知道T了。

if (dynamic_cast<derived1_base*>(foo)) 
{ 
    std::cout << "is derived1"; 
    dynamic_cast<derived1_base*>(foo)->specific_derived1_function(); 
} 
else if (dynamic_cast<derived2_base*>(foo)) 
{ 
    std::cout << "is derived2"; 
    dynamic_cast<derived2_base*>(foo)->specific_derived2_function(); 
} 

注意:我考慮的一個dynamic_cast<>代碼列表,我希望你重新考慮你的方法。

2

解決方案1:增加一個虛函數:

enum DerivedType 
{ 
    One, 
    Two, 
    ... 
}; 

class base 
{ 
public: 
    ~base(){} 
    virtual void foo() {} 
    virtual DerivedType GetType() = 0; 
}; 

template <typename T> 
class derived1 : public base 
{ 
    virtual void foo() {}; 
    virtual DerivedType GetType() { return One; } 
}; 

template <typename T> 
class derived2 : public base 
{ 
    virtual void foo() {}; 
    virtual DerivedType GetType() { return Two; } 
}; 

解決方案2:使用標籤類:

class Base 
{ 
public: 
    virtual ~Base() { } 
}; 

class Derived1Tag 
{ }; 

class Derived2Tag 
{ }; 

template <class T> 
class Derived1 : public Base, public Derived1Tag 
{ }; 

template <class T> 
class Derived2 : public Base, public Derived2Tag 
{ }; 


int main(int argc, char** argv) 
{ 
    Derived1<int> d1; 
    Derived2<int> d2; 

    cout << dynamic_cast<Derived1Tag*>((Base*)&d1) << endl; 
    cout << dynamic_cast<Derived1Tag*>((Base*)&d2) << endl; 

    return 0; 
} 
+0

我必須說,@EmileCormier是正確的,這**可能**反映了糟糕的設計選擇的地方。如果你想運行的函數取決於類型,那麼它可能應該從一開始就是一個虛函數。 – 2012-03-05 02:47:33

3

你可以添加一個虛擬的方法做某種類型的元類型檢查:

class base 
{ 
public: 
    ~base(){} 
    virtual void foo() {} 
    virtual bool isa(const char* type_to_test){ 
      return strcmp(type_to_test,"base")==0;} 
}; 

template <typename T> 
class derived1 : public base 
{ 
    virtual void foo() {}; 
    virtual bool isa(const char* type_to_test){ 
    return strcmp(type_to_test,"derived1")==0;} 
}; 
相關問題