Logo

Programming Linux

Quick search

Navigation

Courses

  • Courses Overview
  • Slide Material
    • Linux
    • Python Programming
    • The C Programming Language
    • C++: TODO List
    • C++: Miscellaneous Live-Hacking
    • C++
    • The New C++ (11-…)
      • Introduction
      • Delegating Constructor
      • Strongly Typed enum
      • New OO Features: = delete, = default, override, final
      • Attributes
      • Brace Initialization (Uniform Initialization)
      • Local Variables In Control Flow Statements
      • Duck Typing (Err, auto) Without A Duck
      • Tuple Unpacking (Err, Structured Binding)
      • Range Based for Loops
      • Miscellaneous
      • Lambda
      • const, constexpr, constinit, consteval
      • std::bind, std::function
      • Smart Pointers (std::unique_ptr, std::shared_ptr)
      • Move Semantics, Rvalue References
      • Perfect Forwarding
      • Multithreading, C++ Memory Model
      • std::any, std::variant, std::optional
      • std::chrono
      • std::filesystem
      • The Spaceship Operator <=> (And Comparison In General)
      • Concepts
      • Ranges
      • Coroutines
      • Modules
      • Drafts
        • Embedded Problems? Code Bloat? Type Erasure? Solutions?
          • Why Replace virtual?
          • Classic Virtual
          • Non-Virtual, But Related
          • Unrelated (Duck-Typed)
          • std::variant (Manual Virtual Dispatch, Using if)
          • std::variant (Manual Virtual Dispatch, Using std::visit)
          • std::variant (Automatic Virtual Dispatch Using Template Method)
          • Type Erasure (Static vs. Dynamic Polymorphism), CRTP
          • Replacing virtual With std::variant<> (In Real Life)
          • std::vector<>: Allocators (Very Incomplete)
        • CRTP
      • Exercises
      • From Concrete To Polymorphic (class Sensor)
      • Polymorphic “Classes” In Good Ol’ C
    • Design Patterns With C++
    • C++ Code
    • C++ Exercises
    • CMake
    • Is Software A Craft? Software Is A Craft! ⟶ Clean Code
    • Unit Testing With googletest
  • How To Book
  • Log Of Past Courses

About

  • Myself: Contact, Impressum, …
  • This Site

Blog

  • Posts

Non-Virtual, But Related¶

  • Overview

  • Sensor Definitions

  • Virtual Access

  • Average Across Many

  • Main Program

Overview¶

  • Goal: eliminate virtual

  • Need dynamic dispatch though (want to store base types polymorphically)

  • Base class

  • static_cast<>, based on a type field that is stored in base class

  • Manual virtual dispatch (see code/unrelated/virtual.h): switch based on type field.

Sensor Definitions¶

code/related-no-virtual/sensors.h¶
#pragma once

enum class DerivedType
{
    SENSOR1,
    SENSOR2,
};

class Sensor
{
public:
    Sensor(DerivedType type) : type{type} {}
    const DerivedType type;
};

class Sensor1 : public Sensor
{
public:
    Sensor1(double temperature)
    : Sensor{DerivedType::SENSOR1},
      _temperature{temperature} {}

    double get_temperature() { return _temperature; }

private:
    double _temperature;
};

class Sensor2 : public Sensor
{
public:
    Sensor2(double temperature)
    : Sensor{DerivedType::SENSOR2},
      _temperature{temperature} {}

    double get_temperature() { return _temperature; }

private:
    double _temperature;
};

Virtual Access¶

code/related-no-virtual/virtual.h¶
#pragma once

#include "sensors.h"

static inline double get_temperature(Sensor* s)
{
    switch (s->type) {
        case DerivedType::SENSOR1: {
            Sensor1* s1 = static_cast<Sensor1*>(s);
            return s1->get_temperature();
        }
        case DerivedType::SENSOR2: {
            Sensor2* s2 = static_cast<Sensor2*>(s);
            return s2->get_temperature();
        }
    }
    return -273.15; // <--- never reached
}

Average Across Many¶

code/related-no-virtual/avg.h¶
#pragma once

#include "virtual.h"

double average(auto& sensors)  // <--- abbreviated function template
{
    double sum = 0;
    unsigned long num = 0;
    for (auto& s: sensors) {
        ++num;
        sum += get_temperature(s);
    }
    return sum/num;
}

Main Program¶

code/related-no-virtual/main.cpp¶
#include "sensors.h"
#include "avg.h"

#include <iostream>

int main()
{
    Sensor1 s1{37.1};
    Sensor2 s2{42.666};

    Sensor* sensors[] = {&s1, &s2};
    
    std::cout << average(sensors) << std::endl;
    return 0;
}
©2019-2025 (GPLv3), Jörg Faschingbauer. | Page source