2026-05-22 (3VO): C++ Inheritance, Revisited#

Last Exercise, Solved#

Here’s one solution to 2026-05-16 (3UE*2): Exercise Polymorphic Types. Sounds much like what was done in 2026-05-11 (3VO): C++: Inheritance (Mocking A Sensor), which not by accident.

@startuml

interface Sensor {
  + double get_temperature()
}

interface PWMPin {
  + void set_duty_cycle(uint64_t)
  + void set_period(uint64_t)
}

class LinuxSysfsPWMPin {}
PWMPin <|.. LinuxSysfsPWMPin

class StdoutPWMPin {}
PWMPin <|.. StdoutPWMPin

note bottom of StdoutPWMPin: writes new period/duty_cycle to std::cout

class Logic
{
  + void loop()
}

Logic -l-> Sensor
Logic -r-> PWMPin

@enduml

Interface: PWMPin#

#pragma once

#include <cstdint>

class PWMPin
{
public:
    virtual ~PWMPin() = default;
    
    virtual void set_period(uint64_t) = 0;
    virtual void set_duty_cycle(uint64_t) = 0;
};

Implementation: StdoutPWMPin#

#pragma once

#include "pwmpin.h"
#include <iostream>


class StdoutPWMPin : public PWMPin
{
public:
    void set_period(uint64_t value) override
    {
        std::cout << "set_period " << value << std::endl;
    }
    void set_duty_cycle(uint64_t value) override
    {
        std::cout << "set_duty_cycle " << value << std::endl;
    }
};

Implementation: StdoutPWMPin#

#pragma once

#include "pwmpin.h"
#include <filesystem>

class LinuxSysfsPWMPin : public PWMPin
{
public:
    LinuxSysfsPWMPin(std::filesystem::path basedir);

    void set_period(uint64_t) override;
    void set_duty_cycle(uint64_t) override;

private:
    std::filesystem::path _basedir;
    bool _ok;
};
#include "pwm-linux-sysfs.h"
#include "fileutil.h"

LinuxSysfsPWMPin::LinuxSysfsPWMPin(std::filesystem::path basedir)
: _basedir(basedir)
{
    if (!std::filesystem::exists(basedir))
        throw std::exception();
    if (!file_is_rwable(basedir / "period"))
        throw std::exception();
    if (!file_is_rwable(_basedir / "duty_cycle"))
        throw std::exception();
}

void LinuxSysfsPWMPin::set_period(uint64_t period)
{ 
    return write_uint64_t_to_file(_basedir / "period", period);
}

void LinuxSysfsPWMPin::set_duty_cycle(uint64_t duty_cycle)
{
    return write_uint64_t_to_file(_basedir / "duty_cycle", duty_cycle);
}

C++ Inheritance Details#

This is the dry technical explanation of the C++ inheritance toolset, apart from what we heard about the “pure” interface/implementation design strategy that we heard about the other day.

It is not something that was interesting enough to make the audience dance on the tables, so I quit with it in the middle of it. I leave the material here in case somebody is interested. The exam will not mention any of this.

From Inheritance And Object Oriented Design: