10月26日 今日の大事なこと
classとインスタンスとオブジェクト
class A { //なんやかんや };
があった時、今まで、class型の変数(のようなもの)とかごまかしてたものがあります。
A myA;
このAとmyAの関係を、今まではclass A型の変数myAとか言っていました。
正式には、この言い方は正しくありません。
通常は、以下のように言います。
- myA は class A のインスタンス(instance)である。
または、classを省略して、
- myA は A のインスタンス(instance)である。
と言います。
ちょっとだけオブジェクト指向の話になると、少し話は微妙になってしまいますが、
- C++では、オブジェクトと言えばclassから実際に生成されたインスタンスの事を指す。
と言えます。
(哲学的な話をすると、オブジェクト指向で記述したC++のプログラムでは、インスタンスはクラス設計をもとに生成されたオブジェクトである。と言えますが、オブジェクトと言えばクラスのインスタンスをいつも指すとは限りません。C++だけに限った話でいうと、インスタンス≒オブジェクトと言えるだけです。)
構造体の時も、構造体型の変数はインスタンスと呼んで大丈夫です。
クラスは、オブジェクトの設計図、その設計図をもとに実際に作り出されたものがオブジェクトやインスタンスと呼ばれます。
設計図から、同じパラメータを持った、別の実体をいくつも作り出すことができます。
設計図に実際に値を設定して、参照できる状態になったものがインスタンス、オブジェクトです。
SetterとGetter
セッターとゲッターってのを学びました。
- Setterはクラスの外から、クラス内のメンバ変数の値をセット(代入)するためのメンバ関数
- Getterはクラスの外から、クラス内のメンバ変数の値をゲット(参照)するためのメンバ関数
です。 オブジェクト指向では、メンバ変数はできる限りprivateなメンバにしておいて、利用側は直接メンバに値を代入したり、参照したりしないようにするのがよいとされています。
class cPoint { public: cPoint();//コンストラクタ int x, y; }; //コンストラクタ:x,yを原点に設定 cPoint::cPoint() { x = 0; y = 0; } int main() { cPoint P; //cPoint型のインスタンスとして点Pを作成 //P(15, 5)を設定 P.x = 15; P.y = 5; std::cout << "P(" << P.x << ", " << P.y << ")" << std::endl; }
上のソースコードで宣言されているクラスは2次元平面上の、整数座標を表すクラスです。
上のソースコードでは、クラスcPointのインスタンスPでパブリックなメンバ変数int x,yに直接値を代入しています。
今までclassを習う前に使っていた構造体では、このような使い方が多かったと思います。
class cPoint { public: int x, y; cPoint();//コンストラクタ }; //コンストラクタ:x,yを原点に設定 cPoint::cPoint() { x = 0; y = 0; } using namespace std; int main() { cPoint P; //国語:80点 英語:60点 P.x = 80; P.y = 60; P.y = P.y + P.x; //なぜかp.yに合計点を計算 //合計点を表示 std::cout << "合計" << P.y << "点" << std::endl; }
このソースコードでは、cPoint型のインスタンスPに、試験の点数を代入して、合計点を求めています。
intの変数を使った計算がしたかったんでしょうね。
上のソースコードのように、変数の型だけを見て、いくらでももともとのクラス設計と違う変数の使い方ができてしまいます。
(ぶっちゃけ、なんでこんなことをしたのかは、訳が分からないかと思いますが、実際このような使い方をする人が多々います。
これをなるべく防ぐにはどうしたらよいでしょうか?
オブジェクト指向では、このようにメンバ変数をパブリックにして、直接値を代入するようなやり方はよくないとされています。
そこで、メンバ変数にアクセスするためのメソッドを作って、間接的に値を変更するという技をよく使います。
以下のソースコードでは、メンバ変数 x, y を private にして外からのアクセスをブロックしています。
メンバ変数 x, y に値を代入、参照する場合は、アクセス用変数を利用するという例です。
class cPoint { private: int x, y; public: cPoint();//コンストラクタ void setX(int _x); void setY(int _y); void setXY(int _x, int _y); int getX(); int getY(); }; //コンストラクタ:x,yを原点に設定 cPoint::cPoint() { x = 0; y = 0; } void cPoint::setX(int _x) { x = _x; } void cPoint::setY(int _y) { y = _y; } void cPoint::setXY(int _x, int _y) { x = _x; y = _y; } int cPoint::getX() { return(x); } int cPoint::getY() { return(y); }