"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).\n",
"\n",
"Replace the `Do()` method by a free function with signature:\n",
"Replace the `TestDisplayContainer::Do()` method by a free function with signature:\n",
"````\n",
"void Loop(int initial_Nbit, int final_Nbit, int increment_Nbit, const TestDisplayContainer& container)\n",
"````\n",
...
...
%% Cell type:markdown id: tags:
# [Getting started in C++](./) - [Object programming](./0-main.ipynb) - [Hands-on 8](./7b-hands-on.ipynb)
%% Cell type:markdown id: tags:
<h1>Table of contents<spanclass="tocSkip"></span></h1>
<divclass="toc"><ulclass="toc-item"><li><span><ahref="#EXERCISE-21:-base-class-TestDisplay"data-toc-modified-id="EXERCISE-21:-base-class-TestDisplay-1">EXERCISE 21: base class <code>TestDisplay</code></a></span></li><li><span><ahref="#EXERCISE-22:-inherit-from-TestDisplayPowerOfTwoApprox"data-toc-modified-id="EXERCISE-22:-inherit-from-TestDisplayPowerOfTwoApprox-2">EXERCISE 22: inherit from <code>TestDisplayPowerOfTwoApprox</code></a></span></li><li><span><ahref="#EXERCISE-23:-Toward-a-TestDisplayContainer-class"data-toc-modified-id="EXERCISE-23:-Toward-a-TestDisplayContainer-class-3">EXERCISE 23: Toward a <code>TestDisplayContainer</code> class</a></span></li><li><span><ahref="#EXERCISE-24:-dynamic-allocation-of-array"data-toc-modified-id="EXERCISE-24:-dynamic-allocation-of-array-4">EXERCISE 24: dynamic allocation of array</a></span></li><li><span><ahref="#EXERCISE-25:-transform-TestDisplayContainer::Do()-into-a-free-function"data-toc-modified-id="EXERCISE-25:-transform-TestDisplayContainer::Do()-into-a-free-function-5">EXERCISE 25: transform <code>TestDisplayContainer::Do()</code> into a free function</a></span></li></ul></div>
%% Cell type:markdown id: tags:
### EXERCISE 21: 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 (respectively 100 or 1000 for our two derived classes)
* Should define the `RoundToInteger` enum (as protected)
* Includes a protected method named `PrintLine()` that will replace the `PrintLine()` we introduced in previous exercise.
The constructors of derived classes will of course have to be modified accordingly: so far we relied on default ones.
**Note:** Don't bother too much for the warning
```shell
warning: 'TestDisplay' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit [-Wweak-vtables]
```
that is the result of the definition of everything in a same file. If you separate declaration in a header file and definition in a source file you wouldn't get it (we'll see that in the very last part of the lecture)
%% Cell type:markdown id: tags:
### EXERCISE 22: 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
The compiler is really right here; the code we proposed to limit the number objects is very clunky. We will improve this in the very next exercise.
%% Cell type:markdown id: tags:
### EXERCISE 24: dynamic allocation of array
Instead of setting an arbitrary size of 3, we will now add a size dynamically in `TestDisplayContainer` constructor; the internal storage will now be:
````
TestDisplay** 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 **capacity** given as its argument (the capacity being the number of elements that *might* be stored inside - we'll see the chosen name is not a whim).
* Keep track of the capacity (the related data attribute should be constant: we don't intend to modify the capacity of the array after construction).
* Set each element to `nullptr`.
Destructor must of course take care of deallocating properly the memory.
%% Cell type:markdown id: tags:
### EXERCISE 25: transform `TestDisplayContainer::Do()` into a free function
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).
Replace the `Do()` method by a free function with signature:
Replace the `TestDisplayContainer::Do()` method by a free function with signature:
````
void Loop(int initial_Nbit, int final_Nbit, int increment_Nbit, const TestDisplayContainer& container)
````
To do so, you will need to add several methods to `TestDisplayContainer`:
- A method that returns the **size** (i.e. the number of non nullptr `TestDisplay*` stored), which will be required to loop over the relevant elements.
- A method to access the `i`-th element stored in the table. Signature might be: