У меня есть некоторые проблемы с виртуальными классами и инкапсуляцией. Рассмотрим следующий минимальный пример программы на C++:Виртуальные интерфейсы и инкапсуляция
#include <iostream>
class IConnection
{
public:
virtual void connect() = 0;
virtual std::string recv() = 0;
virtual void disconnect() = 0;
virtual ~IConnection() {}
};
class ConcreteConnection: public IConnection
{
public:
ConcreteConnection(): m_connected(false) {}
void connect() { m_connected = true; }
std::string recv() { return "Received some text."; }
void disconnect() { m_connected = false; }
private:
bool m_connected;
};
class Container
{
public:
Container() { m_connection = NULL; }
void SetConnection(IConnection *connection) { m_connection = connection; };
void GetData() { std::cout << m_connection->recv() << std::endl; }
~Container() { delete m_connection; }
private:
IConnection *m_connection;
};
int main(void)
{
Container container;
ConcreteConnection *connection = new ConcreteConnection();
container.SetConnection(connection);
container.GetData();
return 0;
}
Этот простой пример прекрасно работает, но я не совсем доволен. Контейнер-объект должен владеть соединением, не беспокоясь о конкретной реализации интерфейса IConnection . Вот почему я создал объект ConcreteConnection вне контейнера. Что мне не нравится, так это то, что Мне нужно передать указатель или ссылку на соединение. Я хотел бы передать копию объекта-соединения, так что основная функция не имеет возможности манипулировать или удалять объект-соединение после передачи его в контейнер . Но, насколько я знаю, невозможно передать копию соединения , не сообщив контейнеру, к которому он относится, конкретную реализацию IConnection.
Итак, у вас есть идеи, как это решить? Возможно ли каким-либо образом передать копию объекта какой-либо функции без указания функции, для которой конкретная реализация интерфейса, к которому принадлежит объект?
Я относительно новым для обоих C++ и объектно-ориентированного программирования, так что не стесняйтесь и скажите мне, если мой класс структура совершенно неправильно и в этом случае не происходит в реальной жизни программный код (и как это должно работа вместо этого).
Заранее спасибо.
На самом деле вы можете реализовать протокол копирования в рамках интерфейса подключения в качестве виртуального метода (скажем, 'clone' или 'copy'), который будет выполнять фактическую работу. Но в более общем плане, если вы хотите, чтобы объект «просачивался» в другие части вашей базы кода («основной» в вашем примере), вы можете реализовать шаблон инъекции зависимостей с помощью «фабричного» синглтона, цель которого заключается в создании и доставке экземпляра соединения. Вы разделили бы существование экземпляра на конечного владельца и метод фабрики, строящий его, и вы также избегаете необходимости в копии. – didierc
Звучит неплохо! Подумайте об этом, чтобы я мог принять это. – lslah
Я лично подобрал бы ответ Керрека С.Б., поскольку он решает проблему на C++, перемещая конструкцию объекта непосредственно в контейнере. Это именно то, что вам нужно, и оно также реализует шаблон инъекции (контейнер не знает, какой конкретный класс получает экземпляр).В моем решении это знание было ограничено фабричным методом, но вы все равно должны были убедиться, что экземпляр не поддерживается им каким-то образом (так как это было вашей первоначальной проблемой). Обратите внимание, что вы все равно можете поместить вызов 'make' в другое место, чем' main' (например, класс, предназначенный для установки приложения). – didierc