C++はC言語をベースとしたオブジェクト指向プログラミング言語です。C++ の始め方をご紹介します。
C++ソースファイルの拡張子は .c または .cpp である。
gcc-c++がインストールされていない場合、以下のエラーが出力される。
$ gcc sample.cppgcc: error trying to exec 'cc1plus': そのようなファイルやディレクトリはありません
または
$ gcc sample.cppgcc: error trying to exec 'cc1plus': execvp: No such file or directory
Red Hat Enterprise Linux及びCentOSでgcc-c++をインストールする場合、yumコマンドを使用する。
# yum install gcc-c++
または
$ sudo yum install gcc-c++
コンパイル時に下記のエラーが出力されるときは、libstdc++をリンクする必要がある。
undefined reference to `__gxx_personality_v0'
collect2: ldはステータス 1 で終了しました
gcc sample.cpp -o sample -lstdc++
std::cout は、標準出力に関連付けられた出力ストリームオブジェクトである。出力はバッファリングされる。std::coutはstd::ostreamクラスのインスタンスで、グローバル変数である。
std::coutはヘッダostreamで定義されているため、std::coutを使用するプログラムはostreamをインクルードする必要がある。ただし、ostreamはヘッダiostreamからインクルードされているため、iostreamをインクルードしていれば、ostreamを明示的にインクルードする必要はない。
#include <iostream>
main() {
std::cout << "Hello C++ world!";
}
旧式のC++では名前空間stdは必要ない。この場合はiostream.hをインクルードする必要がある。
#include <iostream.h>
main() {
cout << "Hello C++ world!";
}
複数の値を「<<」で区切って並べることにより、複数の値を連結して出力することができる。
改行を行うには、「\n」または「std::endl」を出力する。
#include <iostream>
main() {
int cb = 64;
std::cout << cb << "bytes" << std::endl;
}
std::cerrは、標準エラー出力に関連付けられた出力ストリームオブジェクトである。std::clogと異なり、バッファリングされない。std::cerrはstd::ostreamクラスのインスタンスで、グローバル変数である。
std::cerrはヘッダostreamで定義されているため、std::cerrを使用するプログラムはostreamをインクルードする必要がある。ただし、ostreamはヘッダiostreamからインクルードされているため、iostreamをインクルードしていれば、ostreamを明示的にインクルードする必要はない。
#include <iostream>
main() {
std::cerr << "Hello C++ world!";
}
旧式のC++では名前空間stdは必要ない。この場合はiostream.hをインクルードする必要がある。
#include <iostream.h>
main() {
cerr << "Hello C++ world!";
}
std::clogは、標準エラー出力に関連付けられた出力ストリームオブジェクトである。std::cerrと異なり、バッファリングされる。std::clogはstd::ostreamクラスのインスタンスで、グローバル変数である。
std::clogはヘッダostreamで定義されているため、std::clogを使用するプログラムはostreamをインクルードする必要がある。ただし、ostreamはヘッダiostreamからインクルードされているため、iostreamをインクルードしていれば、ostreamを明示的にインクルードする必要はない。
std::cinは、標準入力に関連付けられた入力ストリームオブジェクトである。std::cinはstd::istreamクラスのインスタンスで、グローバル変数である。
std::cinはヘッダistreamで定義されているため、std::cinを使用するプログラムはistreamをインクルードする必要がある。ただし、istreamはヘッダiostreamからインクルードされているため、iostreamをインクルードしていれば、istreamを明示的にインクルードする必要はない。
#include <iostream>
main() {
int a;
std::cout << "a = ";
std::cin >> a;
}
旧式のC++では名前空間stdは必要ない。この場合はiostream.hをインクルードする必要がある。
#include <iostream.h>
main() {
int a;
cout << "a = ";
cin >> a;
}
std::endlは、改行文字をバッファに出力したうえ、バッファをフラッシュするマニピュレータである。
マニピュレータとは、ストリームに対して何らかの処理を加えるためのオブジェクトである。
std::cout << std::endl
std::flushは、出力バッファをフラッシュするマニピュレータである。
マニピュレータとは、ストリームに対して何らかの処理を加えるためのオブジェクトである。
std::cout << std::flush
std::endsは、文字列の終端文字 '\0' をバッファに出力するマニピュレータである。
マニピュレータとは、ストリームに対して何らかの処理を加えるためのオブジェクトである。
std::cout << std::ends
std::wsは、空白文字を読み飛ばして入力するマニピュレータである。
マニピュレータとは、ストリームに対して何らかの処理を加えるためのオブジェクトである。
std::string str;std::cin >> std::ws >> str;
C言語において変数名や関数名などの識別子は、一意(ユニーク)である必要があった。C++では名前空間(ネームスペース)が導入されて、識別子は名前空間込みで一意であればよくなった。
たとえば、次のようなC言語プログラムがあったとする。
int emp_no;
int dept_no;
int main(void) {
emp_no = 1;
dept_no = 2;
}
C++では次のように書ける。
namespace emp {
int no;
}
namespance dept {
int no;
}
int main(void) {
emp::no = 1;
dept::no = 2;
}
C++ では名前空間を定義することができる。
namespace 名前空間名
{
// 変数や関数の宣言
// または、関数やクラスの定義
}
名前空間を定義する例を示す。
#include <iostream>
namespace hello {
const char world[] = "Hello C++ world!";
}
main() {
std::cout << hello::world << std::endl;
}
なお、プリプロセッサのマクロ定義は常に大域(グローバル)名前空間に属する。
namespace myspace1 {
#define BUFSIZE (256)
}
namespace myspace2 {
#define BUFSIZE (512) // 別の識別子ではなく再定義となる
}
using宣言を使って、特定の識別子をスコープ演算子を省略できるようにすることができる。
#include <iostream>
namespace hello {
const char world[] = "Hello C++ world!";
}
main() {
using hello::world;
std::cout << world << std::endl;
}
usingディレクティブを使って、特定の名前空間に含まれるすべての識別子を、スコープ演算子を省略できるようにすることができる。
using namespace namespace-name;
namespace-name にはネームスペース名を指定する。
たとえば、using namespace std; とすることで、std::coutやstd::cinをcoutやcinと記述することができるようになる。
#include <iostream>
namespace hello {
const char world[] = "Hello C++ world!";
}
main() {
using namespace std;
using namespace hello;
cout << world << endl;
}
テンプレートとは、型指定パラメータに基づき関数およびクラスを生成するためのしくみです ("パラメータ化型" と呼ばれることもあります)。テンプレートを使用すると、1 つのクラスを各種のデータ型に適用できるので、型ごとにクラスを作成する必要がなくなります。
たとえば、2 つのパラメータのうち大きい方の値を返すタイプセーフな関数をテンプレートを使わずに作成するには、次に示すように一連のオーバーロード関数を作成する必要があります。
int max(int a, int b) {
return (a > b) ? a : b;
}
double max(double a, double b) {
return (a > b) ? a : b;
}
int main(int argc, char *argv[]) {
int max_int, a_int = 1, b_int = 2;
double max_dbl, a_dbl = 1.1, b_dbl = 2.3;
max_int = max(a_int, b_int);
max_dbl = max(a_dbl, b_dbl);
}
テンプレートを使用すると、次のように重複部分を 1 つの関数テンプレートにまとめることができます。
template <class T> T max(T a, T b) {
return ( a > b ) ? a : b;
}
int main(int argc, char *argv[]) {
int max_int, a_int = 1, b_int = 2;
double max_dbl, a_dbl = 1.1, b_dbl = 2.3;
max_int = max<int>(a_int, b_int);
max_dbl = max<double>(a_dbl, b_dbl);
}
テンプレートを使用すると、型を保証しながらソースコードを大幅に小型化し、コードの融通性を向上できます。
渡された引数の絶対値を戻り値として返す。
整数の絶対値を求める場合は、cstdlibをインクルードする。
int abs(int n);
long int abs(long int n);
long long int abs(long long int n);
#include <iostream>
#include <cstdlib>
main() {
std::cout << std::abs(-1) << std::endl;
}
浮動小数点数の絶対値を求める場合は、cmathをインクルードする。
float abs(float x);
double abs(double x);
long double abs(long double x);
#include <iostream>
#include <cmath>
main() {
std::cout << std::abs(-1.1) << std::endl;
}
渡された2つの引数の値を比較して、大きい方の値を戻り値として返す。
template <class T> const T& max(const T& a, const T& b);
std::maxの使用例を次に示す。
#include <iostream>
#include <algorithm>
main() {
std::cout << std::max(1, 2) << std::endl;
}
渡された2つの引数の値を比較して、小さい方の値を戻り値として返す。
template <class T> const T& min(const T& a, const T& b);
std::minの使用例を次に示す。
#include <iostream>
#include <algorithm>
main() {
std::cout << std::min(1, 2) << std::endl;
}
std::runtime_errorは、例外としてスローされるオブジェクトの型である。プログラムの範囲を超えた事象に起因している、容易に予測できないエラーを報告する。stdexceptヘッダで定義されている。
2つの数値を足した値を返す関数を作成するとする。C言語の場合は次のようになる。
int add_int(int a, int b) {
int ans;
ans = a + b;
return ans;
}
double add_dbl(double a, double b) {
int ans;
ans = a + b;
return ans;
}
int main() {
int ans_int, a_int = 1, b_int = 2;
double ans_dbl, a_dbl = 1.1, b_dbl = 2.3;
ans_int = add_int(a_int, b_int);
ans_dbl = add_dbl(a_dbl, b_dbl);
}
2つの関数add_intとadd_doubleは共に「2つの数値を足した値を返す関数」である。同じ処理を行う関数であるので抽象的には同じ関数であるが、C言語の規則により、それぞれ別の関数名にしなければならない。
C++のオーバーロードを用いれば、これらの関数(メソッド)を同じ名前にすることができる。
int add(int a, int b) {
int ans;
ans = a + b;
return ans;
}
double add(double a, double b) {
int ans;
ans = a + b;
return ans;
}
int main() {
int ans_int, a_int = 1, b_int = 2;
double ans_dbl, a_dbl = 1.1, b_dbl = 2.3;
ans_int = add(a_int, b_int);
ans_dbl = add(a_dbl, b_dbl);
}
どちらの関数(メソッド)が呼び出されるかは、呼び出し側の引数と戻り値の型によってコンパイル時に決定される。
オーバーロードを用いれば同じ関数名(メソッド名)にすることができるが、定義はそれぞれ別々に行わなければならない。C++のテンプレートを用いれば、引数と戻り値の型を抽象化することにより、これらの関数(メソッド)を1つの定義にまとめることができる。
BoostはC++のコミュニティによって公開されているオープンソースのライブラリである。
Boostを使用するには、あらかじめパッケージをインストールしておく必要がある。
Red Hat LinuxおよびCentOSの場合、yum コマンドでBoost C++ライブラリをインストールする。
# yum install boost boost-devel
コンパイル時には、Boostライブラリのインクルードディレクトリを指定する必要がある。
$ gcc -I /usr/include/boost sample.cpp
Microsoft Windows の場合、Boost C++ Libraries のサイトから書庫ファイルをダウンロードする。書庫ファイルを任意のディレクトリに展開する。
filesystem、graphparallel、iostreams、mpi、programoptions、python、regex、serialization、signal、system、thread及びwave以外のライブラリはヘッダファイルをインクルードするだけで使用できる。その他のライブラリを使う場合は、ビルドが必要である。ビルドするには、boootstrapとbjamのコマンドを実行する。コマンドを実行すると、stage\libディレクトリにライブラリファイルが生成される。
bjamは、Boost C++ライブラリをビルドして指定したフォルダにヘッダファイルとライブラリファイルを保存するコマンドである。
bjam [options] [properties] [install|stage]
installを指定した場合は、ライブラリをビルドして、ヘッダファイルとライブラリファイルを指定したディレクトリへコピーする。stageを指定した場合は、ライブラリをビルドして、ライブラリファイルを指定したディレクトリへコピーする。
bjamのコマンドオプションは次のとおり。
値 | 説明 |
---|---|
static | スタティックライブラリ |
shared | ダイナミックリンクライブラリ |
bjam link=static,shared
値 | 説明 |
---|---|
static | スタティックリンク |
shared | ダイナミックリンク |
bjam runtime-link=static,shared
値 | 説明 |
---|---|
msvc | Microsoft Visual C++ |
msvc-8_0 | Microsoft Visual C++ 8.0 |
msvc-9_0 | Microsoft Visual C++ 9.0 |
intel | Intel C++コンパイラ |
gcc | GNU Compiler CollectionのC、C++及びObjective-Cコンパイラ |
値 | 説明 |
---|---|
single | シングルスレッドバイナリ |
multi | マルチスレッドバイナリ |
bjam threading-multi
次に示すオプションは、installを指定した場合にのみ有効である。
次に示すオプションは、stageを指定した場合にのみ有効である。
Boostのライブラリファイル名は次の形式で表される。
libboost_name-vc90-option-version.lib
name はfilesystemやthreadなどのライブラリ名である。
option はライブラリの種類を表している。
option | 説明 |
---|---|
mt | マルチスレッド版 |
mt-gd | マルチスレッド、デバッグ版 |
mt-s | マルチスレッド、スタティックCランタイム版 |
mt-sgd | マルチスレッド、スタティックCランタイム、デバッグ版 |
s | シングルスレッド版 |
version はBoost C++ライブラリのバージョンである。
共有オブジェクト(*.so)にBoostのスタティックライブラリをリンクする場合は、bjamのコマンドオプションに「cxxflags=-fPIC」を指定してBoostライブラリをビルドする。
$ ./bjam link=static --prefix=/home/horiuchi/local cxxflags=-fPIC install