C++はC言語の上にオブジェクト指向プログラミングの概念を組み込み、多くの有用なライブラリとプログラミングパラダイムを追加した言語です。この記事では、C言語の文法の欠点を補うとともに、C++がどのように不合理的設計を改善したかについて説明します。特に、スコープ、入出力、関数、ポインタ、マクロなどについて触れていきます。
1. C++キーワード (C++98)
C++には63のキーワードがあり、C言語には32のキーワードがあります。
ここでは、これらのキーワードの詳細については後回しにし、必要になったときに別途解説します。
2. 名前空間
C言語では、同じスコープ内に同じ関数名や変数名を持つことはできません。例えば、
#include <stdio.h>
#include <stdlib.h>
int rand = 10;
int main()
{
printf("%d\n", rand);
return 0;
}
<stdlib.h>ヘッダファイルでrandが「関数」として定義されており、また「関数」randはグローバルスコープで定義されています。さらに、グローバル変数randを定義すると、「rand」が再定義されたというエラーになります。
しかし、C++では、変数、関数、そして後の章で学ぶクラスなど多くの識別子が存在します。これらはすべてグローバルスコープに存在するため、衝突を引き起こす可能性があります。これを解決するためにC++では名前空間が導入されました。
2.1 名前空間の定義
C++におけるスコープは次のようになります:1. グローバルスコープ;2. 局部スコープ;3. 名前空間スコープ;4. クラススコープ。
名前空間を定義するには、namespaceキーワードを使用し、その後に名前空間の名前を指定し、波括弧で囲む必要があります。波括弧内が名前空間のメンバーとなります。
namespace MyProject
{
int value = 42;
void printValue() {
std::cout << value << std::endl;
}
}
名前空間はネストすることもできます。
namespace Outer {
namespace Inner {
int nestedValue = 100;
}
}
同じプロジェクト内で同じ名前の名前空間を定義することは可能です。コンパイラは最終的にそれらを1つの名前空間として結合します。
2.2 名前空間の使用
名前空間のメンバーを使用するには、次のようにします。
#include <iostream>
namespace MyProject {
int value = 42;
void printValue() {
std::cout << value << std::endl;
}
}
int main() {
// コンパイルエラー:value が見つからない
// std::cout << value << std::endl;
// 正しい使用法
std::cout << MyProject::value << std::endl;
MyProject::printValue();
return 0;
}
名前空間のメンバーを使用するには、名前空間名とスコープ解決演算子(::)を使用します。また、usingディレクティブを使用して名前空間全体または特定のメンバーを現在のスコープに取り込むことも可能です。
#include <iostream>
namespace MyProject {
int value = 42;
void printValue() {
std::cout << value << std::endl;
}
}
int main() {
using namespace MyProject;
std::cout << value << std::endl;
printValue();
return 0;
}
ただし、using namespaceを使用すると名前衝突のリスクがありますので、注意が必要です。
3. C++の入力と出力
次に、C++の基本的な入出力を紹介します。まずは「Hello World」プログラムから始めます。
#include <iostream>
using namespace std;
int main() {
cout << "Hello, World!" << endl;
return 0;
}
<iostream>は入出力ストリームライブラリで、標準入出力のためのオブジェクトを定義しています。stdはC++標準ライブラリの名前空間です。coutはostreamクラスのオブジェクトで、標準出力ストリームを表します。cinはistreamクラスのオブジェクトで、標準入力ストリームを表します。endlは行末を示す特殊なシンボルで、バッファをフラッシュします。
4. デフォルトパラメータ
デフォルトパラメータは、関数のパラメータにデフォルト値を設定できる機能です。
#include <iostream>
using namespace std;
void display(int num = 10) {
cout << num << endl;
}
int main() {
display(); // デフォルト値を使用
display(20); // 引数を指定
return 0;
}
デフォルトパラメータの注意点:
- デフォルトパラメータは関数宣言または定義時に設定します。
- デフォルト値は定数またはグローバル変数でなければなりません。
- デフォルトパラメータはC言語ではサポートされていません。
- デフォルトパラメータを指定するとき、左から順番に行う必要があります。
5. 関数オーバーロード
関数オーバーロードは、同じ名前の関数を異なるパラメータリストで定義することを意味します。
#include <iostream>
using namespace std;
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int main() {
cout << add(5, 5) << endl; // 整数版のaddが呼び出される
cout << add(10.0, 9.9) << endl; // 浮動小数点版のaddが呼び出される
return 0;
}
関数オーバーロードは次の要素によって区別されます:
- パラメータの型
- パラメータの数
- パラメータの順序
関数オーバーロードの原理は、コンパイラが関数名にパラメータ情報をエンコードすることで、同じ名前の関数でも異なるアドレスを持つようにします。