第11回 解答例
IMUとGPSをvirtualで扱う
演習の解答例。まず自分で書いてから読むこと。
解答
#pragma once
class Sensor {
public:
virtual ~Sensor() = default;
virtual void update();
};#include <Arduino.h>
#include "Sensor.hpp"
void Sensor::update() {
Serial.println("Sensor::update");
}#pragma once
#include "Sensor.hpp"
class IMU : public Sensor {
public:
void update() override;
};#include <Arduino.h>
#include "IMU.hpp"
void IMU::update() {
Serial.println("IMU::update");
}確認する
#include <Arduino.h>
#include "GPS.hpp"
#include "IMU.hpp"
#include "Sensor.hpp"
IMU imu;
GPS gps;
void setup() {
Serial.begin(115200);
Sensor* sensor = &imu;
sensor->update(); // IMU::update ← virtual だから
sensor = &gps;
sensor->update(); // GPS::update
}
void loop() {
}virtualを外すとどうなるか
Sensor::update()からvirtualを消して、同じコードを動かす。
Sensor::update()の宣言 | sensor->update()の出力 |
|---|---|
virtual void update(); | IMU::update(実際のオブジェクトで決まる) |
void update(); | Sensor::update(変数の型で決まる) |
virtualがないと、コンパイラは変数の型(Sensor*)だけを見て呼び先を決める。virtualを付けると、実行時に「実際に入っているオブジェクト」を見て決める。この違いは必ず自分で動かして確認すること。
overrideを必ず付ける
class IMU : public Sensor {
public:
void updata() override; // 綴りミス → コンパイルエラーになる
};overrideがなければ、これはSensor::update()とは無関係な新しい関数として受け入れられ、エラーにならない。そしてsensor->update()はSensorの実装を呼び続ける。原因を見つけるのが非常に難しいバグになる。