【C/C++】C++言語文法
C言語を学びなおして、引き続きC++言語の文法の基礎を学習した。備忘録として残しておく。
今回も、C言語に続き、一週間で身につくC++言語の基本を教材として使わせていただいた。これが無料公開されているなんて、本当に感謝しかない。
ファイル分割
C言語同様に、C++のライブラリを #include <ライブラリ名>
で読み込むことができる。
C言語との違い
名前空間
名前空間は、C++言語の重要な概念である。
名前の衝突(同じ名前を付けることで呼び出し先が曖昧になること)を避けることができる。
(名前空間名)::(変数名・クラス名など) // 「::」はスコープ解決演算子 // ex. std::cout // stdという名前空間のcout
毎回、「std::」と定義するのは面倒なので、任意のスコープの冒頭で「using宣言」をすることで省略が可能となる。
using namespace (名前空間名); // ex. using namespace std; // 「std::」を全て省略して、coutに参照できる
using namespace <-name->
で省略して、複数の名前空間で同じ名前の変数・関数名があった場合に、競合してしまうことがある。これでは、名前空間での識別が無意味になってしまう。そのため、省略したい名前空間の変数や関数のみを明示することもできる。
using (名前空間名)::(変数名・クラス名など) // ex. using std::cout; // coutのみ、「std::」を省略して参照できる
C言語では、同じ名前の関数を定義するとエラーになる。
C++言語には、オーバーロード(多重定義)という機能があり、関数名が同じでも、引数が異なっていれば定義可能。
cin/cout、ストリーム
C言語の入出力(scanf / printf 等)も使うことができるが、C++言語では独自の実装方法がある。Linuxの標準入出力と似ている。ストリームというインターフェースを介して、ファイルやコンソールから入力を受け付けたり、出力先として設定することができる。
#include <iostream> int main(){ int a; std::cin >> a; std::cout << "a=" << a << std::endl; return 0; }
オブジェクト | 説明 |
---|---|
cin | 標準入力(stdin) |
cout | 標準出力(stdout) |
cerr | 標準エラー出力(stderr, unbuffered(*1)) |
clog | 標準エラー出力(stderr) |
データの流れは、「>>」「<<」で決定する。
(*1)バッファリングとは、データを一時的に保存しておくこと。バッファからデータが掃き出すことをバッファのフラッシュという。バッファのフラッシュにより、画面に文字が表示される。cerrは、unbufferedとなっているので、毎回フラッシュが行われる。
入出力の書式や制御は、マニピュレータ(manipulator)で行うことができる。
マニピュレータ | 説明 |
---|---|
std::endl | 改行文字を出力してバッファをフラッシュ |
std::flush | バッファをフラッシュ |
詳細は、以下を参照してほしい。
クラス
class CSample { public: CSample(); //コンストラクタ virtual ~CSample(); //デストラクタ void function(); //メンバ関数(メソッド) static void showAll(); //静的メンバ関数 private: int m_num; //メンバ変数 static int m_sum; //静的メンバ変数 };
アクセス指定子 | 意味 |
---|---|
public | すべての範囲から呼び出し・読み出し可能 |
private | 同一クラスまたは同一インスタンス内でのみアクセス可能 |
protected | 同一クラスまたは同一インスタンスおよび、サブクラスおよびそのインスタンス内でのみアクセス可能 |
インスタンスを生成することなく利用するできる変数、関数を静的メンバ変数、静的メンバ関数という。ただし、静的メンバ関数内では、静的メンバ変数のみしか使えないので注意が必要。
メンバへのアクセスを、そのクラスのメンバ関数(アクセスメソッド(*2))からしかできないように制限することをカプセル化(隠蔽)と言う。
(*2) setter, getter
// オブジェクト(インスタンス)の生成
CSample obj;
- メンバ変数やメンバ関数(メソッド)を使うときは、構造体と同様で、ドット演算子(.)を使う
- インスタンスへのポインタを経由するときは、アロー演算子(->)を使う
- 静的メンバ関数を使うときは、
(クラス名)::(メソッド名)()
を使う
メモリの生成と消去
メモリの生成 | メモリの消去 | |
---|---|---|
C言語 | malloc()/calloc()/realloc() | free() |
C++言語 | new演算子 | delete演算子 |
malloc関数やfree関数では、コンストラクタ、デストラクタが呼び出せないため、C++では通常メモリの生成と消去には、new/deleteが用いられる。
コンストラクタ:インスタンス化時に、自動的に一度だけ呼び出される
クラス名::クラス名() : メンバ変数1(初期値1),メンバ変数2(初期値2)… ex. CSample::CSample() : m_num(0) { // インスタンス生成時に実行したい処理 }
デストラクタ:インスタンスが解放される直前に、自動的に一度だけ呼び出される
クラス名::~クラス名() ex. CSample::~CSample() { // 解放直前に実行したい処理 }
配列のメモリを解放する場合は、delete[]
を用いる必要があるので注意。
#include <iostream> int main() { int *p = 0; int i; p = new int[10]; // int型10個分の領域を動的確保 for(i=0; i<10; ++i) { p[i] = i; std::cout << p[i] << std::endl; } delete[] p; // 動的に確保した領域を解放 return 0; }
継承(インヘリタンス)
- 継承とは、基本となるクラスの性質を受け継ぎ、独自の拡張をすることである。
- 継承元になるクラスを、親クラス、スーパークラスという。
- 親クラスを継承して、独自の機能を実装したクラスを、子クラス、サブクラスという。
class Sub : public SupA, public SupB { // Sub member }
- 子クラスのみにアクセスを許すメンバには、
protected
修飾子をつける。 - 親クラス、子クラスに同じ名前、同じ戻り値の型、同じ引数をとるメンバ関数が存在する場合、子クラスのメソッドは、親クラスのメソッドをオーバーライドする。原則的に子クラスに定義されたものが実行される。
ポリモーフィズム(多態性・多様性)
ポリモーフィズム | 説明 |
---|---|
オーバーロード | コンストラクタを含め、すべてのメンバ関数が、引数、および戻り値が違っていれば、同じ名前のついた複数の関数(メソッド)を定義することができる。 |
オーバーライド | 親クラスと同じメソッドが子クラスに存在する場合、子クラスのメソッドで上書きすることができる。 |
- ポリモーフィズムを利用する利点は、メソッドの名前が統一されることにより、名前を覚える必要がなくなることや、記述ミスを減らせることなどが挙げれる。
- オブジェクト指向では、原則的に同じ機能には同じメソッド名をつけることが好ましい。そうすることで、処理に統一感を持たせることができる。
まとめ
C言語に続き、C++言語の文法を学んでみた。C言語の上位互換であるC++言語は、より実装がしやすくなっていると感じた。JavaScriptなどのオブジェクト指向型言語であるC++言語は馴染みやすいと思えた。これからC++言語をもっと極めていきたいと思えた。