我有以下问题。我有这 3 个文件(我做了一个简化的例子,但错误是一样的):
foo.hpp
#pragma once
#include <iostream>
class foo
{
protected:
virtual void bar() const noexcept = 0;
public:
foo() = default;
virtual void callbar() = 0;
};
class baz : public foo
{
protected:
void bar() const noexcept override;
public:
void callbar();
};
foo.cpp
#include "foo.hpp"
inline void baz::bar() const noexcept { std::cout << "baz::bar()" << '\n'; }
inline void baz::callbar() { bar(); }
主要.cpp
#include "foo.hpp"
auto main() -> int
{
baz b;
b.callbar();
}
编译器(我猜实际上是链接器)给我以下错误:
foo.cpp
main.cpp
Generating Code...
Microsoft (R) Incremental Linker Version 14.15.26729.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:foo.exe
foo.obj
main.obj
main.obj : error LNK2001: unresolved external symbol "protected: virtual void __cdecl baz::bar(void)const " (?bar@baz@@MEBAXXZ)
main.obj : error LNK2019: unresolved external symbol "public: virtual void __cdecl baz::callbar(void)" (?callbar@baz@@UEAAXXZ) referenced in function main
foo.exe : fatal error LNK1120: 2 unresolved externals
现在我通过做以下两件事中的任何一件来解决这个问题:
- 删除
内联
关键字 - 保持
inline
不变,但将方法定义移动到.hpp
文件
如果我做其中一件事情,一切都会正常。但我的问题是:为什么?在我的真实代码中,我真的希望编译器内联方法调用,而且我希望它们在 .cpp
文件中定义,以使我的 .hpp
文件更清晰。有解决办法吗?
最佳答案
您的代码中有错误。根据cppreference
The definition of an inline function or variable (since C++17) must be present in the translation unit where it is accessed (not necessarily before the point of access).
显然,当您将定义放在 .cpp 文件中并从其他翻译单元调用这些函数时,这个条件是不满足的。
所以你的两种替代方法都有效,因为它们要么
- 完全删除此条件(当您删除内联说明符时)
- 使定义可见
最后但并非最不重要的一点——C++ inline
说明符与函数内联无关。还有其他依赖于编译器的方法来请求实际的内联,即各种编译器中的 __forceinline
。
关于C++ 继承 - 无法在 cpp 文件中定义方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55615555/