**Discussion 9: More on Classes**
10/20, 10/22
[(back to course webpage)](./mcs360_fall2020.html)
# Recap from previous time: The class Circle
At the end of Discussion 8, I gave a Circle class definition for you guys, and here's a part of it:
```cpp
#include
class Circle {
std::pair center;
double radius;
public:
void dilate(double alpha) {
radius *= alpha;
}
void shift(std::pair A) {
center.first += A.first;
center.second += A.second;
}
};
```
But how do we actually create an object of type Circle and shift/dilate it?
# Constructor: the cousin of __init__()
Our class Circle from last time didn't yet contain a constructor function, so we could not really create a circle object in the `main()` function.
A constructor does exactly the same thing as Python's `__init__()` method: it initializes a class!
## Constructor definition
+ You define a constructor using the class' name, and don't specify a return type.
+ For our Circle method, we can have the following constructor:
```cpp
Circle(double x_center, double y_center, double R) {
center = std::make_pair(x_center, y_center);
radius = R;
}
```
Then, inside the `main()` function, we can create a new `Circle` object by doing `Circle C(1.0, 2.0, 3.0)`: this declares a circle centered at $(1,2)$ and of radius $3$.
## Constructor overloading
+ There can be multiple constructor definitions (this is called function overloading). Say when someone writes `Circle C`, you want to create a unit circle centered at origin.
Then, you would put in the following function as a second constructor:
```cpp
Circle(){
center = std::make_pair(0,0);
radius = 1.0;
}
```
# Outputting a Circle by declaring `operator<<` as a friend: the cousin of __str__()
If you want to be able to see a description of your circle as a string, you would need to declare the `operator<<` as a friend function of your `Circle` class.
```cpp
std::ostream& operator<< (std::ostream& os, const Circle& c) {
os << "Circle[(" << c.center.first << ", " << c.center.second << "), " << c.radius << "]\n";
}
```
I explained what these `std::ostream&` declarations are for in the discussion, so will skip that out over here.
# Putting it all together in ONE CPP FILE
This is the CPP file I provided during discussion:
```cpp
#include
class Circle {
std::pair center;
double radius;
public:
Circle(double x_center, double y_center, double R) {
center = std::make_pair(x_center, y_center);
radius = R;
}
// Creates a circle centered at (x,y) and radius 1
Circle(double x_center, double y_center) {
center = std::make_pair(x_center, y_center);
radius = 1.0;
}
// Creates a unit circle centered at the origin
Circle(){
center = std::make_pair(0,0);
radius = 1.0;
}
void shift(std::pair A) {
center.first += A.first;
center.second += A.second;
}
void dilate(double alpha) {
radius *= alpha;
}
friend std::ostream& operator<< (std::ostream& os, const Circle& C) {
os << "Circle[(" << C.center.first << ", " << C.center.second << "), " << C.radius << "]\n";
return os;
}
};
int main() {
Circle C; // C is a unit circle centered at the origin
Circle D(2); // D is a circle centered at the origin with radius 2
Circle E(1.4,2.5,2.3); // E is a circle centered at (1.4,2.5) with radius 2.3
std::cout << C;
C.dilate(3);
C.shift(std::make_pair(1,2));
std::cout << C;
std::cout << D;
std::cout << E;
return 0;
}
```
# Exercise
Divide this entire code into three files: `circle.h`, `circle.cpp`, `d9.cpp`. The header file should contain the class and its attributes/methods' declaration,
the `circle.cpp` file should contain the definitions of `Circle`'s methods,
and the `d9.cpp` should contain the `main()` function.
circle.h
```cpp
#include
#ifndef circle_H
#define circle_H
class Circle {
std::pair center;
double radius;
public:
// general constructor: circle centered at (x,y) and radius r
Circle(double center_x, double center_y, double r);
// default constructor when center is not provided: centered at (0,0) and radius r
Circle(double r);
// default constructor when no argument is provided: center (0,0) and radius 1
Circle();
void dilate(double alpha);
void shift(std::pair A);
friend std::ostream& operator<< (std::ostream& os, const Circle& c);
};
#endif
```
circle.cpp
```cpp
#include "circle.h"
// general constructor: circle centered at (x,y) and radius r
Circle::Circle(double center_x, double center_y, double r) {
center = std::make_pair(center_x, center_y);
radius = r;
}
// default constructor when center is not provided: centered at (0,0) and radius r
Circle::Circle(double r) {
center = std::make_pair(0,0);
radius = r;
}
// default constructor when no argument is provided: center (0,0) and radius 1
Circle::Circle() {
center = std::make_pair(0,0);
radius = 1.0;
}
void Circle::dilate(double alpha) {
radius *= alpha;
}
void Circle::shift(std::pair A) {
center.first += A.first;
center.second += A.second;
}
std::ostream& operator<< (std::ostream& os, const Circle& c) {
os << "Circle[(" << c.center.first << ", " << c.center.second << "), " << c.radius << "]\n";
}
```
d9.cpp
```cpp
#include
#include "circle.h"
int main() {
Circle C; // C is a unit circle centered at the origin
Circle D(2); // D is a circle centered at the origin with radius 2
Circle E(1.4,2.5,2.3); // E is a circle centered at (1.4,2.5) with radius 2.3
std::cout << C;
C.dilate(3);
C.shift(std::make_pair(1,2));
std::cout << C;
std::cout << D;
std::cout << E;
return 0;
}
```
+ Note: To compile the code, you need to _link_ `circle.cpp` together with `d9.cpp`, and hence use the following to compile:
```
(base) potla@EKR:~/Desktop/mcs360$ g++ -o d9 d9.cpp circle.cpp
```
+ If you don't link `circle.cpp`, you get:
```
(base) potla@EKR:~/Desktop/mcs360$ g++ -o d9 d9.cpp
/tmp/cct49xft.o: In function `main':
d9.cpp:(.text+0x22): undefined reference to `Circle::Circle()'
d9.cpp:(.text+0x44): undefined reference to `Circle::Circle(double)'
d9.cpp:(.text+0x7e): undefined reference to `Circle::Circle(double, double, double)'
d9.cpp:(.text+0x91): undefined reference to `operator<<(std::ostream&, Circle const&)'
d9.cpp:(.text+0xb3): undefined reference to `Circle::dilate(double)'
d9.cpp:(.text+0x10f): undefined reference to `Circle::shift(std::pair)'
d9.cpp:(.text+0x122): undefined reference to `operator<<(std::ostream&, Circle const&)'
d9.cpp:(.text+0x135): undefined reference to `operator<<(std::ostream&, Circle const&)'
d9.cpp:(.text+0x148): undefined reference to `operator<<(std::ostream&, Circle const&)'
collect2: error: ld returned 1 exit status
```