2016-10-05 2 views
-2

Пожалуйста, обратите внимание на следующую программу C++:C Шаблоны ++ и ошибки компоновщика

#include <iostream> 
using namespace std; 

template <class T> class Array 
{ 
    T *pType; 
    int itsSize; 
public: 
    // template <class T> 
    friend ostream &operator<< (ostream &, Array<T> &); 
}; 

template <class T> 
ostream &operator<< (ostream &output, Array<T> &theArray) 
    { 
    return (output); 
    } 

ostream &operator<< (ostream &, Array<int> &); 


int main() 
{ 
    Array<int> theArray; 
    cout << theArray << endl; 
    return 0; 
} 

Приведенный выше код компилируется, но линкер выдает следующую ошибку:

неопределенный символ `оператор < < (Std :: ostream &, массив &)»

Я считаю, что я должен сказать компилятору экземпляр функции для оператора < <, но я не KNO w как это сделать.

Боб

+0

, который не зависит от шаблона. Вы объявляете функцию, но для нее нет определения. – user463035818

+0

Также подпись должна быть 'ostream & operator << (ostream &, const Array &);' –

ответ

1

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

Ваша линия

ostream &operator<< (ostream &, Array<int> &); 

фактически говорит компилятору, что у вас есть некоторые другие оператора для Array<int> так, что он не должен использовать шаблон для этого типа.

Итак, компоновщик ищет этот другой оператор, но, конечно, не находит.

Если вы просто удалите эту дополнительную декларацию, она должна работать намного лучше.

0

Декларация

ostream &operator<< (ostream &, Array<int> &); 

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

В пределах main() использование operator<<() разрешает объявленную функцию. Компилятору не нужно специализировать шаблон, чтобы найти совпадение. Однако, поскольку нет определения (то есть реализации) этой функции, соединение не выполняется.

Удалите эту декларацию, и вы должны найти, что ваш код компилируется и ссылки.

Кстати, операторы потокового вывода обычно не изменяют выводимый объект. Поэтому целесообразно изменить шаблонный ostream &operator<< (ostream &, Array<T> &) быть ostream &operator<< (ostream &, const Array<T> &)

Кроме того, так как шаблоны (как правило) должны быть определены в заголовочных файлах, и файлы заголовков включаются в нескольких исходных файлов, то лучше избегать using namespace std, и заменить ostream с std::ostream.

0

У вас возникли проблемы с вашим кодом, @BoPersson и @Perter указали на некоторые из них.
Но даже если вы измените то, что они предложили (Here is a live demo on ideone), и я тоже запустил его на VS VS 2015. Компиляторы все еще безумны.

Ideone говорит:

prog.cpp:10:55: warning: friend declaration 'std::ostream& operator&)' declares a non-template function [-Wnon-template-friend] 
    friend ostream &operator &); 
                ^
prog.cpp:10:55: note: (if this is not what you intended, make sure the function template has already been declared and add after the function name here) 
/home/FHMhT9/ccNwcxP0.o: In function `main': 
prog.cpp:(.text.startup+0x1b): undefined reference to `operator&)' 
collect2: error: ld returned 1 exit status

И VS дает довольно много же ошибки тоже.

Ideone сообщает мне, что объявление друга в классе объявляет функцию без шаблона.

Таким образом, изменить объявление в классе:

friend ostream &operator<< <T> (ostream &, Array<T> &); 
//      ^^^^^ 
// I added this <T> to tell the compiler that it is a template function. 

Но вам нужно определить функцию перед этим, разрезанная реализацию operator<<, а затем вставьте его перед классом. Но для этого вам понадобится передовая декларация класса. Итак, наконец, ваш код будет примерно таким:

И я изменил Array<T> & на const Array<T> &.

#include <iostream> 

template <typename T> 
class Array; 

template <class T> 
std::ostream &operator<< (std::ostream &output, const Array<T> &theArray) 
{ 
    output << "abc"; 
    return (output); 
} 

template <class T> class Array 
{ 
    T *pType; 
    int itsSize; 
public: 
    // template <class T> 
    friend std::ostream &operator<< <T> (std::ostream &, const Array<T> &); 
}; 

int main() 
{ 
    Array<int> theArray; 
    std::cout << theArray << std::endl; 
    return 0; 
} 

и this version now works.

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