C ++决定switch中的变量类型

时间:2014-04-03 15:33:56

标签: c++ struct

编辑:感谢您的回复。在交换机上添加中断;问题确实是我希望能够在switch语句之后使用struct。

我希望能够执行以下操作:

int foo (int type, void* inVar) {    
    switch(type) {
    case 0:
        struct struct-type-one mystruct = *( (struct struct-type-one*) inVar);
        break;
    case 1:
        struct struct-type-two mystruct = *( (struct struct-type-two*) inVar);
        break;
    case 2:
        struct struct-type-three mystruct = *( (struct struct-type-three*) inVar);
        break;
    }
    // use mystruct.data
}

基本上,我的想法是inVar是指向结构的指针,type告诉我们需要什么类型。结构都有数据,但结构的类型决定了数据的类型。我想这样做是因为在切换后的代码中,我们可以对mystruct.data进行操作,而不必担心数据的实际类型。

我的问题是,我们怎么做?例如,这在Python中很容易,但C ++不喜欢mystruct如何“交叉初始化”,即根据switch语句的哪个分支使用不同的类型。模板是我们与之搏斗的一个想法,但这很难,因为结构的名称是不同的 - 例如struct intStructstruct floatStruct。这很重要,因为这些结构的大小取决于数据类型。有什么想法吗?

4 个答案:

答案 0 :(得分:4)

我不相信它可以直接做你想做的事情(即使它是,它是C / C ++中的反模式)。但是,如果您想使用mystruct.data(而不是mystruct本身),那么您可以这样重写代码:

int foo (int type, void* inVar) {    
    void* mystruct_data = NULL;

    switch(type) {
    case 0:
        mystruct_data = ((struct struct-type-one*) inVar)->data;
        break;
    case 1:
        mystruct_data = ((struct struct-type-two*) inVar)->data;
        break;
    case 2:
        mystruct_data = ((struct struct-type-three*)inVar)->data;
        break;
    }

    // use mystruct_data (and don't forget to check it's not NULL)
}

请注意,您需要在之前声明变量 - 无论您在switch()内声明什么,都只限于switch()范围内。

或者,如果您的数据处理取决于type,那么您可以执行以下操作:

int foo (int type, void* inVar) {    
    switch(type) {
    case 0:
        data_process_1((struct struct-type-one*) inVar);
        break;
    case 1:
        data_process_2((struct struct-type-two*) inVar);
        break;
    case 2:
        data_process_3((struct struct-type-three*) inVar);
        break;
    }
}

答案 1 :(得分:3)

如果(正如标签所示)你正在编写c ++,你应该使用多态或模板或其他语言功能来简化这些事情。

现在您在旧版C代码中经常会看到您所问的内容,因此对于这种语言,使用联盟创建variant types很常见,这就是你这样做(以下是有效的c ++):

假设您有3个类型,如问题

struct Type1 {/*some implementation*/};
struct Type2 {/*some implementation*/};
struct Type3 {/*some implementation*/};

然后你要定义一个变体类型

struct TVariant
{
    int mtype; 
    union {
        struct Type1 *m1;
        struct Type2 *m2;
        struct Type3 *m3;
    };
};

并以这种方式使用它

int foo (int type, void* inVar) 
{ 
    struct TVariant v;
    switch (type) 
    {
    case TYPE_ONE:
        v.mtype = 1;
        v.m1    = (struct Type1*)inVar;
        break;
    case TYPE_TWO:
        v.mtype = 2;
        v.m2    = (struct Type2*)inVar;
        // .... and so on
    // .....
    }
    // Use your v, actually the correct member of the union in v
}

一些评论:

  • 如果只是一个函数,则不需要mtype的成员TVariant,只需使用函数参数int type <就可以跟踪类型/ LI>
  • TYPE_ONETYPE_TWO等是映射到Type1Type2等类型的整数常量
  • 与使用模板相比,它更麻烦,更慢(由于信息丢弃和转换)
  • 使用重载作为一个更简单的解决方案(对于c ++)可以解决问题,因为foo的每个不同版本对每个Type都有不同的实现
  • 如何创建使用unions' properties的变体对象有多种变体。
  • 使用这种方式在C语言中实现多态性的联盟。在C ++中你可以得到alredy,因此不需要这些技巧。
  • 最后和最重要,主要缺点是联合的大小与其成员类型的最大值一样多,所以如果(如问题中暗示的那样)您只希望指针添加到您的类型中,然后m1m2m3 应该是指针和工会&#39; s大小始终具有单个指针的大小

答案 2 :(得分:1)

你几乎就在那里:

int foo (int type, void* inVar) {    
    switch(type) {
    case 0: {
        struct_type_1& mystruct = *static_cast<struct_type_1*>(inVar);
        // use mystruct here
    }
    break;
    case 1: {
        // same thing again
    }
    }
}

你最大的问题可能是并没有在每个箱体周围使用支架。这意味着您的mystruct变量发生了碰撞。

你可能想要查阅更多关于此类事情的关键词是&#34;歧视联盟。&#34;另请参阅Boost Variant以获得另一种处理它的方法。

答案 3 :(得分:0)

您可以使用以下内容:

int bar(Data& data);

int foo (int type, void* inVar) {    
    switch(type) {
        case 0: return bar(static_cast<struct_type_0*>(inVar)->data);
        case 1: return bar(static_cast<struct_type_1*>(inVar)->data);
        case 2: return bar(static_cast<struct_type_2*>(inVar)->data);
    }
    return -1;
}