C++のHello World

第3回は、C++を使ったHello Worldです。C++はC言語を拡張した言語です。たいていのC言語用のプログラムは、C++のプログラムとしてコンパイルしてもそのまま動作します。このため、リスト1のように、C言語用のHello Worldのプログラムをそのまま修正なしにC++のHello Worldのプログラムとすることができます。

リスト1 C言語と同じprintf()を使う方法(cpp_printf.cc)

#include <stdio.h>

int
main()
{
  printf("Hello World\n");   ← C言語と同様にprintf()を使う
  return 0;
}

C++のコンパイル方法はC言語の場合とほとんど同じです。コンパイラとしてgccを使う場合、実行例1のようにg++コマンド使ってコンパイルします。

実行例1 C++のコンパイルと実行

$ g++ -O2 -o cpp_printf cpp_printf.cc   ← g++を使ってC++のソースをコンパイル
$ ./cpp_printf               ← 作成された実行バイナリファイルを実行
Hello World                  ← たしかにHello Worldが表示される
$                            ← シェルのプロンプトに戻る

このほか、第1回でC言語用に作成した、fputs()やwrite()関数などを使ったHello Worldのプログラムも、同様にそのままC++のプログラムとすることができます。

iostreamを使う方法

C言語とまったく同じプログラムではおもしろくないため、C++ならではのHello Worldを考えてみましょう。

C++では、C言語のstdioライブラリに代わってiostreamライブラリが標準で用意されています。iostreamを使う場合、標準出力を表すstd::coutに対して、「<<」演算子を使うことにより、文字列を出力することができます。改行文字は、C言語と同様に"\n"で記述してもかまいませんが、C++ではstd::endlを使って改行することができます。

リスト2 iostreamを使う方法(cpp_iostream.cc)

#include <iostream>                          ← iostreamライブラリを使う

int
main()
{
  std::cout << "Hello World" << std::endl;   ← 標準出力に「<

変数の動的初期化を利用する方法

C++では、変数またはオブジェクトを定数値で初期化するだけではなく、動的な値で初期化することができます。

変数が関数の外部で静的変数(またはグローバル変数)として宣言されている場合、その初期化処理はmain()関数が呼び出される前に行なわれます。そこで、何らかの静的変数を関数の外部に宣言し、その初期化処理としてHello Worldを出力させることができます。

リスト3は、ダミーの静的変数iを宣言し、その動的初期化を利用してHello Worldを出力させている例です(ここではstd::coutなどのstd::を省略するため、「using namespace std;」の記述を加えています)。coutは、「void *」型(voidへのポインタ)に代入できるため、ダミー変数のiは「void *」型として宣言します。この例ではmain()関数の中では何も行なわず、main()の呼び出し前にHello Worldが出力されます。

リスト3 静的変数の動的初期化を利用する方法(cpp_init.cc)

#include <iostream>
using namespace std;    ← coutなどにstd::を付けるのを省略するための記述

static void *i = cout << "Hello World" << endl;  ← 静的変数の動的初期化を利用

int
main()
{
  return 0;             ← main()では何もせずにリターンする
}

ここで、静的変数の動的初期化のタイミングを確認するため、リスト4のようにHelloを静的変数の動的初期化で出力し、Worldをmain()関数内で出力するようにしてみましょう。このようにしても、Hello Worldの順序で出力され、静的変数の動的初期化がmain()よりも前に実行されていることがわかります。

リスト4 静的変数の動的初期化タイミングの確認(cpp_init2.cc)

#include <iostream>
using namespace std;

static void *i = cout << "Hello ";       ← 動的初期化では"Hello "だけを出力

int
main()
{
  cout << "World" << endl;               ← main()では"World"と改行を出力
  return 0;
}

静的変数の動的初期化だけを利用すれば、メッセージの出力はprintf()などのC言語の関数を使っても構いません。リスト5はprintf()を使った例です。一般にprintf()の戻り値は利用されることは少ないですが、戻り値には出力した文字数が返されます。そこで、これをダミーのint型静的変数に代入して動的初期化を行わせることができます。

リスト5 静的変数の動的初期化でprintf()を使う(cpp_init3.cc)

#include <stdio.h>                       ← stdioライブラリを使う

static int i = printf("Hello World\n");  ← printf()の戻り値を動的初期化に利用

int
main()
{
  return 0;         ← main()では何もせずにリターンする
}

クラスを使う方法

さらに、クラスを使わないとC++らしくない、ということで、クラスを使ったHello Worldを書いてみましょう。

リスト6はHelloクラスを定義し、そのコンストラクタの定義の中でHello Worldを出力している例です。このHelloクラスのオブジェクトを宣言すればコンストラクタが実行され、Hello Worldが表示される仕組みです。せっかくなので、Helloクラスをmain()外で静的オブジェクトとして宣言し、main()では何も実行しない方式にしてあります。

リスト6 クラスを使う方法(cpp_class.cc)

#include <iostream>
using namespace std;

class Hello {                        ← Helloクラスの定義
  public:                            ← 外部から操作できるようにpublicにする
    Hello() {                        ← コンストラクタの定義
      cout << "Hello World" << endl; ← メッセージを出力
    }
};

static Hello h;    ← Helloクラスのオブジェクトを静的に宣言する

int
main()
{
  return 0;        ← main()では何もせずにリターンする
}