Оставляя в силе переинтерпретацию void*
к указателю на функцию, UB - это вызов функции через указатель другого типа. Неважно, связаны ли типы, например Plugin* (*)()
и TestPlugin* ()
. Это также UB для доступа к объекту одного типа через указатель другого типа, , даже если эти типы являются производными и базовый класс соответственно . Например
Derived derived;
Base *base;
base = &derived; // OK, will access base subobject
base = reinterpret_cast<Base*>(&derived); // not OK, will access derived object
Ваш код вероятно будет работать, как ожидается, со многими (но, вероятно, не со всеми) популярными компиляторами, если задействовано только одно не виртуальное наследование. Однако нет необходимости брать на себя такие риски. Все это можно легко исправить, просто выставив библиотеку только на интерфейсах Plugin*
.
extern "C" {
Plugin *allocator() {
return new TestPlugin();
}
void deleter(Plugin *ptr) {
delete ptr;
}
}
Эта реализация требует, чтобы плагин имел виртуальный деструктор. В любом случае, это хорошая идея. OTOH функция удаления на самом деле не нужна, клиент может просто вызвать delete Plugin
. А еще лучше вернуть shared_ptr из allocator, возможно, с пользовательским удалением.