模板类在包含友元情况下的分离编写

此案例为模板类的分离编译,以及类中包含友元的情况是出现的错误及改正措施。

#include<iostream>
#include<string>
using namespace std;

template<class T>
class Person
{
public:
    //template<class T>
    friend ostream& operator<< <T>(ostream &os, Person<T>& p);

    //template<class T>
    friend void PrintPerson(Person<T>& p);
    Person(T age, T ID);
    void Show();
private:
    T mAge;
    T mID;
};

template<class T>
Person<T>::Person(T age, T ID)
{
    this->mAge = age;
    this->mID = ID;
}

template<class T>
void Person<T>::Show()
{
    cout << "age:" << mAge << "  ID:" << mID << endl;
}


//"<<"操作符重载
template<class T>
ostream& operator<<(ostream &os, Person<T>& p)
{
    os<< "age:" << p.mAge << "  ID:" << p.mID ;
    return os;
}

//普通友元函数
template<class T>
void PrintPerson(Person<T>& p)
{
    cout << "age:" << p.mAge << "  ID:" << p.mID << endl;

}

void test01()
{
    Person<int> p(12, 12121200);
    cout << p << endl;
    cout << "-----------------------------" << endl;
    PrintPerson(p);
}

int main()
{
    test01();
    return 0;
}

此时无法通过编译:显示以下错误:

严重性    代码    说明    项目    文件    行
错误    LNK1120    1 个无法解析的外部命令    类模板外部实现    D:\Documents\Visual Studio 2015\Projects\C++STL-Test\Debug\类模板外部实现.exe    1
严重性    代码    说明    项目    文件    行
错误    LNK2019    无法解析的外部符号 "void __cdecl PrintPerson(class Person<int> &)" (?PrintPerson@@YAXAAV?$Person@H@@@Z),该符号在函数 "void __cdecl test01(void)" (?test01@@YAXXZ) 中被引用    类模板外部实现    D:\Documents\Visual Studio 2015\Projects\C++STL-Test\类模板外部实现\mian.obj    1

解决方案为:在文件开始处添加以下声明。

//官方解决方案:
template <class T> class Person;
template <class T> void PrintPerson(Person<T>& p);

也可在普通友元声明前增加模板声明,此方法可能在其他编译器无法通过编译,如在Linux中无法通过编译。

    //此方法无法在Linux下通过编译
    template<class T>
    friend void PrintPerson(Person<T>& p);

综上,在模板中不要滥用友元。

posted @ 2019-04-18 22:31  鲸小鱼-  阅读(262)  评论(0编辑  收藏  举报