运行时确定C ++的类型

时间:2009-12-31 08:14:35

标签: c++ runtime types

我想知道在C ++中是否可以将类型确定为运行时信息。

(1)虽然我的问题很笼统,但为简单起见,我将从一个简单的例子开始:

 #include <stdio.h>  
 #include <iostream>  
 #include <cstring>  
 using namespace std;  
 int main(int argc, char * argv[])  
 {  
 if (strcmp(argv[1], "int")==0)   
 {  
     int t = 2;   
 }else if (strcmp(argv[1], "float")==0)  
 {  
     float t = 2.2; 
 } 
 cout << t << endl;  // error: ‘t’ was not declared in this scope
 return 0;  
 }

对于此示例,有两个问题:

(a)“argv [1] to t”是错误的,但C字符串argv [1]中的类型信息是否可以转换为实际的类型关键字?所以我们不需要通过if-else子句和strcmp检查每种类型。

(b)如何在if子句的局部范围内定义的变量t仍在外部有效。即如何将局部变量“导出”到其范围之外?

(2)一般来说,不是特定于上面的简单示例,运行时确定类型的常用方法是什么?在我看来,可能有一些方法:

(a)可以将类型定义的变量的处理放在同一范围内定义。 e.g。

 #include <stdio.h>  
 #include <iostream>  
 #include <cstring>  
 using namespace std;  
 int main(int argc, char * argv[])  
 {  
 if (strcmp(argv[1], "int")==0)   
 {  
     int t = 2;   
     cout << t << endl; 
 }else if (strcmp(argv[1], "float")==0)  
 {  
     float t = 2.2; 
     cout << t << endl; 
 } 
 return 0;  
 }

并且可能使用模板函数使各种类型的公共代码可重用。

(b)或者一个人可以使用抽象类类型和多态来间接导出定义,但我不确定究竟是如何。

感谢您的建议!

3 个答案:

答案 0 :(得分:7)

1a:不,类型不是C ++中的对象或值(例如,在Python中)。但是,您可以使用由argv [1]的值选择的各种值。

1b:对不起,就是不能那样做。

2:dynamic_cast和typeid(两个运算符)是当前由查询类型的语言提供的唯一工具(并不罕见,大多数语言都有很少但专用的工具),并且仅将它们用于查询类型是经常气馁取决于情况(在其他语言中也不常见)。

2a:是的,因为这是简单的,显而易见的,并且在这里工作 - 没有理由使用其他任何东西,但是因为它是示例代码,我们假设您需要一个不同的解决方案。你可以调用一个在正确类型上实例化的函数模板,但由于这与2a的其余部分完全相同,所以我不会进入它。

2b:使用子类模板的示例,只是因为它很方便:

struct Base {
  virtual ~Base() {}
  friend std::ostream& operator<<(std::ostream& s, Base const& v) {
    v._print(s);
    return s;
  }
private:
  virtual void _print(std::ostream&) const = 0;
};

template<class T>
struct Value : Base {
  T data;
  explicit
  Value(T const& data) : data(data) {}
private:
  virtual void _print(std::ostream& s) const {
    s << data;
  }
};

使用:

int main(int argc, char** argv) {
  using namespace std;
  auto_ptr<Base> p;
  string const type = argc > 1 ? argv[1] : "int";
  if (type == "int") {
    p.reset(new Value<int>(2));
  }
  else if (type == "float") {
    p.reset(new Value<double>(2.2));
  }
  cout << *p << '\n';
  return 0;
}

这开始将两种类型合并为一种类型,它们在这里都呈现相同的接口Base。但是,这并不适用于每个解决方案,boost.variant等变体可能更好,特别是当所需的各种类型数量很少且事先知道时。

答案 1 :(得分:5)

您需要一个能够存储不同类型值的类。如果不是工会,Boost's variant class将是正确的选择。

答案 2 :(得分:2)

查看Boost.Variant

相关问题