Вот хороший пример для включения поведения в политики (обратите внимание на защищенный деструктор):
struct some_policy
{
// Some non-virtual interface here
protected:
~some_policy() { ... }
private:
// Some state here
};
struct some_class : some_policy, some_other_policy { ... };
Еще один хороший пример, чтобы избежать раздувания кода в шаблонах. Обратите внимание на защищенный деструктор:
struct base_vector
{
// Put everything which doesn't depend
// on a template parameter here
protected:
~base_vector() { ... }
};
template <typename T>
struct vector : base_vector
{ ... };
Другой пример, называется CRTP. Обратите внимание на защищенный деструктор:
template <typename Base>
struct some_concept
{
void do_something { static_cast<Base*>(this)->do_some_other_thing(); }
protected:
~some_concept() { ... }
};
struct some_class : some_concept<some_class> { ... };
Другой пример, называется Оптимизация пустой базы. На самом деле не наследование, так как это больше хитрость, позволяющая компилятору не резервировать пространство в some_class
для базового класса (который действует как закрытый член).
template <typename T>
struct some_state_which_can_be_empty { ... };
template <typename T>
struct some_class : private some_state_which_can_be_empty<T> { ... };
Как правило, классы, от которых вы наследуете, должны иметь либо виртуальный, либо защищенный деструктор.