这是为 MSVC 准备的。
命名空间本身没有进行名称修改,但是当发生名称修改时,命名空间的名称会合并到函数(或对象)的名称中。此过程未记录在案,但在此处进行了描述。
通过跳来回答您的具体问题:
1) 没有关于名称修改的标准定义行为。标准实际上说的是实现为构造提供了与 C 兼容的链接extern "C"
:
7.5.3 【联动规格】
每个实现都应提供与用 C 编程语言“C”编写的函数的链接,以及与 C++ 函数“C++”的链接。[例子:
complex sqrt(complex); // C + + linkage by default
extern "C" { double sqrt(double); // C linkage }
——结束示例]
最终这意味着,由于 C 没有namespace
s 的概念,如果extern "C"
命名空间中有函数或对象,您导出的名称将失去命名空间限定。这将导致...
3) 是的,您可能会遇到联动问题。试试这个:
主文件
#ifndef MAIN_API
# define MAIN_API __declspec(dllexport)
#endif
namespace x
{
extern "C" MAIN_API void foo();
};
namespace y
{
extern "C" MAIN_API void foo();
};
主文件
#include <cstdlib>
#include <iostream>
using namespace std;
#define MAIN_API __declspec(dllexport)
#include "main.h"
void x::foo()
{
cout << "x::foo()\n";
}
void y::foo()
{
cout << "y::foo()\n";
}
int main()
{
}
这将发出链接器错误,因为 和 的-edextern "C"
版本丢失了它们的命名空间标识,因此它们最终具有完全相同的名称: x::foo()
y::foo()
foo()
2)关于此的最佳实践。如果必须为命名空间中的函数导出 C-ABI,则必须注意最终导出的名称不同。在某种程度上,这违背了namespace
首先使用 a 的目的。但是你可以这样做:
#ifndef MAIN_API
# define MAIN_API __declspec(dllexport)
#endif
namespace x
{
extern "C" MAIN_API void x_foo();
};
namespace y
{
extern "C" MAIN_API void y_foo();
};