Inheritance Basics¶
Sensor
: Plain (Base) Class¶
A plain class
Sensor
with aget_value()
methodNo surprise
#include <iostream>
class Sensor
{
public:
Sensor(double value) : _value{value} {}
double get_value() const
{
std::cout << "Sensor::get_value(): " << _value << std::endl;
return 36.5;
}
private:
double _value;
};
#include "sensors.h"
#include <iostream>
int main()
{
Sensor s{36.4};
double value = s.get_value();
std::cout << "got value " << value << std::endl;
return 0;
}
$ ./code/base/cxx-inher-oo-base
Sensor::get_value()
got value 36.5
Inheriting (Deriving) From Base¶
News
MySensor
is-aSensor
(though the usage of an is-a relationship is not at all clear yet)Given an instance of
Sensor
,Sensor::method()
is calledGiven an instance of
MySensor
,MySensor::method()
is called
Question
When
ms
is of typeMySensor
, but also of typeSensor
(MySensor
is-aSensor
), is it true that I can usems
as aSensor
?If I use a
MySensor
object as-aSensor
, what is the effect of callingget_value()
on it?
#include <iostream>
class Sensor
{
public:
Sensor(double value) : _value{value} {}
double get_value() const
{
std::cout << "Sensor::get_value(): " << _value << std::endl;
return _value;
}
private:
double _value;
};
class MySensor : public Sensor // <-- MySensor *is-a* Sensor
{
public:
MySensor(double basetemp, double correction)
: Sensor{basetemp},
_correction{correction} {}
double get_value() const
{
double value = Sensor::get_value() + _correction;
std::cout << "MySensor::get_value(): " << value << std::endl;
return value;
}
private:
double _correction;
};
Inheritance: Concrete Instances ⟶ No Surprise¶
Instantiation of concrete objects
Method calls directly on objects
⟶ no surprise
#include "sensors.h"
#include <iostream>
int main()
{
Sensor s{36.4};
double value = s.get_value(); // <-- Sensor::get_value()
std::cout << "Sensor value: " << value << std::endl;
MySensor ms{37.3, 0.25};
value = ms.get_value(); // <-- MySensor::get_value()
std::cout << "MySensor value " << value << std::endl;
return 0;
}
$ ./code/derived/cxx-inher-oo-derived-no-surprise
Sensor::get_value(): 36.4
Sensor value: 36.4
Sensor::get_value(): 37.3
MySensor::get_value(): 37.55
MySensor value 37.55
Inheritance: Automatic Pointer-To-Base Conversion¶
Definition of inheritance
Pointer-to-derived is automatically (no type cast needed) converted to pointer-to-base
Not obvious, and maybe unwanted: base class method called, although object is of derived type
#include "sensors.h"
#include <iostream>
int main()
{
MySensor ms{37.3, 0.25};
Sensor* ps = &ms; // <-- Conversion to base class
// <-- *definition of inheritance*
double value = ps->get_value(); // <-- ???
std::cout << value << std::endl;
return 0;
}
$ ./code/derived/cxx-inher-oo-derived-pointer-conversion
Sensor::get_value(): 37.3
Inheritance: Slicing (Automatic Instance Conversion)¶
Instance conversion: derived to base
Rarely wanted
⟶ Slicing
#include "sensors.h"
#include <iostream>
int main()
{
Sensor s{36.4};
MySensor ms{37.3, 0.25};
s = ms; // <-- this is bad!
double value = s.get_value(); // <-- ???
std::cout << value << std::endl;
return 0;
}