Наследование в C ++ - невозможно определить методы в файле cpp - PullRequest
0 голосов
/ 10 апреля 2019

У меня следующая проблема.У меня есть эти 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 Ответ

3 голосов
/ 10 апреля 2019

В вашем коде есть ошибка. Согласно cppreference

Определение встроенной функции или переменной (начиная с C ++ 17) должно быть присутствует в блоке перевода, где к нему осуществляется доступ (не обязательно до точки доступа).

Очевидно, что когда вы помещаете свои определения в файл .cpp и вызываете эти функции из других модулей перевода, это условие не выполняется.

Так что оба ваших альтернативных подхода работают, потому что они либо

  • Удалите это условие полностью (при удалении встроенного спецификатора)
  • Сделать определение видимым

И последнее, но не менее важное: спецификатор C ++ inline не имеет ничего общего с встраиванием функций. Существуют и другие, зависящие от компилятора способы запроса фактической вставки, то есть __forceinline в различных компиляторах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...