从基指针向模板化派生类型的向下转换

Xan*_*lip 7 c++ inheritance dynamic-cast metaprogramming downcast

我有以下层次结构:

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() {};
};
Run Code Online (Sandbox Code Playgroud)

现在给出一个指向base的指针,我想知道底层是derived1还是derived2.问题是derived1和derived2都可以专门用于许多不同类型,使用dynamic_cast来测试向下转换需要知道模板类型.我最终得到了凌乱,不稳定和不完整的代码:

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";
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法,可以处理任何类型的专业化?

Man*_*rse 9

将依赖于类型的逻辑移动到类型中.

代替:

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";
Run Code Online (Sandbox Code Playgroud)

添加一个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";
   }
};
Run Code Online (Sandbox Code Playgroud)


Sjo*_*erd 7

在中间插入一个非模板化的类base,derived1或者derived2:

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() {}
};
Run Code Online (Sandbox Code Playgroud)

在评论中,你提到:

[我想]为每一个调用一个特定的函数 - 顺便说一下,它不仅仅是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();
}
Run Code Online (Sandbox Code Playgroud)

:我考虑的名单dynamic_cast<>一个代码味道,我敦促你重新考虑你的方法.