.h
#ifndef QUEUE_H
#define QUEUE_H
#include<iostream>
template<class T>
class FQueue
{
private:
T fq[10];
public:
\
FQueue(int qs ); //給參數提供默認值
~FQueue();
bool isempty() const;
bool isfull() const;
int queuecount() const;
bool inqueue(const T &item);
bool dequeue(const T &item);
};
void show(); //普通函數這樣是沒有問題的
//下面這個是原型在這h.定義在cpp中
template<class T> void shimobanhwai(T a);
//下面這樣是對的,都放在.h文件中
template<class T> void shimobanhnei(T a)
{
std::cout << "a is " << a << std::endl;
}
#endif // QUEUE_H
.cpp
#include"queue.h"
#include<iostream>
using namespace std;
template<class T>
FQueue<T>::FQueue(int qs) //這樣也不行,必須放在.h中,否則當建立對象時還是會出現未定義
{
T* fqp = new T[qs];
}
template<class T>
FQueue<T>::~FQueue() //class名字後面別忘了加<T>,這是我經常忘的
{}
template<class T>
bool FQueue<T>::isempty() const
{}
template<class T>
bool FQueue<T>::isfull() const
{}
template<class T>
int FQueue<T>::queuecount() const
{}
template<class T>
bool FQueue<T>::inqueue(const T &item)
{}
template<class T>
bool FQueue<T>::dequeue(const T &item)
{}
void show()
{
cout << "Am i right?" << endl;
}
template<class T>
void shimobanhwai(T a)
{
cout << "a is " << a << endl;
}
Main.cpp
#include <iostream>
#include"queue.h"
using namespace std;
//模板函數、模板類
//新發現,模板不能分.h.cpp
int main()
{
shimobanhnei(5);
//shimobanhwai(5);//出錯
show();
// why(3);
cout << " bye!" << endl;
cin.clear(); //清楚標誌位
while (cin.get() != '\n')
continue; //清楚輸入流數據
return 0;
}
stackoverflow上我覺得比較經典的解釋
Q:
Why can templates only be implemented in the header file?
Because when instantiating a template, the compiler creates a new class with the given template argument. For example:
template<typename T>
struct Foo
{
T bar;
void doSomething(T param) {/* do stuff using T */}
};
// somewhere in a .cpp
Foo<int> f;
When reading this line, the compiler will create a new class (let's call it FooInt
),
which is equivalent to the following:
struct FooInt
{
int bar;
void doSomething(int param) {/* do stuff using int */}
}
Consequently, the compiler needs to have access to the implementation of the methods, to instantiate them with the template argument (in this case int
).
If these implementations were not in the header, they wouldn't be accessible, and therefore the compiler wouldn't be able to instantiate the template.
A common solution to this is to write the template declaration in a header file, then implement the class in an implementation file (for example .tpp), and include this implementation file at the end of the header.
// Foo.h
template <typename T>
struct Foo
{
void doSomething(T param);
};
#include "Foo.tpp"
// Foo.tpp
template <typename T>
void Foo<T>::doSomething(T param)
{
//implementation
}
This way, implementation is still separated from declaration, but is accessible to the compiler.
Another solution is to keep the implementation separated, and explicitly instantiate all the template instances you'll need:
// Foo.h
// no implementation
template <typename T> struct Foo { ... };
//----------------------------------------
// Foo.cpp
// implementation of Foo's methods
// explicit instantiations
template class Foo<int>;
template class Foo<float>;
// You will only be able to use Foo with int or float
If my explanation isn't clear enough, you can have a look at the C++ FaqLite on this subject.