我有以下问题。我有这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(); }
main.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
关键字inline
不变,但将方法定义移到.hpp
文件中如果我做其中一件事,一切都会奏效。但我的问题是:为什么?在我的真实代码中,我真的想让编译器内联方法调用以及我希望它们在.cpp
文件中定义,以使我的.hpp
文件更清晰。有解决方案吗?
你的代码中有一个错误。根据cppreference
内联函数或变量的定义(因为C ++ 17)必须存在于访问它的转换单元中(不一定在访问点之前)。
显然,当您将定义放在.cpp文件中并从其他翻译单元调用这些函数时,不满足此条件。
所以你的两种替代方法都可以,因为它们都可以
最后,但并非最不重要 - C ++ inline
说明符与函数内联无关。还有其他依赖于编译器的方法来请求实际的内联,即各种编译器中的__forceinline
。