Commit 4684ad1f authored by CHAMONT David's avatar CHAMONT David
Browse files

Last minute changes

parent ced2cd9a
tmp*
core.*
.ipynb_checkpoints .ipynb_checkpoints
.vscode .vscode
.ionide .ionide
.DS_Store
gcm.cache
*.o *.o
*.exe *.exe
*.log *.log
tmp*
core.*
.fake
\ No newline at end of file
//
// Modify the class Ref, and only this class, so that
// the call to f(make_ref(j)) modify the value of j,
// while f(i) does not modify i.
// The final display should be : 0 42
//
#include <iostream>
template < typename T >
class Ref
{
public :
Ref( T data ) { data_ = data ; }
void operator=( T data ) { data_ = data ; }
private :
T data_ ;
} ;
template < typename T >
Ref<T> make_ref( T & data )
{ return Ref<T>(data) ; }
template < typename T >
void f( T data )
{ data = 42 ; }
int main()
{
int i = 0, j = 0 ;
f(i) ;
f(make_ref(j)) ;
std::cout<<i<<" "<<j<<std::endl ;
return 0 ;
}
...@@ -6,17 +6,15 @@ ...@@ -6,17 +6,15 @@
```cpp ```cpp
#include <iostream> #include <iostream>
struct MyInteger struct MyInteger {
{
MyInteger( int i = 0 ) : i_(i) {} MyInteger( int i = 0 ) : i_(i) {}
int i_ ; int i_ ;
} }
int main() int main() {
{
MyInteger mi() ; MyInteger mi() ;
std::cout<<mi.i_<<std::endl ; std::cout<<mi.i_<<std::endl ;
} }
``` ```
1. nothing, it will fails to compile MyInteger 1. nothing, it will fails to compile MyInteger
...@@ -38,14 +36,13 @@ int main() ...@@ -38,14 +36,13 @@ int main()
## May I copy such an array ? ## May I copy such an array ?
```cpp ```cpp
class Array class Array {
{ public :
public : explicit Array( unsigned s ) { data_ = new double [s]; }
explicit Array( unsigned s ) { data_ = new double [s]; } double & operator[]( unsigned i ) { return data_[i]; }
double & operator[]( unsigned i ) { return data_[i]; } ~Array() { delete data_; }
~Array() { delete data_; } private :
private : double * data_;
double * data_;
} ; } ;
``` ```
...@@ -145,14 +142,16 @@ bool check() ...@@ -145,14 +142,16 @@ bool check()
1. never iterate with a real variable (index) 1. never iterate with a real variable (index)
2. never compare floats with == 2. never compare floats with ==
3. 1.0 is a double 3. some curly braces are lacking
4. index value is never 169.0 4. 1.0 is a double
5. index value is never 169.0
## **Good** and *bad* answers ## **Good** and *bad* answers
* *1* : one can iterate with anything iterable... * *1* : "never" is a little string, one can iterate with anything iterable, and sometimes need to.
* **2** : floating operation are never perfectly exact ; any floating comparison must allow an epsilon error. * **2** : as a general rule, floating operation are never perfectly exact ; any floating comparison should allow an epsilon error.
* **3** : because `1.0` is a double, the result of `index / ( index + 1.0 )` is a double, and will not match the value stored in `ref`, which is a float ; try with `1.0f`, or `static_cast<float>( index / ( index + 1.0 ) )`. * *3* : some curly braces would make the code more readable, but that is not the issue here.
* **4** : best answer here, because `1.0` is a double, the result of `index / ( index + 1.0 )` is a double, and will not match the value stored in `ref`, which is a float ; try with `1.0f`, or `static_cast<float>( index / ( index + 1.0 ) )`.
* *4* : nice try ;) actually no, because the step of `1.0` is 2 power 0, it can be exactly encoded in binary basis, and the last value of `index` will exactly be `169.0` ; if the step was `0.1`, for example, the value of ìndex` would never be exactly `169.0`. * *4* : nice try ;) actually no, because the step of `1.0` is 2 power 0, it can be exactly encoded in binary basis, and the last value of `index` will exactly be `169.0` ; if the step was `0.1`, for example, the value of ìndex` would never be exactly `169.0`.
...@@ -160,15 +159,13 @@ bool check() ...@@ -160,15 +159,13 @@ bool check()
## What is lacking below ? ## What is lacking below ?
```cpp class A {\
class A public :
{ A() {}
public : ~A() {}
A() {} virtual void display() = 0 ;
~A() {} } ;
virtual void display() = 0 ;
}
```
1. one "virtual" 1. one "virtual"
2. several "virtual" 2. several "virtual"
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": 1,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 35, "execution_count": 2,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
...@@ -99,14 +99,14 @@ ...@@ -99,14 +99,14 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 1,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"name": "stdout", "name": "stdout",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Overwriting tmp.ref.cpp\n" "Writing tmp.ref.cpp\n"
] ]
} }
], ],
...@@ -152,7 +152,7 @@ ...@@ -152,7 +152,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": 2,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -161,7 +161,7 @@ ...@@ -161,7 +161,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": 3,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
...@@ -175,6 +175,13 @@ ...@@ -175,6 +175,13 @@
"source": [ "source": [
"!./tmp.ref.exe" "!./tmp.ref.exe"
] ]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
} }
], ],
"metadata": { "metadata": {
......
...@@ -9,10 +9,11 @@ ...@@ -9,10 +9,11 @@
"We are going to start this review by discussing numerical aspects of C++, because this course is all about scientific computing. Then we'll revise pointers, the major source of errors in C++, as well as C. Next we'll go over some advanced and important points of object-oriented programming. We'll finish the review by discussing templates. This C++ feature can give one a headache but, at the same time, it's one of the language's strong points as evidenced by the standard library. Fasten the belt !\n", "We are going to start this review by discussing numerical aspects of C++, because this course is all about scientific computing. Then we'll revise pointers, the major source of errors in C++, as well as C. Next we'll go over some advanced and important points of object-oriented programming. We'll finish the review by discussing templates. This C++ feature can give one a headache but, at the same time, it's one of the language's strong points as evidenced by the standard library. Fasten the belt !\n",
"\n", "\n",
"* [Numbers](en.1-numbers.ipynb)\n", "* [Numbers](en.1-numbers.ipynb)\n",
"* [Pointeurs](en.2-pointers.ipynb)\n", "* [Floating point numbers](en.2-floats.ipynb)\n",
"* [Objects](en.3-objects.ipynb)\n", "* [Classes and objects](en.3-objects.ipynb)\n",
"* [Templates](en.4-templates.ipynb)\n", "* [Pointers and dynamic memory management](en.4-pointers.ipynb)\n",
"* [Specialization](en.5-specialization.ipynb)" "* [Templates](en.5-templates.ipynb)\n",
"* [Templates specialisation](en.6-specialisation.ipynb)"
] ]
} }
], ],
......
This diff is collapsed.
...@@ -26,10 +26,10 @@ ...@@ -26,10 +26,10 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 1,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "subslide" "slide_type": "skip"
} }
}, },
"outputs": [], "outputs": [],
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 2,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "fragment" "slide_type": "fragment"
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 3,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "fragment" "slide_type": "fragment"
...@@ -73,13 +73,23 @@ ...@@ -73,13 +73,23 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 4,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "fragment" "slide_type": "fragment"
} }
}, },
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Base::function1\n",
"Derived::function2\n",
"Derived::function3\n"
]
}
],
"source": [ "source": [
"Derived obj ;\n", "Derived obj ;\n",
"obj.function1() ;\n", "obj.function1() ;\n",
...@@ -102,7 +112,7 @@ ...@@ -102,7 +112,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 5,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "subslide" "slide_type": "subslide"
...@@ -119,7 +129,7 @@ ...@@ -119,7 +129,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 6,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "fragment" "slide_type": "fragment"
...@@ -136,13 +146,38 @@ ...@@ -136,13 +146,38 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 7,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "fragment" "slide_type": "fragment"
} }
}, },
"outputs": [], "outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[1minput_line_13:3:7: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mcall to member function 'display' is ambiguous\u001b[0m\n",
" obj.display(42) ;\n",
"\u001b[0;1;32m ~~~~^~~~~~~\n",
"\u001b[0m\u001b[1minput_line_12:3:8: \u001b[0m\u001b[0;1;30mnote: \u001b[0mcandidate function\u001b[0m\n",
" void display( float ) { std::cout<<\"Derived::display( float \"<<std::endl ; }\n",
"\u001b[0;1;32m ^\n",
"\u001b[0m\u001b[1minput_line_12:4:8: \u001b[0m\u001b[0;1;30mnote: \u001b[0mcandidate function\u001b[0m\n",
" void display( double ) { std::cout<<\"Derived::display( double )\"<<std::endl ; }\n",
"\u001b[0;1;32m ^\n",
"\u001b[0m"
]
},
{
"ename": "Interpreter Error",
"evalue": "",
"output_type": "error",
"traceback": [
"Interpreter Error: "
]
}
],
"source": [ "source": [
"void check( Derived obj )\n", "void check( Derived obj )\n",
" { \n", " { \n",
...@@ -174,7 +209,7 @@ ...@@ -174,7 +209,7 @@
} }
}, },
"source": [ "source": [
"In the previous example, the compiler frst select the `Derived` class, then hesitate to convert its `int` argument into either a `float` or a `double`." "In the previous example, the compiler first select the `Derived` class, then hesitate to convert its `int` argument into either a `float` or a `double`."
] ]
}, },
{ {
...@@ -185,7 +220,7 @@ ...@@ -185,7 +220,7 @@
} }
}, },
"source": [ "source": [
"### Good practice\n", "### Good old-fashioned practice\n",
"\n", "\n",
"When you redefine an inherited member function, **redefine all the base class functions which share the same name**, or you will hide some of them." "When you redefine an inherited member function, **redefine all the base class functions which share the same name**, or you will hide some of them."
] ]
...@@ -205,10 +240,10 @@ ...@@ -205,10 +240,10 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 8,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "subslide" "slide_type": "skip"
} }
}, },
"outputs": [], "outputs": [],
...@@ -218,10 +253,10 @@ ...@@ -218,10 +253,10 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 9,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "-" "slide_type": "subslide"
} }
}, },
"outputs": [], "outputs": [],
...@@ -235,7 +270,7 @@ ...@@ -235,7 +270,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 10,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "fragment" "slide_type": "fragment"
...@@ -252,13 +287,38 @@ ...@@ -252,13 +287,38 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 11,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "fragment" "slide_type": "fragment"
} }
}, },
"outputs": [], "outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[1minput_line_17:5:8: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mcall to member function 'display' is ambiguous\u001b[0m\n",
" obj->display(3.14) ;\n",
"\u001b[0;1;32m ~~~~~^~~~~~~\n",
"\u001b[0m\u001b[1minput_line_15:3:16: \u001b[0m\u001b[0;1;30mnote: \u001b[0mcandidate function\u001b[0m\n",
" virtual void display( int ) { std::cout<<\"Base::display( int )\"<<std::endl ; }\n",
"\u001b[0;1;32m ^\n",
"\u001b[0m\u001b[1minput_line_15:4:16: \u001b[0m\u001b[0;1;30mnote: \u001b[0mcandidate function\u001b[0m\n",
" virtual void display( float ) { std::cout<<\"Base::display( float )\"<<std::endl ; }\n",
"\u001b[0;1;32m ^\n",
"\u001b[0m"
]
},
{
"ename": "Interpreter Error",
"evalue": "",
"output_type": "error",
"traceback": [
"Interpreter Error: "
]
}
],
"source": [ "source": [
"void check( Base * obj )\n", "void check( Base * obj )\n",
" {\n", " {\n",
...@@ -287,14 +347,14 @@ ...@@ -287,14 +347,14 @@
} }
}, },
"source": [ "source": [
"### Good practice\n", "### Good old-fashioned practice\n",
"\n", "\n",
"When you define a base class with virtual functions, overload those functions for all the type of arguments that you expect in the derived classes." "When you define a base class with virtual functions, overload those functions for all the expected type of arguments that you expect in the derived classes."
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 12,
"metadata": { "metadata": {
"slideshow": { "slideshow": {
"slide_type": "-" "slide_type": "-"
...@@ -318,7 +378,7 @@ ...@@ -318,7 +378,7 @@
} }
}, },
"source": [ "source": [
"### Other good practice\n", "### Other good old-fashioned practice\n",
"\n", "\n",
"**Make the destructor `virtual`**. Indeed, you may create a derived object with `new` and store its address in a base class pointer. When calling `delete` on this pointer, one will bypass the derived destructor, unless it is virtual." "**Make the destructor `virtual`**. Indeed, you may create a derived object with `new` and store its address in a base class pointer. When calling `delete` on this pointer, one will bypass the derived destructor, unless it is virtual."
] ]
...@@ -385,7 +445,7 @@ ...@@ -385,7 +445,7 @@
}