2014年2月25日火曜日

C++ テンプレート関数




テンプレート関数の機能は

複数の型に対応した関数を

つくれることです(^^)






テンプレート関数とは、引数や戻り値の型が曖昧な状態の関数です。

そのためコンパイラが、テンプレート関数の呼び出し方を判断して、

具体的な関数に置き換えて処理するのです(*^^)v 賢い!

template<class T>
T GetMaxValue(T num1, T num2)
{
    T temp;

    if (num1 > num2) temp = num1;
    else temp = num2;

    return temp;
}

この class T とか書いてあるところが、テンプレート引数というものです。

別に T である必要はありませんが、分かりやすいし無難に倣っておくのが

良いのではないかと... テンプレートのTということで。(^^;)

仮の型名なので、関数を使用するときに int や double に置き換わります。

ここでは、関数の引数と戻り値に使っています。

関数の呼び出し方法は、特に変わった点はなく

普通に呼び出すだけで使えます(^^)

では、サンプルプログラムで見てみましょう。

include <stdio.h>
#include <iostream>

using namespace std;

// 与えられた引数のうち大きいほうの値を返します
template<class T>
T GetMaxValue(T num1, T num2)
{
    T temp;

    if (num1 > num2) temp = num1;
    else temp = num2;

    return temp;
}

int main(void)
{
    int a = 10;
    int b = 15;
    double c = 3.14;
    double d = 1.23;

    printf("a : %d, b : %d\n", a, b);
    int ans = GetMaxValue(a, b);  //int型を指定した呼び出し
    printf("ans : %d\n", ans);

    cout << "c : " << c << ", d : " << d << endl;
    double ans2 = GetMaxValue(c, d); //double型を指定した呼び出し
    cout << "ans2 : " << ans2 << endl;

    return 0;
}

実行結果
# ./test
a : 10, b : 15
ans : 15
c : 3.14, d : 1.23
ans2 : 3.14

Cでは、int型用、double型用などと2つの関数を

用意しなければなりませんでしたが、

このように一つにまとめることができました。

さすが、C++ 

インクリメントされてるので、ちゃんと進んでるのがわかりますね(^^;)


今日の名言
取り越し苦労をして先のことばかりに目を向け、まだ嵐がやってこない
うちから気をもんで、どうやって防ごうかとうろたえるようでは、神に対する
信頼を失ってしまう。まだこれからどうなるかわからないのに、打つ手や
失敗した時のことまで考えて、わが身を地獄に陥れるとき、我々は
恐怖心を追放してくれるあの「完全な愛」(神)から、完全に見放されて
いるのだ。
                         ヘンリー・ウォード・ビーチャー

まず確かな事実を手元に集めることだ。公平な目でありとあらゆる
事実を集めないうちには、問題に手も触れないことにしよう。
                         デール・カーネギー

ついに起こらなかった害悪のために、我々はいかに多くの時間を
費やしたことか!
                         トーマス・ジェファーソン

2014年2月11日火曜日

C++ 上級編の話



長い間続いた基礎編のネタが終了し、

ついに上級編の部類に突入しました。

では、さっそく見ていきましょう(^^)




テンプレート関数

テンプレートとは、ワープロやデザインなどで使われるフォーマットやデータのことです。

日本語で言うところのひな型、型紙というやつですね。

C++では、テンプレート関数という便利な機能があります。

これは呼び出し側で指定した引数の型に合わせて、関数内で使用する変数の値を

変えることができるというものです。

凄いところは、同じことを C でやろうとすると、引数の型が違うだけの別の関数を

用意する必要がありました。 安直にHogeFunc2() のように...(-_-;)

あとはちょっと気の利いた対応方法として、#define マクロを使う方法があります。

しかし、 #define だと一行で記述しなければならないので、複数行に亘る場合

\ 記号を使って行を連結する必要があります。

これだと分かりにくいし、何より \ 記号を付けるのが面倒でしょうがないデス(>_<)

#define SwapNum(T, a, b) \
        { T tmp = a; \
          a = b;       \
          b = tmp; }

int main(void)
{
    int a = 10;
    int b = 15;

    printf("a : %d, b : %d\n", a, b);
    SwapNum(int, a, b);
    printf("a : %d, b : %d\n", a, b);

    return 0;
}

C++では、テンプレート関数の機能を使えば、複数の型に対応した

関数を記述できるようになります。

#define マクロを使わない方法もあるということを押さえておきたいところです。


演算子のオーバーロード

C++にも足し算のときの + 、掛け算やポインタで使う * 、代入のときの = など

たくさんの演算子があります。

int 型やchar 型という普通の変数の型に対し、何かこれらの演算を行った場合

行われる処理は既に決まっています。

例えば int 型の2つの変数 a, b に対して + 演算子を使うと、2つの値を

足し算する筈...、ですよね(^^)

しかし、オブジェクトに対して同じことをしようと思った場合、

そのまま使うことはできません(^_^;)

もし使いたい場合は演算子をオーバーロードする必要があります。

演算子をオーバーロードすると、既にある演算子に独自の働きを

持たせることができるようになります。 

便利な使い方の例としては、+演算子のオーバーロードで

時間を表現する2つのオブジェクトを足すと

繰り上げ計算を行った上で、合計時間を求める、とか

= 演算子をオーバーロードして、

オブジェクト同士の代入が行われると、

動的に確保したメモリも含めまるっとコピーする

などがあります(^_^;)

少々難しい内容ですが、こちらもぜひ押さえておきたいところです。

今日の名言
みじめな気持になる秘訣は、自分が幸福であるか否かについて
考えるひまを持つことだ。
                         ジョージ・バーナード・ショー

じぶんがいまかかっている病気を我慢する方が、決してかからない
かもしれない病気について思い悩むより利口である。
                         ラ・ロシュフコー

現在の重荷に耐えきれない人間はいない。現在の重荷に過去の
重荷が加わるから、耐えられなくなるのだ。
                         ジョージ・マクドナルド

有名な法律についての金言を掲げよう。「法律は小事に関与せず」
悩みから逃れて、心の安らぎを求めるならば、小事にこだわっては
ならない。
                         デール・カーネギー

困難を予期するな。決して起こらないかもしれぬことに心を
悩ますな。常に心に太陽を持て。
                         ベンジャミン・フランクリン