2012-01-15 3 views
0

Я изучаю C++, и это не было приятным опытом (по крайней мере, по сравнению с Java или VBA). У меня есть следующий код:Шаблоны и .cpp-файлы

//This is in a number.h file 
    #pragma once 
    template <class T> 
    class number{ 
     public: 
       T value1, value2, result; 
     public: 
       T add(); 
       number(T value1_in, T value2_in); 
    }; 

//This is in a number.cpp file 
    template <class T> 
    number<T>::number(T value1_in, T value2_in){ 
       value1 = value1_in; 
       value2 = value2_in; 
    } 

    template <class T> 
    T number<T>::add(){ 
    result = value1 + value2; 
    return result; 
    } 

//This is in main.cpp 
    #include "number.h" 
    #include <iostream> 
    using namespace std; 

    int main(){ 
     int a = 2, b =3; 

     number<int> n1(a,b); 
     cout << n1.add(); 
     system("pause"); 
     return EXIT_SUCCESS; 
    } 

Это, конечно, дает мне ошибку. Хотя я уверен, что он должен работать. Более конкретно, я получаю ошибку компоновщика. После 3 часов рассмотрения этого я решил включить number.cpp в main.cpp, и это волшебным образом заставило его работать. Что, черт возьми, происходит? Я думал, что мне нужно включить заголовочный файл (я написал класс матрицы с группой линейных решателей для разных алгоритмов до этого и включал только заголовочные файлы во всем проекте). Является ли этот специфический или компилятор C++ конкретным? (Я использую Dev-C++ 4.9.9.2, у которого есть Mingw, я думаю)

+0

Дублировать вопрос. Существует два решения. См. [Этот ответ на другой вопрос] (http://stackoverflow.com/a/8752879/146041) –

+0

Возможный дубликат [Почему шаблоны могут быть реализованы только в файле заголовка?] (Http: // stackoverflow.com/questions/495021/why-can-templates-only-be-implement-in-the-header-file) –

ответ

3

У вас не необходимо поместить все определение в заголовочный файл; не слушайте то, что вам говорят другие :-)

Это обычное решение, и вы и я сделаем это довольно часто, но это не единственное решение.

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

template class number<int>; 

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

https://stackoverflow.com/a/8752879/146041

+1

Хотя это в значительной степени увеличивает количество шаблонов. –

+2

Недостатком вашего решения является то, что он ограничивает типы, с которыми может использоваться шаблонный класс. Я понимаю, что иногда это может быть желательно, но это не обычный случай. – buc

+1

Конечно, необычно писать шаблон, а затем потребовать его создания только для одного типа. Вид поражения цели в написании шаблона класса. Но да, вы можете это сделать. –

3

Шаблонные классы или функции всегда должны оставаться в файле заголовка.

Причина в том, что всякий раз, когда вы создаете экземпляр шаблона, препроцессор (внутри компилятора) генерирует новый код для такого типа экземпляра (например, number<double>). Вот почему классы number<double> и number<int> не будут делиться никакими отношениями: они будут двумя совершенно разными классами, хотя оба они были созданы из одного и того же шаблона.

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

Включая файл cpp в ваш main.cpp, сделал трюк, так как он фактически стал заголовком.

+0

Не этот шаблон уже находится в файле заголовка? Или факт, что он объявлен как в number.h, так и number.cpp каким-то образом смущает компилятор? Какие варианты у меня есть для исправления этого, включая include.cpp в main? – YsK

+0

Вы должны включить (not #include) содержимое number.cpp в number.h, и вы #include только заголовок. – buc

+0

И не компилируйте number.cpp –

2

В C++ шаблоны так же, как их называют: шаблоны для класса, функции и т. Д. Поскольку конкретный тип параметра шаблона неизвестен заранее, а скомпилированный объектный код зависит от фактического параметра, они не компилироваться (как обычные классы и функции), пока вы не будете использовать их в любом другом исходном файле, а компилятор узнает, какой тип следует заменить в параметре шаблона.

Вот почему все функции должны быть определены и реализованы в файле заголовка. См. Последний раздел от this documentation или ответы для this similar question для более подробного объяснения.

+0

* Не обязательно добавлять реализацию в заголовок. Существует еще одно действующее решение, которое я использовал несколько раз. См. Http://stackoverflow.com/a/8752879/146041 –

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