我偶然发现了一些看起来像这样的代码:
typedef struct SomeStruct
{
int foo;
void * bar;
#if defined(__cplusplus)
SomeStruct();
#endif
} SomeStruct;
它在标题文件中,该文件将包含在.c和.cpp文件中。从技术上讲,这似乎至少违反了一个定义规则。我看到的显而易见的影响是,如果其中一个在.c文件中声明,则构造函数将无法运行。不幸的是,似乎有人将其用作正确声明结构的正确方法的模式,并宣布了几十个结构。
我试图弄清楚这有多严重。除了构造函数可能没有运行之外,还有其他可能的影响吗?构造函数在.cpp文件中实现。我看到在.c文件(带有malloc)中构造的指针,这些指示传递给了.cpp文件中的函数。它们似乎可以正常工作(据我所知,Suse Linux使用GCC/G 4.6.2编译)。如果还添加了虚拟成员功能,会发生什么事情?目前,除默认构造函数外,这些类别在其Cplusplus部分中都没有任何内容,如上所示。
这并不完全违反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("%dn", p->foo);
}
我会说这是一种糟糕的风格。但它可以作为一种方便的方式将C 库暴露于C API