以下C ++代码使用Visual C ++和g ++进行编译:
struct S
{
static void foo();
};
extern "C"
void S::foo() {}
struct T
{
static void foo();
};
extern "C"
void T::foo() {}
auto main() -> int
{
S().foo();
T().foo();
}
有效吗?
如果它是有效的,因为实现可能在一个单独的翻译单元中,这是否意味着静态成员函数总是具有与C函数相同的调用约定(如果不是,它如何不暗示)?
答案 0 :(得分:8)
C ++ 11 7.5 / 4“链接规范”
在确定语言链接时忽略C语言链接 类成员的名称和类成员的函数类型 功能
因此,您的示例在没有格式错误或错误的意义上是有效的,但extern "C"
应该对S::foo()
或T::foo()
没有影响。
答案 1 :(得分:4)
静态成员函数与C函数具有相同的调用约定。但是,名称修改适用。因此,即使您将静态成员声明为extern "C"
,当您尝试将其与调用该函数的C代码链接时,链接器也可能找不到它。
可以轻松做的是声明一个从普通函数调用静态成员的包装器/存根。此外,您可以将静态成员函数的地址分配给普通函数指针。
答案 2 :(得分:0)
不,它被忽略,问题是 name mangling (链接阶段的函数命名)。所以诀窍是定义一个C函数并使用你的C ++静态方法作为存根来调用它,如下所示:
struct S
{
static void foo();
};
extern "C" void S_foo_impl();
void S::foo() { S_foo_impl(); }
auto main() -> int
{
S::foo();
}
当然,S_foo_impl
应该在外部C模块中定义。