Тип стирания и принадлежности - PullRequest
1 голос
/ 27 августа 2010

Я использовал шаблон стирания типа в C ++, т.е. я скрываю шаблонный класс с абстрактным классом

class Base{

  virtual ~Base(){}

 //pure virtual methods...
};

template<typename T>
class Derived : Base{

Derived<T>(){}
~Derived(){}

//public methods...

private :
vector<T> datas;

};

проблема: если я хочу получить или изменить данные, я должен использовать базовый класс

как мне определить методы доступа getDatas () и SetDatas (векторные данные)?

Ответы [ 4 ]

1 голос
/ 27 августа 2010

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

1 голос
/ 27 августа 2010

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

Как и для всех форм полиморфизмов, производные классы должны иметь что-то общее , которое может синтаксически быть выражено в базовом классе.

Редактировать:

ОК, Ответ Стийна дал мне идею.Хотя я все еще думаю, что вы должны использовать что-то с полки (boost::any), просто для ударов, вот эскиз:

class Base
{
public:
  template< class T >
  bool SetData(const std::vector<T>& data)
  {
    return SetData(&data,typeid(T));
  }
private:
  virtual bool SetData(const void* data, const std::type_info& tid) = 0;
}

template< class T >
class Derived : public Base
{
public:
  bool DoSetData(const std::vector<T>& data)
  {
    // tbd
  }
private:
  virtual bool SetData(const void* data, const std::typeinfo& tid)
  {
    if( tid != typeid(T) )
      return false;
    const std::vector<T>* pdata = reinterpret_cast<const std::vector<T>*>(data);
    return DoSetData(*pdata);
  }
}

Что вы скажете?

1 голос
/ 27 августа 2010

Вы не можете определить SetData (вектор), так как std :: vector нужен тип, и, очевидно, вы не можете определить SetData (std :: vector ) в Base, если у вас нет определения для T.

Так что, если вам это действительно нужно и вы думаете, что это правильный путь, вам придется изучить диспетчеризацию типов (или взломать, используя void *).Boost использует диспетчеризацию типов в некоторых местах, иначе Google предоставляет примеры.

edit простой пример того, как это может выглядеть;на самом деле не диспетчеризация типа, но более простая

class Base
{
public:
  template< class T >
  bool SetData( const std::vector< T >& t )
  {
    return SetData( static_cast< const void* >( &t ), typeid( t ) );
  }

protected:
  virtual bool SetData( const void*, const std::type_info& ) = 0;
};

template< class T >
class Derived : public Base
{
protected:
  bool SetData( const void* p, const std::type_info& info )
  {
    if( info == typeid( std::vector< T > ) )
    {
      const std::vector< T >& v = *static_cast< const std::vector< T >* >( p );
      //ok same type, this should work
      //do something with data here
      return true;
    }
    else
    {
      //not good, different types
      return false;
    }
  }
};
0 голосов
/ 27 августа 2010

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

Возможно, вы сможете настроить несколько общий интерфейс с void *, но пользователю вашего класса все равно придется сопоставить каждый экземпляр класса с конкретным типом, T. Если T - int, пользователи знать, что коллекция основана на int.

Если вы хотите сохранить любой тип в векторе, не беспокоясь о том, какой экземпляр какого типа, вы можете сделать T void *. Если вы сделаете это, вы можете даже пропустить часть template<typename T> производного. Это может стать не шаблонным классом.

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