2012-03-05 105 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;} 
}; 
相关问题