Youtube登録者5000人突破!!

【C++】関数 【はじめてのC++プログラミング入門講座 #8】

はじめてのC++プログラミング入門講座では、プログラミングをやったことのない人でも分かるように、C++について解説します。まずは、C++を知るところからはじめて、初心者がつまづきやすい「ポインタ」までをゴールとして進めていきます。全て無料で学べる内容となってますので、ぜひ最後までお付き合いください。

丁寧に学ぶをモットーに、ひとつずつじっくりと理解しけるように解説します。 はじめは少し退屈かもしれませんが、基礎を身に着けておくと、後が楽になります。また、プログラミング学習でよくあるのが、飛ばしすぎて途中で挫折してしまうことです。続けさえすれば力になります。じっくりゆっくり学んでいきましょう。

本講座はC++の開発環境が必要です。環境構築には第1回のVisual Studioの環境構築を参考にしてください。下記からどうぞ。

前回の第7回では、for文と配列について解説しました。詳細は下記からどうぞ。

重要なポイントは下記の通りです。

  • for文は有限回の繰り返しを行える
  • for文を使うことで、繰り返しを圧縮できてスマートなプログラムが書ける
  • for文はこのように書ける→ for (初期値; 実行範囲; 実行毎に行う処理) {実行部分}
  • 配列は同じ型の要素をまとめて管理する
  • 配列は宣言時に要素数を指定し、各要素に値を代入する(宣言と代入をまとめて行うこともできる)
  • 配列の番号付けは0番目から始まり、(要素数-1)番目で終わる
  • continue はfor文のループ一回分を飛ばす
  • break はfor文を強制的に終了させる

関数

とうとうやってきました、関数の回です。関数の基本的な考え方は数学と同じで、変数を与えてやると、計算されて、値を返す、です。

数学の関数との違いとしては、プログラミングでは関数に計算以外の色々な処理を行わせることができるというところです。例えば、画面に文字を出力したりとか、入力待ちをしたりとかです。

また関数を使うことで、メイン関数がスッキリします。スッキリしたメイン関数であれば流れも理解でき、長いプログラムでもわかりやすいものができます。ひとまとめにできる機能は関数にまとめるクセを付けておきましょう。

このように、関数のメリットは多数あり、プログラミングでは核となる機能です。

誰かが作ったプログラムを使用するときも、基本的に関数の形になっています。例えば、半径を入力してやれば円の面積を求める関数、みたいな感じです。つまり、関数の使い方を覚えるということは、プログラムを全て自分で書く必要がなくなるということです。(いわゆる「車輪の再発明を避ける」というやつです)

関数において大事なのは、「引数(関数に与える値)」「返り値(関数から帰ってくる値)」の2つです。この2つの単語は今後も出てくるので、覚えておきましょう。また、関数は今後出てくる「クラス」の基本要素です。今後、躓かないためにも、基本を固めておきましょう。

今回のプログラムは下記の通りです。

#include <iostream>

using namespace std;

void say_hello() {
	cout << "Hello world" << endl;
}

int doubled(int a) {
	return a * a;
}

int main()
{
	say_hello();
	say_hello();
	say_hello();

	int x = 10;

	int y = x * x;
	int y2 = doubled(x);

	cout << y2 << endl;
}

Hello world
Hello world
Hello world
100

ライブラリと関数

#include <iostream>

using namespace std;

void say_hello(){
  ・・・
}

int doubled(int a) {
  ・・・
}

int main()
{
・・・
}

今回もインクルードするライブラリは入出力ライブラリのiostreamだけです。

また、名前空間の回で紹介した using namespace std も使用します。これは、標準ライブラリを使用する際の名前空間を省略することができます。例えば、標準出力の std::cout を cout だけで記述することができ、プログラムがスッキリします。

今回はメイン関数の前に関数があり、say_helloとdoubledという2つの関数を作成しています。

関数

関数は、 変数を与えてやると、計算されて、値を返します。3つの機能は全て必要なわけではなく、どれかが抜けている関数もあります。何も与えられない、計算しない、値を返さない関数も作ることができます。そんなものを作っても意味はないですが・・・

今回のプログラムを見ながら関数について理解を深めていきましょう。今回はsay_hello関数とdoubled関数を作成します。

void say_hello() {
	cout << "Hello world" << endl;
}

int doubled(int a) {
	return a * a;
}

関数は下記のような構造になっています。

返り値の型 関数名(引数) {
  処理
}

返り値は、関数から返す値のことです。関数をさくせする場合は、関数名の前に返り値の型を指定する必要があります。返り値はreturn文と必ずセットです。今回作成したdoubled関数では、int型の返り値を返すことを関数名の前に記入し、処理内でもreturn文でint型の返り値を返しています。

say_hello関数では、返り値がありません。その場合は、voidを使用します。voidは型を指定する必要がない(返り値がないので、当然型もない)場合、に使用します。

関数名は、自由に決めて構いません。自作の関数は主にメイン関数から呼び出すことになりますが、呼び出しの際に関数名を使用します。

今回の関数名は say_hello というHelloを画面表示する関数と doubled という与えた整数を二敗する関数となっています。どちらも関数名から機能が推測できるようになっています。

引数は、関数に与える変数のことです。 自作の関数は主にメイン関数から呼び出すことになりますが、呼び出しの際に引数を渡すことができます。

doubled関数では(int a)と記入してあり、これは整数型の変数を引数として使えるようにしています。引数を設定しているため、メイン関数における関数呼び出しの際に引数を与える必要があります。呼び出しの際の書き方は何でも良いです。例えば、10という値を使っても良いし、メイン関数で定義した変数(例えばxなど)でも良いです。

つまり引数 (int a) の部分では、doubled関数に引数を与える、そしてその引数をdoubled関数内では a という変数で扱うということが決定されていることになります。この変数は関数が終了すると廃棄されます。必要に応じて返り値として返してあげましょう。

say_hello 関数は引数がありませんので、記述が省略されています。引数に関してはvoidの記入は不要です。

処理の部分にプログラムを書いていきます。関数は多用な使い方ができ、 say_hello 関数のように処理をひとまとめにしただけのものだったり、 doubled関数のように入力と出力を兼ね備えたものも作ることができます。

単純に、プログラムが長くなったらメイン関数を整理するために関数にするということもあります。

メイン関数

ここからはメイン関数の中身を見ていきます。

関数は繰り返しを減らすという意味もありますが、何よりもプログラムを見やすくしてくれるのに役立ちます。今回は今までに比べてメイン関数内が非常にスッキリしています。

	say_hello();
	say_hello();
	say_hello();

	int x = 10;

	int y = x * x;
	int y2 = doubled(x);

	cout << y2 << endl;

上記プログラムではまず初めにsay_hello関数を3回呼び出しています。関数の呼び出しは、関数名+丸括弧()で行います。 say_hello関数は引数と返り値がないので、このようなシンプルな書き方ができます。

Hello world
Hello world
Hello world

次は、引数を2倍する関数doubledを作成します。

比較として、引数を2倍する通常のプログラムを書いています。通常だと、宣言した x を y = x * x で二倍します。

関数にすると、 y2 = doubled(x) の形になります。これは、引数としてxが与えられており、返り値としてy2を返しています。 x(=10)が2倍された結果が画面に出力されます。

100

このように関数は定義に応じた呼び出し方が必要です。呼び出しを作成する際には、関数定義を確認しながらそれにあった書き方をしましょう。

プロトタイプ宣言

プロトタイプ宣言とは、関数の定義と宣言を分けて書く書き方です。

今までは宣言と定義をまとめて書いていたので違いがわかりにくいと思いますが、宣言と定義は違います。

関数の宣言とは、関数名と引数の型と返り値の型の情報です。一方で定義とは宣言の内容に加えて関数内の処理や引数として与える際の変数、返り値の変数(関数内処理のreturn)も含みます。つまり、定義のほうが詳細な情報となります。

プロトタイプ宣言では、関数の宣言をメイン関数より先に書き、関数の定義をメイン関数よりも後に書くことができます。

メリットは、まずコードが見やすくなるというのがあります。普通はメイン関数がプログラムの主流となるので、メイン関数が上に来ればプログラムも見やすくなります。

他には、ヘッダーファイルとして管理することができるというメリットもあります。ヘッダーファイルとは、ライブラリと同じように自作のプログラムをインクルードできるようなファイルのことです。これによって、一度作った関数をたくさんのcppファイルで使用することができます。

プロトタイプ宣言という機能を使用して書いた場合は下記のようになります。自作関数が下に移動したことで、最も重要なメイン関数が目につきやすくなったことがわかります。

#include <iostream>

using namespace std;

void say_hello();

int doubled(int a);

int main()
{
	say_hello();
	say_hello();
	say_hello();

	int x = 10;

	int y = x * x;
	int y2 = doubled(x);

	cout << y2 << endl;
}

void say_hello() {
	cout << "Hello world" << endl;
}

int doubled(int a) {
	return a * a;
}

メイン関数は全く同じ形なので、自作関数の部分だけ見ていきましょう。

・・・
void say_hello();

int doubled(int a);

int main()
{・・・・}

void say_hello() {
	cout << "Hello world" << endl;
}

int doubled(int a) {
	return a * a;
}

メイン関数の前に書いているのが、関数の宣言です。

say_hello関数は返り値も引数もないので、すごくシンプルです。一方で、doubled関数は返り値の型と引数の型情報があります。

double関数を見て頂くと、返り値はint型、引数もint型であることがわかります。返り値の型と引数の型と数という情報があれば、関数の中身がわからなくてもメイン関数で呼び出すことができます。

そのため、プロトタイプ宣言はメイン関数の前には宣言しか書いていませんが、問題なく読むことができます。関数名から何をする関数なのか分かれば、関数の中身は気にしなくても良いのです。

関数の定義については、メイン関数の下に書いてあります。これは普通に関数を書く時と同じ書き方です。

プロトタイプ宣言とライブラリ

プロトタイプ宣言では関数の宣言だけを先頭に持ってきたので、本当に関数の名前だけで呼び出しができるのか疑問が残るかもしれません。

しかし、これはライブラリの使用と同じなので、実は普段から慣れた方法なのです。ライブラリを使用する際は中身は気にせずに、機能と引数と返り値だけ気にすると思います。coutやcinなどの中身は気にせず使えていますよね。

これが理想の関数の形です。関数名だけで動作が理解できて、引数と返り値だけを意識すればツールとして使える状態です。

プログラムは複雑になればなるほど後から読むのも大変です。そこで、関数としてまとめておいて入力と出力を示してやることで、その関数に詳しくない人でも使えるようにして上げることができます。実際、ライブラリと同じ機能を再開発する人はいないように、一度作った関数は中身を見なくても未来永劫使い続けれるのです。

そのためには汎用性の高い関数を作る能力が必要ですが、まずはその方向性だけでも理解しておくと関数を作るときに何が大事かを意識しながら作業を進められると思います。

おわりに

今回は関数について紹介しました。特に宣言と定義の違いやプロトタイプ宣言は知っておかないと他人のプログラムを見る上で支障があります。少し情報量が多いですが、ぜひ理解しておいてください。

重要なポイントは下記の通りです。

  • 関数にすることで自作の機能をまとめられる
  • 関数は、引数を与えたら、処理をして、返り値を返す機能である
  • どれかの機能が抜けていても関数は作ることができる
  • 関数の形は「返り値の型 関数名(引数) { 処理 }」で書ける
  • もし返り値の型がない場合はvoidを書き、引数がない場合は何も書かなくて良い
  • プロトタイプ宣言は、関数の宣言と関数の定義を分けて書く
  • プロトタイプ宣言を使えば、メイン関数より後に自作関数の定義を書ける
  • プログラムを見やすくするために、プロトタイプ宣言を使うのが一般的である

関数はうまく使いこなせば、一生同じプログラムを書かなくて良くなるという活気的な機能です。自分が作れるようになるのも重要ですが、他人の関数を使えるようになるだけでも十分に価値があります。

作り方は難しく感じるかも知れませんが、ぜひ構造を理解しておきましょう。

次回は関数の追加機能であるオーバーロードとテンプレートについて解説します。こちらもどうぞ。

youtubeでも解説動画を出しています。流し聞きでも大体理解できると思います。