条件C / C ++结构定义

时间:2016-12-04 17:19:30

标签: c++ c gcc struct one-definition-rule

我偶然发现了一些看起来像这样的代码:

typedef struct SomeStruct
{
    int foo;
    void * bar;
#if defined(__cplusplus)
    SomeStruct();
#endif
} SomeStruct;

它位于头文件中,将包含.c和.cpp文件。这似乎至少在技术上违反了单一定义规则。我看到的明显影响是,如果其中一个在.c文件中声明,构造函数将不会运行。不幸的是,有人似乎已经使用它作为声明结构的正确方式的模式,并且已经宣布了几十个结构,就像它一样。

我正在试图找出这个问题有多严重。除了可能没有运行的构造函数之外,还有其他可能的影响吗?构造函数在.cpp文件中实现。我看到指向.c文件(带有malloc)中分配的结构的指针,这些结构被传递给.cpp文件中的函数。它们似乎正常工作(如果重要的话,使用gcc / g ++ 4.6.2为Suse Linux编译),据我所知。如果还添加了虚拟成员函数,会有什么问题吗?现在,除了默认构造函数之外,这些类中没有一个在cplusplus部分中有任何内容,如上所示。

1 个答案:

答案 0 :(得分:1)

这并不完全违反ODR。非正式地,C编译器看到POD类型,并且C ++编译器在全局命名空间中看到一个类,该类将成为具有错位名称的实体。更重要的是,该结构仅针对C和C ++编译器声明不同,但它仅在C ++源文件中定义一次。很可能在C ++源文件中有一些分配和自由函数,它们将构造函数/析构函数暴露给C API。例如,

标头文件

$ cat some_struct.h 
#ifndef SOME_STRUCT_H
#define SOME_STRUCT_H

typedef struct SomeStruct {
    int foo;
    void *var;
#if defined(__cplusplus)
    SomeStruct();
#endif
} SomeStruct;

#if defined(__cplusplus)
extern "C" {
#endif

SomeStruct *some_struct_malloc();
void some_struct_free(SomeStruct **);

#if defined(__cplusplus)
} // extern "C"
#endif

#endif // SOME_STRUCT_H

C ++源文件

$ cat some_struct.cpp 
#include "some_struct.h"
#include <cstddef>

SomeStruct::SomeStruct()
{
    foo = 10;
    var = NULL;
}

SomeStruct *some_struct_malloc() { return new SomeStruct; }

void some_struct_free(SomeStruct **pp)
{
    if (*pp)
        delete *pp;
    *pp = NULL;
}

C源文件:

$ cat main.c 
#include "some_struct.h"
#include <stdio.h>

int main()
{
    SomeStruct *p = some_struct_malloc();
    printf("%d\n", p->foo);
}

我会说这是一种糟糕的风格。但它可以作为将C ++库公开给C API的便捷方式