Я пытаюсь создать общедоступный API C ++ для частной базы кода, которая также написана на C ++.Я попытался сделать это следующим образом:
- Создать класс API-оболочки для каждого частного класса.
- Иметь общий базовый класс API, который имеет указатель на закрытый класс.
- Реализации класса API не содержат никакой функциональности, а просто перенаправляют вызовы методов их частным аналогам.
Это казалось разумным подходом.Однако в действительности это быстро приводит к очень неуклюжему коду.Вот пример, который представляет проблему, с которой я столкнулся.
(Изменить: код также можно просмотреть здесь ).
частные классы API (здесь нет проблем)
namespace Core {
// Base class for all Core classes.
class CoreObject
{
public:
virtual ~CoreObject();
};
class Interface;
class Stream;
class Server : public CoreObject
{
public:
Interface * createInterface();
private:
std::vector<Interface*> mInterfaces;
};
class Interface : public CoreObject
{
public:
void addStream(Stream * stream);
const Stream * getStreamByIndex(std::size_t index) const;
std::size_t streamCount() const;
private:
std::vector<Stream*> mStreams;
};
class Stream : public CoreObject
{
public:
void start();
void stop();
private:
std::string mStats;
};
} // Core
объявления классов открытого API (пока что все хорошо)
namespace Core {
class CoreObject;
}
namespace API {
class APIStream;
class APIInterface;
// Base class for all API classes.
class APIObject
{
public:
APIObject(Core::CoreObject * inCoreObject);
virtual ~APIObject();
Core::CoreObject * getCoreObject();
const Core::CoreObject * getCoreObject() const;
void setCoreObject(Core::CoreObject * inCoreObject);
private:
Core::CoreObject * mCoreObject;
};
class APIServer : public APIObject
{
public:
APIServer();
APIInterface * createInterface();
};
class APIInterface : public APIObject
{
public:
APIInterface();
void addStream(APIStream * stream);
const APIStream * getStreamByIndex(std::size_t index) const;
APIStream * getStreamByIndex(std::size_t index);
std::size_t streamCount() const;
};
class APIStream : public APIObject
{
public:
APIStream();
void start();
void stop();
};
Реализация API (слишком много приведений, как правило, неуклюжий)
#include "API.h"
#include "Core.h"
namespace API {
APIObject::APIObject(Core::CoreObject * inCoreObject) :
mCoreObject(inCoreObject)
{
}
APIObject::~APIObject()
{
}
Core::CoreObject * APIObject::getCoreObject()
{
return mCoreObject;
}
const Core::CoreObject * APIObject::getCoreObject() const
{
return mCoreObject;
}
void APIObject::setCoreObject(Core::CoreObject * inCoreObject)
{
mCoreObject = inCoreObject;
}
//
// APIServer
//
APIServer::APIServer() :
APIObject(new Core::Server)
{
}
APIInterface * APIServer::createInterface()
{
Core::Server * coreServer = static_cast<Core::Server*>(getCoreObject());
Core::Interface * coreInterface = coreServer->createInterface();
APIInterface * result(new API::APIInterface);
result->setCoreObject(coreInterface);
return result;
}
//
// APIInterface
//
APIInterface::APIInterface() :
APIObject(new Core::Interface)
{
}
void APIInterface::addStream(APIStream * apiStream)
{
Core::Stream * coreStream = static_cast<Core::Stream *>(apiStream->getCoreObject());
Core::Interface * coreInterface = static_cast<Core::Interface*>(getCoreObject());
coreInterface->addStream(coreStream);
}
//
// APIStream
//
const APIStream * APIInterface::getStreamByIndex(std::size_t index) const
{
const Core::Interface * coreInterface = static_cast<const Core::Interface*>(getCoreObject());
const Core::Stream * coreStream = coreInterface->getStreamByIndex(index);
// Now how I get the the APIStream object?
return 0;
}
std::size_t APIInterface::streamCount() const
{
const Core::Interface * coreInterface = static_cast<const Core::Interface*>(getCoreObject());
return coreInterface->streamCount();
}
APIStream::APIStream() :
APIObject(new Core::Stream)
{
}
void APIStream::start()
{
static_cast<Core::Stream*>(getCoreObject())->start();
}
void APIStream::stop()
{
static_cast<Core::Stream*>(getCoreObject())->stop();
}
} // API
Как видите, реализация выглядит не слишком хорошо.Буду признателен за ваши ответы или советы по этим вопросам:
- Где я ошибся?
- Что я должен был сделать вместо этого?
Обновление
Предложение Джона Диблинга, похоже, работает
действительно хорошо.Как видно из
улучшенного кода , все проблемы решаются аккуратно.
Мне все еще придется применить это решение к реальному коду на работе завтра.Мне интересно посмотреть, насколько хорошо он там работает.