我有以下问题。我有这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
文件更加清晰。有解决方案吗?
答案 0 :(得分:3)
您的代码中有一个错误。根据{{3}}
内联函数或变量的定义(自C ++ 17起)必须为 出现在翻译单元所在的位置(不一定) 在访问点之前。
很显然,当您将定义放入.cpp文件并从其他翻译单元调用这些函数时,此条件不满足。
因此,您的两种替代方法都可以起作用,因为它们之一都可以
最后但并非最不重要的一点-C ++ inline
说明符与函数内联无关。还有其他依赖于编译器的方法来请求实际的内联,即各种编译器中的__forceinline
。