CH15 Templates, Vector and Exception
本文為 2021-Fall 學期旁聽台大資管系孔令傑教授開授的 Programming Design 所記錄的課程筆記。課程內容程式碼可以參閱我的 Github repo: C++ Programming-Design-2021-Fall
Templates
Recall Warriors and wizards
class Character
{
protected:
static const int EXP_LV = 100;
string name;
int level;
int exp;
int power;
int knowledge;
int luck; // ...
};
在前一章節的範例中我們用 srtring name
作為key來搜尋或區別不同的object,但當有多個object的name attribute是相同的時候就會出問題,因此可能會想要把string name這個attribute改成 int id之類的來做為區別不同object的key。然而若我們把name的type改為int,或許我們某一天又會想要把它改回來成string,我們可能會考慮implement兩個不同版本的class,但這又路造成閱讀與維護上的麻煩。
Templates
從上面Character的範例中我們需要key
的data type
可供彈性選擇,在C++裡templates
就可以做到這件事,且不只可以應用在class也可以應用在function。
C++ class templates 要求我們在呼叫function或建立物件時傳入一個data-type argument
,如:
Warrior<string> w1("Alice", 10);
Wizzard<int> w2(16, 5);
Template declaration
Template的用意就是讓使用者可以一情況決定傳入或者要使用的member的data type
,因此data type對於template來說就像是一個變數,我們在宣告的時候會用到template
與typename
template<typename T>
class TheClassName
{
// T can be treated as a type inside the class definition block
};
當使用template來宣告class,它的成員變數也要一起改變寫法
template<typename T>
T TheClassName<T>::f(T t)
{
// t is a variable whose type is T
};
template<typename T>
void TheClassName<T>::f(int i)
{
//follow the rule even if T is not used
};
Template invocation
To instantiate an object, pass a type argument.
int main()
{
TheClassName<int> a;
TheClassName<double> b;
TheClassName<AnotherClassName> c;
};
exp:
#include <iostream>
using namespace std;
template<typename T>
void f(T t)
{
cout << t;
}
int main()
{
f<double>(1.2); // 1.2
f<int>(1.2); // 1
return 0;
}
// When we invoke f with f<double>, the function is
void f(double t)
{
cout << t;
}
// When we invoke f with f<int>, the function is
void f(int t)
{
cout << t;
}
We may also have multiple type parameters.
#include <iostream>
using namespace std;
template<typename A, typename B>
void g(A a, B b)
{
cout << a + b << endl;
}
int main()
{
g<double, int>(1.2, 1.7); // 2.2
return 0;
}
An example with classes
#include <iostream>
using namespace std;
template<typename T>
class C
{
public:
T f(T i);
};
template<typename T>
T C<T>::f(T i)
{
return i * 2;
}
int main()
{
C<int> c;
cout << c.f(10) << endl;
return 0;
}