2010-06-28 2 views
3

Уважаемый всех, я застрял в этой проблеме сейчас несколько дней, и мои поиски не увенчались успехом.Понимание классов шаблонов в C++ - проблема с новым оператором

Что я пытаюсь сделать: Я хочу, чтобы класс читателя шаблона (VariableReader) обрабатывал различные типы переменных (обычно без знака int и указатели на вектор).

Я начал с

#ifndef READER_H_ 
#define READER_H_ 
#include <string> 

namespace BAT { 
template <typename variableType = unsigned int> 
class VariableReader { 
public: 
VariableReader<variableType>(); 
VariableReader<variableType>(std::string varName); 
virtual ~VariableReader<variableType>(); 
std::string getVariableName(); 
void setVariableName(std::string varName); 
bool isValidVariableName(std::string varName); 
variableType getVariable(); 
private: 
std::string variableName; 
variableType variable; 

}; 

} 

#endif 

и

#include "../../interface/Readers/VariableReader.h" 

namespace BAT { 

template<typename variableType> 
VariableReader<variableType>::VariableReader() : 
variableName("") { 
// TODO Auto-generated constructor stub 
} 

template <typename variableType> 
VariableReader<variableType>::VariableReader(std::string varName) : 
variableName(varName) { 

} 

template <typename variableType> 
std::string VariableReader<variableType>::getVariableName() { 
return variableName; 
} 

template <typename variableType> 
void VariableReader<variableType>::setVariableName(std::string varName) { 
if (VariableReader::isValidVariableName(varName)) { 
    variableName = varName; 
} 
} 

template <typename variableType> 
bool VariableReader<variableType>::isValidVariableName(std::string varName) { 
return varName != ""; 
} 

template <typename variableType> 
VariableReader<variableType>::~VariableReader() { 
// TODO Auto-generated destructor stub 
} 

} 

Однако, несмотря на это, кажется, компилировать я не могу использовать его в других проектах. EDIT: забыл опубликовать тест-код:

#include "cute.h" 
#include "ide_listener.h" 
#include "cute_runner.h" 

#include "Readers/VariableReader.h" 
using namespace BAT; 

static VariableReader<int> *reader; 

void setUp(){ 
reader = new VariableReader<int>::VariableReader();//this is problem-line 
} 

void thisIsATest() { 
    ASSERTM("start writing tests", false); 
} 

void runSuite(){ 
    cute::suite s; 
    //TODO add your test here 
    s.push_back(CUTE(thisIsATest)); 
    cute::ide_listener lis; 
    cute::makeRunner(lis)(s, "The Suite"); 
} 

int main(){ 
    runSuite(); 
} 

Я получаю следующее сообщение об ошибке:

Building target: BAT_Tests 
Invoking: GCC C++ Linker 
g++ -L"/workspace/BAT/Debug Gcov" -fprofile-arcs -ftest-coverage -std=c99 -o"BAT_Tests" ./src/Test.o -lBAT 
./src/Test.o: In function `setUp()': 
/workspace/BAT_Tests/Debug Gcov/../src/Test.cpp:13: undefined reference to `BAT::VariableReader<int>::VariableReader()' 
collect2: ld returned 1 exit status 
make: *** [BAT_Tests] Error 1 

Как я понимаю, что линкер пытается найти конструктор для VariableReader, который явно не определено, так как Я хочу иметь только общий конструктор.

Пожалуйста, помогите мне понять, чего у меня нет.

+0

Почему вы вызываете конструктор явно? 'reader = new VariableReader ();' должно быть достаточно – DaClown

+0

Это дает мне такую ​​же проблему компоновщика, что и раньше. – DragonTux

ответ

6

раздел C++ FAQ Lite на How can I avoid linker errors with my template functions? показывает два решения:

  1. Move методов класса шаблона в .h файла (или файла, включаемого в файл .h).
  2. Создайте шаблон в файле .cpp, используя template VariableReader<unsigned int>;.
+0

Спасибо за ссылку, это помогло мне понять немного больше. Я создал экземпляр шаблона в файле C++. Однако это кажется мне недостатком концепции шаблона. Почему я должен определять шаблон для каждого типа? В любом случае, это работает сейчас, я попробую № 1 позже. Thx – DragonTux

+0

@ Golden: вы правы, это недостаток шаблонов. Создавая только заголовок, вы избегаете явно указывать, с какими типами он работает, за счет вытягивания большего количества кода везде, где используется ваш класс. 99% времени, тем не менее, это более полезный выбор. –

3

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

+0

Обычно это означает, что вам нужна реализация в файле заголовка. – DanDan

+0

Чтобы удалить аргументы шаблона из c'tor и d'tor, сработанные для компиляции, но не для связи. Мне еще нужно поставить template VariableReader :: VariableReader(); в файле .cpp. Кажется, что нет ничего подобного шаблону, как хотелось бы. В принципе, я хотел, чтобы класс, который принимает шаблон для создания отдельной переменной: VariableReader * intReader = new VariableReader(); VariableReader <вектор *> * floatReader = new VariableReader(); int var = intReader-> getVariable(); vector * var2 = intReader-> getVariable(); – DragonTux

Смежные вопросы