#pragma twice

KAB-studio > プログラミング > #pragma twice > 351 Version 16.24 デフォルト値vsオーバーロード

#pragma twice 351 Version 16.24 デフォルト値vsオーバーロード

前のページへ 表紙・目次へ 次のページへ

 Version 16.24
デフォルト値vsオーバーロード

前回はデフォルト値について説明しました
引数にデフォルトの値を渡せるってゆーことだったね
で、実はこのデフォルト値と同じことが、オーバーロードでもできるんで

オーバーロードでも……あれ? もしかしてそれって引数省略するってだ
けのこと?
そういうこと。前回の UseDefault() 関数をオーバーロードで実現すると
以下のようになります

// Data.h

// デフォルト値ではなくオーバーロードで実現します。
// void UseDefault( int p_i1, int p_i2 = 100 );
void UseDefault( int p_i1, int p_i2 );
void UseDefault( int p_i1 );


// Main.cpp
#include <Windows.h>
#include <stdio.h>

#include "Data.h"

/*
void UseDefault( int p_i1, int p_i2 )
{
    // 配列の方を出力します。
    char pch[256];
    sprintf( pch, "%d, %d\n", p_i1, p_i2 );
    OutputDebugString( pch );
    // 100, 101
}
*/

// デフォルト値ではなくオーバーロードで実現します。
void UseDefault( int p_i1, int p_i2 )
{
    // 配列の方を出力します。
    char pch[256];
    sprintf( pch, "%d, %d\n", p_i1, p_i2 );
    OutputDebugString( pch );
    // 100, 101
}

void UseDefault( int p_i1 )
{
    // 第2引数にはデフォルト値を渡します。
    UseDefault( p_i1, 100 );
}

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    // デフォルト値を使用します。
    UseDefault( 100 );
    // 100, 100

    // デフォルト値を使用しません。
    UseDefault( 200, 300 );
    // 200, 300

    return 0;
}

まず、引数が1つの関数と2つの関数の両方作ります

void UseDefault( int p_i1, int p_i2 );
void UseDefault( int p_i1 );

これでオーバーロードできました。引数2つの方は前回の実装と同じ、引数
1つの方は引数2つの方にデフォルト値を渡して呼び出します

void UseDefault( int p_i1 )
{
    // 第2引数にはデフォルト値を渡します。
    UseDefault( p_i1, 100 );
}

なるほど、そうすれば前回のとまったく同じになるってわけね
そういうこと。こうすることで、ほぼデフォルト値と同じことを
オーバーロードで実現できるというわけです
ほぼ同じ?
前回の説明を思い出して。デフォルト値は、関数の宣言部で記述したで
しょ
あ、今回は定義の中だね
その違い。 Version 15.02 ( No.302 ) で説明したように、関数の宣言は
〈こういう関数がある〉という情報でしかありません
実際に結び付けるのはリンクの時だもんね
だから、 Data.h をインクルードせず、以下のようにすることだって
できるんです

// Main.cpp
#include <Windows.h>
#include <stdio.h>

// デフォルト値を持つ、 UseDefault() 関数の宣言。
void UseDefault( int p_i1, int p_i2 = 200 );

// 引数のデフォルト値を持つ関数。
void UseDefault( int p_i1, int p_i2 )
{
    // 配列の方を出力します。
    char pch[256];
    sprintf( pch, "%d, %d\n", p_i1, p_i2 );
    OutputDebugString( pch );
    // 100, 101
}

int WINAPI WinMain
    ( HINSTANCE p_hInstance
    , HINSTANCE p_hPrevInstance
    , LPSTR p_pchCmdLine
    , int p_iCmdShow
    )
{
    // デフォルト値を使用します。
    UseDefault( 100 );
    // 100, 100

    // デフォルト値を使用しません。
    UseDefault( 200, 300 );
    // 200, 300

    return 0;
}

あ、こっちはデフォルト値の例だね
この例では、 Data.h をインクルードせず、勝手に UseDefault() 関数の
宣言を書いて、勝手にデフォルト値を指定しています

// デフォルト値を持つ、 UseDefault() 関数の宣言。
void UseDefault( int p_i1, int p_i2 = 200 );

げ、ホントだ
でも、これができるのも仕方ないんです。関数宣言というのは、関数を使
う側にとっての情報だから
好きにしていいってこと?
そういうこと。呼び出す側にとって、ヘッダーファイルは〈インクルード
した方が便利〉だからインクルードするだけだからね
つまり?
つまり、呼び出される側に強制力はない、ってこと
そか、つまりデフォルト値は変えられるかもしれない、強制できないって
ことね
そういうこと。デフォルト値はいわば〈呼び出す側が使用する、省略した
時に渡す値〉。たとえば

    // デフォルト値を使用します。
    UseDefault( 100 );

としたら、これが呼び出すときに

    // デフォルト値を使用します。
    UseDefault( 100, 200 );

となる、という話なんです
その値を宣言で指定している、と
そしてそれは呼び出す側で自由に変えられる、ってことは結局普通に渡し
ているのと同じ。プログラマーにとって楽、というだけのことなんです
で、オーバーロードの方は
デフォルト値は定義内で渡すから、呼び出す側で変えることはできません。
しかも、何を渡すかも分からないかもしれません
あ、そういえばそうだよね、 DLL になってたら分かんないよね
それに、この例では引数2つの方を呼び出しているけど、呼び出さないか
もしれません
あ、そういえば……そか、オーバーロードの時は、引数が減ってるだけ
じゃなく関数が別っていうのもあるんだ
それも重要な点。デフォルト引数は関数は1つだけどオーバーロードは2つ
以上あるわけだから、中身は全然違うかもしれないんです。それに、関数が
多いってことは、それだけ関数を作らなきゃいけないってことでもあるんで

げ!
引数が5つあって、そのうち4つ省略したい場合、デフォルト値なら1つの
関数で済むけど、オーバーロードの場合は
4つ作らなきゃいけない!
ただ、デフォルト値を設定しない引数を、設定した引数の後に入れること
はできないんです。たとえば

void UseDefault( int p_i1, int p_i2 = 100, int p_i3 );

っていうのは駄目
あー、じゃあ引数の一部だけ省略するのはデフォルト値じゃ無理なんだ
オーバーロードならその辺は柔軟にできるし、あと呼び出す側で違いを把
握できないっていうのは、オーバーロードは全てそうだから

たとえば int と double のオーバーロード
あ! そか、型が違うオーバーロードでも、同じように動くようにしな
きゃいけないって言ってたよね
 Version 11.19 ( No.219 ) で説明したね。引数を省略する時も同じ。加
えて、宣言部の記述に関係なく正しい値が渡される、ってことを考えると
デフォルト値よりオーバーロードの方がお勧めかな
って、関数いっぱい作らなきゃいけないって問題は?
努力でカバー
……

/*
    Preview Next Story!
*/
 C++ って、似たような機能のって多いよね
その中から選択しなきゃいけないから大変かな
だよね、メリットデメリット考えないといけないんだもん
次の static メンバ変数もそんな感じかな
またー?
というわけで次回
< Version 16.25 static メンバ変数 >
につづく!
本当の理解が必要なのが C++ 言語!
理解しなくても使える言語があるの?
うーん……難しい質問だねそれは
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。