C++のデフォルト引数とオーバーロードを徹底比較!関数の使い方完全ガイド
生徒
「C++で関数を作っているのですが、引数の数を変えたいときはどうすればいいですか?」
先生
「それには『デフォルト引数』を使う方法と、『関数オーバーロード』を使う方法の2種類がありますよ。」
生徒
「2つもあるんですか!?どっちを使えばいいのか迷っちゃいそうです。」
先生
「似ているようで実は使い道が違うんです。それぞれの特徴をわかりやすく解説しますね!」
1. デフォルト引数とは?「省略できる設定」の仕組み
C++のデフォルト引数とは、関数を呼び出すときに値を入れなかった場合、あらかじめ決めておいた「予備の値」が自動的に使われる仕組みのことです。プログラミング未経験の方でも、家電製品の「初期設定」を思い浮かべると分かりやすいでしょう。
例えば、炊飯器でご飯を炊くとき、特にこだわりがなければ「ふつう」モードで炊けますよね。これがデフォルト設定です。もし「かため」がいいときは、自分で設定を変更します。プログラムでも同じように、「基本はこの値でいいけれど、必要なときだけ変えたい」という項目にデフォルト引数を使います。これにより、関数を呼び出す側は、毎回すべての情報を入力しなくて済むようになり、コードがスッキリと読みやすくなるのです。
2. デフォルト引数の具体的な書き方
デフォルト引数を使うには、関数を定義する際に、引数の名前に続けて「= 値」と記述します。これだけで、その引数は「省略可能」なものになります。難しい言葉で引数の既定値とも呼ばれます。
以下の例では、挨拶を表示する関数を作っています。名前を指定すればその名前に挨拶し、省略すれば「お客様」と表示するように設定しています。パソコンに詳しくない方でも、この「省略できる」という便利さを感じてみてください。
#include <iostream>
#include <string>
// 名前を省略した場合は「お客様」が使われる設定
void sayHello(std::string name = "お客様") {
std::cout << "こんにちは、" << name << "さん!" << std::endl;
}
int main() {
sayHello("太郎"); // 名前を指定する場合
sayHello(); // 名前を省略する場合(デフォルト引数が使われる)
return 0;
}
こんにちは、太郎さん!
こんにちは、お客様さん!
このように、一つの関数だけで二通りの呼び出し方に対応できるのがデフォルト引数の強みです。ただし、デフォルト引数は右側の引数から順番に設定しなければならないというルールがあることも覚えておきましょう。
3. 関数オーバーロードとは?「同じ名前の別物」
一方で、関数オーバーロードとは、同じ名前の関数を複数作ることができる仕組みのことです。「同じ名前で混乱しないの?」と思うかもしれませんが、C++は「引数の種類(型)や数」が違えば、それらを全く別の関数として認識してくれます。
これを例えるなら、ハサミのようなものです。私たちは「紙を切るハサミ」も「髪を切るハサミ」も「キッチンバサミ」も、全部ひっくるめて「ハサミ」と呼びますよね。でも、切る対象(引数)に合わせて、無意識に適切な道具を使い分けています。プログラムの世界でも、同じ「表示する」という目的でも、数字を表示する場合と文字を表示する場合で中身の処理を分けたいときに、このオーバーロードが活躍します。
4. オーバーロードで処理を切り替える実例
オーバーロードは、引数の「型」が違うときによく使われます。例えば、整数を表示する処理と、小数点以下の数字を表示する処理を、同じ名前の関数で用意してみましょう。C++が賢く判断して、適切な方を実行してくれます。
#include <iostream>
// 整数を表示するバージョン
void printData(int value) {
std::cout << "整数のデータです: " << value << std::endl;
}
// 小数(double型)を表示するバージョン
void printData(double value) {
std::cout << "小数のデータです: " << value << std::endl;
}
int main() {
printData(100); // 上の関数が呼ばれる
printData(3.14); // 下の関数が呼ばれる
return 0;
}
整数のデータです: 100
小数のデータです: 3.14
デフォルト引数との大きな違いは、「中身の処理を完全に変えられる」という点です。型によって全く違う計算をさせたい場合は、オーバーロード一択になります。
5. デフォルト引数とオーバーロード、最大の違いは?
ここで二つの違いを整理しましょう。プログラミング初心者が一番迷うポイントですが、見分けるコツは「中身が同じかどうか」です。
- デフォルト引数: 基本的な処理の流れは一緒。単に「データが足りないときに補うだけ」の場合に使います。コード(プログラムの命令)を何個も書かなくて済むので、修正が楽になります。
- オーバーロード: 引数の種類によって、処理のやり方自体を変えたいときに使います。また、引数の数が全く違う複雑な関数を作りたいときにも適しています。
もし、デフォルト引数で済むところをオーバーロードで書くと、同じような命令を何度も書くことになり(二重管理)、後から直すのが大変になります。逆に、中身が違うのに無理やりデフォルト引数を使おうとすると、関数の中に複雑な分岐が必要になり、読みづらいプログラムになってしまいます。
6. 実践例:お買い物計算で使い分けを学ぼう
実際のお買い物プログラムで、両方を使い分ける例を見てみましょう。商品の価格を計算する関数を作ります。基本は「税抜き価格」を渡せば消費税10%を計算しますが、もし「特別割引」がある場合は割引後の価格を出すようにします。
#include <iostream>
// デフォルト引数の例:税率を基本10%にする
void calcPrice(int basePrice, double taxRate = 0.1) {
int total = basePrice * (1.0 + taxRate);
std::cout << "支払金額: " << total << "円" << std::endl;
}
int main() {
std::cout << "通常のお買い物:" << std::endl;
calcPrice(1000); // 税率10%で計算
std::cout << "軽減税率のお買い物:" << std::endl;
calcPrice(1000, 0.08); // 税率8%で計算
return 0;
}
通常のお買い物:
支払金額: 1100円
軽減税率のお買い物:
支払金額: 1080円
この例では「計算式」そのものは変わっていないため、デフォルト引数が最適です。もしこれが「会員カードの有無で計算アルゴリズムが根本から変わる」といった場合には、オーバーロードを検討することになります。
7. どっちを使うべき?初心者のための判断基準
最後に、自分でプログラムを書くときの「魔法の基準」を教えます。迷ったらこう考えてください。
「その関数に渡す情報は、オプション(おまけ)ですか?」
YESなら、デフォルト引数を使いましょう。例えば、グラフを描く関数の「色」や、ファイルを保存するときの「保存先」などがこれにあたります。
「渡す情報の種類によって、道具(関数)を使い分ける必要がありますか?」
YESなら、オーバーロードです。例えば、料理を「焼く」関数に、肉を渡すのか魚を渡すのかで、焼き時間や温度の管理が全く別物になるような場合です。この考え方を身につければ、Google検索で調べものをしている他のプログラミング初心者よりも、一歩リードした美しいコードが書けるようになりますよ。
8. 注意点:曖昧な呼び出しに気をつけよう
実は、デフォルト引数とオーバーロードを同時に使いすぎると、C++が「どっちを呼べばいいの?」と混乱してしまうことがあります。これを曖昧な呼び出し(アンビギュアス)といいます。パソコンは非常に真面目なので、少しでも迷う要素があるとエラーを出して止まってしまいます。
例えば、引数なしの関数と、すべてにデフォルト引数がついた関数を同時に作ると、何も書かずに呼び出したときにエラーになります。初心者のうちは、あまり欲張りすぎず、まずはどちらか一方の仕組みを使って、シンプルなプログラムを作ることから始めるのが上達の近道です。C++の関数の奥深さを楽しみながら、一つずつ確実に覚えていきましょう。