C ++继承-无法在cpp文件中定义方法

时间:2019-04-10 14:50:40

标签: c++ inheritance linker

我有以下问题。我有这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文件更加清晰。有解决方案吗?

1 个答案:

答案 0 :(得分:3)

您的代码中有一个错误。根据{{​​3}}

  

内联函数或变量的定义(自C ++ 17起)必须为   出现在翻译单元所在的位置(不一定)   在访问点之前。

很显然,当您将定义放入.cpp文件并从其他翻译单元调用这些函数时,此条件不满足。

因此,您的两种替代方法都可以起作用,因为它们之一都可以

  • 完全删除此条件(当您删除内联说明符时)
  • 使定义可见

最后但并非最不重要的一点-C ++ inline说明符与函数内联无关。还有其他依赖于编译器的方法来请求实际的内联,即各种编译器中的__forceinline