Skip to main content
Ctrl+K
Jörg Faschingbauer - Home Jörg Faschingbauer - Home
  • Training Courses
  • About
  • Blog
  • Training Courses
  • About
  • Blog

Section Navigation

  • Course Descriptions
  • Pricing, Organizational
  • Log Of Past Courses
  • Complete Slide Material
    • Linux: Introduction, Userland/Kernel Programming, Hardware/Embedded
    • Python Programming
    • C Programming
    • C++ Programming
      • C++ < 11
      • C++ >= 11
        • Introduction
        • The Rule Of Three/Five/Zero
        • 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
        • The constexpr Engine
        • std::bind, std::function
        • Smart Pointers: std::unique_ptr, std::shared_ptr (And std::weak_ptr)
        • Move Semantics, Rvalue References
        • Perfect Forwarding
        • Multithreading, C++ Memory Model
        • std::array
        • std::any, std::variant, std::optional
        • std::chrono
        • std::filesystem
        • Formatting Library (std::format(), std::print())
        • std::span
        • Explicit Object Member Functions (A.k.a Deducing this)
        • The Spaceship Operator <=> (And Comparison In General)
        • Concepts
        • Ranges And Views
        • Coroutines
        • Modules
        • Drafts
        • Exercises
        • From Concrete To Polymorphic (class Sensor)
        • Polymorphic “Classes” In Good Ol’ C
      • Design Patterns With C++
      • C++: Miscellaneous Live-Hacking
      • C++ Code
      • C++ Exercises
    • Build Tools, Unit Testing, Design, And More
  • Training Courses
  • Complete Slide Material
  • C++ Programming
  • C++ >= 11
  • Drafts
  • Embedded Problems? Code Bloat? Type Erasure? Solutions?
  • Non-Virtual, But Related

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;
}
On this page
  • Overview
  • Sensor Definitions
  • Virtual Access
  • Average Across Many
  • Main Program

© Copyright 2019-2025 (GPLv3), Jörg Faschingbauer.

Created using Sphinx 8.1.3.

Built with the PyData Sphinx Theme 0.16.1.

Show Source