Index |
 |
HOME >
プログラムTOP >
C++ |
|
C++の基礎知識(10)
【クラス篇】
| ●宣言と実装 | ●作成と破棄 | ●アクセス修飾子 | ●thisポインタ | ●継承 |
クラスでは変数や定数、関数を定義することができます。使用する際は通常の変数と同じように扱うことができます。これらのクラス独自の変数や関数をメンバと呼びます。宣言時の書式は構造体などに準じており、以下のようなものになります。
// クラスの宣言
class Code /* クラス名 */
{
public: /* アクセス修飾子 */
int id; // メンバ変数
char name[50]; // メンバ変数
Code(){} // コンストラクタ
~Code(){} // デストラクタ
void Show() { /* メンバ関数 */
printf("%d, %s\n", id, name);
}
} ;
| // main関数
void main() {
// クラスの実体の作成
Code code1;
// メンバ変数へ値を代入
code1.id = 9999;
strcpy(code1.name, "abc");
// メンバ関数の実行
code1.Show();
}
|
通常、定義はヘッダファイルに、実装はソースファイルに記述します。この時、メンバ関数の実装の際は、どのクラスのメンバかを明確にするため、クラス名+演算子 " :: " をメンバ名の前につける必要があります。
/* code.h */
#include <stdio.h>
// クラスの定義
class Code
{
public:
int id;
int sect;
char name[50];
Code();
~Code();
void Show();
} ;
| /* code.cpp */
#include "code.h"
// クラスの実装
Code::Code() {
}
Code::~Code() {
}
void Code::Show() {
printf("%d, %s\n", id, name);
}
|
コンストラクタはクラスの実体(インスタンス)を作成すると呼び出されます。また、デストラクタは実体が破棄されるときに呼び出されます。これらは次のような特徴を持ちます。
・コンストラクタはクラス名と同じであること。
・デストラクタはクラス名の頭に "~ " を付けたものであること。
・全く値を返さないこと。(データ型の記述はなし)
コンストラクタでは、以下のようにメンバ変数の初期値の設定などの処理を行うことができます。なお、コンストラクタとデストラクタの定義は省略が可能で、また、コンストラクタはオーバーロード(多重定義)が可能です。ただし、定義をする時は、少なくとも引数を持たないコンストラクタがひとつ必要です。
// コンストラクタと初期値の設定
// ": "の後に続けて記述
// "変数1(値), 変数2(値) ... "
Code::Code() : id(9999), sect(1)
{
strcpy(name, "None");
}
| // コンストラクタのオーバーロード
Code(); // 引数なし(必須)
Code(int _id); // 引数あり
// 実体作成(呼出)
Code code1; // 引数なし
Code code2(9999); // 引数あり
|
アクセス修飾子は、メンバの外部とのアクセス範囲を定めるためのものです。記述した部分以降のすべてのメンバに適用されます。また、省略すると private が適用されます。
| 種類 | クラス内からのアクセス | 継承クラスからのアクセス | 外部関数からのアクセス |
| private
| ○ | × | × |
| protected
| ○ | ○ | × |
| public
| ○ | ○ | ○ |
// アクセス修飾子
class Code {
private :
int id; // private
void SetID(int); // private
public :
int sect; // public
Code(); // public
protected :
~Code(); // protected
int GetID(); // protected
public :
void Show(); // public
} ;
|
// メンバへのアクセス
void main()
{
Code cd1;
int a = cd1.id; // アクセス不可
int b = cd1,sect; // アクセス可
cd1.SetID(99); // 呼出不可
int c = cd1.GetID(); // 呼出不可
cd1.Show(); // 呼出可
}
|
上記の他に friend修飾子があり、これをつけた外部の関数(friend関数)からは privateメンバへのアクセスが可能となります。また、friend修飾子をつけた外部のクラス(friendクラス)からも privateメンバへのアクセスができます。。friend関数と friendクラスは、適用するクラス内で friend をつけて宣言し、実体定義の際の friendの記述は必要ありません。
// クラスの宣言
class Code
{
private :
int id; // privateメンバ
public :
Code();
~Code();
friend void Show(Code cd);
} ;
// クラスの実装
Code::Code() {
}
Code::~Code() {
}
// Show関数
void Show(Code cd) {
cd.id = 5555; // アクセス可
printf("%d", cd.id);
}
// main関数
void main() {
Code code1;
Show(code1);
}
| // クラスの宣言
class Code {
private:
int id; // privateメンバ
public:
Code() {}
~Code() {}
friend class Sect;
};
class Sect {
public:
Sect() {}
~Sect() {}
void Show(Code cd);
};
// クラスの実装
void Sect::Show(Code cd){
cd.id = 5555; // アクセス可
printf("%d", cd.id);
}
// main関数
void main() {
Code code1;
Sect sect1;
sect1.Show(code1);
}
|
thisポインタ(this->メンバ名)は実体がある時に、自分自身を指します。本来メンバへのアクセスにはメンバ参照演算子( ". " , "->" )の記述が必要ですが、自分のクラスで自分のメンバ名を使用する際は通例は省略されます。 ただし、記述が必要なケースもあります。例えば、以下のコンストラクタの引数名に "id" を使いたい場合、すでにクラスのメンバ名になっているので、このまま代入すると正常な値が代入されません。この時、メンバ側に thisポインタをつけると、自らを指すことが明確になり正常な値が代入されます。
// thisポインタで、
// 記述が必要なケース
Code::Code(int id)
{
this->id = id;
strcpy(name, "None");
}
| // thisポインタは、
// 通常は省略(あえて記述)
void Code::Show()
{
printf("%d\n", this->id);
printf("%s\n", this->name);
}
|
クラスは別クラスに引き継ぐことができます。この時、protecteメンバか publicメンバであれば、元クラスのメンバを自動的に取り込むことになります。また、コンストラクタは、まず元クラスのコンストラクタが呼ばれ、続いて自クラスのコンストラクタが呼ばれます。
// 元クラスの宣言
class Code
{
protected:
int id; // protectedメンバ
public:
Code() {}
~Code() {}
};
// 継承クラスの宣言
class Sect : public Code
{
int room; // クラス独自のメンバ
public:
Sect() {}
~Sect() {}
void Show();
};
|
// 継承クラスの実装
void Sect::Show()
{
// idは元クラスから受継いだメンバ
id = 7777;
printf("%d", id);
// roomは独自のメンバ
room = 999;
printf("%d", room);
}
// main 関数
void main()
{
Code code1;
Sect sect1;
sect1.Show();
}
|
|
www.sasaraan.net |
(c) morijoh |