简体   繁体   中英

C++ inheritance - cannot define methods in cpp file

I have a following problem. I have these 3 files (I made a simplified example, but the errors are the same):

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();
}

Compiler (actually the linker I guess) gives me the following error:

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

Now I've gotten around this by doing either one of those two things:

  • Remove inline keyword
  • Leave inline as it is, but move the methods definitions to .hpp file

If I do one of those things, everything works. But my question is: why? In my real code I really wan the compiler to inline the method calls plus I want them to be defined in .cpp file, to make my .hpp file more clear. Is there a solution to that?

Your code has a bug in it. According to 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).

Obviously, when you put your definitions in .cpp file and call those functions from other translation units, this condition is not satisfied.

So your two alternative approaches both work because they either

  • Remove this condition altogether (when you remove inline specifier)
  • Make the definition visible

And last, but not the least - C++ inline specifier has nothing to do with function inlining. There are other, compiler-dependent ways to request the actual inlining, ie __forceinline in various compilers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM