必须。不加__declspec(dllexport),类的符号不会写入DLL导出表,调用方链接时报LNK2019;需用宏(如MYLIB_API)在DLL编译时展开为dllexport、调用方展开为dllimport,并加在class关键字前统一控制。

Windows下C++动态库导出类必须加__declspec(dllexport)吗?
必须。不加__declspec(dllexport),编译器不会把类的符号(如构造函数、虚表、成员函数)写入DLL的导出表,调用方链接时会报LNK2019: unresolved external symbol。即使头文件里声明了类,没有导出标记,DLL里的实现就“看不见”。
注意:这个修饰只在**编译DLL项目时生效**;调用方(EXE或另一个DLL)包含同一头文件时,必须改用__declspec(dllimport),否则可能运行时报错或性能下降(间接调用开销)。
怎么用宏统一控制__declspec(dllexport)和__declspec(dllimport)?
靠预定义宏区分编译场景,典型写法:
#ifdef MYLIB_EXPORTS #define MYLIB_API __declspec(dllexport) #else #define MYLIB_API __declspec(dllimport) #endif
MYLIB_EXPORTS需在DLL项目的“属性 → C/C++ → 预处理器 → 预处理器定义”里手动添加(Visual Studio默认不设)。EXE项目不定义它,自然走dllimport分支。
立即学习“C++免费学习笔记(深入)”;
使用时直接修饰类声明:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
class MYLIB_API MyClass {
public:
MyClass();
void doSomething();
};
常见错误:忘记在DLL工程中定义MYLIB_EXPORTS,结果类没导出,但调用方又用了dllimport——链接能过,运行时构造函数地址为空,一调就崩。
导出类时__declspec(dllexport)要加在哪儿?
加在class关键字前,且必须作用于整个类声明(不能只加在某个成员函数上):
- ✅ 正确:
class MYLIB_API MyClass { ... }; - ❌ 错误:
class MyClass { MYLIB_API void foo(); };(成员函数单独加无效) - ❌ 错误:
MYLIB_API class MyClass { ... };(语法错误,__declspec必须紧贴class)
如果类有模板,__declspec不支持模板类直接导出(VC报C2491),得显式实例化并导出具体类型,例如:
template class MYLIB_API std::vector<int>;
为什么导出类后调用方仍报LNK2019?
大概率是这几个点漏了:
- DLL项目没在预处理器定义里加
MYLIB_EXPORTS - 头文件被EXE和DLL共用,但EXE编译时也意外定义了
MYLIB_EXPORTS(比如CMakeLists里全局加了) - 类的析构函数是
virtual但没定义(哪怕空实现),导致虚表不完整,导出失败 - 调用方没链接DLL的
.lib文件(仅加头文件不够,必须在“链接器 → 输入 → 附加依赖项”里填mylib.lib)
最隐蔽的坑:类里用了STL容器(如std::string、std::vector)且DLL和EXE用不同运行时(/MD vs /MT),会导致二进制不兼容——此时即使导出成功,运行时也可能崩溃。建议DLL和调用方统一用/MD。


















