Exercise: Sensor Interface

Project Setup

TODO: this needs more thinking

Problem: Polymorphic Thermometer Usage

ConstantSensor and RandomSensor are completely unrelated - they don’t share a common base class. They just look similar. This programming technique, Duck Typing, is heavily used in dynamic languages such as Python (see Abstract Base Classes (abc), And Duck Typing). It is not appropriate in a strongly tyoed language like C++ though, as we will see.

The following program uses an instance of each in an array of a hypothetical interface/base class to measure two temperature points. It calculates the average of both points, and outputs that.

#include <sensor-const.h>
#include <sensor-random.h>

#include <iostream>

int main()
{
    ConstantSensor cs(42.7);
    RandomSensor rs(7, 42);

    Sensor* sensors[2];
    sensors[0] = &cs;
    sensors[1] = &rs;

    double sum = 0;
    unsigned int count = 0;
    for (int i=0; i<2; i++) {
        count++;
        sum += sensors[i]->get_temperature();
    }

    double avg = sum/count;
    std::cout << avg << std::endl;

    return 0;
}

The Exercise

  • Download the program into the bin/ directory, and register it with that directory’s CMakeLists.txt file:

  • In addition to the program, download two tests into the tests/ directory, and register them with that directory’s CMakeLists.txt file:

    #include <sensor-const.h>
    
    #include <gtest/gtest.h>
    
    
    TEST(sensor_const_suite, is_a_sensor)
    {
        ConstantSensor cs(36.4);
    
        Sensor* s = &cs;                                   // <--- ConstantSensor is-a Sensor
    
        // avoid "unused' warning
        (void)s;
    }
    
    #include <sensor-random.h>
    
    #include <gtest/gtest.h>
    
    
    TEST(sensor_random_suite, is_a_sensor)
    {
        RandomSensor rs(36.4, 42.3);
    
        Sensor* s = &rs;                     // <--- ConstantSensor is-a Sensor
    
        // avoid "unused" warning
        (void)s;
    }
    
  • It won’t build

  • Add the missing Sensor interface (create a file sensors/sensor.h to contain it), and make the program compile and run. In UML, the new sensor hierarchy would look like follows:

    ../../../../../_images/sensor-hierarchy1.png
  • Run the program

    $ ./bin/cxx-exercises-sensors-avg
    27.5731
    
  • Run the tests

    $ ./tests/cxx-exercises-sensors-core--suite
    Running main() from /home/jfasch/work/jfasch-home/googletest/googletest/src/gtest_main.cc
    [==========] Running 4 tests from 2 test suites.
    [----------] Global test environment set-up.
    [----------] 2 tests from sensor_const_suite
    [ RUN      ] sensor_const_suite.basic
    [       OK ] sensor_const_suite.basic (0 ms)
    [ RUN      ] sensor_const_suite.is_a_sensor
    [       OK ] sensor_const_suite.is_a_sensor (0 ms)
    [----------] 2 tests from sensor_const_suite (0 ms total)
    
    [----------] 2 tests from sensor_random_suite
    [ RUN      ] sensor_random_suite.basic
    [       OK ] sensor_random_suite.basic (0 ms)
    [ RUN      ] sensor_random_suite.is_a_sensor
    [       OK ] sensor_random_suite.is_a_sensor (0 ms)
    [----------] 2 tests from sensor_random_suite (0 ms total)
    
    [----------] Global test environment tear-down
    [==========] 4 tests from 2 test suites ran. (0 ms total)
    [  PASSED  ] 4 tests.
    

Topics Covered

cluster_linux Linux cluster_linux_basics Linux Basics cluster_linux_basics_shell The Shell (Bash - “Bourne Again Shell”) cluster_linux_basics_intro Introduction: Concepts and Terminology cluster_linux_toolchain Toolchain, And Cross Development cluster_cxx03 C++ cluster_cxx03_inheritance_oo Inheritance And Object Oriented Design cluster_cxx03_data_encapsulation Data Encapsulation cluster_c The C Programming Language cluster_c_introduction Introduction cluster_cxx C++: Miscellaneous Live-Hacking cluster_cxx_exercises C++ Exercises linux_basics_shell_paths Absolute and Relative Paths linux_basics_shell_commandline Commandline linux_basics_shell_paths->linux_basics_shell_commandline linux_basics_intro_overview Overview linux_basics_shell_commandline->linux_basics_intro_overview linux_basics_shell_cwd Current Working Directory linux_basics_shell_cwd->linux_basics_shell_paths linux_basics_shell_cwd->linux_basics_shell_commandline linux_basics_intro_process Processes, Scheduling, Address Spaces linux_basics_shell_cwd->linux_basics_intro_process linux_basics_shell_file_dir_create_rm Creating And Removing Files and Directories linux_basics_shell_file_dir_create_rm->linux_basics_shell_paths linux_basics_shell_file_dir_create_rm->linux_basics_shell_cwd linux_basics_intro_process->linux_basics_intro_overview linux_toolchain_separate_compilation Zooming In: Separate Compilation, and Linking Statically linux_toolchain_basics Toolchain: Basics linux_toolchain_separate_compilation->linux_toolchain_basics linux_toolchain_cmake_local CMake: Local Build linux_toolchain_static_library Object Code Archives/Static Libraries linux_toolchain_cmake_local->linux_toolchain_static_library linux_toolchain_basics->linux_basics_shell_file_dir_create_rm linux_toolchain_static_library->linux_toolchain_separate_compilation cxx03_introduction Introduction c_introduction_installation Installation cxx03_introduction->c_introduction_installation cxx03_inheritance_oo_virtual_method Virtual Methods cxx03_inheritance_oo_basics Inheritance Basics cxx03_inheritance_oo_virtual_method->cxx03_inheritance_oo_basics cxx03_inheritance_oo_interface C++ “Interfaces” cxx03_inheritance_oo_interface->cxx03_inheritance_oo_virtual_method cxx03_inheritance_oo_polymorphism Polymorphic Usage Of Objects cxx03_inheritance_oo_interface->cxx03_inheritance_oo_polymorphism cxx03_inheritance_oo_virtual_destructor Virtual Destructors cxx03_inheritance_oo_interface->cxx03_inheritance_oo_virtual_destructor cxx03_inheritance_oo_polymorphism->cxx03_inheritance_oo_virtual_method cxx03_inheritance_oo_virtual_destructor->cxx03_inheritance_oo_virtual_method cxx03_inheritance_oo_virtual_destructor->cxx03_inheritance_oo_polymorphism cxx03_inheritance_oo_destructor Destructors And Inheritance cxx03_inheritance_oo_virtual_destructor->cxx03_inheritance_oo_destructor cxx03_inheritance_oo_destructor->cxx03_inheritance_oo_basics cxx03_data_encapsulation_ctor_dtor More Constructors, Destructors cxx03_inheritance_oo_destructor->cxx03_data_encapsulation_ctor_dtor cxx03_data_encapsulation_classes_objects Classes and Objects cxx03_inheritance_oo_basics->cxx03_data_encapsulation_classes_objects cxx03_data_encapsulation_ctor_default Default Constructor cxx03_data_encapsulation_ctor_dtor->cxx03_data_encapsulation_ctor_default cxx03_data_encapsulation_ctor_custom Custom Constructor cxx03_data_encapsulation_ctor_dtor->cxx03_data_encapsulation_ctor_custom cxx03_data_encapsulation_classes_objects->cxx03_introduction cxx03_data_encapsulation_c Object Oriented Programming In Good Ol’ C cxx03_data_encapsulation_classes_objects->cxx03_data_encapsulation_c cxx03_data_encapsulation_c->cxx03_introduction cxx03_data_encapsulation_ctor_default->cxx03_data_encapsulation_ctor_custom cxx03_data_encapsulation_ctor_custom->cxx03_data_encapsulation_classes_objects cxx_exercises_sensor_interface Exercise: Sensor Interface cxx_exercises_sensor_interface->linux_toolchain_cmake_local cxx_exercises_sensor_interface->cxx03_inheritance_oo_interface