Как представить базовое поведение Mixin в C ++ - PullRequest
3 голосов
/ 15 апреля 2011

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

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

Тогда будет смешан класс расширения / расширения.быть хорошим решением.Но это не тривиально в C ++.

Быстрое и грязное решение состоит в том, чтобы написать функцию, отправляющую тип объекта с помощью оператора dynamic_cast , и выполнить требуемый код длякаждый тип иерархии.Но это несколько плохая практика, так как она подвержена ошибкам при записи, она нарушает инкапсуляцию и не поддерживает безопасно будущие изменения.

Я думаю о том, чтобы где-нибудь поддерживать какую-то хеш-таблицу с определением {идентификатор типа rtti, функция для вызова}", и используйте это как поддельный VTable для функции, которую я хочу написать и переопределить. Но я не уверен, что будет лучше...

Любые другие идеи? Изменение VTable среды исполнения? Решение для метапрограммирования шаблонов? Другое?

Не забывайте: я определенно не могу изменить исходные классы (ни заголовки, ни реализацию).

Ответы [ 3 ]

2 голосов
/ 15 апреля 2011

Если вы не можете изменить исходную иерархию, то шаблонное метапрограммирование вряд ли поможет.Помните, что это основано на информации времени компиляции.

Изменение vtable кажется крайне плохой идеей, очевидно, оно непереносимо и предполагает, что вы немного знаете его физическое расположение ... даже если вы все сделаете правильно, оно будетбыть кошмаром обслуживания.

Мне очень нравится идея std::map<type_info, Func>.std::type_info::before предлагает вам все необходимое для реализации (не полагайтесь на имя или адрес).

2 голосов
/ 18 июля 2013

На самом деле я пишу библиотеку, которая делает именно это: позволяет вам составлять и изменять типы из существующих классов во время выполнения, за исключением возможности вызывать методы как ... er-методы, но как внешние функции с первым аргументом this. Он не навязчив, поэтому вам не нужно каким-либо образом изменять существующие классы.

Код: https://github.com/iboB/boost.mixin

Документ: http://ibob.github.io/boost.mixin/

Надеюсь, это поможет.

PS. Он называется Boost.Mixin, потому что я собираюсь отправить его в Boost, но это еще не часть Boost.

1 голос
/ 15 апреля 2011

Написать бесплатную функцию.

void vfunc(base& param);

// ...
base b;
vfunc(b);

deriv0 d0;
vfunc(d0);
...