在C结构中定义C ++函数

时间:2017-08-01 08:46:36

标签: c++ c struct

阅读后

  1. possible to define a function inside a C structure? [duplicate]
  2. Define functions in structs
  3. 我想知道以下解决方法是否有效,以及它在编译器级别的最深层含义。

    // foo.h
    typedef struct foo
    {
        int i;
    #ifdef __cplusplus
        foo(int _i) : i(_i) {};
    #endif
    } foo;
    
    // bar.c
    #include "foo.h"
    foo bar;
    bar.i = 1;
    
    // bar.cpp
    #include "foo.h"
    foo bar(2);
    

    在我看来,这是一个利用" struct polymorphism"的一个很好的技巧,能够保持与C遗留代码的可移植性,但我感觉在某种程度上我现在正在使用两个不同的类型。

3 个答案:

答案 0 :(得分:4)

从您的问题中查看此struct定义:

typedef struct foo
{
    int i;
#ifdef __cplusplus
    foo(int _i) : i(_i) {};
#endif
} foo;

当使用针对同一平台的C和C ++编译器进行编译时,可能导致相同的内存表示形式。但你应该从不依赖于此。 C ++编译器看到的类型比C编译器看到的类型多一个成员,因此它们基本上是不同的类型。因此,将它们视为相同的是未定义的行为。如果这可以按预期工作,那就是纯粹的运气,并且可能随时中断。

正如已经评论的那样,引入virtual函数几乎可以保证打破它,因为C ++编译器需要将vtable存储在struct中的某个位置。但即使没有它,还有许多其他方式可以打破,例如因为编译器会添加不同的填充。只是不要这样做。

您可以做的是使用 plain C struct并在需要时在C ++中添加包装类

答案 1 :(得分:3)

这两种是不同的类型。编译为C会产生与编译为C ++不同的类型。同时在同一个程序中使用它们(即将C和C ++对象链接在一起成为一个exectuable),结果将是未定义的行为,因为违反了C ++中的单定义规则。

这不是保持C和C ++之间可移植性的方法。行为是未定义的,所以你可能会很幸运,并发现它可以按你的意愿运行。但是,同样地,行为是未定义的,因此可能无效。

答案 2 :(得分:2)

如果您想确保与C库的兼容性,那就不是这样了。

您想要定义是-a foo的类型,并且可以将其传递给库函数。就这样做,继承:

class shiny_foo : foo {
  // Member functions and anything that changes the object layout.
};

extern "C" void c_bar_func(foo *);

void cxx_bar_func(shiny_foo& obj) {
  // do stuff
  c_bar_func(&obj); // obj *is-a* foo as well, remember
}