我想知道在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)或者一个人可以使用抽象类类型和多态来间接导出定义,但我不确定究竟是如何。
感谢您的建议!
答案 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)