2015-03-26 2 views
0

В настоящее время вы практикуете шаблоны на C++, и я столкнулся с некоторыми осложнениями при использовании функций друзей при их перегрузке. Я получаю печально известную нерешенную ошибку внешнего символа как в потоке, так и в istream. Любая помощь в этом была бы действительно оценена.Функция шаблона друга в C++

файл .h

#pragma once 
#include "TriangleInterface.h" 

template <class type> 
class Triangle : public TriangleInterface<type> { 

private: 
    const int SIZE = 3; 

    type height; 
    type base; 
    type length; 

    vector<type> angles; 


public: 

    Triangle(); 
    Triangle(type aHeight, type aLength, type aBase, type firstAngle, type secondAngle, type thirdAngle); 

    ~Triangle(); 

    void setHeight(type aHeight); 
    void setBase(type aBase); 
    void setLength(type aLength); 
    void setAngles(vector<type> &theAngles); 

    type getHeight(); 
    type getBase(); 
    type getLength(); 
    type getArea(); 


    void determineType(); 

    friend ostream & operator << <>(ostream &out, const Triangle &aTriangle); 

    friend istream &operator >> <>(istream &in, Triangle &aTriangle); 

}; 

.cpp FILE

#include "Triangle.h" 
using namespace std; 


template<class type> 
Triangle<type>::Triangle() { 

    height = 0; 
    length = 0; 
    base = 0; 

    angles.assign(60); 




} 

template<class type> 
Triangle<type>::Triangle(type aHeight, type aLength, type aBase, type firstAngle, type secondAngle, type thirdAngle) { 

    angles.push_back(firstAngle); 
    angles.push_back(secondAngle); 
    angles.push_back(thirdAngle); 

    height = aHeight; 
    length = aLength; 
    base = aBase; 


} 
template<class type> 
Triangle<type>::~Triangle() {}; 


template <class type> 
void Triangle<type>::setBase(type aBase) { 

    this->base = aBase; 
} 

template <class type> 
void Triangle<type>::setHeight(type aHeight) { 

    this->height = aHeight; 
} 

template <class type> 
void Triangle<type>::setLength(type aLength) { 


    this->length = aLength; 
} 

template <class type> 
void Triangle<type>::setAngles(vector<type> &theAngles) { 

    this->angles = theAngles; 
} 

template<class type> 
type Triangle<type>::getBase() { 
    return this->base; 
} 

template<class type> 
type Triangle<type>::getHeight() { 
    return this->height; 
} 

template<class type> 
type Triangle<type>::getLength() { 
    return this->length; 
} 

template <class type> 
type Triangle<type>::getArea() { 


    return (this->(base * height)/2); 
} 


template<class type> 
void Triangle<type>::determineType() { 

    if (base == length && length == height && angles[0] == angles[1] && angles[1] == angles[2]) 
     cout << "This is an equilateral triangle.\n"; 
    else if (base == length || base == height || length == height && angles[0] == angles[1] || angles[1] == angles[2] || angles[0] == angles[2]) 
     cout << "This is an Isosceles Triangle.\n"; 
    else 
     cout << "This is a Scalene Triangle.\n"; 

} 

template<class type> 
ostream &operator << (ostream &out, const Triangle<type> &aTriangle) { 

    out << endl; 
    out << "The height of your triangle is " << aTriangle.getHeight() << endl; 
    out << "The base of your triangle is " << aTriangle.getBase() << endl; 
    out << "The length of your triangle is " << aTriangle.getLength() << endl; 
    out << endl; 

    out << "The Area of your triangle is " << aTriangle.getArea() << endl; 
    out << aTriangle.determineType() << endl; 

    for (int i = 0; i < SIZE; i++) { 
     out << "Angle #" << i << " : " << angles[i] << endl; 
    } 

    return out; 
} 

template<class type> 
istream &operator >> (istream &in, Triangle<type> &aTriangle) { 

    cout << "Enter the height: "; 
    in >> aTriangle.height; 

    cout << "Enter the length: "; 
    in >> aTriangle.length; 

    cout << "Enter the base: "; 
    in >> aTriangle.base; 

    cout << "Enter the angles: " << endl; 
    for (int i = 0; i < SIZE; i++) { 
     cout << "Angle #" << i << " : "; 
     in >> angles[i]; 
    } 
    return in; 
} 

ОШИБКИ:

Error 5 error LNK1120: 4 unresolved externals C:\Users\Silvestrini\Dropbox\CECS 3212\Week 3\HomeWork\Week 3\Debug\Triangle ADT.exe 1 1 Triangle ADT 
Error 4 error LNK2019: unresolved external symbol "class std::basic_istream<char,struct std::char_traits<char> > & __cdecl std::>>(class std::basic_istream<char,struct std::char_traits<char> > &,class Triangle<double> &)" (?>>@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@[email protected]@@@Z) referenced in function _main C:\Users\Silvestrini\Dropbox\CECS 3212\Week 3\HomeWork\Week 3\Triangle ADT\driver.obj Triangle ADT 
Error 3 error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl std::<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Triangle<double> const &)" (?<<@[email protected]@[email protected][email protected]@[email protected]@@[email protected]@[email protected]@@@Z) referenced in function _main C:\Users\Silvestrini\Dropbox\CECS 3212\Week 3\HomeWork\Week 3\Triangle ADT\driver.obj Triangle ADT 
Error 2 error LNK2019: unresolved external symbol "public: __thiscall Triangle<double>::~Triangle<double>(void)" ([email protected]@@[email protected]) referenced in function _main C:\Users\Silvestrini\Dropbox\CECS 3212\Week 3\HomeWork\Week 3\Triangle ADT\driver.obj Triangle ADT 
Error 1 error LNK2019: unresolved external symbol "public: __thiscall Triangle<double>::Triangle<double>(void)" ([email protected]@@[email protected]) referenced in function _main C:\Users\Silvestrini\Dropbox\CECS 3212\Week 3\HomeWork\Week 3\Triangle ADT\driver.obj Triangle ADT 
+1

Знаете ли вы, почему шаблоны могут быть реализованы только в файле заголовка] (http://stackoverflow.com/q/495021/1782465)? – Angew

+0

Может возникнуть проблема с размещением определений в файле .cpp. Дело в шаблонах заключается в том, что определение должно быть доступно при встрече с шаблоном. Если вы решите разделить шаблонные функции через .h и .cpp-файл, вам может быть излишне заставлять себя затем явно создавать шаблоны в файле .cpp как «шаблон ostream & operator >> (istream & in, Triangle & aTriangle) ; 'и т. д. – AndyG

+0

Один очень важный комментарий:' 'thestream & operator >> ...' предназначен только для чтения данных объекта из потока ввода - не для подсказки - вы не должны 'cout << ...' в нем. Если вам нужна такая функция - напишите ее - но не назовите ее 'operator >>' ... – PiotrNycz

ответ

1

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

Вкратце, добавьте содержимое вашего .cpp-файла в конец .h-файла и исключите файл .cpp из сборки (не компилируйте его или не свяжите в соответствующем объектном файле).

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

Это не поможет, что нет #include <iostream> в любом коде, который вы указали. Этот заголовок является необходимым для использования с std::istream и std::ostream типами.

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

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