第13回 解答例
センサを配列でまとめて更新する
演習の解答例。まず自分で書いてから読むこと。
解答
#include <Arduino.h>
#include "GPS.hpp"
#include "IMU.hpp"
#include "Sensor.hpp"
#include "ToF.hpp"
IMU imu;
GPS gps;
ToF tof(6);
Sensor* sensors[] = {&imu, &gps, &tof};
const int SENSOR_COUNT = sizeof(sensors) / sizeof(sensors[0]);
void setup() {
Serial.begin(115200);
}
void loop() {
for (int i = 0; i < SENSOR_COUNT; i++) {
sensors[i]->update();
sensors[i]->print();
}
delay(1000);
}センサを1種類追加したとき
ToFを追加するために変更が必要だったのは、次の2行だけである。
ToF tof(6); // 追加
Sensor* sensors[] = {&imu, &gps, &tof}; // 1要素追加loop()の中は1文字も変えていない。これがポリモーフィズムの効果である。
loop() ← Sensorの種類を知らない
│
↓
Sensor* ← 共通の約束ごと
│
┌──────┼──────┐
↓ ↓ ↓
IMU GPS ToF ← 増えても loop() は無関係もしポリモーフィズムを使わなかったら
// 良くない例
void loop() {
imu.update();
imu.print();
gps.update();
gps.print();
tof.update(); // センサを増やすたびに loop() を直す
tof.print();
}センサが増えるたびにloop()が伸びていく。種類ごとにifで分岐するコードも同じ問題を抱える。
組み込みでの注意
仮想関数を使うと、次のコストがかかる。
- 各オブジェクトに仮想関数テーブルへのポインタ(多くの環境で4バイト)が付く
- 呼び出しが1段階間接的になる
- コンパイラがインライン展開しにくくなる
センサ数個の制御では問題にならない。ただし「割り込みの中で何万回も呼ぶ」ような場所では測定してから判断する。