我希望能够做到以下几点:
我有一个包含数据类型的字符串数组:
string DataTypeValues[20] = {"char", "unsigned char", "short", "int"};
然后,我想在运行时创建一个数据类型的变量。我不会在编译时知道正确的数据类型应该是什么。
因此,例如,如果在运行时我确定变量x需要是int:
类型DataTypeValues[3] x = 100;
显然这不起作用,我怎么能这样做呢?
答案 0 :(得分:16)
简单的答案是你不能 - 在C ++编译时需要知道类型。
,你可以使用boost :: any或unions之类的东西来做类似的事情。答案 1 :(得分:12)
你必须使用联合来实现类似的东西,但处理联合是一个非常困难的事情,所以你应该选择一个容器类,它将联合逻辑包装在一个接口之后,如Boost.Variant或Qts {{3 }}
答案 2 :(得分:3)
你做不到。 C ++不支持这种运行时元编程。
答案 3 :(得分:2)
每个人都说你不能用C ++做到这一点是缺少一个明显的解决方案。这是您可以使用基类的地方,您需要在那里定义常用的接口,然后所有派生类都是您需要的类型。把它放在适合容器的智能指针中,然后就可以了。如果你不能在基类中放置足够的接口,你可能不得不使用动态类型推断,因为它很丑陋,但它总是令人不悦,但它是有原因的。动态分配你的类型可能不是最有效的,但一如既往,它取决于你使用它的目的。
答案 4 :(得分:1)
你唯一能做的就是手动循环遍历这些类型并比较每个类型。还有可能在这里使用工厂对象 - 但这将涉及堆。
答案 5 :(得分:1)
我认为你真的在寻找一种动态类型的语言。如果必须坚持使用C ++,请嵌入口译员。
或者您可以使用接口来处理包装数据,从而实现类似于组件模型的东西。从宇宙基类 - IObject开始,然后为IInteger,IDouble,IString等实现接口。然后,对象本身将由工厂创建。
或者你可以将void缓冲区与工厂一起使用......这是避免使用C / C ++中的静态类型(不使用基于继承的多态)的古老方法。然后撒上大量的reinterpret_cast。
答案 6 :(得分:1)
Visual Basic的'Variant'数据类型就是您所说的。它可以包含任何东西,主要数据类型,数组,对象等。
“OLE自动化中的Collection类可以存储不同数据类型的项目。由于在编译时无法识别这些项目的数据类型,因此向集合中添加项目和从集合中检索项目的方法使用变量。如果在Visual中使用For Each构造的基本,迭代器变量必须是对象类型或变体。“ - 来自http://en.wikipedia.org/wiki/Variant_type
上面的页面提供了有关如何使用变体的一些见解,它显示了如何在C ++中使用OLE来处理变体。
答案 7 :(得分:1)
最接近的是模板:
template<int i> class Data { };
template<> class Data<0> { typedef char type; }
template<> class Data<1> { typedef unsigned char type; }
template<> class Data<2 { typedef short type; }
template<> class Data<3> { typedef int type; }
Data<3>::Type x;
如果你需要更复杂的东西,Boost有一个C ++ - Python桥。
答案 8 :(得分:1)
在您的简单示例中,不仅仅使用列表中最宽的类型作为通用容器并在必要时(或者甚至依赖于隐式转换)转换为较小的类型,几乎没有什么好处。
你可以对工会,类,多态,RTTI,Boost变体等进行详细说明,但仅仅是为了获得不同宽度整数的列表,这是值得的。
在我看来,你有一个明显的问题,你发明了一个不切实际的解决方案,你现在正在寻求帮助。你可能会更好地描述你的原始问题,而不是让你的解决方案成为问题!
答案 9 :(得分:1)
另外,不要忘记必须对这种神秘数据类型进行操作的所有功能。大多数功能仅设计为使用一种类型,例如添加。重载函数以处理其他类型。
您如何在运行时知道变量类型是什么?
答案 10 :(得分:0)
现在想到的唯一方法是旧的C风格,其中使用指向void的指针,如:
void *unkown;
Leter on你可以像下面那样分配任何对象:
unkown = (void *)new int(4);
如果您知道运行时中的类型,那么您可以在如下变量上运行指定的函数:
if(type==0) { // int
printf("%d\n", * ((int*)unkown) );
} else {
// other type
}
这种方式(cast void *)用于例如当使用malloc [等]函数时。
我并不是说当c ++现在更加发达时这是一个好习惯。 仍然同意那些说这不是解决问题的最佳解决方案的人。但也许经过一些重新设计后你会觉得它很有帮助。
从C ++ 11开始,您可能会发现有趣的自动类型。 http://en.cppreference.com/w/cpp/language/auto
答案 11 :(得分:0)
我想这个回复会迟到几年。但对于可能碰巧查看此线程的人来说,可能的解决方案是使用变量模板。例如:
template<typename T>
T var;
template<typename T>
T arr[10];
int main() {
int temp;
var<int> = 2;
cout << var<int> << ' '; // this would output 2
var<char> = 'a';
cout << var<int> << ' '; // var<int> value would be a space character
cout << var<char> << ' '; // this would output 'a'
for(int i = 0; i < 10; i++) {
switch(i % 2) {
case 0:
arr<int>[i] = ++temp;
break;
case 1:
arr<char>[i] = 'a' + ++temp;
break;
}
cout << endl;
for(int i = 0; i < 10; i++) {
switch(i % 2) {
case 0:
cout << arr<int>[i] << ' ';
break;
case 1:
cout << arr<char>[i] << ' ';
break;
}
}
return 0;
}
唯一的问题是,你需要知道变量当前的变量类型(例如,在整数数组中存储变量的“id”(你给它的id),特定类型)。如果您不知道或没有条件知道特定变量或数组位置内的内容,我建议不要使用它。
答案 12 :(得分:0)
使用union并创建自己的动态类。 伪代码,如:
union all{
char c;
unsigned char uc;
short s;
int i;
};
class dynamic{
public:
char Type;
all x;
template <class T>
dynamic(char type_,T y){
int Int;
char Char;
unsigned char Uchar;
short Short;
if(typeof(y) ==typeof(Char)){
Type=1;
}else if(typeof(y) ==typeof(Uchar)) {
Type=2;
}else if(typeof(y) ==typeof(Short)) {
Type 3;
}else{
Type=4;
}
switch (Type) {
case 1: x.c=y; break;
case 2: x.uc=y; break;
case 3: x.s=y; break ;
case 4: x.i=y; break ;
}
}
auto get() {
switch(Type) {
case 1: return x.c;
case 2: return x.uc;
case 3: return x.s;
case 4: retuen x.i;
}
}
//make also the operators function you like
} ;
但是您应该避免使用动态类型,因为它的内存效率低
(在此示例中,动态对象的每个对象将占用5个字节)
它也会使您的代码变慢(一点)。
如果在您的示例中,您只想使用动态类型的数字变量来减少内存使用,则应该忽略动态的,仅使用整数作为类型(其中整数可以包含所有char,unsigned char和short一次)。
但是,如果要使用它是因为您需要在真正不同的东西之间(例如int和字符串或自定义对象之间)使用动态类型,那么它将是您的选择之一。