第6回
クラスとオブジェクト
C++の中心的な考え方であるクラスを理解する。
クラスを使わない場合
int motorSpeed;
void setMotorSpeed(int speed) {
motorSpeed = speed;
}問題:
- 関連するデータと処理が離れている
- グローバル変数が増える
- モータが複数あると管理しづらい
クラス化
class Motor {
public:
void setSpeed(int speed);
private:
int speed;
};データと処理をまとめる。これがクラスの一番の役割である。
オブジェクト
Motor motor1;
Motor motor2;同じクラスから複数のオブジェクトを作れる。motor1とmotor2はそれぞれ独立したspeedを持つ。
class Motor ← 設計図
│
┌────┴────┐
↓ ↓
motor1 motor2 ← 実体(オブジェクト)メンバ変数
private:
int speed;メンバ関数
public:
void setSpeed(int speed);アクセス制御
クラスのメンバにはアクセス制御が適用される。詳細は第8回カプセル化を参照。
public: 公開。外部からアクセス可能private: 非公開。クラス内部でのみアクセス可能protected: 限定公開。派生クラスからはアクセス可能
this
void Motor::setSpeed(int speed) {
this->speed = speed;
}引数speedとメンバ変数speedを区別する。
コンストラクタ
class Motor {
public:
Motor(int pin);
private:
int pin;
};Motor::Motor(int pin) {
this->pin = pin;
}使用:
Motor motor(24);コンストラクタは、オブジェクトが作られるときに必ず1回呼ばれる。「初期化を忘れさせない」ための仕組みである。
メンバ初期化リスト
Motor::Motor(int pin)
: pin(pin) {
}こちらを推奨する。
動かして確かめる
演習に入る前に、まずこのサンプルを動かして結果を見る。追加の部品は要らない。光るのはボードに載っている内蔵LEDで、それ以外はシリアルモニタの出力で確かめられる。code/examples/06-led-class/を開き、pio run -t uploadで書き込んでからpio device monitorで出力を見る(手順と、外付けのLEDなどをつなぐ場合は開発環境にまとめてある)。
// 第6回:LEDクラス(1ファイル版)
// まずは main.cpp の中だけでクラスを書く。分割は第7回で行う。
#include <Arduino.h>
class LED {
public:
/**
* @brief コンストラクタ
* @param pin LEDを繋いだピン番号
*/
LED(int pin)
: pin(pin), state(false) {
}
/**
* @brief ピンを初期化して消灯状態にする
*/
void begin() {
pinMode(pin, OUTPUT);
off();
}
/**
* @brief 点灯する
*/
void on() {
state = true;
digitalWrite(pin, HIGH);
}
/**
* @brief 消灯する
*/
void off() {
state = false;
digitalWrite(pin, LOW);
}
/**
* @brief 点灯と消灯を切り替える
*/
void toggle() {
if (state) {
off();
} else {
on();
}
}
private:
int pin;
bool state;
};
// 同じクラスから複数のオブジェクトを作れる。違うのはピン番号だけ
LED led1(LED_BUILTIN); // ボード上のRGB LED。配線なしで見える
LED led2(23); // 何もつないでいないピン。外付けLEDを挿せば光る
void setup() {
led1.begin();
led2.begin();
}
void loop() {
led1.toggle();
delay(500);
led2.toggle();
delay(500);
}RGB LED(led1)が0.5秒ごとに切り替わる。led2はGPIO23に割り当ててあるが、ボード上のLEDは1つしかないので2つ目の点滅は見えない。2つ同時に見たい場合は、GPIO23に外付けのLEDを1つつなぐ(部品と配線は開発環境の「実物をつなぐ場合」にまとめてある)。つながなくても、この回の主題は出力ではなくコードの形なので先に進んでよい。
確かめること。
LEDクラスからled1とled2の2つを作っている。違うのはコンストラクタに渡したピンだけtoggle()が内部でstateを見て切り替えている。使う側は今の状態を知らなくてよいpinとstateはprivateなので、外から直接は触れない- クラス定義の最後の
;を消すと、どんなエラーになるかを見ておく
演習:LEDクラスを作る
必要な機能:
LED led(23);
led.on();
led.off();- コンストラクタでピン番号を受け取り、メンバ初期化リストで初期化する
on()/off()の中でdigitalWrite()を呼ぶpinMode()をどこで呼ぶべきかを考える