Фабричный шаблон для дочерних классов с изменением параметров / возвращаемых типов в виртуальных функциях

#c #generics #design-patterns #factory

#c #общие #шаблоны проектирования #фабрика

Вопрос:

Я хотел бы написать фабрику для классов, которые по существу отличаются только типом обрабатываемого сообщения, но в остальном полностью одинаковы. Я думал о написании дочернего класса и позволил им наследовать от него, чтобы иметь общего предка. Поскольку типы сообщений, которые должны обрабатывать дочерние элементы, различаются, я подумал об использовании шаблонного класса в качестве общего предка, почти как в следующем примере.

 template <typename T>
class Parent 
{
public:
  virtual void Set(T message); 
  virtual T Get();
}

class ChildA : public Parent<MessageType_A>
{
public:
  void Set( MessageType_A message);
  MessageType_A Get(); 
private:
  MessageType_A mMessage;
}

class ChildB : public Parent<MessageType_B>
{
public:
  void Set( MessageType_B message);
  MessageType_B Get(); 
private:
  MessageType_B mMessage;
}
 

Однако из-за шаблона в родительском, у меня нет общего базового класса для использования на заводе и не могу придумать способ решения проблемы.
Я думал об использовании std::any, объединений или вариантов, но они создают только больше препятствий для моей проблемы, а не решают их.
У кого-нибудь есть идея о том, как я мог бы создать фабрику с моими описанными требованиями?

Комментарии:

1. вы всегда можете добавить другой (не шаблонный) общий базовый класс, вопрос в том, насколько он полезен, когда разные классы не имеют общего интерфейса

2. Как вы ожидаете использовать (несвязанный) ChildA / ChldB ?

3. @largest_prime_is_463035818: отсутствие общих интерфейсов, к сожалению, не сработает для меня.

4. @Jarod42: это проблема, которую я надеялся решить с помощью общего родителя

5. «Мне придется отправлять сообщения в виде байтовых строк», похоже, это общий интерфейс. Если общим для всех сообщений является то, что вы можете получить char* из них некоторые и размер, то это то, что принадлежит общему базовому классу. Если у них действительно нет ничего общего, фабрика не может помочь

Ответ №1:

Разные экземпляры Parent — это разные несвязанные типы.

Я думал об использовании шаблонного класса в качестве общего предка

Для and нет общего предка ChildA ChildB . Один наследует от Parent<MessageType_A> другого от Parent<MessageType_B> .

Подумайте, можете ли вы сделать так, чтобы у всех ChildX был общий интерфейс. В качестве примера рассмотрим, что сообщения считываются из istream и записываются в ostream, тогда общий интерфейс может выглядеть следующим образом:

 struct Common {
    virtual void In(std::istreamamp;) = 0;
    virtual void Out(std::ostreamamp;) = 0;
};
 

Parent тогда было бы

 template <typename T>
class Parent : public Common
{
public:
  void In(std::istreamamp; in) {
      T t;
      in >> t;
      Set(t);
  }
  void Out(std::ostreamamp; out) {
      out << Get();
  }
protected:
  virtual void Set(T message);
  virtual T Get();
}
 

Теперь вы можете наследовать разные ChildX от разных Parent<T> , и все они имеют общего предка Common .