5
    template <class T> void checkObject(T genericObject)
    {
      MyClassA* a = dynamic_cast<MyClassA*>(genericObject);
      if (a != NULL)
      {
        //we know it is of type MyClassA
      }
      MyClassB* b = dynamic_cast<MyClassB*>(genericObject);
      if (b != NULL)
      {
        //we know it is of type MyClassB
      }
    }

这样的事情可能吗?我们有一个模板类型但我们想知道它的实际类型?

4

3 回答 3

7

在模板世界中,您可能只想为每种类型专门化模板,而不是进行运行时检查,即

 template<typename T>
 void foo(T obj);

 template<>
 void foo<MyClassA>(MyClassA obj) {
 }

 template<>
 void foo<MyClassB>(MyClassB obj2) {
 }

这将允许编译器通过推断您的参数在编译时生成正确的模板。

请注意,这仅根据实例的 static type 解析,即没有编译时知道您的变量是 aMyClassC继承自的变量MyClassB,因此应该使用泛型形式。所以这行不通:

  MyClassC* cinstance = new MyClassC();
  foo(cinstance); //compiler error, no specialization for MyClassC

一般来说,这指向一个一般规则,即编译时和运行时多态性是非常不同的系统。模板在没有继承知识的情况下严格处理静态类型的领域。这可能会让来自 Java/C# 的人感到惊讶,因为它们在这两个功能之间具有更无缝的集成。

对于类功能的运行时专业化,您的选项是

  1. 定义虚拟方法——可能不合适,这取决于这个功能是否真的应该是这个对象的一部分
  2. 使用 dynamic_cast (你目前正在做的事情)——有点不受欢迎,但它可能是每个人都能得到的最直接的解决方案。
  3. 访问者模式——一种使用重载在运行时解析为正确类型的函数的设计模式。
于 2013-01-10T20:15:43.367 回答
4

这是可能的,但MyClassA必须MyClassB 至少有一个虚拟成员函数才能dynamic_cast工作。我也相信你实际上想要 ( T* genericObject) 而不是T genericObject在你的函数签名中(否则它就没有什么意义了)。

基于模板专业化的解决方案对于static polymorphism是可以的,但我相信问题是如何启用输入类型的运行时检测MyClassA 我想象这个模板被一个指针调用,该指针的类型要么是MyClassB. 在这种情况下,模板专业化将无法提供正确的答案。

无论如何,我有一种强烈的感觉,你正在尝试做错误的事情来实现你想要实现的目标(不管它是什么)。当你发布这类问题时,我建议你明确你想去哪里,你的目标什么;这可能只是错误道路上的障碍。

于 2013-01-10T20:24:21.663 回答
1

是的,这是可能的。请注意,动态转换发生在运行时,模板在编译期间生成代码。因此,该函数仍将生成,但会在运行时对您描述的情况进行检查。

编辑:看看Doug T.'s answer以正确的方式做你想做的事。

于 2013-01-10T20:16:17.740 回答