第12回 解答例

純粋仮想関数とToFの追加

演習の解答例。まず自分で書いてから読むこと。

Sensorを抽象クラスにする

include/Sensor.hpp
#pragma once

class Sensor {
public:
    virtual ~Sensor() = default;

    virtual void update() = 0;      // 実装を持たない
    virtual void print() const = 0;
};

= 0を付けるとSensor.cppは不要になる。Sensorは「約束ごと」だけを表す。

直接オブジェクトを作れないことを確認する

Sensor sensor;   // コンパイルエラー

エラーメッセージの例:

error: cannot declare variable 'sensor' to be of abstract type 'Sensor'
note:   because the following virtual functions are pure within 'Sensor':
note:     virtual void Sensor::update()

「Sensorは抽象型なので変数を作れない。update()が純粋仮想のままだから」と書かれている。エラーメッセージを読む練習になる。

ToFを追加する

include/ToF.hpp
#pragma once

#include "Sensor.hpp"

class ToF : public Sensor {
public:
    ToF(int pin);

    void update() override;
    void print() const override;

    int getDistanceMm() const;

private:
    int pin;
    int distanceMm;
};
src/ToF.cpp
#include <Arduino.h>

#include "ToF.hpp"

ToF::ToF(int pin)
    : pin(pin), distanceMm(0) {
}

void ToF::update() {
    // 実機では距離センサから読む
    distanceMm = analogRead(pin);
}

void ToF::print() const {
    Serial.print("ToF distance=");
    Serial.println(distanceMm);
}

int ToF::getDistanceMm() const {
    return distanceMm;
}

継承と抽象クラスの使い分け

やりたいこと使うもの例
共通の実装をまとめたい普通の継承Deviceのピン番号とbegin()
共通の約束ごとを決めたい抽象クラスSensorは必ずupdate()を持つ

→ 第12回の本文に戻る