带方法的 C++ 结构,不带方法的 C 声明

Posted

技术标签:

【中文标题】带方法的 C++ 结构,不带方法的 C 声明【英文标题】:C++ struct with methods, C declaration without methods 【发布时间】:2015-09-17 23:52:13 【问题描述】:

我已经高度怀疑这是可行的,而且根本没有风险,但我仍然想确定,所以这是我的事情......

我有一个 C++ 代码,它使用相当大的结构(15-30 个字段)作为容器,作为类构造函数的参数。这些结构的问题是我需要使用 C99 语法(与 C++ ffs 不兼容)声明它们:

FooBar fb =  .foo = 12, .bar = 3.4 ;

因为拥有构造函数对我来说是不可想象的,因为在初始化这些结构时可以安全地跳过某些字段,而其他字段则不能,等等(它们仅且专门由“用户提供”数据初始化,用户就是我发生),有点像他们描述的配置。

不管怎样,点了,我只需要使用一个.h 头文件,它使用纯 C 语法声明结构,以及一个包含我初始化的结构的 .c 文件,然后我在我的 .cpp 文件中使用外部“C”。它工作得很好......除了我会发现能够为这些结构提供方法非常方便。

所以我的问题是,是否可以像这样声明结构

#ifdef __cplusplus
    // C++ compatible declarations with methods
    struct foobar 
        int foo;
        float bar;

        int method1();
        int method2();
        void method3();
        [etc.]
    ;
#else
    /* C compatible declarations, no methods */
    struct foobar 
        int foo;
        float bar;
    ;
#endif

这样我可以在 C++ 中使用一些绑定到结构的方法(它更优雅,面向 OOP),并且我可以使用 C99 的指定初始化程序在我的 C 代码中安全地初始化它们。

我担心的是一些潜在的未知问题,这些问题最终可能导致 C 代码中的结构偏移与 C++ 代码中的不同。这些问题是否存在?

谢谢

【问题讨论】:

不确定我是否理解正确:您是否需要 C99 指定初始化程序功能以方便使用,或者因为您需要在(现有)C 代码中初始化这些对象? 不,我使用 C99 的指定初始化程序在 C 文件中声明一组结构,然后在我的 C++ 代码中使用 C 文件中的那些结构(使用 extern "C" struct_name blabla使它们在 CPP 代码中可访问) 是的,但是 “因为我无法想象有一个构造函数 [...]” 段落对我来说听起来有点像你在 C 中初始化对象文件,因为 C(99) 具有指定的初始值设定项功能。是这样吗,还是有其他原因导致您这样做? 呃我实际上没有回答你的问题。是的,为了方便起见,我需要 C99 指定的初始化程序。在某些情况下我只需要初始化 3-4 个字段时,使用 30 个参数创建一个构造函数一点也不漂亮。在这种情况下,用于“替换”指定初始化程序的构造函数模型根本不适合(参数太多),因此我在 C99 文件中进行初始化工作。 I have a C++ code that use **quite big structs (15-30 fields)** 可能是真正的问题。当您关心more elegant, OOP oriented 事物时,请考虑通过正确设计对象(而不是发明黑客)隐式解决问题中的问题的场景。 SRP 在这里被违反了。删除The God Object,放置更小的、可维护的对象。 【参考方案1】:

在 C++11 中,如果您的 struct标准布局,那么它的布局与等效的 C 结构相同。构成标准布局结构的规则如下:

A standard-layout class is a class that:

— has no non-static data members of type non-standard-layout class (or array of such types) or reference,

— has no virtual functions (10.3) and no virtual base classes (10.1),

— has the same access control (Clause 11) for all non-static data members,

— has no non-standard-layout base classes,

— either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and

— has no base classes of the same type as the first non-static data member.

由于您的结构只有几个公共数据成员和一些非虚拟方法,因此您的结构是标准布局。你可以用更少的重复来表达它

struct foobar 
    int foo;
    float bar;
#ifdef __cplusplus
    int method1();
    int method2();
    void method3();
#endif
;

在以前的 C++ 版本中,您的类型必须是普通旧数据 (POD) 类型,并且还有一些限制。但是,您的结构仍然是 POD(没有虚函数、没有构造函数或析构函数、没有基类),因此它仍然与 C 布局兼容。

【讨论】:

Standard-layout 应该使布局与 C 兼容,但是 C++ 标准并未严格规定细节,留待实现。如果 OP 的方法导致 ODR 或严格别名问题,我不会感到惊讶。 我能问你吗,我理解它不需要在类中包含任何虚拟内容的事实,因为它会在结构的开头创建一个 vtable,从而改变偏移量。但是为什么没有构造函数(纯粹是好奇,而不是我在特定需要中需要一个构造函数)?构造函数(不是虚拟的)是否会像虚拟成员一样修改内部结构布局? @Yannick:旧的 POD 定义比新的标准布局定义更严格。 POD 类还必须静态初始化,即它们必须在没有任何特殊代码的情况下进行初始化(想想能够在不调用任何构造函数的情况下调整对象的vector 的大小)。 但要回答您的直接问题:构造函数不应导致任何布局更改,尽管这(当然)取决于 C++ 编译器实现者的判断。

以上是关于带方法的 C++ 结构,不带方法的 C 声明的主要内容,如果未能解决你的问题,请参考以下文章

将 C++ 类编组为结构

定义C++类对象的方法

c语言函数。

C语言的结构体和C++结构体的区别

带有用 C 编写的库的智能指针

QT中头文件带不带.h的问题