gpt4 book ai didi

c++ - 实现 pimpl 习惯用法时出现链接器错误

转载 作者:行者123 更新时间:2023-11-27 23:28:30 24 4
gpt4 key购买 nike

经过编辑以使提供者更加清晰。很抱歉让大家感到困惑。

这是在 Windows 下。

我有一个静态库,它使用 pimpl 习惯用法实现了一个类。 pimpl header 不仅由消费代码使用,而且还链接到静态库。然而,当我编译使用代码 (.exe) 时,链接器提示 pimpl header 本应隐藏的实现类 上未解析的外部。

这怎么可能?

// Foo.lib

// Foo.h

class FooImpl;

class Foo
{
std::shared_ptr<FooImpl> pimpl_;
public:
Foo();
};

// Foo.cpp

#include "Foo.h"
#include "FooImpl.h"

Foo::Foo() : pimpl_(new FooImpl())
{
}

// This is how its used in Bar.exe
// Bar.exe links against Foo.lib

// Bar.h

#include "Foo.h"

class Bar
{
Foo access_foo_;
};

// Bar.cpp

#include "Bar.h"

当我编译/链接 Bar.exe 时,链接器提示它无法解析 FooImpl。我忘记了它到底说了什么,因为我现在无法访问我的工作 PC,但这就是它的要点。这个错误对我来说没有意义,因为走 pimpl 路线的目的是让 Bar.exe 不必担心 FooImpl。

确切的错误是这样的:

1>Foo.lib(Foo.obj) : error LNK2019: 未解析的外部符号“public: __thiscall FooImpl::FooImpl(void)” (??0FooImpl@@QAE@XZ) 在函数“public: __thiscall Foo”中引用::Foo(void)"(??0Foo@@QAE@XZ)

最佳答案

当您创建静态库时,链接器不会尝试解析所有缺失的内容;它假定您稍后会将其链接到另一个库,或者可执行文件本身将提供一些缺失的功能。您一定忘记了在库项目中包含一些关键的实现文件。

另一种可能是pimpl实现类是模板类。模板不会立即生成代码,编译器会等到您尝试使用它们并填充模板参数。您的实现文件必须包含模板的实例化以及您的库将支持的参数。


看到您的编辑后,问题是 Foo::Foo 构造函数需要访问 FooImpl::FooImpl 构造函数,但链接器不知道在哪里可以找到它。当链接器将库放在一起时,它不会尝试解析所有的引用,因为它可能依赖于另一个库。唯一需要解决所有问题的时间是将可执行文件放在一起时。因此,即使 Bar 不需要直接了解 FooImpl,它仍然依赖于它。

您可以通过以下两种方式之一解决此问题:将 FooImpl 与 Foo 一起从库中导出,或者确保 Foo 在编译时可以访问 FooImpl,方法是将它们都放在 Foo.cpp 中,FooImpl 在 Foo 之前。

关于c++ - 实现 pimpl 习惯用法时出现链接器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7616281/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com