为什么C ++ 11不支持声明的extern" C"在静态成员函数? [英] Why does C++11 not support declaring extern "C" on a static member function?
问题描述
(无效(*回调)()); 以下code是优雅而非法
Provided that I have a C library containing a function declared as void g(void (*callback)());
The following code is elegant yet illegal:
struct A
{
// error C2159: more than one storage class specified (VC++ Nov 2012 CTP)
static extern "C" void callback()
{}
};
g(A::callback);
为什么C ++ 11不支持此?
Why does C++11 not support this?
推荐答案
这是一个特别令人困惑的话题涉进。让我们的进攻第7.5节联动规范[dcl.link]
This is a particularly confusing topic to wade into. Let's attack §7.5 "Linkage specifications" [dcl.link].
1)所有的函数类型,具有外部链接的函数名,并与外部链接的变量名有一个的语言联动的。
1) All function types, function names with external linkage, and variable names with external linkage have a language linkage.
请注意该语言联动特性适用于两种完全不同类型的实体:类型的和的名称的
Note that the property of language linkage applies to two completely different kinds of entities: types and names.
一个函数在其类型可识别哪个ABI它符合信息通常不可见位:C调用约定,帕斯卡尔,Fortran语言,都可以被指定为以不同方式使用栈,所以通过指针美其名曰需要知道无形的语言标签。
A function has a generally-invisible bit of information in its type which identifies which ABI it conforms to: C calling conventions, Pascal, Fortran, all might be specified to use the stack in different ways, so calling them through a pointer requires knowing the invisible language-tag.
这是另一种语言的变量或函数的的名称的语法可以通过C ++的访问,或者从其他语言指的是C ++声明。但是,并非每一种语言可以用C ++的命名方案和模型OO匹配。因此,在这个方案的接口不包含的类。
The name of a variable or function from another language can be accessed syntactically through C++, or from the other language referring to a C++ declaration. But not every language can match up with C++'s naming scheme and OO model. So interfaces in this scheme don't include classes.
由于这些东西是分开管理的,它可能有不同的链接在其类型的东西(调用约定),它的名字(链接符号)。
Because these things are managed separately, it's possible to have something with different linkage in its type (calling conventions) and its name (linker symbol).
4)联动规格窝。当联动规格窝,最里面的那个决定语言
连锁。链接规范没有建立一个范围。 A 联动规范的,应仅在命名空间范围(3.3)发生。在联动规范的,指定的语言联动应用于函数类型的所有函数声明的,具有外部链接的函数名,并用联动规范内声明的外部链接的变量名。的交流语言联动确定类成员的名字的语言联动的类成员函数的函数类型上被忽略。
4) Linkage specifications nest. When linkage specifications nest, the innermost one determines the language linkage. A linkage specification does not establish a scope. A linkage-specification shall occur only in namespace scope (3.3). In a linkage-specification, the specified language linkage applies to the function types of all function declarators, function names with external linkage, and variable names with external linkage declared within the linkage-specification. A C language linkage is ignored in determining the language linkage of the names of class members and the function type of class member functions.
的的externC{}
影响所有函数声明,包括指针和引用,除了成员函数。由于功能可能只在一个命名空间或作为成员来定义,C函数只能在空间范围内定义。
The extern "C" {}
affects all function declarations, including pointers and references, except member functions. Since a function may only be defined in a namespace or as a member, C functions can only be defined at namespace scope.
这里的标准给出了一个例子:
The standard gives an example here:
extern "C" typedef void FUNC_c();
class C {
// the name of the function mf1 and the member
// function’s type have C++ language linkage; the
// parameter has type pointer to C function
void mf1(FUNC_c*);
// the name of the function mf2 and the member
// function’s type have C++ language linkage
FUNC_c mf2;
// the name of the data member q has C++ language
// linkage and the data member’s type is pointer to
// C function
static FUNC_c* q;
};
您可以模拟你想要的行为,使用的typedef
,虽然。从第7.5节/ 4另外一个例子,
You can emulate the behavior you want using a typedef
, though. From another example in §7.5/4,
extern "C" typedef void FUNC();
// the name f2 has C++ language linkage and the
// function’s type has C language linkage
FUNC f2;
结合这些例子与你,你可以有
Combining these examples with yours, you can have
extern "C" typedef void callback_t();
callback_t A_callback; // declare function with C++ name and C type
struct A
{
static callback_t &callback; // not a member function
};
// in source file:
// definition matches semantics of declaration, although not syntax
void A_callback() { ... }
// define static member reference
callback_t &A::callback = A_callback;
g(A::callback); // call syntax is emulated
在实践中,它很少有差别。 C和C ++在大多数平台上兼容使用调用约定(请参阅本页面例外乔纳森Wakely的评论),只要你不要试图传递或返回一个非POD C ++类的类型。这是C ++的实现的功能较少,由于术语和概念上的区别从细微学术的混乱超载。
In practice, it seldom makes a difference. C and C++ use compatible calling conventions on most platforms (see Jonathan Wakely's comments on this page for exceptions), as long as you don't try to pass or return a non-POD C++ class type. This is a less-implemented feature of C++, due to the confusing overloading of terms and conceptual distinctions ranging from subtle to academic.
这篇关于为什么C ++ 11不支持声明的extern" C"在静态成员函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!