You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 10:36:07