Пока клиент не должен использовать указатель для чего-либо, кроме , передавая его обратно в вашу DLL, вы можете просто использовать объявление вперед; вы не можете получить неполный тип. (В тот момент, когда я столкнулся с аналогичным случаем , я отправился целым свиным гриппом и разработал специальный тип обертки на основе void*
. В коде интерфейса много отливок, но , что клиент не может сделать ничего, кроме как пройти значение возвращается к me.)
Если классы, о которых идет речь, реализуют интерфейс, который также должен использовать клиент , существует два решения. Первое заключается в том, чтобы изменить это: , заменяя каждую из функций-членов свободной функцией, которая принимает указатель на тип и просто предоставляет объявление вперед. второй использовать что-то вроде:
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
в распределенных заголовках .
[C++ 11 имеет последнее ключевое слово] (http://en.cppreference.com/w/cpp/language/final) – Borgleader
... аннотация final? – Wintermute
Основная проблема заключается в том, что вы * делаете * необходимость подкласса в своей собственной реализации. Таким образом, в вашей реализации вам нужно будет увидеть другое объявление, чем ваши вызывающие. (например, 'final' или private CTor). Это, безусловно, возможно для большинства реализаций с помощью reinterpret_cast, но я бы посоветовал это сделать, поскольку это был бы уродливый взлом с предельными преимуществами. – peterchen