🖥️

【C++言語入門】 第6回 オーバーロードと名前空間

2025/02/23に公開

https://youtu.be/dDy_iAMCA5k

四国めたん
\textcolor{pink}{四国めたん: }教師役ですわ

ずんだもん
\textcolor{lime}{ずんだもん: }生徒役なのだ

\footnotesize \textcolor{pink}{四国めたん:} こんにちは。四国めたんです

\footnotesize \textcolor{lime}{ずんだもん:} ずんだもんなのだ。こんにちはなのだ

\footnotesize \textcolor{pink}{四国めたん:} 今回は関数の オーバーロード についてお話ししますわ

\footnotesize \textcolor{lime}{ずんだもん:} オーバーロード

\footnotesize \textcolor{pink}{四国めたん:} 以前の回でゲッターやセッター、コンストラクタなどで同じ名前のメソッドを定義していたのを覚えていますか?

\footnotesize \textcolor{lime}{ずんだもん:} おぼえているのだ

\footnotesize \textcolor{pink}{四国めたん:} 同じ名前の関数やメソッドを定義できる仕組みが オーバーロード ですわ

\footnotesize \textcolor{lime}{ずんだもん:} 詳しく教えて欲しいのだ

関数名を使い回わそう

\footnotesize \textcolor{pink}{四国めたん:} 前々回までの説明で、 ゲッターセッターコンストラクタ などについて、同じメソッド名で複数のメソッドを宣言、定義していましたわ

\footnotesize \textcolor{lime}{ずんだもん:} 不思議に思っていたのだ

\footnotesize \textcolor{pink}{四国めたん:} C言語では明らかにエラーとなってしまいますが、C++言語では問題なく使えていますわね

\footnotesize \textcolor{lime}{ずんだもん:} そうなのだ

\footnotesize \textcolor{pink}{四国めたん:} これはクラス中のメソッドだけではなく、メイン関数を除く一般の関数でも同じですわ

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} はい、このように同じ関数名で複数の関数を宣言、定義することを オーバーロード と言いますわ

\footnotesize \textcolor{lime}{ずんだもん:} オーバーロード

\footnotesize \textcolor{pink}{四国めたん:} オーバーロード 可能な条件はいくつかありますが、基本的には「引数の数もしくは型が異なる」場合に可能ですわね

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

\footnotesize \textcolor{pink}{四国めたん:} まぁ、関数やメソッドを呼び出す際に、どの関数を呼び出すかを特定できるならOKだと思いますわ

\footnotesize \textcolor{pink}{四国めたん:} とりあえず実例を見てみましょう

#include <iostream>

float add(float a, float b) {
  float c = a + b;
  return c;
}

int add(int a, int b) {
  int c = a + b;
  return c;
}

int main(int argc, char* argv[]) {
  int x = 1;
  int y = 2;
  int z = add(x, y);
  float d = 3.0;
  float e = 4.0;
  float f = add(d, e);
  std::cout << "xとyの和は" << z << "です" << std::endl;
  std::cout << "dとeの和は" << f << "です" << std::endl;
  return 0;
}

関数のオーバーロード

\footnotesize \textcolor{pink}{四国めたん:} 【C言語超入門】 第16回 関数の解説の際にエラーとなったプログラム例をC++言語向けに修正したものですわ

\footnotesize \textcolor{lime}{ずんだもん:} あの時にはエラーがたくさん出ていたのだ

\footnotesize \textcolor{pink}{四国めたん:} はい、今回はadd関数を2つ定義していますが、正常に動作していますわ

\footnotesize \textcolor{lime}{ずんだもん:} おもしろいのだ

\footnotesize \textcolor{pink}{四国めたん:} これはadd関数に渡す引数の値がintfloatかで区別がつくからですわ

\footnotesize \textcolor{lime}{ずんだもん:} たしかにその通りなのだ

\footnotesize \textcolor{pink}{四国めたん:} ここでadd関数の引数を全てfloat型にして、戻り値のみ異なる関数としてみましょう

#include <iostream>

float add(float a, float b) {
  float c = a + b;
  return c;
}

int add(float a, float b) {
  int c = a + b;
  return c;
}

int main(int argc, char* argv[]) {
  int x = 1;
  int y = 2;
  int z = add(x, y);
  float d = 3.0;
  float e = 4.0;
  float f = add(d, e);
  std::cout << "xとyの和は" << z << "です" << std::endl;
  std::cout << "dとeの和は" << f << "です" << std::endl;
  return 0;
}

オーバーロードのエラー

\footnotesize \textcolor{lime}{ずんだもん:} 今回は「E0311 戻り値の型だけで識別される関数はオーバーロードできません」と云うエラーが出ているのだ

\footnotesize \textcolor{pink}{四国めたん:} 結局、戻り値の型が異なっていても、引数が同じであれば関数やメソッドを オーバーロード はできませんわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

名前空間で区別しましょう

\footnotesize \textcolor{lime}{ずんだもん:} 結局、引数が同じ関数を複数同時に定義もしくは宣言することはできないのか...

\footnotesize \textcolor{pink}{四国めたん:} まぁ、方法はありますわ

\footnotesize \textcolor{pink}{四国めたん:} 例えば会社などでプロジェクトを組んで、複数のプログラマーが一緒にプログラムを組む場合、C言語などでは関数名が被らないようにしなければなりませんわ

\footnotesize \textcolor{lime}{ずんだもん:} 定数の名前や構造体名なども同じなのだ

\footnotesize \textcolor{pink}{四国めたん:} そんな場合には、例えば個々のプログラマーにIDを割り振って、名前の前にIDを付加して区別するなどの工夫をしますわね

\footnotesize \textcolor{lime}{ずんだもん:} Add関数をZundaAddと云う名前にするとか...

\footnotesize \textcolor{pink}{四国めたん:} そうですわね

\footnotesize \textcolor{lime}{ずんだもん:} C++言語でも同じように、 オーバーロード が可能でも引数と関数名がかぶってしまうことがありそうなのだ

\footnotesize \textcolor{pink}{四国めたん:} はい、そのためC++言語では 名前空間 もしくは namespace という、C言語に比べて少し洗練された機能が追加されていますわ

\footnotesize \textcolor{lime}{ずんだもん:} 名前空間

\footnotesize \textcolor{pink}{四国めたん:} 今までのプログラム例でも使ってきましたが、std::coutstdなどが、その一例ですわ

\footnotesize \textcolor{lime}{ずんだもん:} あぁ、あの...

\footnotesize \textcolor{pink}{四国めたん:} 名前空間 を指定することで同じ名前の関数を区別することができますわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

名前空間の指定は波括弧で括るだけですよ

\footnotesize \textcolor{lime}{ずんだもん:} 名前空間 の指定はどのようにおこなうのだ?

\footnotesize \textcolor{pink}{四国めたん:} 方法はシンプルで、このようにしますわ

namespace 名前空間名 {
   :
   :
}

\footnotesize \textcolor{pink}{四国めたん:} 関数やクラス、構造体、外部変数、定数などを波括弧"{}"で括ってnamespaceキーワードに続けて"名前空間名"を指定するだけですわ

\footnotesize \textcolor{lime}{ずんだもん:} 結構、簡単なのだ

\footnotesize \textcolor{pink}{四国めたん:} はい、"名前空間名"は基本的にスネークケースで記述することが推奨されているようですわ

\footnotesize \textcolor{lime}{ずんだもん:} スネークケース?

\footnotesize \textcolor{pink}{四国めたん:} いわゆる小文字の英数字とアンダースコアのみで構成される名前ですわ

\footnotesize \textcolor{lime}{ずんだもん:} 名前に決まりはあるのか?

\footnotesize \textcolor{pink}{四国めたん:} 名前のつけ方自体は仕様ではありませんので、好きなように名前をつけてもOKかと思いますわ

\footnotesize \textcolor{lime}{ずんだもん:} たとえば?

\footnotesize \textcolor{pink}{四国めたん:} 会社名やプログラム名、個人名などにシリアル番号を付加したものなどは判りやすいかと思いますわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

\footnotesize \textcolor{pink}{四国めたん:} ただstdという名前空間名はC++言語に付随する 標準テンプレートライブラリ でデフォルトで使われている名前なので、使わないようにしましょう

\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ

\footnotesize \textcolor{pink}{四国めたん:} ちなみに#defineで定義された定数に関しては、波括弧内に記述しても名前空間からは完全に独立して処理されますわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

名前空間内のオブジェクト指定は::を使います

\footnotesize \textcolor{lime}{ずんだもん:} では 名前空間 内のオブジェクト、例えばクラスや定数、外部変数を指定するにはどうすればいいのだ?

\footnotesize \textcolor{pink}{四国めたん:} 基本的にはstd::coutを見れば判る通り、コロンを2つつなげた スコープ解決演算子 "::"を使いますわ

\footnotesize \textcolor{lime}{ずんだもん:} スコープ解決演算子

\footnotesize \textcolor{pink}{四国めたん:} はい、名前空間名::クラス名のように指定しますわ

\footnotesize \textcolor{lime}{ずんだもん:} つまりstd::coutは"std" 名前空間 に属する外部変数"cout"と云うことか

\footnotesize \textcolor{pink}{四国めたん:} その通りですわ

名前空間を実際に使ってみよう

\footnotesize \textcolor{pink}{四国めたん:} すでにプログラム例では 名前空間 を使っていますが、改めて 名前空間 を使ってadd関数を書き直してみますわ

\footnotesize \textcolor{lime}{ずんだもん:} おねがいするのだ

#include <iostream>

namespace float_return {
float add(float a, float b) {
  float c = a + b;
  return c;
}
}  // namespace float_return

namespace integer_return {
int add(float a, float b) {
  int c = a + b;
  return c;
}
}  // namespace integer_return

int main(int argc, char* argv[]) {
  int x = 1;
  int y = 2;
  int z = integer_return::add(x, y);
  float d = 3.0;
  float e = 4.0;
  float f = float_return::add(d, e);
  std::cout << "xとyの和は" << z << "です" << std::endl;
  std::cout << "dとeの和は" << f << "です" << std::endl;
  return 0;
}

名前空間

\footnotesize \textcolor{lime}{ずんだもん:} お~、関数名のバッティングが回避されているのだ

\footnotesize \textcolor{pink}{四国めたん:} はい、int型の変数をfloat型の引数に渡すことでワーニングは出ていますが、同じaddという関数名でのバッティングは回避されていますわ

いちいち名前空間を指定するのは面倒です!

\footnotesize \textcolor{lime}{ずんだもん:} ところでバッティングしない関数名や外部変数名にまで スコープ解決演算子 を使って 名前空間 を指定するのは面倒なのだ

\footnotesize \textcolor{pink}{四国めたん:} たしかにその通りですわね

\footnotesize \textcolor{pink}{四国めたん:} そこでC++言語ではusingというキーワードを用意していますわ

\footnotesize \textcolor{lime}{ずんだもん:} using

\footnotesize \textcolor{pink}{四国めたん:} はい、一般的には usingディレクティブ と呼ばれていますわ

\footnotesize \textcolor{lime}{ずんだもん:} どのように使うのだ?

\footnotesize \textcolor{pink}{四国めたん:} こんな感じで使いますわ

using namespace 名前空間名;

\footnotesize \textcolor{lime}{ずんだもん:} なるほど、using namespaceの後に 名前空間 の名前を記述するのか

\footnotesize \textcolor{pink}{四国めたん:} はい、機能としてはusing以降の関数やクラス、外部変数などについて、指定した名前空間名を省略できますわ

\footnotesize \textcolor{lime}{ずんだもん:} お~、便利なのだ

\footnotesize \textcolor{pink}{四国めたん:} 当然ですが、 名前空間 を省略しても一意に決められることが前提ですわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

\footnotesize \textcolor{pink}{四国めたん:} それではプログラム例のstd名前空間を省略してみましょう

#include <iostream>

using namespace std;

namespace float_return {
float add(float a, float b) {
  float c = a + b;
  return c;
}
}  // namespace float_return

namespace integer_return {
int add(float a, float b) {
  int c = a + b;
  return c;
}
}  // namespace integer_return

int main(int argc, char* argv[]) {
  int x = 1;
  int y = 2;
  int z = integer_return::add(x, y);
  float d = 3.0;
  float e = 4.0;
  float f = float_return::add(d, e);
  cout << "xとyの和は" << z << "です" << endl;
  cout << "dとeの和は" << f << "です" << endl;
  return 0;
}

usingによる省略

\footnotesize \textcolor{lime}{ずんだもん:} 問題なく動作しているのだ

\footnotesize \textcolor{pink}{四国めたん:} using namespace std;により、今までのstd::coutstd::endlからstd::を省いてcoutendlとすることができていますわ

\footnotesize \textcolor{lime}{ずんだもん:} なるほどなのだ

\footnotesize \textcolor{pink}{四国めたん:} なおusingを使った 名前空間 の省略ですが、多用はお勧めしませんわ

\footnotesize \textcolor{lime}{ずんだもん:} そうなのか?

\footnotesize \textcolor{pink}{四国めたん:} はい、大きいプログラムでは関数名やクラス名の重複などは意外に発生するものですわ

\footnotesize \textcolor{lime}{ずんだもん:} その通りなのだ

\footnotesize \textcolor{pink}{四国めたん:} usingを使った 名前空間 の省略を行うと、関数名やクラス名の重複によって訳のわからないバグなどが発生する場合があるのですわ

\footnotesize \textcolor{lime}{ずんだもん:} それは大変なのだ

\footnotesize \textcolor{pink}{四国めたん:} ですので多少面倒ではありますが、関数名などは省略せずにしっかりと 名前空間 の指定を行うようにしてくださいね

\footnotesize \textcolor{lime}{ずんだもん:} りょうかいなのだ

まとめ

\footnotesize \textcolor{pink}{四国めたん:} お疲れさまでした

\footnotesize \textcolor{lime}{ずんだもん:} おつかれさまなのだ

\footnotesize \textcolor{pink}{四国めたん:} 以上で オーバーロードと名前空間 の説明を終わりますわ

Discussion