---
# System prepended metadata

title: C++ structure and class
tags: [C++]

---

---
type: slide
tags: C++
slideOptions:
  theme: white
---

# C++ structure and class

---

#### What is struct/class
* What: Encapsulate multiple data to one.
* Why: Give the structure a meaning.
* How:
``` cpp
struct People {
    std::string name;
    int age;
    int height;
    int weight
};
```

---

#### The expression of the struct/class
* Keyword: `struct/class`
* Member `variables/functions`
* Access specifiers: `public/private/protected`
    * 表示外部的code是否可以訪問這個作用域
    * 如果表示為private的函式跟變數，除了自己以外不能使用
    * 如果表示為public的函式或變數則為公開變數，可以供人使用
* Remember add the semicolon at the end.

---

#### The expression of the struct/class
``` cpp
// use class to define
class People {
    // Access specifiers
    public:
        // member functions
        std::string getName() {return name;}
        std::string getAge() {return age;}
        void setName(std::string n){name=n;}
        void setAge(int a){age=a;}
        void introduceMySelf() {
            std::cout<<"My name is "<<getName()
                     <<", and age is "<<getAge()<<"\n";
        }
    private:
        // member variables
        std::string name;
        int age;
}; // <-- Add the semicolon
```

---

### Example
``` cpp
int main() {
    std::string name;
    int age;
    std::cin>>name>>age;

    People Ann;
    // Ann.name = name, compile error because name is a private member
    // Ann.age = age, compile error because age is a private member
    Ann.setName(name);
    Ann.setAge(age);
    
    Ann.introduceMySelf();
    // My name is Ann, and age is 18
}
```

---

#### What is difference between class and struct.
* In C language, there is only struct and no member functions in it.
* In C++ language, only one difference.
    * The default access specifier is private for class and public for struct.

---

#### LifeTime and Initialization
* 所有的變數都有它的生命週期
* 全域變數會存活在整個程式中，生命週期無限大
* 區域變數會存活在某一個區間
    * 兩個括號之間{}
    * 或者一個function之間

---

#### LifeTime and Initialization
* 區域變數會存活在某一個區間
    * 兩個括號之間{}
    * 或者一個function之間
    ``` cpp
        int main() {
            int a = 0; // 在宣告時創造，在離開main時結束
            if (a==0) {
                People Ann; // 在進入if後創造它，並在離開if時結束
                Ann.setAge(18);
                std::cout<<Ann.getName()<<"\n";
                //        ↑--------------↑--- 
                //        getName回傳的std::string只存在於<<之間 
            }
            {
                People Ann; // 在進入這個{}後創造它，並在離開{}時結束
            }
        }
    ```
    

---


#### LifeTime and Initialization
* 所有的變數都有它的生命週期
* 全域變數會存活在整個程式中，生命週期無限大
* 區域變數會存活在某一個區間
    * 兩個括號之間{}
    * 或者一個function之間
* 任何變數在使用前都要先思考要怎麼初始化，以及怎麼解構
    * class has constructor/desturctor

---


#### LifeTime and Initialization
![image](https://hackmd.io/_uploads/BkeYYN5WA.png)


---

#### Initialization
* 有兩種初始化的寫法
    * 第一種直接在宣告member variable的時候給定初始值
    * Constructor
```cpp=
class People {
    int age=0;
    std::string name="";
}
```

---

#### Initialization
* Constructor
    * 於class中特殊的寫法，使用跟class相同名稱當作開頭
    * 從: 到 {} 中間為initialize list(初始化列表),以','分隔
    * 初始化列表內的順序要跟member一致
    * {}內可想像成function body，做一些初始化會做的事情
```cpp=
class People {
    public:
        People():age{0}, name{""}{}
    private:
        int age;
        std::string name;
}
```

---

#### Initialization
* Constructor 可接受多個變數
``` cpp=
class People {
    public:
        People(std::string n, int a):age{a}, name{n}{}
    private:
        int age;
        std::string name;
}

int main() {
    People Ann{"Ann", 18};
    return 0;
}
```

---

#### specifal constructor and destructor
* default constructor
* copy constructor
* copy assignment
* move constructor
* move assignment
* destructor

---

#### specifal constructor and destructor

```cpp=
int main() {
    People Ann;                   // Default constructor
    People Ann2 = Ann;            // Copy constructor
    People Ann3;                  // Default constructor
    Ann3 = Ann;                   // Copy Assignment;
    Poeple Ann4 = std::move(Ann3) // move constructor
    Ann3 = std::move(Ann);        // move assignment;
} // Call destructor of Ann/Ann2/Ann3/Ann4 before leave main
```

---

#### specifal constructor and destructor
``` cpp=
class People {
    public:
        // Default constructor
        People():age{0}{}
        // Copy constructor, use const People& in the parameters.
        People(const People& p):age{p.age}{}
        // Move constructor, like copy but use People&&
        People(People&& p):age{p.age}{}
        // Copy Assignment, redefine the = for People
        // Return type must be People&
        // Return *this at the end.
        People& operator=(const People& p){age=p.age; return *this;}
        // Move Assignment, like copy assignment but parameter use People&&
        People& operator=(People&& p){age=p.age; return *this;}
        // Destructor
        ~People(){}
    
    private:
        int age;
}
```

---

#### Example
* [Link](https://godbolt.org/z/1PPPPbE97)
``` cpp=
class People {
    public:
        People():name{"Default"}{std::cout<<"I'm born!\n";}
        ~People(){std::cout<<"I'm "<<name<<", and I leave!\n";}
        void setName(std::string n){name=n;}
    private:
        std::string name;
};
```
```cpp=
int main() {
    People Ann;
    Ann.setName("Ann");
    {
        People Terry;
        Terry.setName("Terry");
    }
}
```

---

#### Example 2
* 請問這邊會印出甚麼東西來. [Link](https://godbolt.org/z/dYnEbKzvv)
``` cpp=
class People {
    public:
        People()                           {std::cout<<"Ctor\n";}
        People(const People& p)            {std::cout<<"Copy Ctor\n";}
        People(People&& p)                 {std::cout<<"Move Ctor\n";}
        People& operator=(const People& p) {std::cout<<"Copy Ass\n"; return *this;}
        People& operator=(People&& p)      {std::cout<<"Move Ass\n"; return *this;}
        ~People()                          {std::cout<<"Dtor\n";}
};
int main() {
    People p1;
    People p2 = p1;
    People p3 = std::move(p2);
    p3 = p1;
    p3 = std::move(p1);
}
```

---

#### Constructor and Destructor
* 為什麼需要這麼複雜的constructor跟destructor呢
* 在未來會學到pointer，或者你用到別人設計的class時會用到
    * pointer需要更為複雜的初始化跟解構
    * 別人了class可能需要複雜的初始化以及解構
* Rule of 5 or Rule of 0
    * 意思就是說，要馬全部的constructor都寫出來。要馬都不寫。
    * 現階段妳可以先不寫這些東西

---

#### You can define everything outside the class
* Why: 你的class應當簡潔有力，把定義包含其中會顯得混亂
* How: 在定義時加入 \<ClassType>::
```cpp=
class People {
    public:
    	People();
    	People(int a);
    	~People();
    	int getAge();
    	void setAge(int a);
    private:
        int age;
};
int main(){
    //...
}

People::People():age{0} {}
People::People(int a):age{a}{}
People::~People(){}
int People::getAge(){return age;}
void People::setAge(int a){age=a;}

```

---

#### Exercise
* 設計一個簡單的點餐系統。
    1. 請輸入Steak, Fish, Chicken, IceCream, Cake的價格
    2. 輸入預定人名以及想要預定的時間
    3. 輸入想要吃的主餐是甚麼(Steak, Fish, Chicken, None擇一)
    4. 輸入想吃的甜點是甚麼(IceCream, Cake, None擇一
    5. 輸入是否有會員(Yes/No, 有會員的話打九折)
    6. 輸出人名，時間，主餐，甜點，是否有折價，總價格

---

#### Exercise
* [Link](https://godbolt.org/z/K3qrr1E4b)
* 輸入如下
    * ![image](https://hackmd.io/_uploads/r1NeQHc-A.png)  
* 輸出如下
    * ![image](https://hackmd.io/_uploads/r10_MBqW0.png)
* [ANS](https://godbolt.org/z/x981v9sE3)