C++におけるクラスの特徴
C#やJavaとは異なり、C++ではクラスを作ることができますが、クラスを作らなくてもプログラムの作成は可能です。
クラスを作る。
構文
|
1 2 3 4 5 6 7 |
class クラス名{ private: //非公開関数と変数 データメンバ名 変数名; public: //公開関数と変数 } |
Privateを省略した場合は、指定がないメンバに関してはprivateになります。
また、class自体は「classキーワード」だけではなく、「structキーワード」を使うこともできます。その場合は、指定なしのメンバはpublicになるので、その違いに注意しましょう。
クラスを使う。
構文
自動メモリにクラスを定義
|
1 2 |
クラス名 インスタンス名; インスタンス名.メンバ名; |
フリーストアにクラスを定義
|
1 2 |
インスタンス名 -> メンバー変数 インスタンス名 -> メンバー関数() |
|
1 2 |
クラス* インスタンス名 = new クラス名(); インスタンス名 -> 関数(); |
C++のクラスで、Java等のクラスと異なる点としては、「クラス」にもポインタを使うことができる点でしょう。
メンバ変数の定義
静的メンバ変数を定義する。
メンバ変数にstaticキーワードをつけると、全てのインスタンス共通のメンバ変数とすることができます。
下記のように、クラス内で実体を宣言しないとコンパイルエラーになってしまうので注意です。
|
1 |
型 クラス名::変数名; |
メンバ関数を定義する。
プログラムが大きくなる場合は、クラスの定義をヘッダファイル(.h)に記述し、メンバ関数をソースファイル(.cpp)に記述するのが一般的になります。少し、JavaやC#のメソッド定義とは異なりますよね。
これは、ヘッダファイル「クラスの定義(仕様)」と、ソースファイル「実装」を分離して、コードを単純化する目的があるためです。
構文
クラス定義の中で、メンバ関数の宣言をまず行います。
|
1 2 3 |
class クラス名{ 戻り値 メンバ関数(パラメータリスト); } |
次に、メンバ関数を定義します。具体的な処理内容はクラスの外で定義するので注意です。
また、メンバ関数が属するクラスを明示します。
|
1 2 3 |
戻り値の型 クラス名::メンバ関数名(パラメータ){ 処理内容 } |
クラステンプレートを使う。
クラスもテンプレート化することができます。
構文
|
1 |
template <typename T> |
クラス内で「T」という型を指定することで、クラス生成時に色々な型(int、double等)を定義することができます。
クラスの初期化
コンストラクタを使う。
クラスからオブジェクトを構築する場合に「コンストラクタ」というメンバ関数が呼ばれます。
クラス内で下記の構文を使います。
|
1 2 3 |
クラス名(パラメータリスト){ 処理内容 } |
デフォルトコンストラクタ
引数のないコンストラクタのことを「デフォルトコンストラクタ」と呼びます。
何も記述しなければ、暗黙的に定義されますが、一つでもコンストラクタを定義してしまうと暗黙定義のコンストラクタは定義されないので注意です。
初期化専用の構文を使う。
C++のクラスでは、「コントラクタ」以外にも初期化専用の構文が用意されています。
場合によっては、それを使った方が効率が良くなる場合があります。
|
1 |
クラス名(パラメータリスト) : フィールド名(値),… |
クラスの解体(デストラクタ)
デフォルトコンストラクタと同様に、クラスを解体するときに暗黙的に定義されます。
ただ、暗黙デストラクタは何もしないので、何かさせたい場合は下記のように明示します。
|
1 2 3 |
~クラス名() { 処理内容 } |
なお、クラスの解体はメインプログラムの方で、delete文を使うと解体されます。
デストラクタの重要な役割
デストラクタの重要な役割としては、データメンバがフリーストアに配置をされる場合です。
データメンバが持つポインタをdelete ポインタとして、解体してあげる必要があります。
そうしないとメモリリークの発生率が高まってしまいます。
ポインタをクラスメンバにする意義
前提
例えば、下記のようなクラスがあるとします。
|
1 2 3 |
class Test{ int a; } |
メインプログラムの中で、下記のようにnewでフリーストアに対してオブジェクトを格納したとしたら、解放する前に途中で例外が発生したりするとメモリリークの危険性が増してしまいます。
|
1 2 3 4 5 |
//クラスをnewする。 Test* test = new Test; ★ここで例外発生 //作ったクラスを解放する。 delete test; |
そこで、下記のようにリソースを管理するための別のオブジェクトを作成して、コンストラクタとデストラクタでのみオブジェクトの作成と解放を行わせます。
|
1 2 3 4 5 6 7 8 9 |
class Test{ int a; } class WrapTest{ Test* test; WrapTest(): test(new test){} ~WrapTest() {delete test;} } |
このような手法のことを資源獲得時初期化と呼んでいて、よく使われています。
標準関数
C++は、関数の集合体になり、プログラムで実行される操作のほとんどを関数の中に記述することになります。
使い方
基本的には、「#include <ヘッダファイル名>」でライブラリをインクルードして、引数と戻り値の型さえ意識すれば普通に使うことができます。
下記のようなサイトで確認することができます。
cppjp
cplusplus
http://www.cplusplus.com/
自作関数
もちろん、自分で関数を作ることも可能です。
構文
|
1 2 3 |
戻り値の型 関数名(パラメータ名){ 処理内容; } |
外部ファイルの関数をするには?
関数プロトタイプ宣言をすればそれだけで外部ファイルの関数を使えます。
例
参照元
|
1 2 3 4 5 6 7 |
#include <iostream> using namespace std; void Func() { cout << "参照されます。"; } |
参照先
|
1 2 3 4 5 6 7 8 9 10 11 |
#include <iostream> using namespace std; //プロトタイプ宣言 void Func(); int main() { //外部ファイルの関数を使える。 Func(); } |
変数の場合は、外部ファイルの変数を使う場合は、externをつける必要がありましたが、関数の場合はプロトタイプ宣言をすれば使えるのです。
外部ファイルから関数を参照させたくない場合
外部ファイルでプロトタイプ宣言をすれば、外部から関数を参照できます。
それをさせたくない場合は、staticキーワードを付けます。
|
1 2 3 |
static 戻り値 関数名(){ 処理内容; } |
仮想関数とは?
C++において基底クラスの関数をオーバーライドする際に、必要な条件の一つです。
オーバーライドさせたい基底クラスの関数は、「仮想関数」にする必要があるのです。
構文
仮想関数の定義は簡単です。
基底クラスの関数の一番先頭に「Virtual」というキーワードをつけるだけです。
|
1 2 3 |
class 基底クラス名{ virtual void 関数名(){}; } |
関数テンプレートとは?
例えば、戻り値や、引数の型だけ違い、処理内容が全く同じという関数がある場合があると思います。
そうした場合に、型を定めずに、記述するというC++の「関数テンプレート」という機能があります。
構文
|
1 2 3 4 5 |
template <typename T> T 関数名(T num){ numを使った処理内容 } |
テンプレート仮引数
色々使われますが、最もよく使われるのが「typename」というテンプレート仮引数になります。
入出力演算子
C言語でいうところの「print()」(出力)や、「scanf()」(入力)にあたる機能のことです。
出力演算子
構文例
|
1 |
count << 出力したい値 |
coutは、既定義のストリームになります。
出力文字列の最後で改行したい場合は、endlというキーワードを使います。
|
1 |
cout << "出力文字列" << endl; |
入力演算子
|
1 |
cin >> 入力したい値 |
サンプルプログラム
|
1 2 3 4 5 6 7 8 9 10 |
#include <iostream> using namespace std; int main() { int i; cout << "値を入力してください:"; cin >> i; cout << i; } |


この記事へのコメントはありません。