Запретить наследование абстрактного класса интерфейса в переполнении стека

Я предоставляю SDK своим пользователям, позволяя им писать библиотеки DLL на C ++ для расширения программного обеспечения.

Заголовки SDK в основном содержат определения классов интерфейса. Эти классы бывают двух типов:

  • Некоторые из которых пользователь должен создать подкласс и реализовать
  • Некоторые из них являются обертками для базовых классов, передаваемых приложением в функции DLL в качестве указателей, которые затем могут использоваться в качестве аргументов кодом DLL для вызова основных функций. Эти интерфейсы не должны быть разделены на подклассы пользователем и переданы основным функциям, поскольку они ожидают определенного основного подкласса.

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

Можно ли было бы предотвратить создание подклассов некоторых интерфейсов в заголовках SDK?

0

Решение

Пока клиент не должен использовать указатель ни для чего, кроме
передав его обратно в вашу DLL, вы можете просто использовать предварительное объявление;
вы не можете получить из неполного типа. (Когда сталкиваюсь с похожим
Дело в том, что недавно я пошел на все, и разработал специальный тип обертки
основанный на void*, В коде интерфейса много кастингов, но
нет никакого способа, которым клиент может сделать что-то кроме передачи значения обратно
мне.)

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

class InternallyVisibleInterface;

class ClientVisibleInterface
{
private:
virtual void doSomething() = 0;
ClientVisibleInterface() = default;
friend class InternallyVisibleInterface;
protected:      //  Or public, depending on whether the client should
//  be able to delete instances or not.
virtual ~ClientVisibleInterface() = default;
public:
void something();
};

и в вашей DLL:

class InternallyVisibleInterface : public ClientVisibleInterface
{
protected:
InternallyVisibleInterface() {}

//  And anything else you need.  If there is only one class in
//  your application which should derive from the interface,
//  this is it.  If there are several, they should derive from
//  this class, rather than ClientVisibleInterface, since this
//  is the only class which can construct the
//  ClientVisibleInterface base class.
};

void ClientVisibleInterface::something()
{
assert( dynamic_cast<InternallyVisibleInterface*>( this ) != nullptr );
doSomething();
}

Это предлагает два уровня защиты: первый, хотя деривация
прямо из ClientVisibleInterface возможно, это невозможно для
результирующий класс должен иметь конструктор, и поэтому он не может быть
инстанцирован. А во-вторых, если клиентский код обманывает,
будет ошибка во время выполнения, если он сделает это.

Вам, вероятно, не нужны обе защиты; тот или другой должен
достаточно. Закрытый конструктор приведет к ошибке времени компиляции,
а не во время выполнения. С другой стороны, без этого вы не
даже упомянуть имя InternallyVisibleInterface в
распределенные заголовки.

0

Другие решения

Как только у разработчика появляется среда разработки, он может делать практически все, и вы даже не должны пытаться это контролировать.

ИМХО лучшее, что вы можете сделать, — это определить предел между основным приложением и библиотеками расширений и убедиться, что объекты получены из этих библиотек. являются или исправьте класс и прервите с отличительным сообщением, если они не.

Использование RTTI и typeid как правило, осуждают, потому что это, как правило, признак плохого ООП-проекта: в нормальный В случае использования достаточно вызвать виртуальный метод, чтобы вызвать соответствующий код. Но я думаю, что это можно смело рассмотреть в вашем случае использования.

0

По вопросам рекламы [email protected]