こんにちは、現役エンジニアの inno_tech です。
C++のクラステンプレート(class template)の使い方についてお困りでしょうか?今回は、クラステンプレートの使い方をサンプルコードを交えながら解説します。
C++ クラステンプレートとは?
クラステンプレートは、class内で使用するメンバー変数やメソッドの型をパラメータとして動的な変更を可能にする機能です。
クラステンプレートを使用しない場合、例えば2次元の座標を管理するclassは 引数がint型かdouble型かによって、それぞれ別のclassを用意する必要があります。
class Coordinate2D
{
public:
Coordinate2D(){};
~Coordinate2D(){};
/* setter */
void SetData(int x, int y){
x_ = x;
y_ = y;
}
/* method: データの表示 */
void PrintData(){
std::cout << "(x,y) = (" << x_ << "," << y_ << ")" << std::endl;
};
/* member */
int x_; // X座標
int y_; // Y座標
protected:
private:
};
一方、クラステンプレートを使えば、1つのclassを定義するだけでそれぞれの型を変更したインスタンスを生成できるようになります。
なお、似たような機能の関数テンプレート機能についてはこちらの記事でまとめています。
続いて、サンプルコードを交えて使い方を解説します。
サンプルコードを交えて解説
クラステンプレートの宣言
クラステンプレート機能を使うにはクラス定義の前にtemplate <typename [テンプレート型名]>
を付けます。
[テンプレート型名] の部分は自由に設定可能です。
それではサンプルコードです。[テンプレート型名]は Tとしました。先ほどと同じ、2次元の座標を管理するclassをクラステンプレートに書き換えてみます。
template <typename T>
class Coordinate2D
{
public:
Coordinate2D(){};
~Coordinate2D(){};
/* setter */
void SetData(T x, T y){
x_ = x;
y_ = y;
}
/* method: データの表示 */
void PrintData(){
std::cout << "(x,y) = (" << x_ << "," << y_ << ")" << std::endl;
};
/* member */
T x_; // X座標
T y_; // Y座標
protected:
private:
};
クラステンプレートからインスタンスを生成
クラステンプレートから特定の型をもつインスタンスを生成するには、クラス名の後ろに<使用したい型>を指定します。
つまり、class名<[使用したい型名]>(コンストラクタ引数)
という呼び出し方です。
それではサンプルコードです。int, double でそれぞれインスタンスを生成します。
void TestTemplateCls_001()
{
printf("** test1-A: int型を指定 **\n" );
Coordinate2D<int> coord_i;
coord_i.SetData(5.1, 10.1);
coord_i.PrintData();
printf("** test1-B: double型を指定 **\n" );
Coordinate2D<double> coord_d;
coord_d.SetData(5.1, 10.1);
coord_d.PrintData();
return;
}
結果は [テンプレート型名]は T が<>で指定した型に置き換わって処理されてます。
** test1-A: int型を指定 **
(x,y) = (5,10)
** test1-B: double型を指定 **
(x,y) = (5.1,10.1)
Coordinate2D coord_i;
はint型に置き換えられるので、(x,y) = (5.1, 10.1) が整数に切り捨てられ、(x,y) = (5,10)という結果になりました。一方、Coordinate2D coord_d;
は少数として処理されていることがわかります。
クラステンプレートに初期の型を宣言
クラステンプレートの場合、デフォルトの型名を指定することが可能です。
先ほどの例で、デフォルト型をintにする場合は、template <typename T=int>
のように指定します。
template <typename T>
class Coordinate2D
{
public:
Coordinate2D(){};
~Coordinate2D(){};
/* setter */
void SetData(T x, T y){
x_ = x;
y_ = y;
}
/* method: データの表示 */
void PrintData(){
std::cout << "(x,y) = (" << x_ << "," << y_ << ")" << std::endl;
};
/* member */
T x_; // X座標
T y_; // Y座標
protected:
private:
};
呼び出す側はテンプレート型を省略すればOKです。ただし、class名の後ろに<>
をつけないとコンパイルエラーとなります。
void TestTemplateCls_001()
{
printf("** test1-A: int型を指定 **\n" );
Coordinate2D<> coord_i;
coord_i.SetData(5.1, 10.1);
coord_i.PrintData();
//(x,y) = (5,10) となる
return;
}
クラステンプレートの特殊化
クラステンプレートで1つのクラス定義で様々な型に対応できることがわかりました。
一方で「ある型の場合の場合だけは処理を変えたい」というような場合はどうすればよいでしょうか?その答えは、「特殊化」というテクニックを使うことで実現ができます。
特殊化については、関数テンプレートの特殊化と同じようにできるので今回は説明を省略します。
まとめ
今回のまとめです。
- クラステンプレートにより型が違うだけのクラスは1つにまとめることができる。
- クラステンプレートでは型の初期値が指定可能。(関数テンプレートでは指定不可)
- クラステンプレートからインスタンスを生成するには
class名<[使用したい型名]>(コンストラクタ引数)
というように型を指定する。
ちなみに、Qiitaでもっとも検索されている書籍がこちらです。技術面で遅れていかないように知識を補充していきましょう。
話は変わりますが、プログラミングを習得したい, 仲間が欲しい人は、プログラミングスクールに通うのがおすすめです。
自己学習でかかるコストを考えると十分元が取れると思います。
少しでも興味があれば、まずは無料のオリエンテーションを受講し、自分に合うか試してみるのがよいでしょう。
まずは一歩行動して、将来の自分に楽をさせてあげましょう。
いかがだったでしょうか。
ほかにも役立つ情報が他のページにもあるかもしれません。
ご覧いただくかはあなた次第です!
この記事がイイねと思ったら、Twitterフォロー か にほんブログ村のどちらかしてくれたら嬉しいよ!
コメント / ご要望