#pragma twice

KAB-studio > プログラミング > #pragma twice > 350 Version 16.23 引数のデフォルト値

#pragma twice 350 Version 16.23 引数のデフォルト値

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

 Version 16.23
引数のデフォルト値

今回は引数のデフォルト値について説明します
演算子のオーバーロードからうってかわって、って感じだね
ううん、実はとても関係があるんです
え?
まずは実例から。引数のデフォルト値は普通の関数でもメンバ関数でもで
きるから、普通の関数で試してみます

// Data.h
void UseDefault( int p_i1, int p_i2 = 100 );


// Data.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
}

 UseDefault() の第2引数で 100 というデフォルト値を使用しています
【 int p_i2 = 100 】がそうね
使用例は以下のようになります

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

#include "Data.h"

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;
}

最初の方は、デフォルト値を使用して呼び出しています

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

このように、引数を省略するとデフォルト値が使用されます。つまり、 
p_i2 に 100 が渡されて呼び出される、ということです

    // デフォルト値を使用します。
    UseDefault( 100  /* 第2引数を省略 */ );
                 ↓            ↓
                 ↓            ↓
                 ↓            →→→→→
                 →→→                ↓
                      ↓               ↓
void UseDefault( int p_i1, int p_i2 = 100 );
                     ↓               ↓
                     ↓         ←←←←
                     ↓         ↓
void UseDefault( int p_i1, int p_i2 )
{
// 略

省略すると、その値が渡されるってわけね
もちろん、デフォルト値を使用しないこともできます

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

だからデフォルト値、なんだもんね
そういうこと
……質問!
はい火美ちゃん
これって宣言の方だけでいいの? 定義の方はいらないの?
そこが複雑なところなんです。たとえば、以下のようにデフォルト値の
設定を、定義の方だけしたとします

// Data.h
void UseDefault( int p_i1, int p_i2 );

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

#include "Data.h"

// 引数のデフォルト値を持つ関数。
void UseDefault( int p_i1, int p_i2 = 100 )
{
// 略

げ、コンパイルエラーになった!

    // デフォルト値を使用します。
    UseDefault( 100 );
    // コンパイルエラー:
    // error C2660: 'UseDefault' : 
    //     関数が不正な 1 個の実引数をともなって呼び出されました。

なんでなんで!? 宣言の方に書かないといけないの?
宣言の方に書かなきゃいけないわけじゃなくて、コンパイルするときに
デフォルト値の情報がないといけないんです
???
コンパイラのことを思い出して。まず、コンパイルはソースファイル単位
で行うよね
 Version 15.01 ( No.301 ) とかで教わったね
コンパイラは、 Main.cpp をコンパイル中に、以下の文にでくわします

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

コンパイラは、この UseDefault() 関数の引数と戻り値の情報を取得しよ
うとします。その情報はどこに書かれてる?
 Data.h と Data.cpp 
でも、コンパイルはソースファイル単位でしょ
あ、そっか。 Main.cpp のコンパイルしてるときには Data.cpp は見てな
いんだ。 Main.cpp からは Data.h をインクルードしてるから見えるけど

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

#include "Data.h"

そう、だから Main.cpp のコンパイル時には Data.h の情報を持つことに
なります。その中で、以下の関数を見つけます

// Data.h
void UseDefault( int p_i1, int p_i2 );

デフォルトの引数使っていないバージョンね
コンパイラは、呼び出し元の引数が1つだけなのに、宣言の方は引数が2つ
の関数しかないから、どの関数を呼び出せばいいのかわかりません
コンパイラは Data.h しか見られないから、定義の方にデフォルト値書い
ても分からない、って話?
そういうこと。デフォルト値はコンパイル時に使用されるので、コンパイル
するときに見に行く Data.h の宣言に書く必要があります

// Data.h
void UseDefault( int p_i1, int p_i2 = 100 );

このようにすることで、コンパイラは呼び出し部分にデフォルト値を渡す
ようにします

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

呼び出すとこにデフォルト値を渡しちゃう渡すわけね
このように、デフォルト値はコンパイル時に処理されるので、宣言に書く
必要があります
コンパイラから見えなきゃいけないわけね
ただ、定義に書いてもいい場合もあります
定義に書いてもいい場合?
定義しかない場合とかね

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

// 引数のデフォルト値を持つ関数。
void UseDefault( int p_i1, int p_i2 = 100 )
{
    // 配列の方を出力します。
    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;
}

あー、定義ファイルにしかない場合は仕方ないよね
どちらにしろ、コンパイラがデフォルト引数が得られればいい、ってこ
とだから

/*
    Preview Next Story!
*/
あれ? オーバーロードと関係してるって話は?
引数を省略、ってオーバーロードでもできるでしょ
そういえば、ってここで言われても
じゃあ1回そのために取りましょう

というわけで次回
< Version 16.24 デフォルト値vsオーバーロード >
につづく!
こうしてどんどん伸びていく
自分で言うなー! もう7年だよー!?
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。