类模板和类模板里面声明的函数的实现写在不同的文件里面,分别写在.h和.cpp文件中

一般来说,如果将声明类模板的.h文件、实现类模板函数的.cpp文件、以及主函数所在的.cpp文件写在3个文件里,则主函数所在的.cpp问价需要包含类模板实现的.cpp文件,而不能像普通的函数那样包含.h文件。这时因为C++对类模板的编译是二次编译,主函数所在.cpp只包含类模板的.h文件的话,主函数体里面是无法找到类模板的函数体实现的。

例如:

//1.mytest.h文件

#ifndef MYTEST_H
#define MYTEST_H

#include <iostream>

using namespace std;

template <typename T>
class Complex
{
    //注意,友元函数在类模板的类体里面声明的时候,在函数的名字和函数参数类型之间加了一个<T>,若不加这个<T>,则编译通不过!
    friend ostream& operator<<<T>(ostream& out,Complex& c);
    
public:
    Complex(T,T);//构造函数
    Complex operator+(Complex& );//重载“+”操作符
    Complex operator-(Complex& );//重载“-”操作符
    void printCom();//普通函数
    
private:
    T a;
    T b;
};

#endif



//2.mytest.cpp文件
#include <iostream>
#include "mytest.h"
using namespace std;


//注意友元函数在类体里面的声明的写法!
template <typename T>
ostream& operator<<(ostream& out,Complex<T>& c)
{
    out<<c.a<<"+"<<c.b<<"i";
    return out;
}

template <typename T>
Complex<T>::Complex(T a,T b)
{
    this->a=a;
    this->b=b;
}

template <typename T>
Complex<T> Complex<T>::operator+(Complex<T>& c)
{
    Complex<T> temp(this->a+c.a,this->b+c.b);
    return temp;
}

template <typename T>
Complex<T> Complex<T>::operator-(Complex<T>& c)
{
    Complex<T> temp(this->a-c.a,this->b-c.b);
    return temp;
}

template <typename T>
void Complex<T>::printCom()
{
    cout<<this->a<<"+"<<this->b<<"i"<<endl;
}



//3.main.cpp文件
#include <iostream>
#include "mytest.cpp"

using namespace std;

int main()
{
    Complex<float> c1(1.2,2.5),c2(3.2,5.3);

    cout<<c1+c2<<endl;

    return 0;
}

一般来说,都会把类模板的声明和实现放在一个.h文件里面,然后直接扔给别人一个.h文件,这样一般不会出现编译错误。

原文地址:https://www.cnblogs.com/jswu-ustc/p/8516675.html