C++の基礎を説明しています。
この「C++入門」は、wxWidgesのコードを読むための必要最小限な説明をしています。
他の言語などの予備知識は必要としていません。
お好きなエディタで次のコードを記述してください。そしてhello.cppという名前で保存してください。WindowsでMSYSを使う場合は、
C:¥msys64¥home¥ユーザー名
に保存するのが便利です。C++のコードファイルの拡張子は.cppになります。
#include <iostream>
int main()
{
std::cout << "Hello C++!" << std::endl;
return 0;
}
C++はコンパイル型の言語です。高速で実行することができます。
コンパイルとは、ソースコードをコンピュータが理解できる機械語に変換することです。
ターミナルもしくはコマンドプロンプトもしくはMSYSを開いて、hllo.cppを保存したディレクトリに移動してください。MSYSの場合で、hello.cpp を C:¥msys64¥home¥ユーザー名
に、保存した場合は、MSYS が起動した画面がそのディレクトリになります。そして次のようにコンパイルして実行します。
g++ hello.cpp
// macOS、Ubuntu、Mintでは実行ファイル a.out が作成されます
// Windowsでは実行ファイル a.exe が作成されます
// macOS、Ubuntu、Mintで実行するには次のようにします
./a.out
// Windowsで実行するには次のようにします
./a.exe
//もしくは
./a
// 実行結果
Hello C++!
なお、WindowsでMSYSを使った場合には、作成された a.exe をデスクトップなどに移動させ、コマンドプロンプトで a.exe と実行しようとしても「~~~.dll が見つかりません」などの警告が出て実行できません。これを修正するには、MSYS2でコンパイルするときに次のようなオプションをつけます。
g++ hello.cpp -static -lstdc++ -lgcc
// 作成された a.exe をデスクトップなどに移動させてコマンドプロンプトを起動します
// コマンドプロンプトで a.exe を移動させたディレクトリに移動します
// そして次のように実行します
a.exe
// もしくは
a
// 実行結果
Hello C++!
なお、最初からWindowsのコマンドプロンプトでコンパイルする場合は、このオプションをつける必要はありません。
#include <iostream>
標準装置からの入力と、標準装置への出力に関する機能が定義された iostreama というファイルを読み込んでいます。
標準入力装置はキーボードに、標準出力装置はディスプレイに設定されています。
このような何かの処理をする機能のことを「関数」と呼びます。そして、関数が定義されたこのようなファイルのことをヘッダーと呼びます。
< と > に囲まれたヘッダーは、そのヘッダーが保存されている場所を開発環境が知っていること意味しています。
なお、開発環境のことを一般的には「処理系」と呼びます。
int main() {
C++のプログラムは、main( )関数というものから始まる決まりになっています。main( )関数の前にはint
と記述しなければなりません。そして関数が実際に行う処理は { と } で囲むことになっています。
std::cout << "Hello C++!" << std::endl;
return 0;
main関数は、何かの整数値を返さなければなりせん。何かを返す場合は、return を使います。main関数は正常に終了する場合は 0 を返す決まりになっています。
}
関数が実際に行う処理は、必ず { と } で囲まなければなりません。
hello.cppで使われている int
と return
は、C++によって定められたキーワード(key word)です。キーワードには、それぞれに意味が定めらています。
int
は整数値型という意味です。
return
は何かを返すという意味です。
main()
の前にint
と記述していたのは、main()
関数は整数値を返すという意味だったのです。
hello.cppは、次のように書き換えることができます。
#include <iostream>
using namespace std;
int main()
{
cout << "Hello C++!" << endl;
return 0;
}
using namespace std;
と記述することで、std::cout
とstd:endl
をそれぞれcout
、endl
と省略して記述することができます。
このような仕組みのことを名前空間(name space)と言います。
プログラムの中にメモを記述することができます。このメモのことをコメント言います。コメントはプログラムの動作になにも影響を与えません。
#include <iostream>
using namespace std;
/*
hello.cpp
2019/11/30
(c) vivacocoa.jp
*/
int main()
{
cout << "Hello C++!" << endl; // Hello C++!と表示されます
return 0;
}
/* と */ で囲まれた部分はコメントになります。複数行もコメントにすることができます。
// で始まる部分は、// から、その行の行末までがコメントになりますので、一行コメントとも呼ばれます。
C++では、データのタイプ(type、型)が決まっています。まずは、文字列型と整数値型があることを覚えまておきしょう。
#include <iostream>
using namespace std;
int main()
{
cout << "This is a string." << endl;
// This is a string.は文字列型です
cout << 100 << endl;
// 100は整数値型です
return 0;
}
This is a string.
100
C++は、コンパイルする時にソースコードにエラーがないかを調べます。このチェックは色々な方面で行われますが、そのチェックの一つとして、データ型を使って間違ったデータが使われていないかを調べています。
変数(へんすう)とは、データを保存できる容れ物です。変数を定義する時には、どの型のデータの容れ物であるかを指定しなければいけません。変数の中のデータは、指定された型のデータであれば何度でも上書きすることができます。しかし違う型のデータで上書きしようとするとエラーになります。
#include <iostream>
int main()
{
std::string name;
name = "Jane";
std::cout << name << std::endl;
name = "Mary";
std::cout << name << std::endl;
int number;
number = 100;
std::cout << number << std::endl;
number = 200;
std::cout << number << std::endl;
return 0;
}
Jane
Mary
100
200
std::string name;
文字列型の name という変数を定義しています。変数は「型 変数名;
」と記述して定義します。型の指定の部分で std:string
という関数を使っていますが、文字列は複雑な型なので、C++ では、関数を使って文字列型を指定します。using namespace std;
を使えば、この部分は string
と記述できますので、簡単で意味も分かりやすくなります。
name = "Jane";
変数に値(データ)を入れる場合は、=
(イコール)という記号を使います。=
を使えば、左辺の変数に、右辺の値を上書きするという意味になります。このデータの上書きのことを C++ では、「代入(assign、割り当て)」と呼びます。なお、C++で、イコール(同じ)という意味を表す記号は ==
となります。
また、文字列を表すデータはダブルクォーテーションの "
で囲む決まりになっています。
std::cout << name << std::endl;
変数はコード(式、文)中で上記のように使うことができます。変数の部分は、その変数に入れている値に置き換わります。
int number;
整数型の変数の型指定には、int
キーワードを使います。
C++には、ポインター(pointer)という変数もあります。
C++では、変数を定義するとメモリーに値を入れる場所が確保されます。
ポインターは、そのメモリーの場所の先頭位置を 0 から 0xfffffff...(コンピューターに備わっているメモリー次第)という16進数の整数値として入れる変数です。
なお、このメモリーの場所のことをアドレス(address)とも言います。
#include <iostream>
using namespace std;
int main()
{
int num = 100;
int *ptr = #
cout << num << endl;
cout << ptr << endl;
cout << *ptr << endl;
cout << &num << endl;
num = 200;
cout << num << endl;
cout << *ptr << endl;
cout << ptr << endl;
cout << &num << endl;
return 0;
}
100
0x7ffeec062b88
100
0x7ffeec062b88
200
200
0x7ffeec062b88
0x7ffeec062b88
int *ptr = #
cout << ptr << endl;
cout << *ptr << endl;
ポインターの値(16進数のアドレス)を取得するには、ポインター名をそのまま記述します。
ポインターが指し示すアドレスに入っている値を取得するには、ポインター名の前に * をつけます。
num = 200;
cout << ptr << endl;
変数 num の値を変更しても、そのポインターが表すアドレスは変わりません。
次の「関数」で説明します。
#include <iostream>
using namespace std;
void func()
{
cout << "I am func." << endl;
}
int main()
{
func();
}
I am func.
関数は、次のように記述して定義します。
戻り値の型 関数名( 引数 )
{
処理;
}
func();
関数は呼び出される前に定義されていなければなりませんが、複数の関数が、お互いを呼び出すようなプログラムを記述する場合は、大変なことになります。そこで「関数の前方宣言」という方法を使います。
前方宣言を使うと function.cpp は、次のようになります。
#include <iostream>
using namespace std;
void func(); // 関数の前方宣言
int main()
{
func();
}
void func() // 関数の実際の定義は、関数の呼び出しよりも後で記述しています。
{
cout << "I am func." << endl;
}
前方宣言は関数の実装部分以外( { } 以外の部分)にセミコロン ; をつけたものです。前方宣言はプロトタイプ(prototype)とも呼ばれます。
変数名や関数名のようにプログラマーが自由につけられる名前のことを識別子(identifier)と言います。識別子には次の命名規則があります。
#include <iostream>
using namespace std;
int sum(int a, int b);
int main()
{
cout << sum(5, 5) << endl;
}
int sum(int a, int b)
{
return a + b;
}
10
int sum(int a, int b);
cout << sum(5, 5) << endl;
関数を呼びだす側では、引数に実際の値を、仮引数の順序に合うように、カンマ( , )で区切って指定します。
関数の呼び出し側で与える引数のことを「実引数(argument)」と言います。
return a + b;
ここで使われている + のような記号ことを「演算子(operator)」と言います。+ 演算子の意味は数学と同じで、「足す」という意味です。
引数の使い方には、「値渡し(by value)」と「参照渡し(by reference)」があります。
#include <iostream>
using namespace std;
int plus100(int a);
void plus200(int *a);
int main()
{
int a = 100;
a = plus100(a);
cout << a << endl;
plus200(&a);
cout << a << endl;
return 0;
}
int plus100(int a)
{
return a + 100;
}
void plus200(int *a)
{
*a = *a + 200;
}
200
400
plus100 関数では、aの値のコピーが引数として渡されています。aが直接渡されているわけではありません。したがってplus100 関数の中で、渡された値を加工しても、main 関数の中の a の値は変わりません。このような引数の渡し方を値渡しと言います。
一方、plus200 関数では、aのアドレス(ポインター)が引数として渡されています。plus200 関数の中では、ポインターをたどって main 関数の中の a の値を直接加工することができま。このような引数の渡し方を参照渡しと言います。
ポインターが必要となる大きな理由の一つとして、上記の引数の渡し方の違いにあります。値渡しで渡されるのは元のデータのコピーです。元のデータが動画データのような大きなサイズだった場合は、それと同様のメモリー容量が必要となります。
一方、ポインターを使った参照渡しでは、新たに必要となるメモリーサイズは、ポインター(アドレスを格納する変数)に必要な 8 バイトだけです。また、直接データが加工ができることも大きな点です。
関数がデータを戻り値として返す場合、その戻り値もメモリーに新たにコピーされ、新たなメモリー領域が消費されます。