Commit 5aa17e4e authored by GILLES Sebastien's avatar GILLES Sebastien
Browse files

Minor corrections + remove cells already executed.

parent 8b83636e
......@@ -75,7 +75,7 @@
"outputs": [],
"source": [
"Vector::Vector()\n",
": x_(0.), // \n",
": x_0.),\n",
"y_(0.),\n",
"z_(0.)\n",
"{ }"
......@@ -210,7 +210,7 @@
" \n",
" Vector2();\n",
" \n",
" Vector2(double xyz);\n",
" Vector2(double x);\n",
" \n",
" Vector2(double x, double y, double z);\n",
" \n",
......@@ -459,7 +459,7 @@
"source": [
"struct SafeClass\n",
"{\n",
" int a_ = 5; // The default value is provided here in the class declaration. \n",
" int a_ { 5 }; // The default value is provided here in the class declaration. \n",
" \n",
" SafeClass() = default;\n",
" \n",
......@@ -624,7 +624,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -645,7 +645,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -658,7 +658,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -673,20 +673,9 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Memory for array 3 is properly freed here.\n",
"Memory for array 4 is properly freed here.\n",
"Memory for array 2 is properly freed here.\n",
"Memory for array 1 is properly freed here.\n"
]
}
],
"outputs": [],
"source": [
"{\n",
" Array array1(1, 5ul);\n",
......
%% Cell type:markdown id: tags:
# [Getting started in C++](/) - [Object programming](/notebooks/2-ObjectProgramming/0-main.ipynb) - [(Base) constructors and destructor](/notebooks/2-ObjectProgramming/3-constructors-destructor.ipynb)
%% Cell type:markdown id: tags:
<h1>Table of contents<span class="tocSkip"></span></h1>
<div class="toc"><ul class="toc-item"><li><span><a href="#Introduction-to-base-constructor" data-toc-modified-id="Introduction-to-base-constructor-1">Introduction to base constructor</a></span></li><li><span><a href="#Initializing-a-reference-data-attribute" data-toc-modified-id="Initializing-a-reference-data-attribute-2">Initializing a reference data attribute</a></span></li><li><span><a href="#Delegating-constructor" data-toc-modified-id="Delegating-constructor-3">Delegating constructor</a></span></li><li><span><a href="#Default-constructor" data-toc-modified-id="Default-constructor-4">Default constructor</a></span></li><li><span><a href="#Good-practice:-data-attribute-initialization" data-toc-modified-id="Good-practice:-data-attribute-initialization-5">Good practice: data attribute initialization</a></span></li><li><span><a href="#Good-practice:-use-explicit-constructors-by-default" data-toc-modified-id="Good-practice:-use-explicit-constructors-by-default-6">Good practice: use <code>explicit</code> constructors by default</a></span></li><li><span><a href="#Destructor" data-toc-modified-id="Destructor-7">Destructor</a></span><ul class="toc-item"><li><span><a href="#Default-destructor" data-toc-modified-id="Default-destructor-7.1">Default destructor</a></span></li></ul></li></ul></div>
%% Cell type:markdown id: tags:
## Introduction to base constructor
In fact, our previous `init()` function is meant to be realized through a dedicated method called a **constructor**. By convention, a constructor shares the name of the struct or class.
Several constructors may be defined for a given class, provided there is no signature overlap.
%% Cell type:code id: tags:
``` C++17
struct Vector
{
double x_;
double y_;
double z_;
Vector(); // Constructor
Vector(double x, double y, double z); // Another constructor
double norm() const;
};
```
%% Cell type:markdown id: tags:
Data attributes may be initialized more efficiently with a special syntax shown below:
%% Cell type:code id: tags:
``` C++17
Vector::Vector(double x, double y, double z)
: x_(x), // See the syntax here: `:` to introduce data attributes initialization,
y_(y), // and commas to separate the different data attributes.
z_(z)
{ }
```
%% Cell type:code id: tags:
``` C++17
Vector::Vector()
: x_(0.), //
: x_0.),
y_(0.),
z_(0.)
{ }
```
%% Cell type:code id: tags:
``` C++17
double Vector::norm() const
{
return std::sqrt(x_ * x_ + y_ * y_ + z_ * z_);
}
```
%% Cell type:code id: tags:
``` C++17
#include <iostream>
{
Vector v(5., 6., -4.2); // note the creation of an object with a constructor call.
std::cout << v.norm() << std::endl;
}
```
%% Cell type:markdown id: tags:
**WARNING:** There is a technicality for constructor without arguments: they must be called without parenthesis (the reason is a possible confusion with a [functor](/notebooks/3-Operators/5-Functors.ipynb) - see Item 6 of \cite{Meyers2001} or [this blog post](https://www.fluentcpp.com/2018/01/30/most-vexing-parse/) if you want to learn more about the reasons of this):
%% Cell type:code id: tags:
``` C++17
#include <iostream>
{
Vector v; // no parenthesis here!
std::cout << v.norm() << std::endl;
}
```
%% Cell type:markdown id: tags:
## Initializing a reference data attribute
We saw above a new syntax to initialize data attributes, but there is no harm defining the same as we did in our former `init()` method. That is however not true when there is a reference data attribute, for which the reference must absolutely be defined with the new syntax:
%% Cell type:code id: tags:
``` C++17
struct First
{
};
```
%% Cell type:code id: tags:
``` C++17
struct Second
{
const First& first_;
Second(const First& first);
};
```
%% Cell type:code id: tags:
``` C++17
Second::Second(const First& first)
{
first_ = first; // COMPILATION ERROR: can't initialize a reference data attribute here!
}
```
%% Cell type:code id: tags:
``` C++17
Second::Second(const First& first)
: first_(first) // OK!
{ }
```
%% Cell type:markdown id: tags:
The reason for this behaviour is that the reference must be defined at the very moment the object is created, and in fact the body of a constructor is run _after_ the actual creation occurs. With the proper syntax, the data is properly initialized in the same time the object is created.
## Delegating constructor
Since C++ 11, it is possible to use a base constructor when defining another constructor:
%% Cell type:code id: tags:
``` C++17
struct Vector2
{
double x_, y_, z_;
Vector2();
Vector2(double xyz);
Vector2(double x);
Vector2(double x, double y, double z);
void Print() const;
};
```
%% Cell type:code id: tags:
``` C++17
#include <iostream>
void Vector2::Print() const
{
std::cout << "(x, y, z) = (" << x_ << ", " << y_ << ", " << z_ << ")" << std::endl << std::endl;
}
```
%% Cell type:code id: tags:
``` C++17
#include <iostream>
Vector2::Vector2()
: x_(-1.),
y_(-1.),
z_(-1.)
{
std::cout << "Calling Vector2 constructor with no arguments." << std::endl;
}
```
%% Cell type:code id: tags:
``` C++17
Vector2::Vector2(double x, double y, double z)
: x_(x),
y_(y),
z_(z)
{ }
```
%% Cell type:code id: tags:
``` C++17
Vector2::Vector2(double x)
: Vector2()
{
x_ = x; // As the first constructor is assumed to build fully the object, you can't assign data attributes
// before the body of the constructor.
}
```
%% Cell type:code id: tags:
``` C++17
{
std::cout << "Constructor with no argument:" << std::endl;
Vector2 v1;
v1.Print();
std::cout << "Constructor with no delegation:" << std::endl;
Vector2 v2(3., 7., 5.);
v2.Print();
std::cout << "Constructor that calls a delegate constructor:" << std::endl;
Vector2 v3(3.);
v3.Print();
}
```
%% Cell type:markdown id: tags:
## Default constructor
If in a `class` or `struct` no constructor is defined, a default one is assumed: it takes no argument and sports an empty body.
As soon as another constructor is defined, this default constructor no longer exists:
%% Cell type:code id: tags:
``` C++17
struct ClassWithoutConstructor
{ };
```
%% Cell type:code id: tags:
``` C++17
{
ClassWithoutConstructor my_object;
}
```
%% Cell type:code id: tags:
``` C++17
struct ClassWithConstructorWithArg
{
ClassWithConstructorWithArg(int a);
};
```
%% Cell type:code id: tags:
``` C++17
ClassWithConstructorWithArg::ClassWithConstructorWithArg(int a)
{ }
```
%% Cell type:code id: tags:
``` C++17
{
ClassWithConstructorWithArg my_object; // COMPILATION ERROR!
}
```
%% Cell type:markdown id: tags:
This must seem messy at first sight, but doing otherwise would be nightmarish: if you define a very complex class that must be carefully initialized with well-thought arguments, you do not want your end-user to bypass this with a inconsiderate call to a constructor without arguments!
If you want to enable back constructor without arguments, you may do so by defining it explicitly. C++11 introduced a nice way to do so (provided you wish an empty body - if not define it explicitly yourself):
%% Cell type:code id: tags:
``` C++17
struct ClassWithConstructorWithAndWithoutArg
{
ClassWithConstructorWithAndWithoutArg() = default;
ClassWithConstructorWithAndWithoutArg(int a);
};
```
%% Cell type:code id: tags:
``` C++17
ClassWithConstructorWithAndWithoutArg::ClassWithConstructorWithAndWithoutArg(int a)
{ }
```
%% Cell type:code id: tags:
``` C++17
{
ClassWithConstructorWithAndWithoutArg my_object; // OK!
}
```
%% Cell type:markdown id: tags:
## Good practice: data attribute initialization
In a constructor, you are expected to initialize properly all the data attributes. You can't expect a default behaviour if you fail to do so:
%% Cell type:code id: tags:
``` C++17
struct BadlyInitialized
{
int a;
};
```
%% Cell type:code id: tags:
``` C++17
#include <iostream>
{
BadlyInitialized my_object;
std::cout << "Undefined behaviour: no guarantee for the value of the data attribute!: " << my_object.a << std::endl;
}
```
%% Cell type:markdown id: tags:
You are therefore supposed to define explicitly all the data attributes in all of your constructors. It was easy to get trumped by this in C++98/03: if you added a new data attribute and forgot to initialize it in one of your constructor, you would have undefined behaviour that is one of the worst bug to track down! (as on your machine/architecture you may have a "good" behaviour haphazardly).
Fortunately, C++ 11 introduced a mechanism I strongly recommend to provide a default value:
%% Cell type:code id: tags:
``` C++17
struct SafeClass
{
int a_ = 5; // The default value is provided here in the class declaration.
int a_ { 5 }; // The default value is provided here in the class declaration.
SafeClass() = default;
SafeClass(int new_value);
};
```
%% Cell type:code id: tags:
``` C++17
SafeClass::SafeClass(int new_value)
: a_(new_value)
{ }
```
%% Cell type:code id: tags:
``` C++17
#include <iostream>
{
SafeClass no_Arg;
std::cout << "If constructor doesn't change the value, default is used: " << no_Arg.a_ << std::endl;
SafeClass modified(10);
std::cout << "If constructor changes the value, choice is properly used: " << modified.a_ << std::endl;
}
```
%% Cell type:markdown id: tags:
Please notice doing so doesn't prevent you to use the efficient initialization of `a_` in the constructor with arguments: the values thus provided in the data attributes definitions are used only in the constructor doesn't supersede them.
%% Cell type:markdown id: tags:
In the same spirit, if you get pointers as data attributes it is a good idea to set them by default to `nullptr`: this way you may check with an [`assert`](/notebooks/5-UsefulConceptsAndSTL/1-ErrorHandling.ipynb#Assert) it has been correctly initialized before use.
## Good practice: use `explicit` constructors by default
Let's study the following case:
%% Cell type:code id: tags:
``` C++17
struct ClassWithIntConstructor
{
ClassWithIntConstructor(int a);
};
```
%% Cell type:code id: tags:
``` C++17
#include <iostream>
ClassWithIntConstructor::ClassWithIntConstructor(int a)
{
std::cout << "Constructor called with argument " << a << std::endl;
}
```
%% Cell type:code id: tags:
``` C++17
{
ClassWithIntConstructor my_object(5);
my_object = 7; // Dubious but correct: assigning an integer!
}
```
%% Cell type:markdown id: tags:
So what happens here? In fact, the compiler implicitly convert the integer read into a constructor with an integer argument...
There are situations in which this might be deemed the right thing to do (none to my mind but I guess it depends on your programming style) but more often than not it's not what is intended and a good old compiler yell would be much preferable.
To do so, in C++ 11 you must stick the keyword **explicit** in the declaration in front of the constructor. Personally I tend to always provide it to my constructors, following the likewise advice by \cite{Meyers2015}.
%% Cell type:code id: tags:
``` C++17
struct ClassWithExplicitIntConstructor
{
explicit ClassWithExplicitIntConstructor(int a);
};
```
%% Cell type:code id: tags:
``` C++17
#include <iostream>
ClassWithExplicitIntConstructor::ClassWithExplicitIntConstructor(int a)
{
std::cout << "Constructor called with argument " << a << std::endl;
}
```
%% Cell type:code id: tags:
``` C++17
{
ClassWithExplicitIntConstructor my_object(5);
my_object = 7; // COMPILATION ERROR! YAY!
}
```
%% Cell type:markdown id: tags:
## Destructor
%% Cell type:markdown id: tags:
The pendant of the constructor is the **destructor**, which is called when the object is terminated. Contrary to constructors, there is only one destructor for a given class, and by design it takes no parameter.
The syntax is like a constructor with no parameter with an additional `~` in front of the name.
%% Cell type:code id: tags:
``` C++17
#include <limits> // for std::numeric_limits
struct Array
{
Array(int unique_id, std::size_t array_size);
~Array(); // Destructor!
double* array_ = nullptr;
const int unique_id_ = std::numeric_limits<int>::min(); // to provide absurd value if not initialized
// That can't happen here, but might if a constructor
// was added later on.
};
```
%% Cell type:code id: tags:
``` C++17
Array::Array(int unique_id, std::size_t array_size)
: unique_id_(unique_id)
{
array_ = new double[array_size];
}
```
%% Cell type:code id: tags:
``` C++17
#include <iostream>
Array::~Array()
{
std::cout << "Memory for array " << unique_id_ << " is properly freed here." << std::endl;
delete[] array_;
}
```
%% Cell type:code id: tags:
``` C++17
{
Array array1(1, 5ul);
{
Array array2(2, 3ul);
{
Array array3(3, 5ul);
}
Array array4(4, 2ul);
}
}
```
%%%% Output: stream
Memory for array 3 is properly freed here.
Memory for array 4 is properly freed here.
Memory for array 2 is properly freed here.
Memory for array 1 is properly freed here.
%% Cell type:markdown id: tags:
It's important to notice the ordering here: as soon as an object becomes out of scope, it is immediately destroyed; the creation order doesn't matter at all!
We will see a bit [later](/notebooks/5-UsefulConceptsAndSTL/2-RAII.ipynb) how to take advantage of this behaviour to write programs that do not leak memory.
### Default destructor
If not specified, C++ implicitly defines a destructor with an empty body. Personally I like even in this case to make it explicit, which is done the same way as for a constructor from C++11 onward:
%% Cell type:code id: tags:
``` C++17
struct MyClass
{
MyClass() = default; // explicit default constructor
~MyClass() = default; // explicit default destructor
}
```
%% Cell type:markdown id: tags:
This is however a matter of personal taste; see for instance [this post from FluentCpp](https://www.fluentcpp.com/2019/04/23/the-rule-of-zero-zero-constructor-zero-calorie) for the opposite advice of not defining explicitly default constructor / destructor if you don't have to.
%% Cell type:markdown id: tags:
# References
[<a id="cit-Meyers2001" href="#call-Meyers2001">Meyers2001</a>] Scott Meyers, ``_Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library_'', 2001.
[<a id="cit-Meyers2015" href="#call-Meyers2015">Meyers2015</a>] Scott Meyers, ``_Effective modern C++: 42 specific ways to improve your use of C++11
and C++14_'', 2015. [online](http://www.worldcat.org/oclc/890021237)
%% Cell type:markdown id: tags:
© _CNRS 2016_ - _Inria 2018-2019_
_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)_
......
......@@ -81,7 +81,7 @@
},
{
"cell_type": "code",
"execution_count": 1,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -105,7 +105,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -117,7 +117,7 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -131,7 +131,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -143,17 +143,9 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The value is 5\n"
]
}
],
"outputs": [],
"source": [
"{\n",
" SecondClass object(5);\n",
......@@ -163,31 +155,9 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[1minput_line_13:4:12: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1m'SetValue' is a private member of 'SecondClass'\u001b[0m\n",
" object.SetValue(7); // COMPILATION ERROR: trying to call publicly a private method\n",
"\u001b[0;1;32m ^\n",
"\u001b[0m\u001b[1minput_line_7:11:14: \u001b[0m\u001b[0;1;30mnote: \u001b[0mdeclared private here\u001b[0m\n",
" void SetValue(int a);\n",
"\u001b[0;1;32m ^\n",
"\u001b[0m"
]
},
{
"ename": "Interpreter Error",
"evalue": "",
"output_type": "error",
"traceback": [
"Interpreter Error: "
]
}
],
"outputs": [],
"source": [
"{\n",
" SecondClass object(5);\n",
......@@ -222,13 +192,13 @@
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"struct Rectangle\n",
"{\n",
" Rectangle(double length, double widgth);\n",
" Rectangle(double length, double width);\n",
"\n",
" double length_;\n",
" double width_;\n",
......@@ -240,7 +210,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -253,31 +223,9 @@
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[1minput_line_19:1:17: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1mredefinition of 'Print'\u001b[0m\n",
"void Rectangle::Print() const\n",
"\u001b[0;1;32m ^\n",
"\u001b[0m\u001b[1minput_line_17:1:17: \u001b[0m\u001b[0;1;30mnote: \u001b[0mprevious definition is here\u001b[0m\n",
"void Rectangle::Print() const\n",
"\u001b[0;1;32m ^\n",
"\u001b[0m"
]
},
{
"ename": "Interpreter Error",
"evalue": "",
"output_type": "error",
"traceback": [
"Interpreter Error: "
]
}
],
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#include <iostream>\n",
"\n",
......@@ -289,18 +237,9 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"My rectangle is 5 x 4 so its area is 20\n",
"My rectangle is 23 x 4 so its area is 20\n"
]
}
],
"outputs": [],
"source": [
"{\n",
" Rectangle rect(5., 4.); \n",
......@@ -319,7 +258,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -340,7 +279,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -353,7 +292,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -367,31 +306,9 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[1minput_line_25:5:10: \u001b[0m\u001b[0;1;31merror: \u001b[0m\u001b[1m'length_' is a private member of 'MoreSecureRectangle'\u001b[0m\n",
" rect.length_ = 0.; // can't do that! \n",
"\u001b[0;1;32m ^\n",
"\u001b[0m\u001b[1minput_line_21:9:16: \u001b[0m\u001b[0;1;30mnote: \u001b[0mdeclared private here\u001b[0m\n",
" double length_;\n",
"\u001b[0;1;32m ^\n",
"\u001b[0m"
]
},
{
"ename": "Interpreter Error",
"evalue": "",
"output_type": "error",
"traceback": [
"Interpreter Error: "
]
}
],
"outputs": [],
"source": [
"{\n",
" MoreSecureRectangle rect(5., 4.); \n",
......@@ -409,7 +326,7 @@
},
{
"cell_type": "code",
"execution_count": 16,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -433,7 +350,7 @@
},
{
"cell_type": "code",
"execution_count": 17,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -446,7 +363,7 @@
},
{
"cell_type": "code",
"execution_count": 18,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -460,7 +377,7 @@
},
{
"cell_type": "code",
"execution_count": 19,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -473,7 +390,7 @@
},
{
"cell_type": "code",
"execution_count": 20,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -486,18 +403,9 @@
},
{
"cell_type": "code",
"execution_count": 21,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"My rectangle is 5 x 4 so its area is 20\n",
"My rectangle is 23 x 4 so its area is 92\n"
]
}
],
"outputs": [],
"source": [
"{\n",
" Rectangle3 rect(5., 4.); \n",
......@@ -530,7 +438,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -550,14 +458,14 @@
"\n",
" private:\n",
" \n",
" double length_ = -1.20; // a stupid value which at least is deterministically known...\n",
" double width_ = -1.20;\n",
" double length_ = -1.e20; // a stupid value which at least is deterministically known...\n",
" double width_ = -1.e20;\n",
"};"
]
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -569,7 +477,7 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -581,7 +489,7 @@
},
{
"cell_type": "code",
"execution_count": 25,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -593,7 +501,7 @@
},
{
"cell_type": "code",
"execution_count": 26,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -605,7 +513,7 @@
},
{
"cell_type": "code",
"execution_count": 27,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -617,7 +525,7 @@
},
{
"cell_type": "code",
"execution_count": 28,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -629,18 +537,9 @@
},
{
"cell_type": "code",
"execution_count": 29,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Area = 26\n",
"Area = 20\n"
]
}
],
"outputs": [],
"source": [
"#include <iostream>\n",
"\n",
......@@ -665,7 +564,7 @@
},
{
"cell_type": "code",
"execution_count": 30,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -700,7 +599,7 @@
},
{
"cell_type": "code",
"execution_count": 31,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -712,7 +611,7 @@
},
{
"cell_type": "code",
"execution_count": 32,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -726,7 +625,7 @@
},
{
"cell_type": "code",
"execution_count": 33,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
......@@ -738,7 +637,7 @@
},
{
"cell_type": "code",
"execution_count": 34,
"execution_count": null,
"metadata": {},
"outputs": [],