Можно ли поместить определения шаблонов абстрактных (чисто виртуальных) классов в исходные файлы c ++ - PullRequest
3 голосов
/ 06 сентября 2010

В соответствии с Хранением определений функций шаблона C ++ в файле .CPP

легко разделить интерфейс и реализацию класса шаблона,

.h file

template<typename T> 
class foo 
{ 
   public: 
     foo();
     ~foo();
     void do(const T& t); 
}; 

.cpp file

template <typename T> 
void foo::foo() 
{ 
    // initiate 
} 

//destructor

template <typename T> 
void foo::do(const T& t) 
{ 
    // Do something with t 
} 

void foo<int> fi; 
void foo<std::string> fs; 

Хитрость заключается в том, чтобы специализировать класс шаблона путем создания экземпляров в конце.cpp файл.

Но что, если это был чисто виртуальный шаблон класса

.h файл

template<typename T> 
class foo 
{ 
   public:
     foo();
     ~foo(); 
     virtual void do(const T& t) = 0; 
}; 

и мы получили конкретный классотсюда:

template<typename T> 
class foobar : public foo<T>
{ 
   public: 
     void do(const T& t); 
}; 

исходный файл для этого класса выглядит как

.cpp file

template <typename T> 
void foobar::do(const T& t) 
{ 
    // Do something with t 
} 

void foobar<int> fi; 
void foobar<std::string> fs;

и исходный файл для fooвыглядит так же, за исключением того, что инициализации удалены (поскольку конечно, foo теперь является абстрактным классом).

Но теперь есть ошибка компоновщика;foo<int>() не разрешено в конструкторе foobar<int>.Это исправлено перемещением конструктора и деструктора foo обратно в файл заголовка из исходного файла.

Итак, мой вопрос: как мы можем создать абстрактные базовые классы шаблона и сохранить определение класса шаблона скрытым в исходном файле ??

Ответы [ 3 ]

2 голосов
/ 06 сентября 2010

Я предлагаю вам создать для этого дополнительный класс:

#include <string>

template<typename T_Foo>
struct FooCompilation
{
  void operator()()
  {
    T_Foo foo;
    typedef typename T_Foo::T T;
    T t;
    foo.do(t);
  }
};

template FooCompilation<Foo<int> >;
template FooCompilation<Foo<std::string> >;

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

1 голос
/ 06 сентября 2010

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

template<typename T> 
class foo 
{ 
   public: 
     foo();
     ~foo();
     void something(const T& t); 
}; 

template <typename T> 
foo<T>::foo() 
{ 
    // initiate 
} 

//destructor

template <typename T> 
void foo<T>::something(const T& t) 
{ 
    // Do something with t 
} 
template<typename T>
foo<T>::~foo() {
}

template class foo<int>;

Это создаст экземпляр foo для типа int, но вам не нужно возиться с переменными.*

1 голос
/ 06 сентября 2010

Вам также нужно создать экземпляр конструктора в foo.cpp:

template void foo<int>::foo(const int&);

Вам также нужно будет сделать это за foobar, чтобы он был пригоден для использования.

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