Укажите параметры шаблона базовых классов при создании производного класса? - PullRequest
2 голосов
/ 17 января 2011

Я понятия не имею, имеет ли название смысл, но я не могу найти правильные слова, чтобы описать мою «проблему» в одной строке. Во всяком случае, здесь моя проблема. Есть интерфейс для поиска:

template <typename InputType, typename ResultType> class Search {
public:
    virtual void search (InputType) = 0;
    virtual void getResult(ResultType&) = 0;

};

и несколько производных классов, таких как:

template <typename InputType, typename ResultType> 
    class XMLSearch : public Search<InputType, ResultType> {
public:
    void search (InputType) { ... };
    void getResult(ResultType&) { ... };

};

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

Search *s = new XMLSearch<int, int>();

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

template <typename T> class Derived;

class Base {
public:
 template <typename T>
 bool GetValue(T &value) {
  Derived<T> *castedThis=dynamic_cast<Derived<T>* >(this);
  if(castedThis)
   return castedThis->GetValue(value);
  return false;
 }
 virtual void Dummy() {}
};

template <typename T> class Derived : public Base {
public:
 Derived<T>() {
  mValue=17;
 }

 bool GetValue(T &value) {
  value=mValue;
  return true;
 }
 T mValue;
};

int main(int argc, char* argv[])
{
 Base *v=new Derived<int>;
 int i=0;
 if(!v->GetValue(i))
  std::cout<<"Wrong type int."<<std::endl;
 float f=0.0;
 if(!v->GetValue(f))
  std::cout<<"Wrong type float."<<std::endl;
 std::cout<<i<<std::endl<<f;
 char c;
 std::cin>>c; 
 return 0;
}

Есть ли лучший способ сделать это?

1 Ответ

1 голос
/ 17 января 2011

Есть ли лучший способ сделать это?

Да, этот дизайн немного лучше, поскольку он использует статическую диспетчеризацию при вызове GetValue() (я предполагаю, что dynamic_cast это опечатка, вы на самом деле хотели набрать static_cast в Base::GetValue()).В этом варианте Base::GetValue() не является виртуальным, но он может вызывать Derived::GetValue(), используя указатель типа Base.Это делает его немного быстрым.

Но даже ваш путь не так уж и плох.Все, что вам нужно для создания шаблонов ваших классов, вот так:

Search<int,int> *s = new XMLSearch<int, int>();

Ваш Search *s = new XMLSearch<int, int>() является неправильным !


Вы можете typedef ваши шаблоныследующим образом:

typedef Search<int,int> iisearch;
typedef XMLSearch<int,int> iixmlsearch;

Затем используйте их:

iisearch *s = new iixmlsearch();

Это выглядит лучше, верно?


Небольшая модификация

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

template <typename InputType, typename ResultType> class Search {
public:
    void search (InputType input) //it's not virtual anymore!
    {
        xmlsearch *_this = getXmlSearch();
        xmlsearch->search(input);
    }
    void getResult(ResultType& result) //it's not virtual anymore!
    {
        xmlsearch *_this = getXmlSearch();
        xmlsearch->getResult(result);
    }
private:
    typedef XMLSearch<InputType, ResultType> xmlsearch;
    xmlsearch* getXmlSearch()
    {
       static xmlsearch *_this= static_cast<xmlsearch* >(this);
       return _this;
    }

};

Теперь ваш базовый класс не является абстрактным, поскольку он не определяет виртуальные функции.Этот дизайн немного быстрее, чем ваша версия!

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