为何OSFramework析构函数触发多重定义符号链接错误?
问题:我操作了什么导致出现多重定义符号链接错误?
OSFrameworkWindows10Module.ixx
module; #include <memory> export module OSFrameworkWindows10Module; export class OSFramework { private: struct impl; std::unique_ptr<impl> _impl; public: OSFramework(); ~OSFramework(); }; typedef struct OSFramework::impl { impl(); ~impl(); } impl; impl::impl() {} impl::~impl() = default; OSFramework::OSFramework() : _impl{ std::make_unique<impl>() } {} OSFramework::~OSFramework() = default;
winmain.cpp
#define WIN32_LEAN_AND_MEAN #include <windows.h> import OSFrameworkWindows10Module; int WINAPI wWinMain ( _In_ HINSTANCE hinst, _In_opt_ HINSTANCE, _In_ PWSTR, _In_ int ) { auto os_framework = std::make_unique<OSFramework>(); return S_OK; };
编译输出
1>------ Build started: Project: Vegas22Metroidvania1, Configuration: Debug x64 ------ 1>Scanning sources for module dependencies... 1>OSFrameworkWindows10Module.ixx 1>Compiling... 1>OSFrameworkWindows10Module.ixx 1>winmain.cpp 1>OSFrameworkWindows10Module.ixx.obj : error LNK2005: "public: __cdecl OSFramework::~OSFramework(void)" (??1OSFramework@@QEAA@XZ::<!OSFrameworkWindows10Module>) already defined in winmain.obj 1>D:\projects\Vegas22Metroidvania1\x64\Debug\Vegas22Metroidvania1.exe : fatal error LNK1169: one or more multiply defined symbols found 1>Done building project "Vegas22Metroidvania1.vcxproj" -- FAILED.
我十分困惑为何OSFramework::~OSFramework会被判定为多次定义。我只是为类实例创建智能指针,却似乎在winmain.cpp中实例化了它。相关环境:使用Visual Studio 17.4.3。
原因与解决方法
出现链接错误的核心原因是:你在模块接口单元的类外部定义OSFramework::~OSFramework() = default时,没有将其声明为inline。在C++20模块中,这类外部定义的成员函数默认是外部链接属性,当winmain.cpp导入模块后,编译器会在两个翻译单元(模块单元和winmain.cpp)中分别生成该析构函数的符号,最终导致链接时出现多重定义冲突。
解决这个问题有两种简单的方式:
将析构函数的默认定义移至类内部
类内部的默认函数会被隐式视为inline,避免多重定义:export class OSFramework { private: struct impl; std::unique_ptr<impl> _impl; public: OSFramework(); ~OSFramework() = default; // 移至类内,隐式inline };在外部定义时显式添加
inline关键字
如果坚持在类外部定义析构函数,需要显式标记为inline:inline OSFramework::~OSFramework() = default;
另外,代码中typedef struct OSFramework::impl { ... } impl;是多余的,可以直接简化为struct OSFramework::impl { ... };,不过这不会影响链接错误的修复。
内容的提问来源于stack exchange,提问作者Teeeeeeeeeeeeeeeeeeeeeeeeeeeej
相关产品推荐
相关产品推荐

