pimpl для защищенного члена во время наследования

У меня есть большое количество защищенных функций-членов, объявленных в файле hpp `базового класса, который используется производным классом. Моя идея состоит в том, чтобы удалить их из файла заголовка, чтобы уменьшить зависимость компиляции. Я также подумал об использовании метода pimpl для защищенного члена.

Я определил класс Impl в файле cpp класса Base и переместил все защищенные функции внутрь класса Impl. Кроме того, я сделал предварительное объявление класса Impl в заголовочном файле класса Base в качестве защищенного члена.

protected:
    class Impl;
    Impl* impl_;

Но при этом, когда я вызываю защищенную функцию, используя impl_ из производного класса, при компиляции производного класса возникает следующая ошибка:

error: invalid use of incomplete type ‘class Base::Impl’
    if (false == impl_->EncodeMMMsgHeader(mm_msg_header_)) {
error: forward declaration of ‘class Base::Impl’

Я думаю, что ошибка возникает из-за того, что нельзя использовать предварительное объявление в любом случае, когда компилятору нужна контекстная информация о классе, и компилятору бесполезно сообщать ему только немного о классе.

Есть ли способ, с помощью которого я мог бы преодолеть вышеуказанную проблему? Если нет, то может ли кто-нибудь предложить мне лучший метод для достижения моей цели.


person Sourav    schedule 19.07.2018    source источник
comment
защищенные и виртуальные методы являются частью интерфейса и не должны быть скрыты в pimpl.   -  person Jarod42    schedule 19.07.2018
comment
не уверен @Jarod42, защищенные виртуальные функции чаще являются частью реализации и почти никогда частью интерфейса.   -  person Eduard Rostomyan    schedule 19.07.2018
comment
@EduardRostomyan: производные классы видят и могут использовать protected данные и могут переопределять каждый virtual (не final) метод.   -  person Jarod42    schedule 19.07.2018
comment
согласен, но это не делает его частью интерфейса класса, а наоборот, делает частью реализации   -  person Eduard Rostomyan    schedule 19.07.2018


Ответы (1)


Вы можете добавить слой, чтобы уменьшить зависимости:

Из

#include "lot_of_dependencies"

#include <memory>

class MyClass
{
public:
    ~MyClass();
    /*...*/
protected:
    /* Protected stuff */
private:
    struct Pimpl;
    std::unique_ptr<Pimpl> impl;
};

добавлять

MyClassProtectedStuff.h

#include "lot_of_dependencies"

class MyClassProtectedStuff
{
public:
    /* Protected stuff of MyClass */
private:
    // MyClass* owner; // Possibly back pointer
};

а потом

МойКласс.h

#include <memory>

class MyClassProtectedStuff;

class MyClass
{
public:
    ~MyClass();
    /*...*/
protected:
    const MyClassProtectedStuff& GetProtected() const;
    MyClassProtectedStuff& GetProtected();
private:
    struct Pimpl;
    std::unique_ptr<Pimpl> impl;
    std::unique_ptr<MyClassProtectedStuff> protectedData; // Might be in Piml.
};

И тогда производный класс должен включать оба заголовка, тогда как обычный класс включает только MyClass.h

person Jarod42    schedule 19.07.2018
comment
У меня есть еще одна цель удалить защищенную функцию-член из файла заголовка. Поскольку мне нужно включить заголовочный файл MyClass.h в большое количество других файлов, для которых не потребуется этот защищенный материал. Хотя ваша идея будет работать нормально, она помешает моей вышеупомянутой цели, которая не менее важна. - person Sourav; 19.07.2018