C++ — базовый класс и закрытый заголовок

Я пишу библиотеку на С++ и имею такую ​​иерархию классов:

файл message.h (в ./mylib/src)

class Message
{
};

файл request.h (в ./mylib/include/mylib)

#include "message.h"

class Request : public Message
{
};

файл response.h (в ./mylib/include/mylib)

#include "message.h"

class Response : public Message
{
};

Я хочу, чтобы все в моей папке mylib/src было скрыто от пользователя, и хочу распространять только файлы в mylib/include. Но проблема в том, что и requst.h, и response.h #include message.h, поэтому пользователь получит ошибку «Нет такого файла», когда #включит request.h и response.h. Есть ли способ обойти эту проблему?


person jpen    schedule 24.01.2013    source источник


Ответы (3)


Вы можете просто предоставить общедоступный интерфейс для Message и скрыть фактический класс:

class IMessage
{
    Message* pImpl;
};

Распространите этот заголовок и используйте предварительное объявление для Message.

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

person Luchian Grigore    schedule 24.01.2013
comment
Дополнительная информация о pimpl: herbsutter.com/gotw/_100 и herbsutter.com/gotw/_101 - person R. Martinho Fernandes; 24.01.2013
comment
Спасибо. Я бы пошел по второму варианту. - person jpen; 24.01.2013

Если вы хотите иметь возможность использовать Response и Request, вам необходимо включить файлы заголовков, в которых они объявлены. Вот почему вы должны поместить эти заголовки в общедоступную папку include.

person Ivaylo Strandjev    schedule 24.01.2013
comment
Спасибо за ваш ответ. В идеале я хотел бы распространять только один файл заголовка (скажем, mylib.h) и разрешить пользователю использовать как запрос, так и ответ, # включая этот файл заголовка. Это возможно? Если да, то что будет содержать mylib.h? - person jpen; 24.01.2013

Базовый класс должен быть общедоступным, иначе вам придется писать механизмы сериализации/десериализации.

person Gaetan    schedule 24.01.2013