简体   繁体   中英

Friend template function in C++

Currently doing some practice with templates on C++ and I have come to face some complications when using friend functions while overloading them. I'm getting the infamous unresolved external symbol error in both ofstream and istream. Any help towards to it would be really appreciate.

.H FILE

#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;
}

ERRORS:

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> &)" (?>>@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@1@AAV21@AAV?$Triangle@N@@@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 &)" (?<<@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@ABV?$Triangle@N@@@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)" (??1?$Triangle@N@@QAE@XZ) 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)" (??0?$Triangle@N@@QAE@XZ) referenced in function _main  C:\Users\Silvestrini\Dropbox\CECS 3212\Week 3\HomeWork\Week 3\Triangle ADT\driver.obj   Triangle ADT

With most compilers, it is necessary by default for the definition of templates to be in the header file that declares them. That's because the compiler needs complete visibility of the template definition in every compilation unit that instantiates the template.

In short, add the contents of your .cpp file to the end of the .h file, and exclude the .cpp file from the build (don't compile it, or link in the corresponding object file).

Note: depending on your compiler, there are alternatives but, if you can't get your code working in the way I've described, you will struggle even harder to use those alternatives.

It doesn't help that there is no #include <iostream> in any of the code you have shown. That header is sort of necessary to use to std::istream and std::ostream types.

And never employ using namespace std; in a header file (which mean in anything related to your template declarations) because, in certain circumstances, doing that causes ambiguity in ways that are difficult to fix - use full names of std::istream and std::ostream .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM