笔者这几天在熟悉vs2015工具编辑c++,(从前用的都是vc++6.0)。发现还真是不容易使用,简单的一个小程序会报错一大堆你看不懂的问题。现将我发现的重要的一个问题呈现给大家。
在使用类模板设计对象时,通常会使用友元函数提供对该类的内部私有成员数据访问,请看下面这段代码,定义了一个顺序表的基本运算
1 template <typename T> 2 class SqListClass { //顺序表类模板 3 T * data; //存放顺序表中的元素 4 int length; //存放顺序表的长度 5 public: 6 SqListClass(); //构造初始化,分配存储空间,初始化表长度为0 7 ~SqListClass(); //析构函数,释放分配空间 8 void CreateList(T a[], int n); //用给定的数组元素创建顺序表 9 void DispList(); // 输出顺序表所有元素 10 int ListLength(); //获取顺序表长度 11 bool GetElem(int i, T &e); //求顺序表中某序号的元素值 12 int LocateElem(T e); //按元素值查找序号 13 bool ListInsert(int i, T e); //插入数据元素 14 bool ListDelete(int i); //删除数据元素 15 16 //其他函数算法实现 17 //template <typename T> 18 friend void Reserve(SqListClass<T> & L); //将顺序表元素逆置 例L={1,2,3,4}变为L={4,3,2,1} 19 // template <typename T> 20 friend bool DeleteElem(SqListClass<T> & L,T e); //删除指定元素值 21 // template <typename T> 22 friend void Merge2(SqListClass<T> & L1, SqListClass<T> & L2, SqListClass<T> &L3); //二路归并算法 23 };
具体实现不列出来了,然后我在主函数中是这样调用的
1 #include<iostream> 2 #include "SqListClass.cpp" 3 using namespace std; 4 int main() 5 { 6 SqListClass<int> s1, s2; 7 int a[4] = { 1,2,3,4 }; 8 s1.CreateList(a, 4); 9 10 int b[3] = { 5,7,9 }; 11 s2.CreateList(b, 3); 12 13 SqListClass<int> s3; 14 Merge2(s1, s2, s3); 15 s3.DispList(); 16 }
在编译时会报错如下
解决方法:在定义模板类和模板函数时候,必须加上template <typename T>这一行语句
即:
①当定义模板类时,在类定义头文件(*.h)可以这样写
template <typename T>
class A{
//类体
};
在类实现(*.cpp)里面,每一个成员函数都要这样写
template <typename T>
返回值 A<T>::函数名(形参列表){
//函数体
}
②在模板类中要定义友元函数不免也是要定义模板函数的
此时需要注意,(*.h)头文件中模板友元函数的定义应该是
template <typename T>
friend 返回值 函数名(形参表);
(*.cpp)文件中模板友元类实现如下:
template <typename T>
返回值 函数名(形参表)
{
//函数体
}
这样就不会报错2019了。问题解决
同理,在设计模板友元类B时,不管是提前声明友元类B,还是在类A中定义友元模板类B,还是定义模板友元类B都不要忘记加上
template <typename T>
链接微软提供的报错2019 解决方法https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ZH-CN&k=k(LNK2019)&rd=true