---
# System prepended metadata

title: 計算機程式

---

# 計算機程式

[台大公開課](http://ocw.aca.ntu.edu.tw/ntu-ocw/ocw/cou/101S112/1/V/1)



## 硬體小筆記
Chapter 1

- ### Main Memory
    - #### RAM(random access memory): 
        - 存取的時間與儲存位置的排序無關。
        - 存取速度很快，相較於Secondary Storage Unit/ROM(read only memory)。
        - 具揮發性： 斷電後儲存的資料會消失。
    - #### DRAM(dynamic random access memory)
        - 半導體記憶體，利用電容內儲存電荷的多寡儲存0與1。
        - 現實中電晶體會漏電，會影響儲存內容的正確性，故須透過刷新來進行週期性充電（稱之為動態的原因）。
    - #### SRAM（static random access memory)
        - 只要維持通電的情況，不需要刷新也不會丟失儲存的內容。
        - 常用於CPU當中的cache memory。
        - 存取速度快，但是貴。

## Background Knowledge
### compile/ link/ executable file


---

![](https://i.imgur.com/qB7x3oF.png)


---

- #### Windows System
    - 順序:
        - .cpp compile to .o (machine code)
        - .o linking to .exe (executable code)
    - 方法:
        - Single File
            - 一行指令完成
                `g++ -o hello.exe hello.cpp`
            - 分行完成
                ```
                // Compile-only with -c option
                g++ -c Hello.cpp
                // Link object file(s) into an executable
                g++ -g -o Hello.exe Hello.o
                ```
                - note:
                    - -Wall: prints "all" Warning messages.
                    - -g: generates additional symbolic debuggging information for use with gdb debugger.
        - Multiple File
            - 一行指令
                `g++ -o myprog.exe file1.cpp file2.cpp `
            - 分行完成
                ```
                g++ -c file1.cpp
                g++ -c file2.cpp
                g++ -o myprog.exe file1.o file2.o               
                ```
        - MakeFile
            - 建立無附檔名的makefile
                ```
                //makefile
                all: hello.exe

                hello.exe: hello.o
                     g++ -o hello.exe hello.o

                hello.o: hello.cpp
                     g++ -c hello.cpp

                clean:
                     rm hello.o hello.exe               
                ```
            - 使用指令:
                `make
                `
                - 實際執行:
                    ```
                    g++ -c hello.cpp
                    g++ -o hello.exe hello.o
                    ```
            - **注意事項**:
                - 只會執行makefile第一行，然後根據需求往下找；故第一行需是all的資訊
                       
- #### Unix System
    - 順序:
        - .cpp compile to .o (machine code)
        - .o linking to 執行檔(無檔名) (executable code)
    - 方法:
        - Single File 
            - 一行指令完成
                `g++ -o hello hello.cpp`
            - 分行完成
                ```
                g++ -c hello.cpp
                g++ -o hello hello.o
                ```

        - Multiple File
            - 一行指令完成
                `g++ -o myprog.exe file1.cpp file2.cpp `
            - 分行完成
                ```
                g++ -c file1.cpp
                g++ -c file2.cpp
                g++ -o myprog file1.o file2.o
                ```
        - MakeFile
            - 建立無附檔名的makefile
                ```
                //makefile
                all: hello

                hello: hello.o
                     g++ -o hello hello.o

                hello.o: hello.cpp
                     g++ -c hello.cpp

                clean:
                     rm hello.o hello               
                ```
            - 使用指令:
                `make
                `
                - 實際執行:
                    ```
                    gcc -c hello.cpp
                    gcc -o hello hello.o
                    ```
            - **注意事項**:
                - 只會執行makefile第一行，然後根據需求往下找；故第一行需是all的資訊

### Object Oriented Programming (OOP)
####  特性
- 封裝
    - 把物件的屬性跟方法包在一起，在內部的屬性跟方法定義完後，外部只能透過物件提供的介面去進行操作。可以避免外部的不當操作，在使用上也可以變得比較簡單，不需要去在意內部的實作。
- 繼承
    - 提升程式的重用性、延展性，可以把一些共通性很高的類別定義在同個父類別，子類別可以繼承父類別共通的屬性，再根據子類別的一些特異性去定義自己的屬性與方法。
    
- 多型
    - 用同一個介面來實現不同的方法。
    - 包含overload(靜態)跟override(動態)，同名的function根據接收者不同可以對同一事件做出不同回應。
    - overload是指同樣function名稱透過輸入數量或類型不同，function會做不同的事情。
    - override指的是子類別，在有宣告virtual的情況下，父類別同名的function可以直接改寫父類別的function，但是父類別跟子類別function的參數必須相同。
    - overwrite指的是將父類別的function隱藏起來，(覆寫掉父類別的function)，父類別跟子類別同名function的參數可以相同也可以不同。
    - virtual function也是多型的一個實踐，也就是看接收者是誰再來決定實作內容。如果父類別跟子類別都有同一個function，在父類別的function加上virtual，在外部做運用的時候，只要透過父類別的pointer來指父類別跟子類別的物件，就能根據他們實際上的類別來實踐這個同名的function。
    
####  優點
- 可重用性、延展性、彈性

##  Array, Pointer and String
Chapter 6~8:
- ### Array
    - 分配一段連續的儲存位置
    - 宣告陣列的方法：
        - 需要提供allocate的位置的大小
        - 需要**類型**及**大小**等資訊
     ```
     int arr[7];
     int arr2[3]={1,2,3};
     ```
    - 須注意的地方：
        - 使用到一開始宣告的陣列以外的位置
        - 如該位置存在且為變數，即可以變動它
         ```
         int arr[3]={1,2,3};
         arr[8] = arr[1] + arr[2];
         ```
       - 將不想被變動的值設為常數
        ```
        const int a = 5;
        ```
    - 1D Array傳到function中
        - pass by value
            ```
            int a[5];   
            void printa(int a[]){...}
            printa(a);
            ```
        - pass by reference
            ```
            int a[5];   
            void printa(int (&a)[5]){...}
            printa(a);
            ```
        - pass by address
            ```
            int a[5];   
            void printa(int* a{...}
            printa(a);
            ```
- ### Pointer
    - 為一個儲存位置的地址，需要提供此位址指向的**類型**
    - 須透過此地址更改或存取該位址當中的值
        - 宣告指向的位置及存取值：
        ```
        int a = 5;
        int *p = &a;
        cout << 'the value of variable a is' << a << endl;
        cout << 'the pointer p is pointed to the address of a.'<< endl;
        cout << 'the place of the pointer p pointed to stores the value of ' << *p << endl;
        ```
        > Output:     
        > the value of variable a is 5
        > the pointer p is pointed to the address of a.
        > the place of the pointer p pointed to stores the the value of 5.
        - 更改指向位置儲存的值：
        ```
        int a = 5;
        int *p = &a;
        *p = 10;
        cout << 'the value of variable a now is ' << a <<endl;
        ```
        > Output:
        > the value of variable a now is 10        
    - 須注意的事項：
        - 清除pointer目前指向的位置，指向0或NULL皆可。
        ```
        int *p = 5;
        p = 0;
        p = NULL;

        ```
        - 宣告時可以與同類型的變數一併出現
        ```
        int a, *x = &a;
        ```
        - **非常重要： 勿與Reference(參考）搞混**
            - Reference是一個**已經存在的變數**的**ailias（別名）**
                - 易與位址搞混，當作位址時該位址的變數須先被宣告
                ```
                int a, int &b = a;
                cout << 'an integer variable a was defined, while b was not defined as a variable before: b was an ailias of variable a.' << endl;
                
                int c, int d = &c;
                cout << 'an integer variable c was defined: d was an integer storing the address of variable c now.' <<endl;
                ```
                > Output:
                > 整數變數a已定義，但b並未被定義成任何變數： b是變數a的別名/參考. (翻譯）
                > 整數變數c已定義： d是一個整數變數，目前儲存變數c的位址。(翻譯）
            - Reference的目的在於盡可能**節省空間**，減少在不必要的情況下新增一個新的變數。
            ```
            int addNum(int a,int b){
                return a+b;
            }
            
            int betterAddNum(int &a, int &b){
                return a+b;
            }
            
            void main(){
                int num1 = 5;
                int num2 = 3;
                
                cout << '1. with allocation of new variables a and b for function addNum <<endl;
                cout << '   addNum(num1,num2) = ' << addNum(num1,num2) << endl;
                
                cout << '2. instead of allocation of new variables a and b, just pass the value of variable num1 and num2 by creating their ailiases and calling by references.' >>endl;
                cout << '   betterAddNum(num1,num2) = ' <<betterAddNum(num1,num2) << endl;
            }
            ```
            >Output:
            > 1. 為了函式addNum，有分配位置給新的變數a及b（翻譯）
            > addNum(num1,num2) = 8
            > 2. 取代分配位置給新的變數a及b，建立num1及num2的別名，並透過呼叫參考的方式將它們的值直接傳入（翻譯）
            > betterAddNum(num1,num2) = 8
            
            -    Reference 傳送的是該物件的別名，代表傳進去的其實就是那個物件，如更改那個物件的值，是**會改變該物件**的。   
            ```
            //main.cpp
            //用比較混亂的寫法但比較好呈現，實際操作請把dog.cpp,dog.h分開
            
                class Dog(){
                    public:
                        Dog& olderDog(Dog& dog){
                            dog.age += 1;
                            return dog;
                        }
                        Dog(int a){
                            age = a;
                        }
                        int getAge(){
                            return age;
                        }
                    private:
                        int age;
                }
            
                void main(){
                    Dog apple(10);
                    
                    cout<<"apple's age = " << apple.getAge()<<endl;
                    
                    Dog apple2 = apple.OlderDog();
                    
                    cout<<"apple's age now = "<<apple.getAge()<<endl;
                    cout<<"the one return = "<<apple2.getAge()<<endl;
                    
                    return;
                }
            ``` 
            >Output:
            > apple's age = 10.
            > apples age now = 11.
            > the one return = 11.
- ### String
    - 字符陣列也可用來表示字串，字串宣告必伴隨截斷符號（\0)
    ```
    char c[] = "blue";
    char d[] = {'b','l','u','e','\0'};
    ```
    - 陣列名稱與pointer具相同功能
    ```
    char color[5] = "blue";
    char const *p = color;
    char const *t = &color[0];
    
    cout << "char color[3] is " << color[3] << " and *(p+3) is " << *(p+3) <<endl;
    ```
    > Output:
    > char color[3] is e and *(p+3) is e     

- ### Vector
    - Pass 2D vector into function
        - 方法一: pass by value
            `void passVector(vector<vector<int>> v){...}`
        - 方法二: pass by reference
            - 避免pass by value造成的copy and pass
            `void passVector(vector<vector<int>>& v){...}`
##  Classes and Data Abstraction
Chapter 9~10
- ### Classes
    - 存取與修改權限： public, private, protected
    - 宣告方法
    ```
    class Dog{
        public:
            void setAge(int a){ age = a; }
            void setGender(int g){ gender = g; }
            int getAge(){ return age; }
            int getGender(){ return gender; }
            int fitness(){ return weight*age/1.495*(gender+0.45); }
            Dog(int a,int g,int w){ age = a; gender = g; weight = w;}
        
        private:
            int age = 0;
            int gender = 0; //girl,boy
            int weight = 0;
    }
    ```
    - 拆分成header(.h)與implementation(.cpp)檔案：
        - header
        ```
        //dog.h

        #ifndef DOG_H
        #define DOG_H

        class Dog{
            public:
                void setAge(int a);
                void setGender(int g);
                int getAge();
                int getGender();
                float fitness();
                Dog(int a, int g, int w);
            private:
                int age = 0;
                int gender = 0;
                int weight = 0;
        }

        #endif
        ```
        - cpp
        ```
        //dog.cpp

        #include "dog.h"

        Dog::Dog(int a, int g, int w){
            age = a;
            gender = g;
            weight = w;              
            }        
        void Dog::setAge(int a){
            age = a;            
            }    
        void Dog::setGender(int g){
            gender = g;

           }    
        int Dog::getAge(){
            return age;
           }    
        int Dog::getGender(){
            return gender;
          }    
        float Dog::fitness(){
            return age*weight/1.495*(gender+0.45);
            }
        ```
    - 在main.cpp如何使用class:
    ```
    //main.cpp
    
    #include "dog.h"
    ```
    - extern 與靜態（static）用法
        - extern:
            - 令其他cpp file可以存取其他檔案中的特定變數
            ```
            //main.cpp
            
            #include "dog.h"
            using namespace std;
            
            void main(){
                cout << "a = " << a << endl;
                a = 0;
                cout << "a = " << a << endl;
            }    
            ```
            
            ```
            //dog.h
            
            #ifndef DOG_H
            #define DOG_H
            
            extern int a;
            void greeting();
            
            #endif
            ```
            
            ```
            //dog.cpp
            
            #include "dog.h"
            
            int a = 1;
            void greeting(){
                cout<< "hello its me."
            }
            
            ```
        - static(靜態)
            - 存在時間與主程式（main)執行時間相同，該函式結束時仍保存著
            ```
            int couting(){
                static int counter = 0; //only initialized at the first time
                return counter++;
            }
            ```
            - **作用域不變**，宣告於function內，可存取的位置仍是function內：防止不同檔案中相同變數名稱在link時出現錯誤
            ```
            //a.h
            
            #ifndef A_H
            #define A_H
            
            static int dds;
            
            #endif
            ```
            
            ```
            //b.h
            
            #ifndef B_H
            #define B_H
            
            static int dds;
            
            #endif
            ```
            
            ```
            //main.cpp
            
            #include "a.h"
            #include "b.h"
            
            ......
            
            ```
            
            ```
            //sh
            g++ -c main.cpp //產生main.o
            g++ -c a.cpp    //產生a.o
            g++ -c b.cpp    //產生b.o
            g++ -o main main.o a.o b.o //如果未加入"static": 錯誤產生，因為main.cpp裡面include a.h以及b.h，但當中有重複變數名稱dds
            ```
            - **非常重要!! static 使用在class當中不屬於任何物件**
                - 使用在class variable前：
                    - 此variable不屬於此class的任何object，即不屬於任何instance;為**整個class共用之變數**
                    - **初始化**的方法，**不可以在class宣告時做**，需要在class外面、main外面。
                - 使用在class function前：
                    - 此function不屬於此class的任何object，即不屬於任何instance;為整個class**共用之函式**
                ```
                #include <iostream>
                using namespace std;

                class Object {
                public:
                    Object() {
                        ++counter;
                        cout << "counter = " << counter << endl;
                    }

                    static int getCounter() { return counter; }
                private:
                    static int counter;
                };

                int Object::counter = 0; // initializing the static int

                int main() {
                    Object obj1;
                    Object obj2;
                    Object obj3;
                    cout << Object::getCounter() << endl;
                    return 0;
                }
                ```
                
    - constant(const) object:
        - 只能呼叫const function，無法呼叫non-const function; **但是const function可以被const object以及non-const object呼叫！**
        - **只能用member initializar**的方式創建物件並賦予初始值：
        ```
        //constMember.cpp include header definition version
        Class Dog{
            public:
                int get_weight() const;
                Dog(int a,int g); //constructor using member initializer
            private:
                int age;
                int gender;
        }
        
        int Dog::get_weight() const { return a+g/g*2;}
        Dog::Dog(int a,int g) : age(a),gender(g){} //constructor using member initializer
        ```
        
        ```
        //main.cpp
        
        #include "constMember.cpp"
        using namespace std;
        
        void main(){
            //member initializer= 
            //CLASS_NAME INSTANCE_NAME(first_value,second_value );
            
            const Dog doggy(5,0); //const object
            Dog kitty(3,1);      //non-const object
            doggy.get_weight();
            kitty.get_weight();
            
            //使用pointer創建物件的呼叫方法
            Dog* dog_ptr = new Dog(10,1);
            (*dog_ptr).get_weight();
            dog_ptr->get_weight();
            
        }
        
        ```  
    - **一般 const 用法**:
        - 基本使用:
            `const int a = 10; //不可修改a的值`
            
        - 指標使用：
            ```
            const int* ptr;        //不可修改ptr指向的內容
            int* const ptr;        //不可修改ptr指向的位置
            const int* const ptr; //指向的內容、指向的位置都不可修改
            ```
        - 回傳使用：
            ```
            const int foo(); //函式外部不可修改回傳的值
            ```
    - **constant(const) member function** vs return const object:
        - const member function **無法改動成員屬性**
        ```
        //passenger.h

        class Passenger{
            public:
                int get_age();
                const Passenger get_nextSeats(); //return回去的值是const
                int get_bus_number() const; //member function是const，即此函式不能改動成員屬性
            private:
                ...
        }
        ```  
        - **須注意!!!的std結構operator:**
            - std::map中的$[]$與**at**差異:
                - []: 確認輸入key是否存在而返回，不存在會**insert**這個key進去；在const member function**不可以使用**
                - **at**: 確認輸入key是否存在而返回，不存在會throw exception；在const member function中**可以使用**

- **兩個classes的object互call的極端狀況**
    - 解法一
        - 使用header file, cpp file來儲存各自的程式碼
        - **不要互相於header file include對方**，會造成程式從A->B，又從B->A，但A已經被執行過，導致B無法參考A。
        - **依照實作時參考的順序，來include在header file**；而cpp當中一般是include自己的header檔，但自己的header檔無包含對方的header檔，則**需在cpp內include以知道如何實作**。
            ```
            main.cpp
            #include "A.h"
            #include "B.h"
            ...
            ```
            ```
            A.h
            #include "B.h"
            ...
            ```
            ```
            B.h
            ...
            ```
            ```
            A.cpp
            #include "A.h"
            ...
            ```
            ```
            B.cpp
            #include "A.h"
            #include "B.h"
            
            ```
    - 解法二
        - 共同放在一個source cpp，使用**前置宣告+動態配置記憶體**(pointer to class object / vector of class object)，不然compiler不知道要**預留多少空間**，且可能會報錯無"對應的建構子"。
        ```
        main.cpp
        
        class Dog;
        
        class Cat
        {
            private:
                int id;
                string name;
                Dog* friend; // 全部Dog* pointer可抽換成vector<Dog> 
            public:
                Cat(int i, string n, Dog* f);
                Dog* get_friend(); 
        }
        
        class Dog
        {
            private:
                int id;
                string name;
                Cat* Cat; // 全部Cat* pointer可抽換成vector<Cat> 
            public:
                Dog(int i,string n, Cat* f);
                Cat* get_friend();
        }
        ```
## Operator Overloading

Chapter 11~12

- ### Function Overloading
    - function 名稱相同，但是作得內容不同
    - 考量：
        - 輸入引數(parameter)數量
        - 輸入引數(parameter)種類
        - 輸入引數(parameter)順序



- ### Operator Overloading
    - 不能更改運算元(operant)的數量
    - 只能使用已存在的operator
    - 一些無法overloading的運算子： condition operator(?:),address(&),...etc
    - 一些系統會自己預設的運算子： assignment(=),reference(&),comma(,)，不須特別做。
    - assignment(=):
        - 如未overload, class object之間會直接用copy的方式->創建一個物件，把每個屬性照抄過來。
        - 只能利用member function去做overload.
    - copy constructor:
        ```
        Dog dog1(10,2,10.5);
        Dog dog2(dog1); //copy constructor
        ```
    - operator+ , <,  > overloading:
        ```
        class Dog{
            public:
                Dog(int a){
                    age = a;
                }
                int getAge(){
                    return age;
                }
                Dog operator+ (Dog dogB){ //operator add overloading
                    return Dog(age + dogB.age); 
                }
               bool operator> (Dog dogB){ //operator add overloading
                    return age > dogB.age; 
                }
               bool operator< (Dog dogB){ //operator add overloading
                    return age < dogB.age; 
                }
            private:
                int age;
        }
        
        void main(){
            Dog dog1(10);
            Dog dog2(20);
            
            cout<<"dog 1 + dog 2 = "<<(dog1+dog2).getAge()<<endl;
        
            return;
        }
        
        ```
        > Output:
        > dog 1 + dog 2 = 30        
    
    - **須注意!!!****std.h**中的必須做operator overloading**特例**:
        - 如**map與set**等**ordered** structure
        - 故當儲存在map、set當中的是class object時，在進行insert等動作時，需要進行**排序**(key的**比較**等)
        - 故需針對該class做 **>、<** 等運算子做**operator overloading**
            ```
            #include "passenger.h"
            using namespace std;
            
            std::map<int,Passenger> passenger_list;
            Passenger p1(10);
            
            passenger_list[10] = p1; //insert需要排序比較
            ```

## Inheritance
Chapter 13

- ### 名詞解釋
    - **Base** Class vs **Derived** Class
        - base: 原先就存在的class，比較general。
        - derived: 比較specific，繼承base class的特性（是base class的object)，但可以有自己獨立的一些特性。

    - **Direct** Base Class vs **Indirect** Base Class
        - direct base: 你爸媽，直系繼承的第一個class
        - indirect base: 你阿公阿嬤等，直系繼承但是好幾層以上的class

    - **Single** Inheritance vs **Multiple** Inheritance
        - single: 只繼承一個base class
        - multiple: 繼承多個base class，校長同時是"老師"也是"管理者"

- ### **Inheritance Mode**
    - public / private / protected inheritance
        ```
        class Animal{
            public:
                void set_name(string n){ name=n; }
            private:
                string name;
            protected:
                string weight;
        
        class Dog: public Animal{ //public inheritance
            public:
                void bark(){}
            private:
                string barksound;
        }
        class Cat: private Animal{ //private inheritance
            public:
                void meow(){}
            private:
                string meowsound;
        }
        class Bird: protected Animal{ //protected inheritance
            public:
                void fly(){}
            private:
                string flysound;
        }
        }
        
        ```
    - public/private/protected inheritance 存取權限
        ```
        class A{
            public:
                method_public;
            private:
                method_private;
            protected:
                method_protected;
        }

        class B: public A{
            // method_public: public
            // method_private: 不可存取
            // method_protected: protected
        }

        class C: private A{
            // method_public: private(可於內部呼叫，不可於外部呼叫）
            // method_private: 不可存取
            // method_protected: private(可於內部呼叫，不可於外部呼叫）    
        }

        class D: protected A{
             // method_public: protected(可於內部呼叫但有接收者，不可於外部呼叫）
            // method_private: 不可存取
            // method_protected: protected(可於內部呼叫但有接收者，不可於外部呼叫）          
        }

        class E:  A{ //默認private inheritance
            // method_public: private(可於內部呼叫，不可於外部呼叫）
            // method_private: 不可存取
            // method_protected: private(可於內部呼叫，不可於外部呼叫）          
        }
        ```
        - 須注意: derived class也**無法存取**base class的**private member**
        - 如果是public繼承:
            - 派生類別與外部**可直接存取**基類**public function**
            - 派生類別與外部**無法存取**基類的**private function**
            - **派生類別內部可以直接存取**基類的**protected function**，但若無提供介面給外部，**外部是不可直接存取**基類的protected function
                - 如何提供介面？
                - 在派生類別建立public function，外部透過此public function可以存取protected function/variables
    
    -  **建構子及解構子順序**
        ```
        class A{
            private:
                int age;
                B b;
                C c;
                
        }
        class B{}
        class C{}
        class D: public A{}
        
        A* a = new A();
        delete a;
        D* d = new D();
        delete d;
        ```
        > 順序：
        > 建構B->建構C->建構A       
        > 解構A->解構C->解構B
        > 建構B->建構C->建構A->建構D
        > 解構D->解構A->解構C->解構B         
        
        ```
        class A{
            public:
                A(int k){ age = k; }
            private:
                int age;
                
        }
        class B: public A
        {    
            public:
                B(int a, int b):A(a){ cc = b; }
            private:
                int cc;
        }
        
        B* b = new B(27,4);
        delete b;
        ```    
        > 順序：
        > 建構A->建構B
        > 解構B->解構A
    - ### 重要!!! **Base and Derived Class Behavior**
        ```
        #include <iostream>
        #include <string>
        #include <stdlib.h>
        #include <stdio.h>

        using namespace std;

        class Base 
        {
        public:
         Base() {
          my_name = 10;
          key = 'a';
          cout<<"create base," << endl;
         }
         ~Base() { cout << "destroy base," << endl; }
         void f1() { cout<<"base f1," << endl; }
         virtual void f2() { cout<<"base f2" << endl; }
        private:
         int my_name;
         char key;
        };

        class Derived : public Base
        {
        public:
         Derived() {
          kk = "abc";
          cout << "create derived," << endl;
         }
         ~Derived() { cout << "destroy derived"<<endl; }
         void f1() { cout << "derived f1," << endl; }
         virtual void f2() { cout << "derived f2" << endl; }
         void f3() { cout << "derived specific function" << endl; }
        private:
         string kk;
        };


        int main() 
        {
         Base* bp = new Base(); //base obj 
         cout << "---" << endl;
         Base* bd = new Derived(); //base obj with override
         cout << "---" << endl;
         Derived* dr = new Derived(); //derived obj
         cout << "---" << endl;
         Base* d = bd; //base -> base
         Base* b = dr; //derived -> base : slicing
         cout << "---" << endl;
         
         //base->derived : will cause problem:
         //Derived* d = bd; Derived* d = bp; 
         
         bp->f1();
         bp->f2();

         bd->f1();
         bd->f2();
         
         //bd->f3() : bd is base obj override by derived : no f3 function 
         
         delete bp;
         cout << "---" << endl;
         delete bd;
         cout << "---" << endl;
         delete dr;
         cout << "---" << endl;


         return 0;
        }
        ```
    - #### **輸出與結論**
        ![](https://i.imgur.com/CJH20g6.png)
        - #### **建立、初始化：**
            - 情況一： **以Base pointer指向新配置的Derived空間**:
                - Base* bd = new Derived();
                - 建立一個derived obj , **constructor : base->derived**(根據new後面的class)
                - slicing 成一個base obj，override改寫f2()
                - 不具有f3()這個derived obj才有的function
            - 情況二： **Derived 透過slicing跟override可以初始化 Base，反之不行:**
                - **1. Derived 透過slicing跟override可以初始化 Base Obj**:
                    - ex1. Base* b = bd;
                    - ex2. Base* b = dr;
                    - b會被視作指向一個slicing後的base obj，但是由於override改寫了f2()
                - **2. 無法透過 Base Obj 初始化 Derived Obj:**
                    - ex1. (compile error!) Derived* d = bd;
                    - ex2. (compile error!) Derived* c = dr;
                    
        - #### **刪除、釋放記憶體：**
            - 視作釋放一個base obj, destructor: base
                - **pointer是指向Base obj的**
                - ex1. delete b;
                - ex2. delete bd;
            - 視作釋放一個derived obj, destructor: derived -> base
                - **pointer是指向Derived obj的**
                - delete dr;
        

## Polymorphism
Chapter 14

- ### Polymorphism：
    - 定義:
        - 根據接收者是誰決定實際上執行的行為
    - 條件須三項吻合:
        - Inheritance
        - Overloading
        - Overriding


- ### **Virtual Function**: 
    - 用在polymorphism，會加在base class中，不知道明確如何implement的function上
    - 實用此情境時，使用**base class的pointer**來導向base class以及derived class
    ```
    class Operate{
        public:
            virtual void press(){
                cout<<"按下開關。"<<endl;
                }
    class SW1: public Operate{
        public:
            void press(){
                cout<<"按下101大樓內電梯裡的開關"<<endl;
            }
    }
    class SW2: public Operate{
         public:
            void press(){
                cout<<"按下101大樓內頂樓陽台的開關"<<endl;
            }   
    }
    
    void turnoff(Operate *Q1){ //一定要用pointer或reference喔！
        Q1->press();
    }
    
    Operate Q1;
    SW1 s1;
    SW2 s2;
    
    turnoff(&Q1);     // base class
    turnoff(&s1);    // derived class 1
    turnoff(&s2);    // derived class 2
    
    }
    
    ```
    > Output:
    > 按下開關。
    > 按下101大樓內電梯裡的開關
    > 按下101大樓內頂樓陽台的開關    

- 一旦有pure virtual的function存在，該class即是一個抽象class，不可有該class的instance存在。

- ### Casing
    - Upcasting vs Downcasting
        - Upcasting: 把derived class obj指派(assign)給base class obj，但有slicing problem，即遺失derived class才有的特性(善用virtual function避免輸出遺失的特性）
            ```
            class Pet{}
            class Dog: public Pet{}
            Pet pet;
            Dog dog;
            pet = dog; // upcasting with slicing
            ```
        - Downcasting: 把base class指派給derived class，僅允許使用在pointer+dynamic casting的時候
            ```
            class Pet{}
            class Dog: public Pet{}
            Pet pet = new Dog();
            Pet p = new Pet();
            Dog dog = new Dog();
            
            //correct one
            Dog d = dynamic_cast<Dog*>pet; // downcasting should with dynamic_cast
            
            //error cases
            Dog d = pet; // error without dynamic_cast
            Dog c = dynamic_cast<Dog*>p; //error because the object p point to is actually a Pet class
            
            ```
![image](https://hackmd.io/_uploads/Sy06xtfD6.png)
