"where `position` is the index at which `test_display` will be stored. This function should of course check `position` is valid; if not use the following function:"
...
...
%% Cell type:markdown id: tags:
# [Getting started in C++](/) - [Object programming](/notebooks/2-ObjectProgramming/0-main.ipynb) - [TP 7](/notebooks/2-ObjectProgramming/6b-TP.ipynb)
%% Cell type:markdown id: tags:
<h1>Table of contents<spanclass="tocSkip"></span></h1>
<divclass="toc"><ulclass="toc-item"><li><span><ahref="#EXERCICE-22:-base-class-TestDisplay"data-toc-modified-id="EXERCICE-22:-base-class-TestDisplay-1">EXERCICE 22: base class <code>TestDisplay</code></a></span></li><li><span><ahref="#EXERCICE-23:-inherit-from-TestDisplayPowerOfTwoApprox"data-toc-modified-id="EXERCICE-23:-inherit-from-TestDisplayPowerOfTwoApprox-2">EXERCICE 23: inherit from <code>TestDisplayPowerOfTwoApprox</code></a></span></li><li><span><ahref="#EXERCICE-24:-loop()-function"data-toc-modified-id="EXERCICE-24:-loop()-function-3">EXERCICE 24: loop() function</a></span></li><li><span><ahref="#EXERCICE-25:-make-loop()-a-class"data-toc-modified-id="EXERCICE-25:-make-loop()-a-class-4">EXERCICE 25: make <code>loop()</code> a class</a></span></li><li><span><ahref="#EXERCICE-26:-store-TestDisplay-objects-in-Loop"data-toc-modified-id="EXERCICE-26:-store-TestDisplay-objects-in-Loop-5">EXERCICE 26: store <code>TestDisplay</code> objects in <code>Loop</code></a></span></li><li><span><ahref="#EXERCICE-27:-simplification"data-toc-modified-id="EXERCICE-27:-simplification-6">EXERCICE 27: simplification</a></span></li><li><span><ahref="#EXERCICE-28:-dynamic-allocation-of-array"data-toc-modified-id="EXERCICE-28:-dynamic-allocation-of-array-7">EXERCICE 28: dynamic allocation of array</a></span></li><li><span><ahref="#EXERCICE-29:-move-ownership-into-Loop"data-toc-modified-id="EXERCICE-29:-move-ownership-into-Loop-8">EXERCICE 29: move ownership into <code>Loop</code></a></span></li><li><span><ahref="#EXERCICE-30:-transform-Loop-into-TestDisplayContainer"data-toc-modified-id="EXERCICE-30:-transform-Loop-into-TestDisplayContainer-9">EXERCICE 30: transform <code>Loop</code> into <code>TestDisplayContainer</code></a></span></li></ul></div>
%% Cell type:markdown id: tags:
### EXERCICE 22: base class `TestDisplay`
Create a base class `TestDisplay` from which both `TestDisplayPowerOfTwoApprox` and `TestDisplaySum` will inherit publicly.
This class:
* Should get a constructor which sets the resolution.
* Includes a protected method named `PrintNumericalError()` that will replace the `print_numerical_error()` we introduced in previous exercice.
The constructors of derived classes will of course have to be modified accordingly: so far we relied on default ones.
%% Cell type:markdown id: tags:
### EXERCICE 23: inherit from `TestDisplayPowerOfTwoApprox`
We would like to get back former output in which we got first all outputs for 0.65, then all the ones for 0.35.
To do so, we will create two classes `TestDisplayPowerOfTwoApprox065` and `TestDisplayPowerOfTwoApprox035` that inherits from `TestDisplayPowerOfTwoApprox`.
Of course, we still abide by the DRY principle and we want to specialize only the code related to `Do()` method.
The `main()` to use:
%% Cell type:code id: tags:
``` C++17
int main(int argc, char** argv)
{
static_cast<void>(argc); // to silence warning about unused argc - don't bother
static_cast<void>(argv); // to silence warning about unused argv - don't bother
To do so, you will need to define `Do()` as a virtual method in `TestDisplay()`. As `TestDisplay` is not meant to be instantiated directly, make sure to make this class pure virtual.
%% Cell type:markdown id: tags:
### EXERCICE 25: make `loop()` a class
Replace `loop()` by a class `Loop` with a method `Do()` which is called.
Replace `loop()` by a class `Loop` with a method `Do()`.
%% Cell type:markdown id: tags:
### EXERCICE 26: store `TestDisplay` objects in `Loop`
Add to the `Loop` class:
* A data attribute to store 5 `TestDisplay` objects: `TestDisplay* test_display_list_[5]`. We will store them as pointers for two reasons:
* There are no default constructor for `TestDisplay`, so the compiler would have yelled.
* We want polymorphism to be put in motion, and it requires either pointers or references.
* A method to register an array in this internal array, with prototype:
where `position` is the index at which `test_display` will be stored. This function should of course check `position` is valid; if not use the following function:
`Loop::Do()` won't take any longer a `TestDisplay` argument but instead act upon all the ones stored in the data attribute; if nullptr is found for an object it will be skipped (so don't forget to correctly set them initially to this value!)
`main()` to use is:
%% Cell type:code id: tags:
``` C++17
int main(int argc, char** argv)
{
static_cast<void>(argc); // to silence warning about unused argc - don't bother
static_cast<void>(argv); // to silence warning about unused argv - don't bother
Let's face it: the possibility to place the `TestDisplay` where we want is a bit overkill: we just need to iterate through all objects and don't really need to know the exact position of each of them.
So we will:
* Remove the position argument; each new `TestDisplay` object registered is added to the first position available.
* A new data attribute `next_position_available_` will tell which is not yet used.
* The error handling will now check `next_position_available_` has not reached 5 when a new `Register()` call is done.
%% Cell type:markdown id: tags:
### EXERCICE 28: dynamic allocation of array
Instead of setting an arbitrary size of 5, we will now add a size dynamically in `Loop` constructor; the internal storage will now be:
````
TestDisplay** test_display_list_;
````
meaning we will store an array of pointers (don't worry, we will see later how to avoid such monstruosities... but it is useful nonetheless to try them a bit).
Constructor must now:
* Allocate the array of `TestDisplay*` with a size given as its argument.
* Keep track of the size (the related data attribute should be constant: we don't intend to modify the size of the array after construction).
* Set each element to `nullptr`.
Destructor must of course take care of deallocating properly the memory.
**NOTE:** To avoid a warning you should use `std::size_t` when allocating the array: this is the type used for array (which is in all compilers I've used an alias to `unsigned long`).
%% Cell type:markdown id: tags:
### EXERCICE 29: move ownership into `Loop`
Currently `Loop` use pointers to underlying `TestDisplay` objects but do not own them: it is not in charge of deallocating them. This may prove dangerous in a more complicated program than this one; we will now change this so that `Loop` gain ownership over the content.
Of course, we should make sure they are properly deallocated at destruction.
New main will be:
%% Cell type:code id: tags:
``` C++17
int main(int argc, char** argv)
{
static_cast<void>(argc); // to silence warning about unused argc - don't bother
static_cast<void>(argv); // to silence warning about unused argv - don't bother
### EXERCICE 30: transform `Loop` into `TestDisplayContainer`
Once again we probably went a bridge too far: it is useful to provide an object which contains several `TestDisplay` together, but making it take in charge the loop might not be that good an idea (in a real program you might for instance interact with this container by another mean than the pre-defined loop).
We will therefore rename the class `Loop``TestDisplayContainer`, and reintroduce a `loop()` function that will interact with it. The `main()` is now:
%% Cell type:code id: tags:
``` C++17
int main(int argc, char** argv)
{
static_cast<void>(argc); // to silence warning about unused argc - don't bother
static_cast<void>(argv); // to silence warning about unused argv - don't bother
_This notebook is an adaptation of a lecture prepared and redacted by David Chamont (CNRS) under the terms of the licence [Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)_
_The present version has been redacted by Sébastien Gilles and Vincent Rouvreau (Inria)_