代码之家  ›  专栏  ›  技术社区  ›  user7893856

用C预处理器模拟继承

  •  3
  • user7893856  · 技术社区  · 8 年前

    我有一个关于如何在C中实现接口的想法。这个想法非常简单,但当搜索讨论这个问题时,我没有看到它被提及。

    因此,C中的“标准”继承模拟方法本质上是

    struct dad {
       arm_t right_arm;
       arm_t left_arm;
    }
    
    struct kid {
       struct dad parent;
       diaper_t diaper;
    }
    

    because kid.parent.right_arm 只是没有什么意义 kid.right_arm 。如果您不介意使用gcc独占标志,显然还有另一种方法,这类似于

    struct kid {
        struct dad;
        diaper_t diaper;
    }
    

    但这不是便携式的。然而,便携的是

    // file: dad.interface
    arm_t right_arm;
    arm_t left_arm;
    
    // file: kid.h
    struct kid {
        #include dad.interface
        diaper_t diaper;
    }
    

    2 回复  |  直到 8 年前
        1
  •  3
  •   John Bollinger    8 年前

    既然你是在继承的背景下提出这个问题的,我想一个更完整(更正确)的例子是这样的:

    arm_t right_arm;
    arm_t left_arm;
    

    struct dad {
        #include "dad.interface"
    };
    

    文件:kid.h

    struct kid {
        #include "dad.interface"
        diaper_t diaper;
    };
    

    这其中有几个问题:

    1. 这并不是真正的继承——它只是两个碰巧有匹配初始成员的结构。 struct kid 没有其他关系 struct dad 从s的角度来看,甚至不清楚 存在。

    2. 虽然你没有使用这个词,但人们通常(尽管没有根据)会认为 多态性 结构儿童 struct dad * 违反了严格的别名规则,因此会产生未定义的行为。(在以下情况下不适用此规定) 结构儿童 结构dad 作为其第一个成员。)

    3. struct son struct daughter 继承自 结构儿童 结构儿童 的成员也放入其单独的标题中。我想如果你能预测任何人可能想要从哪些结构类型继承,或者你只需要对每一种结构类型进行继承,你就可以先发制人地做到这一点。哎呀,真是一团糟。

        2
  •  2
  •   Vlad Dinev    8 年前

    你可以这样做:

    #define myclass_members int a;\
                    void (*f)(void)
    
    struct myclass {
        myclass_members;
    };
    
    #define derived_cls_members myclass_members;\
                                double d;\
                                void (*g)(void)
    
    struct derived_cls {
        derived_cls_members;
    };
    

    here .

    编辑:事实证明,这种方法可能有效,但正如其他人指出的那样,它是可疑的。更好的选择是使用c11中添加的匿名结构扩展,正如@tgregory所指出的,它仍然可以与预处理器一起使用。

    #define myclass_members struct { int a; void (*f)(void); }
    

    编辑2:进一步研究表明,第一种方法(只有预处理器)实际上应该可行。因此,如果您不关心注释分配问题中提到的问题,或者使用memset()/memcpy()等函数可能会出现的问题,那么应该没问题。

    资料来源:

    Are C-structs with the same members types guaranteed to have the same layout in memory?

    What is the strict aliasing rule?