У меня есть класс интерфейса (см. Первый блок кода), реализация (см. Второй блок кода) не генерирует ошибку, хотя CreateMessage() не определен... Я совершенно смущен, потому что, насколько я вижу это не должны составляться.
О, используя Visual Studio 2010 на Microsoft 7... кто-нибудь видел это раньше или у меня есть ошибка в моем коде?
Блок кода 1:
namespace Common
{
namespace Messaging
{
class iNetworkMessageFactory
{
public:
// +----------------------------------------------------------------------
// + Description : iNetworkMessageFactory class destructor.
// +----------------------------------------------------------------------
virtual ~iNetworkMessageFactory() { }
// +----------------------------------------------------------------------
// + Description : Create a network message.
// +----------------------------------------------------------------------
virtual iNetworkMessage *CreateMessage() = 0;
};
} // Namespace Common
} // Namespace Messaging
Блок кода 2:
#include <Messaging/iNetworkMessageFactory.h>
class NetworkMessageFactory : public Common::Messaging::iNetworkMessageFactory
{
public:
// +----------------------------------------------------------------------
// + Description : NetworkMessageFactory class constructor.
// +----------------------------------------------------------------------
NetworkMessageFactory();
// +----------------------------------------------------------------------
// + Description : NetworkMessageFactory class destructor.
// +----------------------------------------------------------------------
~NetworkMessageFactory();
/*
// +----------------------------------------------------------------------
// + Description : Create a network message.
// +----------------------------------------------------------------------
iNetworkMessage *CreateMessage( NetworkMessageType typeID
, iNetMsgBody *body
, ConnectionID connID );
*/
};
Это прекрасно и не должно генерировать ошибку. В противном случае вы не сможете иметь более одного абстрактного предка. Вы получите ошибку времени выполнения, если попытаетесь вызвать чистый виртуальный.
Например, C++ позволит вам подклассифицировать NetworkMessageFactory и обеспечить реализацию чистой виртуальной функции в производном классе. Нет никаких оснований для обеспечения реализации реализации в самом классе NetworkMessageFactory.
Это разрешено, но вы не сможете создать экземпляр класса NetworkMessageFactory, потому что чистые виртуальные методы CreateMessage не определены.
Рассмотрим следующий случай: у вас есть чистый виртуальный базовый класс "A", который имеет два чистых виртуальных метода: do_work и do_more_work. Скажем, у вас есть еще два класса, B и C, которые имеют ту же реализацию "do_work", но другую реализацию "do_more_work". тогда у вас есть класс под названием "D", который имеет ту же реализацию "do_more work", что и C, но другой "do_work", реализация.
Запутанный? Да. Но в этой гипотетической ситуации вы можете создавать промежуточные классы, которые определяют общие реализации виртуальных методов, а затем имеют A, B, C и D наследуют эти определения от них. Эти промежуточные классы необязательно будут иметь определение как для do_work, так и для do_more_work, поэтому C++ позволяет вам определять эти промежуточные классы для использования в вашей иерархии классов, но не создавать их самостоятельно.
Пример, который я описал, улучшает повторное использование кода (хотя и по стоимости), а в идеале, делает ваш код легче поддерживать (это спорно!). Прежде чем вы начнете писать такой код, внимательно изучите вашу проблему и попробуйте найти более простое решение; такого рода вещи могут дать вам и вашим коллегам серьезную головную боль.