Как лучше всего выставить частное наследование базовому классу?

Я проектирую иерархию объектов, в которой базовый класс всех объектов Node, который, как ожидается, будет разделен на подклассы. Подклассы Node будет содержать дочерние элементы, но тип дочернего элемента может варьироваться от одного подкласса к другому.

Я реализую право собственности на дочерние элементы путем частного наследования от Owner<> класс, который является просто оберткой для std::vector, Я хочу показать это владение базовому классу (но никому другому), потому что существует много повторений в отношении добавления и удаления дочерних элементов. Итак, я придумал это:

#include <vector>
using namespace std;

//Class to contain child items
template <typename T>
struct Owner {
    vector<T> children;
};

//Types of children that can be owned by nodes in the hierarchy
struct ChildType1{};
struct ChildType2{};
struct ChildType3{};

//Node base class
template <typename DERIVED_T>
struct Node {
    Node(DERIVED_T& _derivedThis):
        derivedThis(_derivedThis)
    {}

    template <typename ITEM_T>
    void AddItem() {
        /*Possibly do a lot of pre-checks here before adding a child*/
        derivedThis.Owner<ITEM_T>::children.emplace_back();
    }

    //Reference to the most-derived subclass instance
    DERIVED_T& derivedThis;
};

//A possible subclass of Node
struct DerivedNode:
        private Owner<ChildType1>,
        private Owner<ChildType2>,
        public Node<DerivedNode>
{
    friend struct Node<DerivedNode>;

    DerivedNode():
        Node(*this)
    {}
};


int main() {
    DerivedNode d;
    d.AddItem<ChildType1>();
    d.AddItem<ChildType2>();
    //d.AddItem<ChildType3>();  //Fails to compile (intended behavior; DerivedNode should not own ChildType3 objects)

    return 0;
}

Этот подход выглядит немного грязно, потому что я храню ссылку на производный класс в базовом классе (я никогда раньше этого не видел). Это хорошая практика? Существуют ли более эффективные способы сохранения дочернего владения в производном классе при обработке общего обслуживания детей в базовом классе?

1 ответ

Решение

Вы почти там. Не храните ссылку на DERIVED_T в Node, Просто пиши:

     auto derivedThis& = *static_cast<DERIVED_T*>(this);

в каждой из функций, которые нуждаются в этом. (Или же const DERIVED_T* при необходимости).

Другие вопросы по тегам