# 5779 a

```cpp
#include <iostream>
using namespace std;

using namespace std;
class A {
public:
    A() { cout << "A(0)" << endl; }
    A(const A& a) { cout << "A(1)" << endl; }
};

class B {
public:
    B() : a() { cout << "B(0)" << endl; }
    B(const B& b) { cout << "B(1)" << endl; }
private:
    A a;
 };

int main() {
    B object1;
    B object2 = object1;
    return 0;
}
```

#### What is the output?

```cpp
B object1;
```

will result in, since **a** is a member field of **B** it will initialized before and the constructor will be called before Bs ctor

```
A(0)
B(0)
```

and

```cpp
B object2 = object1;
```

will output, since the *copy ctor* `B(const B& b)` will be called

```
A(0)
B(1)
```

***Remember!***

An object is copied when:

1. Constructing new object from existing          **Copy ctor**
2. Passing parameter by value                            **Copy ctor**
3. Returning by value.                                            **Copy ctor**
4. Assigning existing to existing.                          **Assignment ctor**

**Cases 1-3** are handled by copy constructor;

**Case 4** is handled by assignment operator.

### part b

remove this line

```cpp
B(const B& b) { cout << "B(1)" << endl; }
```

And now what will be the output?

```cpp
#include <iostream>
using namespace std;

using namespace std;
class A {
public:
    A() { cout << "A(0)" << endl; }
    A(const A& a) { cout << "A(1)" << endl; }
};

class B {
public:
    B() : a() { cout << "B(0)" << endl; }
private:
    A a;
 };

int main() {
    B object1;
    B object2 = object1;
    return 0;
}
```

### Solution

```cpp
A(0)
B(0)
A(1)
```

first `B object1;` will result in `A(0) B(0)` as above.

Now the copy ctor is called since it is the creation of the `object2`. Since **a** is initialized before any object it uses the default.

### part c

now delete this line and return the previous line

```cpp
A(const A& a) { cout << "A(1)" << endl; }
```

```cpp
#include <iostream>
using namespace std;

class A {
public:
    A() { cout << "A(0)" << endl; }
};

class B {
public:
    B() : a() { cout << "B(0)" << endl; }
    B(const B& b) { cout << "B(1)" << endl; }
private:
    A a;
};

int main() {
    B object1;
    B object2 = object1;
    return 0;
}
```

What is the output?

### Solution

```
A(0) B(0) A(0) B(1)
```

first `B object1;` will result in `A(0) B(0)` as above. Then initialize **a** `A(0)` and finally call the copy ctor `B(1)`

## Question 2 (9pts)

```cpp
#include <iostream>
using namespace std;

class A;

class B {
public:
  explicit B (A& o) { cout << "B (A)" << endl; }
};

class A {
public:
  A() { cout << "A()" << endl; }
};

void printit(B arg) {}

int main() {
      A a;
      B b(a);
      printit(a);
      return 0;
 }
```

The following cause a compile time error

```cpp
printit(a);
```

Explain the error and why does it happen

### Solution

`printit(B arg)` receives a **B** object but was given an **A** object, it can't **convert** `a` since the ctor is `explicit`

## Part b

fix the code above, **only fix this line**

```cpp
B b(a);
printit(a); // <======= this line
return 0;
```

### Solution

We can call converting ctor explicitly

```cpp
printit(B (a))
```

or just give a **B** object

```cpp
printit(b)
```

## Part c

After the fix what will be the output?

### Solution

If we used the 1st answer above `printit(B (a))` then the output would be like this

```cpp
int main() {
      A a;            // A()
      B b(a);         // B (A)
      printit(B (a)); // B (A)
      return 0;
 }
```

If we used the 2nd answer above `printit(b)` then the output would be like this

```cpp
int main() {
      A a;            // A()
      B b(a);         // B (A)
      printit(b);     
      return 0;
 }
```

> `printit(B arg)` will call the copy ctor, which hasn't been defined

## Question 3: (9pts)

```cpp
#include <iostream>
using namespace std;

class Shape {
public:
    virtual void draw() = 0;
    virtual ~Shape() { cout << "~Shape()" << endl; }
};


class Circle : public Shape {
public:
    void draw() { cout << "Circle::draw()" << endl; }
    ~Circle() { cout << "~Circle()" << endl; }
};


void drawTheShape(Shape s) {
     s.draw();
}

int main() {
    Circle c;
    drawTheShape(c);
    return 0;
}
```

## Part a:

On this the following line there is a compile time error

```cpp
void drawTheShape(Shape s) {
```

Explain the error, and why is it happening?

### Solution

`void drawTheShape(Shape s)` Here a new instance of Shape is called but since Shape is **pure virtual** as seen here

```cpp
class Shape {
public:
    virtual void draw() = 0;
```

Objects can't be created.

## Part b:

fix the line `void drawTheShape(Shape s) {` and only this line

### Solution 1:

receive **s** by **reference**.

```cpp
void drawTheShape(Shape& s) {
```

### Solution 2:

receive an implemented class type

```cpp
void drawTheShape(Circle s) {
```

## Part c:

what is the output?

### using the previous Solution 1:

```cpp
Circle::draw()
~Circle()
~Shape()
```

> This is because we first call the derived dtor and only after we call the bases dtor.

### using the previous Solution 2:

```cpp
Circle::draw()
~Circle()
~Shape()
~Circle()
~Shape()
```

## Question 4: (9pts)

```cpp
#include <iostream>
#include <string>
using namespace std;

class string {
    const char* p;
public:
    string(const char* p) {this->p = p;}
};

int main() { // a demo program
    string s = "abc";
}
```

```
main.cpp:12:2: error: reference to 'string' is ambiguous
string s = "abc";
^
```

## Part a:

Why type of error is this:

* compilation
* linker
* runtime
* logic
* memory leak

Additionally, what caused the error?

### Solution

This is a **compile-time** error

* We included `#include <iostream>` which includes `std::string`
* Also, we used `using namespace std;`
* Finally, we created a class by the name of `string`

```cpp
  class string {
      ...
  };
```

Now the compiler doesn't know which string to call, **our** `string` or `std::string`

Read more [here](https://www.cs.bu.edu/teaching/cpp/debugging/errors/#compiler) and [here](https://www.geeksforgeeks.org/difference-between-compile-time-errors-and-runtime-errors/) about different types of errors

This make sense that here is a compile error since it has nothing to do typing object files together or using a library rather ambiguity.

### Part b:

Fix the code by **removing only 1 line of code**, don't alter the main

### Solution

remove this line

```cpp
using namespace std;
```

now the compiler will knows who to call since `string` refers to our class and `std::string` refers to the std

### Part c

```cpp
class string {
    const char* p;
public:
    string(const char* p) {this->p = p;}
};
```

Here `string` has pointer **p** but `string` doesn't have a dtor.

Will this cause an error? If so, why type of error, if not why won't it cause an error?

### Solution

This is no error, notice the following

```cpp
string(const char* p) {this->p = p;}
```

string doesn't allocate memory there is no `new` or `malloc` it only receives a pointer to allocated memory

## Question 5-6: (22pts)

## Question 7: (22pts)

```cpp
#include <iostream>
using namespace std;
#include "Money.hpp"
using ariel::Money;

int main() {
// Set the exchange rates in shekels:
    Money::set_rate("ILS", 1);
    Money::set_rate("USD", 4);
    Money::set_rate("EUR", 6);
// Define amounts and do calculations:
    Money shekel1(1, "ILS");
    Money dollar3(3, "USD");
    Money sum = shekel1 + dollar3;
    cout << sum << endl; // 13 ILS
    cout << (dollar3 + Money(1, "EUR")) << endl; // 4.5 USD
    (sum += Money(2, "EUR")) += Money(0.5, "ILS");
    cout << sum << endl; // 25.5 ILS
// Money(1, "XXX"); // throws an exception
}
```

* Write `Money.cpp` and `Money.hpp`
* Allow addition of different sums with automatic conversion of units
* The rate of each coin is set in the beginning of the code

## Solution

`Money.hpp`

```cpp
#include <string>
#include <map>
#include <iostream>
using std::string, std::map, std::endl, std::ostream, std::ifstream;
namespace ariel{
    class Money {
        double amount;
        string currency;
        double rate;
        static map<string,double> map_currency_to_rate;
    public:
        Money(double amount, string currency): amount(amount), currency(currency) {
            rate = map_currency_to_rate.at(currency); // throws exception if not found
        }
        friend Money operator+(const Money& a, const Money& b);
        friend Money& operator+=(Money& a, const Money& b);
        friend ostream& operator<< (ostream& out, const Money& m);
        static void set_rate(string currency, double rate) {
            map_currency_to_rate[currency] = rate;
        }
    };
}
```

`Money.cpp`

```cpp
#include "Money.hpp"
namespace ariel {
    Money operator+(const Money& a, const Money& b) {
        double amount = a.amount + b.amount*b.rate/a.rate;
        return Money(amount, a.currency);
    }

    Money& operator+=(Money& a, const Money& b) {
        a.amount += b.amount*b.rate/a.rate;
        return a;
    }

    ostream& operator<< (ostream& out,  const Money& m) { //on test forgot const and &
        return (out << m.amount << " " << m.currency) << endl;
    }

    map<string,double> Money::map_currency_to_rate{};
}
```

```
13 ILS

4.5 USD

25.5 ILS
```
