クラス


C++の中核

いよいよ、C++言語の真髄でありオブジェクト指向プログラミングの中核であるクラスを扱います
クラスの学習はC言語の「構造体」の理解があれば比較的容易です
C言語の構造体と比較しながら、少しずつその機能を紹介します

C++は、手続き型言語のCを直接拡張したものなので、オブジェクト指向性は比較的低いですが
オブジェクト指向型言語では、全てがこの「クラス」単位でプログラムされます

クラスの宣言は class キーワードを使用します
class class-name {
	member...;
} object-list;
構造体の宣言によく似ていることがわかりますね
class-nameには、このクラス型を識別するクラス名を指定します。これは、構造体のタグと同じです
object-listはクラスのオブジェクトを宣言しますが、構造体同様に省略可能です
また、class-nameも object-list 以外でオブジェクトを作成しなければ省略してもかまいません

memberには、メンバ変数などを宣言、定義します
構造体同様に、クラス内部で定義されるデータはメンバと呼びます

構造体では、宣言したメンバに直接アクセスすることができました
しかし、オブジェクト指向ではアクセス制御という概念があります
つまり、外部からデータにアクセスして良いものと、ダメなものを明示的に分けます
そうすることでモジュールのブラックボックス化を簡易に行い、高い保守を可能にします

クラスは構造体と異なりデフォルトでデータにアクセスできないのです
そこで、外部からアクセスするにはpublicキーワードでデータを公開する必要があります
class class-name {
	//外部からのアクセスはできない領域
public:
	//アクセス可能領域
} object-list ;
このように、オブジェクト指向ではデータの目的ごとにアクセス権を割り当てます
メンバ変数の宣言と役割については、構造体とまったく変わりません
アクセス方法も構造体と同じで クラス型変数名.メンバ名 というようにアクセスします
#include <iostream>
using namespace std;

class Kitty {
public:
	char *str;
} obj ;

int main() {
	obj.str = "Kitty on your lap";
	cout << obj.str;

	return 0;
}
このプログラムでは Kitty クラスを宣言しています
ここで定義されている obj は、Kitty型の変数と呼ぶことができます
この obj のようなクラス型変数を、オブジェクト指向ではオブジェクトと呼びます

構造体と同じように、クラス型変数「オブジェクト」は
生成されたオブジェクトごとにメンバ変数には異なるデータを保有します


メンバ関数

さて、上で紹介したクラスの宣言、定義方法は理解していただけたでしょうか
この状態では、構造体にアクセス制御が付加されただけですね
しかし、本質的なクラスの魅力からみれば、まだその機能の本の一角しか紹介していません

クラスには、メンバ変数だけではなく関数を持つこともできます
クラスに関連付けられた関数をメンバ関数と呼びます
(これはC++固有のもので、基本的にオブジェクト指向型言語ではメソッドと呼ぶ)

メンバ関数は、そのクラスのオブジェクトの「ふるまい」を定義することができます
通常の関数とは違い、メンバ変数同様にオブジェクトに作用する関数なのです

メンバ関数は、プロトタイプをクラス内部のメンバとして宣言します
これは、通常の関数とまったく違いはありません
class class-name {
	type function(type) {
		statements...;
	}
};
typeには戻り値及び仮引数の型を指定します。今までと同じですね
statements.. には、メンバ関数の内容を定義します
定義したメンバ関数へのアクセス方法は、メンバ変数同様にオブジェクト名とドット演算子を使用します
#include <iostream>
using namespace std;

class Kitty {
public:
	char *str;
	void print() {
		cout << str;
	}
} obj ;

int main() {
	obj.str = "Kitty on your lap";
	obj.print();
	return 0;
}
このプログラムでは、Kitty クラスに print() メソッドが定義されています
このメソッドは、オブジェクトが持つメンバ変数 str を出力するものです
関数が独立しているわけではなく、オブジェクトに割り当てられているのがわかると思います

さらに、クラス内部ではメンバ関数のプロトタイプだけを宣言することができます
class class-name {
	type function();
};
ここで宣言した関数の定義は、クラスの外部で行います
メンバ関数の定義を行う時は、その関数がどのクラスの関数かを明示しなければいけません
そこで スコープ解決演算子( :: ) を用いてクラスと関数名を指定します

type class-name::function(type) {
//関数の内容
}

メンバ関数は、同一クラス内のメンバ変数及びメンバ関数
関数内部のローカル変数、及びグローバル変数にアクセスすることができます

また、クラスの外部からアクセスできない領域というものがありました
しかし、クラスの外部からアクセスできなければどこからアクセスするのかという問題があります
そこで、外部と内部のデータのインターフェイスとなるのもメンバ関数になります

細かいアクセス制御の概念は、クラスの基本を網羅してから再び紹介します
この場では、publicに対するアクセス不能領域をprivateキーワードで明示できることを知ってください
プライベート領域に値の変更にシビアなメンバを置くことで、外部からの誤ったオペレートを避けることができます

#include <iostream>
using namespace std;

class Kitty {
private:
	int point;
public:
	void setPoint(int i);
	int getPoint(int i);
};

void Kitty::setPoint(int i) {
	point = i;
}

int Kitty::getPoint(int i) {
	point += i;
	return point;
}

int main() {
	Kitty obj;
	obj.setPoint(0);
	for (int i = 0 ; i < 10 ; i++)
		cout << obj.getPoint(i) << "\n";
	return 0;
}
setPoint()はprivateエリアのpoint変数に渡された値を代入し
getPoint()は 引数で与えられた数+point を返します

このように、プライベートエリアへのアクセスにメンバ関数をインタフェイスとすることで
例えば不正な値は代入できないようにするなど、セキュリティを高めることができます

上のプログラムの場合 private キーワードがクラスの先頭で使われていますが
その領域はデフォルトで private のため、省略しても問題はありません


class

class [tag [: base-list]]
{
member-list
} [declarators];

[ class ] tag declarators

クラス型を宣言する、またはクラスのオブジェクトを定義します
オブジェクトを生成する時には省略可能です

tag - クラス型の名前を指定します

base-list - ベースクラスを指定します(後記)。省略可能です

member-list - クラスのメンバ、またはフレンド(後記)を宣言します

declarators - オブジェクトを1つ以上宣言します。グローバルの場合は省略可能です



前のページへ戻る次のページへ