0

Я проектирую иерархию объектов, в которой базовым классом всех объектов является 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; 
} 

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

+2

Вы когда-нибудь читали о [CRTP] (https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)? –

+0

Думаю, я только прочитал первый абзац в Википедии. Использование 'static_cast (это)' никогда не приходило мне ... спасибо. – Carlton

ответ

3

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

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

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