C ++中的朋友模板功能

时间:2015-03-26 12:41:01

标签: c++

目前正在使用C ++模板进行一些练习,在重载时使用友元函数时遇到了一些复杂问题。我在流和istream中都得到了臭名昭着的未解决的外部符号错误。任何对它的帮助都会非常感激。

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

错误:

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

1 个答案:

答案 0 :(得分:1)

对于大多数编译器,默认情况下,模板的定义必须位于声明它们的头文件中。这是因为编译器需要在实例化模板的每个编译单元中完全可见模板定义。

简而言之,将.cpp文件的内容添加到.h文件的末尾,并从构建中排除.cpp文件(不要编译它,或链接到相应的目标文件中)。

注意:根据您的编译器,还有其他选择,但如果您无法按照我所描述的方式运行代码,那么您将更难以使用这些替代方案。

在您显示的任何代码中都没有#include <iostream>没有帮助。该标头对于std::istreamstd::ostream类型而言非常必要。

并且永远不会在头文件中使用using namespace std;(这意味着与模板声明相关的任何内容),因为在某些情况下,这样做会导致难以修复的方式模糊 - 使用{{的全名1}}和std::istream