在C ++中动态声明数据类型

时间:2010-05-14 12:39:00

标签: c++

我希望能够做到以下几点:

我有一个包含数据类型的字符串数组:

string DataTypeValues[20] = {"char", "unsigned char", "short", "int"};

然后,我想在运行时创建一个数据类型的变量。我不会在编译时知道正确的数据类型应该是什么。

因此,例如,如果在运行时我确定变量x需要是int:

类型
DataTypeValues[3] x = 100;

显然这不起作用,我怎么能这样做呢?

13 个答案:

答案 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和字符串或自定义对象之间)使用动态类型,那么它将是您的选择之一。