Должен ли шаблон C ++ использоваться в этом случае? - PullRequest
1 голос
/ 25 марта 2009

У меня есть класс, который мой клиент использует для получения () пакета. Пакет содержит std :: vector, тип которого неизвестен до тех пор, пока пакет не будет сгенерирован внутренне в моем классе интерфейса (в этом примере это зависит от переменной Packet :: type).

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

Проблема с этим, насколько я могу судить, заключается в том, что клиент не имеет ни малейшего представления, какой это тип пакета, пока не получит пакет и не посмотрит на элемент Packet :: type. Таким образом, это не будет работать, потому что он не сможет объявить переменную, которую Get () вернет (?)

Может ли шаблон элегантно использоваться в этом случае?

Одна альтернатива, о которой я мог подумать, - это определить базовый класс и создать дочерний класс для каждого типа. Затем метод Get () может вернуть указатель на базовый класс. Затем клиент может просто посмотреть на Packet :: type (packet-> type) и привести его к соответствующему дочернему классу. Но это немного грязно? Есть ли более элегантное решение?

Код ниже примерно демонстрирует сценарий:

enum
{
  T_FLOAT,
  T_COMPLEX
} TYPE_ENUM;

// T can either be of type float or std::complex
template<typename T>
class Packet
{
public:
  TYPE_ENUM       type;
  std::vector<T>  data;
};

class Interface
{

public:
  // Method that client calls to obtain the packet
  Packet<>  Get()
  {
    return queue.pop(); // return current packet in queue
  }

private:
  Queue<Packet>   queue;
};

Ответы [ 3 ]

8 голосов
/ 25 марта 2009

Все шаблоны имеют время компиляции разрешение типа ... если вы не можете определить тип до времени выполнения, значит, вы не подходите для применения шаблонов.

Вам понадобится переключатель времени выполнения для окончательного типа пакета, как вы описали.

5 голосов
/ 25 марта 2009

Используйте абстрактный базовый класс и виртуальные методы для операций над типом пакета. Вам не нужно приводить класс пакета. Коллекция шаблонных классов проблематична - у вас будут проблемы с добавлением и удалением элементов из нее.

3 голосов
/ 25 марта 2009

Вы хотели бы создать базовый класс и сохранить шаблонный класс Packet, который у вас есть. Назовите этот базовый класс PacketBase. Ваш класс Packet будет производным от нового класса PacketBase. То есть каждый тип Packet <>, который генерируется во время компиляции, будет производным от PacketBase.

class PacketBase
{ 
};

// T can either be of type float or std::complex or ...
template<typename T>
class Packet : public PacketBase
{
public:
  std::vector<T>  data;

  //Put other members you need here
  //Note you don't need the type member that you had before. 
};

Interface :: Get вернет PacketBase *. Здесь PacketBase просто используется как общее имя, которое содержит любой тип Packet <>. В очереди будет храниться коллекция PacketBase *.

class Interface
{

public:
  // Method that client calls to obtain the packet
  PacketBase*  Get()
  {
    return queue.pop(); // return current packet in queue
  }

private:
  Queue<PacketBase*>   queue;
};

Чтобы выяснить, какой тип пакета у вас есть, вы можете использовать RTTI с dynamic_cast.

InterfaceObject o;
//fill the queue
PacketBase *pPacket = o.Get();
if(dynamic_cast<Packet<float> * >(pPacket) != NULL)
   ;//You have a Packet<float>
else if(dynamic_cast<Packet<std::complex> * >(pPacket) != NULL)
   ;//You have a Packet<std::complex>
//... for each Packet<> type you have

Вы также можете улучшить свою PacketBase с помощью некоторых виртуальных методов. Затем вы можете вызывать их напрямую вместо RTTI dynamic_cast.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...