Cpp_class


※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

クラスについて


C++使うならクラスを始めにやりたいですよね。
C++のクラスの見た目は関数をメンバーに持つ構造体みたいなもんです。まずは実際に作って使ってみましょう。

ちなみに 次のようなクラスはタブー です。publicな意味で。でも構造体っぽさを出すためにこんなんにしました。

#include<string>
using namespace std;
#include<stdio.h>
#define POW_ON	1
#define POW_OFF 0

class Computer{
  public://やっちゃだめな例だけどわかりやすく。
    int power;
    string inputBuffer;
    void switchPow(){
      printf("スイッチ切り替え。");
      getchar();
    };//関数
};

int main(void){
	Computer com1;
	com1.power = POW_ON;//構造体みたいに代入可能
	com1.inputBuffer = "test.";
	com1.switchPow();//関数実行も可能
}

構造体と違うところ


  • 関数をメンバーに含められる
  • アクセス修飾子(ここではpublic)などを指定しなければいけない
関数を無くせば完全に構造体です。(実際にC++の構造体はpublicなclassのことだったりする)

では先ほどのソースはタブーなのですが、タブーを解消したソースを書くと次のようになります。(クラスの部分のみ)

class Computer{
  private:
    int power;
    string inputBuffer;
  public:
    void switchPow(){
      printf("スイッチ切り替え。");
      getchar();
    };//関数
};

こんな感じ。private:という単語が出てきました。
privateにしたメンバーは=でオブジェクトの外から値を代入できなくなります。
実際にコンパイルを行うとVC++では次のように怒られます。
'Computer::power' : private メンバ (クラス 'Computer' で宣言されている) にアクセスできません。
'Computer::inputBuffer' : private メンバ (クラス 'Computer' で宣言されている) にアクセスできません。

ね、代入できないでしょ?

というわけで、アクセサメソッドとかゲッターセッターとか呼ばれるものを使います。

オブジェクトとオブジェクトとのやりとりは基本は関数を用いて行います。
なので変数のようなものは内部に隠蔽して、
getOOOOやsetOOOOなどの通称アクセサメソッドを介して値を代入します。

#include<string>
using namespace std;
#include<stdio.h>
#define POW_ON	1
#define POW_OFF 0

class Computer{
  private:
    int power;
    string inputBuffer;
  public:
    void setPower(int p){
      power=p;
    };
    void setText(string s){
      inputBuffer = s;//値渡しキライよ
    };
    void switchPow(){
      printf("スイッチ切り替え。\n");
    };
};

int main(void){
  Computer com1;
  com1.setPower(POW_ON);  //引数に代入
  com1.setText("test.\n");
  com1.switchPow();
  getchar();
}

こんな感じに関数を経由して内部の変数を代入させるようにします。
classの中にあるモノ同士であれば問題なく値の利用ができるので、
引数から入ってきた値をメンバ変数に代入しています。

中を見たい!

もちろん代入ができるのだから、値の利用も可能です。
classのpublic:になっている部分に次の関数を追記してください。
void drawText(){
  printf("%s",inputBuffer.c_str());
};

main関数のgetchar();の前で
com1.drawText();
を実行してみてください。

setTextで指定した文字が表示されるはずです。

switchPowがあるのに何故使わない!Computerらしくせい。

ということで、ちゃんとswitchPowを利用してみましょう。
switchPowを呼び出した時に行われる動作は
  1. PowerがPOW_ONならPOW_OFFをPowerに代入
  2. PowerがPOW_OFFならPOW_ONをPowerに代入
です。何を当たり前と思いますが、そのとおりです。
でshowTextの処理を次のように変えましょう。
  1. PowerがPOW_OFFなら電源つけろ!メッセージを表示
  2. PowerがPOW_ONなら今まで通りinputTextを表示

という処理です。ちょっとコンピュータらしくなった?
あとsetPowerも消しましょう。電源値を設定するとかそれらしくないから。

#include<string>
using namespace std;
#include<stdio.h>
#define POW_ON	1
#define POW_OFF 0

class Computer{
  private:
    int power;
    string inputBuffer;
  public:
    Computer(){
      power=POW_OFF;
      inputBuffer="";
    };
    void setText(string s){
      inputBuffer = s;//値渡しキライよ
    };
    void switchPow(){
      if(power==POW_ON){
        power=POW_OFF;
      }else if(power==POW_OFF){
        power=POW_ON;
      }
    };
    void drawText(){
      if(power==POW_OFF){
        printf("電源つけろ。\n");
      }else{
        printf("%s\n",inputBuffer.c_str());
      }
    }
};
int main(void){
  Computer com1;
  com1.setText("test");
  com1.drawText();//電源ついてない実行
  com1.switchPow();
  com1.drawText();//電源ついてる実行
  getchar();
}
どや。

で、何気に使ってたコンストラクタ。

C言語で厄介だったもんは?って聞くといっぱいありすぎて困っちゃうと思いますが、
その一つに初期化というものがあります。
ポインタは初めにNULLを入れないと危ないし、フツーの変数も値を入れないと変な動作するし。
ということで、C++にはコンストラクタという仕組みがあります。
classの名前と同じ関数がclassの中で宣言されていますね。ここではComputer。
このComputerはこのオブジェクトが作られた瞬間に実行されます。
(オブジェクトの説明は最後にでも。)

初期化に複雑な処理を行わないのであれば次のように書くのが通例になってるみたいです。
Computer():power(POW_OFF),inputBuffer(""){};

ちなみに戻り値の型はいりませんし、関数内部でreturnしたならエラー吐きます。

main関数で2個以上Computerを定義すると?

構造体を複数定義すれば複数のデータが生成されて、
その分だけ保存可能になりますよね。
Classも同じで、宣言すれば宣言しただけデータが生成されます。
main関数を次のように打ち変えてください。

int main(void){
  Computer com1;
  Computer com2;
  com1.switchPow();
  com1.setText("test.\n");
  com2.showText();
  com1.showText();
  getchar();
}

com2はswitchPowをしていないので、電源が入っていません。
なのでcom2のshowTextを実行すると、電源つけろメッセージが出ます。
com1のshowTextは電源が入っているのでshowTextを受け付けて、

退屈だけどまとめ::オブジェクトとは?

1、内部に値を保持する(フィールド)
2、振る舞い方が定義されている(関数)
3、内部の値によって振る舞いを変える

というモンだと僕が解釈してます。ここでオブジェクトとは変数宣言したあとのcom1やcom2の
中に入ってるモノのことです。com1やcom2は変数なのでcom1やcom2自体がオブジェクトというわけではありません。(ややこしいですが。)
C言語で言うところの“値”に対応するものとして“オブジェクト”があるという感じです。
オブジェクトを作るにはクラスを定義してやる必要があります。
クラスで変数を作るとその変数の中に自動的に“オブジェクト”が作られます。
このような方法でできたオブジェクトを「静的オブジェクト」と呼びます。


個人的疑問点