---
# System prepended metadata

title: OOP note using C++

---

# OOP note using C++

紀錄考試筆記

## ***Access Modifiers***
**public**: 能被物件以及使用物件的地方使用
**private**: 只能在物件內被使用
**protected**: 只能在物件內被使用，也可以被繼承(inheritance)該物件的物件使用
>  https://www.geeksforgeeks.org/access-modifiers-in-c/
```c++=
class Parent 
{ 
	protected: 
	    int id_protected; 
};
class Child : public Parent 
{ 
	public: 
	void setId(int id) { 
		id_protected = id; 
	} 
	void displayId() { 
		cout << "id_protected is: " << id_protected << endl; 
	} 
}; 
int main() { 
	Child obj1; 
	obj1.setId(81); 
	obj1.displayId(); 
	return 0; 
} 
```
![螢幕擷取畫面 2024-06-12 150154](https://hackmd.io/_uploads/SygzupLHC.png)


---

## ***class***
1. ### **constructor v.s. destructor**
    > https://learn.microsoft.com/zh-tw/cpp/cpp/destructors-cpp?view=msvc-170
    * constructor : 自訂類別初始化其成員的方式，或在建立類別的物件時叫用函式
    * destructor: 解構函式是成員函式，當**物件超出範圍**或由 或**呼叫delete**明確終結時，會自動叫用。
    * 解構子就是建構子的相反，不過建構子可以overload，解構子不行 (只能有一個解構子)。compiler會自動解構子，所以就算不寫也會解構。

        寫法：
        ```c++=
        class A{
            ~A(){ /**<---這就是解構子，加一個波浪**/
            }
        };
        ```
2. ### **this**
    - points to the object
    ex:
        ```c++=
        private:
            int num;
        public:
            void setNum(int num){ 
                this->num = num; 
            }
        ```
3. ### **const**
    ![螢幕擷取畫面 2024-06-15 230320](https://hackmd.io/_uploads/SyRrpmsrA.png)

4. ### **static member**
    * #### 使用在一個member variable前面
        全部object的這個變數都是同一個memory address
    * #### 使用在一個member function前面
        看瞴中...
5. ### **friend**
    * 不是同個class中的member，但可使用private的東東
6. ### **copy constructor**
    * Student s2 = s1 or Student s2(s1)，s1的東東會複製給s2
    * 當有使用pointer時會出錯 (因為pointer指向地址，會造成複製後指向地址依然相同)
        解法: 自己重建pointer
        ```c++=
        class CpClass
        {
            int *p;
            public:
                CpClass(const CpClass &obj)
                { p = new int; *p = *obj.p; }
                CpClass(int v = 0)
                { p = new int; *p = v; }
                ~CpClass(){delete p;}
        };
        ```
7. ### **inheritance**
    ex:
    ```
    class Base{
    
    };
    class Derived : public Base{
    
    };
    ```
    protector & public 內的member可在繼承後拿到
8. ### **virtual** & **override**
    >https://medium.com/theskyisblue/c-%E4%B8%AD%E9%97%9C%E6%96%BC-virtual-%E7%9A%84%E5%85%A9%E4%B8%89%E4%BA%8B-1b4e2a2dc373
    >https://viml.nchc.org.tw/archive_blog_547/
    *virtual* : 被用在修飾member function，代表若有 derived class 的話，該函式可以被 redefined
    *override* : 只要在衍生類別裡面、要覆寫函式後面加上「override」、告訴編譯器這個函式是要用來覆寫基礎類別的虛擬函式就可以了。
    ex:
    ```c++=
    class Base{
        public:
            virtual void func1() {}
            virtual void func2() {}
            void nonVirtualFunc() {}
    };
    class Derived : public Base{
        public:
            virtual void func2() override {}
            void nonVirtualFunc() {}
    };
    Base myBase;
    ```
    關係圖:
    ![螢幕擷取畫面 2024-06-16 015829](https://hackmd.io/_uploads/HyfDULjBA.png)
    沒有virtual的function不可被改寫
9. ### **pure virtual function**
    > https://medium.com/@s9224914/oop-%E4%BB%80%E9%BA%BC%E6%98%AF%E6%8A%BD%E8%B1%A1-virtual-function-with-c-example-e4d386866709
    ex:
    ![螢幕擷取畫面 2024-06-16 020222](https://hackmd.io/_uploads/rJ9nw8ir0.png)
    Base 類別中的 showInfo() 為 pure virtual function，
意味著 Base 類別不可被實體化成 instance；繼承Base的衍生類別**必須**實作 showInfo() 函式。
    ex:
    ![螢幕擷取畫面 2024-06-16 021230](https://hackmd.io/_uploads/HJFX5UjrC.png)
![螢幕擷取畫面 2024-06-16 021249](https://hackmd.io/_uploads/SJJe5IjHR.png)
![螢幕擷取畫面 2024-06-16 021308](https://hackmd.io/_uploads/H1yxqIorC.png)
    File_filter內做了pure virtual function : transform 
    其他兩個class必須實作 transform 這個function(如果有.h檔，必須實作在.h檔內，不能實作在.cpp)


---

## ***struct***
ex:
```c++=
struct Student{ 
    int studentID;
    string name;
};
```

* 使用 "." 運算 refer to members of struct variables
ex: Student s1; s1.name = "tavha";
* or 可以直接initial
ex: Student s1 = {s1088888, "tavha"};
可以   s1 = {s1088888};  // 只宣告第一個
但不行 s1 = {, "tavha"}; //不可跳過member
* A struct with constructor
ex: 
```c++=
struct Dimensions
{
    int length, width, height;
    // Constructor
    Dimensions(int L=0, int W=0, int H=0)
    {length = L; width = W; height = H;}
};
```
---

## ***Overload*** 
1. ### ***overload constructor***
    * 重載的建構函數本質上具有**相同的名稱**（類別的確切名稱），但**參數的數量和類型不同**。
    * **根據傳遞的參數的數量和類型**呼叫建構函數。
    * 建立物件時，必須傳遞參數以讓編譯器知道需要呼叫哪個建構子。

    > https://www.geeksforgeeks.org/constructor-overloading-c/
    ```c++=
    class construct {  
        public: 
            float area;  
            construct() { 
                area = 0; 
            }
            construct(int a, int b) { 
                area = a * b; 
            } 
    };
    ```
2. ### ***overloading operator***
    使用類別成員來超載二元運算子時，會有一個限制，就是運算子的左邊一定要是原物件。
    使用 *friend*函式重載二元運算子時，您要指定兩個參數型態，分別表式運算子左右邊的運算元型態。
    * **"+"**
        > https://openhome.cc/Gossip/CppGossip/friendOverLoadOperator.html
        
        ex:
        ```c++=
        OpClass OpClass::operator+(OpClass r){   
            OpClass sum;
            sum.x = this->x + r.x;
            return sum;
        }
        
        OpClass a, b, s;
        s = a + b;
        ```
        ![螢幕擷取畫面 2024-06-16 011659](https://hackmd.io/_uploads/r1Y2hBor0.png)
        ```c++=
        //定義Point2D.h：
        class Point2D {
            public:
                friend Point2D operator+(const Point2D&, int); 
                friend Point2D operator+(int, const Point2D&); 
            private:
                int _x;
                int _y;       
        };

        //再實作Ball.cpp：
        #include "Point2D.h"
        Point2D operator+(const Point2D &p, int i) {
            Point2D tmp(p._x + i, p._y + i);
            return tmp;
        }
        Point2D operator+(int i, const Point2D &p) {
            Point2D tmp(i + p._x, i + p._y);
            return tmp;
        }

        //接著您就可以直接如下進行運算：
        Point2D p1(5, 5);
        Point2D p2;
        p2 = 10 + p1;
        ```
        
    * **"="**
        ex:
        ```c++=
        CpClass CpClass::operator=(CpClass r){
            *p = *r.p;
            return *this;
        };

        ```
    * **"=="**
        ex:
        ![螢幕擷取畫面 2024-06-16 012235](https://hackmd.io/_uploads/SJZgRHjSA.png)
    * **"++"** & **"--"**
        //考完試補
    * **"<<"** & **">>"**
        ex:
        在class的.h檔建friend function
        ![螢幕擷取畫面 2024-06-16 013444](https://hackmd.io/_uploads/BycybLjrC.png)
        在.cpp檔實做(記得要兩個reference)
        ![螢幕擷取畫面 2024-06-16 013429](https://hackmd.io/_uploads/HJUvb8jBC.png)
    * conversion
        //考完試補
---


## ***Something special***  (* ~ *)
### 1. Type Conversion
> https://www.scaler.com/topics/cpp/type-conversion-in-cpp/
* **Implicit type conversion (automatic)**
編譯器自動完成型別轉換的地方。
編譯器會自動將**所有資料類型轉換為表達式中存在的最高資料類型**。
ex:
```c++=
int main() {
  int int_var = 50;
  char char_var = 'a';

  int_var = int_var + char_var;

  cout << "The value of (50 + 'a') is: " << int_var << endl;

  float float_var = int_var * 1.5;

  cout << "The value of float_var is: " << float_var << endl;

  return 0;
}
```
output:
```c++=
The value of (50 + 'a') is: 147
The value of float_var is: 220.5
```
![data-loss-chart](https://hackmd.io/_uploads/B1kdsCIHR.png)

* **Explicit type conversion**
顯式類型轉換是由程式設計師手動完成的那些轉換。
    * Using the Assignment Operator
        ex: int_var = (int) char_var;
    * Using the **Cast** Operator
        1. *static_cast*
        方式和上面差不多
    ex: 
        ```c++=
        double num = 3.7;
        int cast_var;
        cast_var = static_cast <int> (num);
        ```
        2. *dynamic_cast*
        當我們從父類別(Base)到衍生類別(Derived)進行類型轉換時才能使用此轉換。如果轉換失敗，該表達式將傳回 NULL 值。
        ex:
        ```c++=
        class Base {
          public:
            virtual void print() {}
        };

        class Derived: public Base {};

        int main() {
          Base* b = new Derived;
          Derived* d = dynamic_cast <Derived*> (b);

          if (d != NULL) {
            cout << "dynamic_cast done" << endl;
          } 
          else {
            cout << "dynamic_cast not done" << endl;
          }
          return 0;
        }
        ```
        3. *const_cast* 
        通常用在具有一個或多個物件的程式中，這些物件具有一些常數值，需要在程式中的某個時刻進行更改。
        ex:
        ```c++=
        int main() {
          const int var1 = 10;
          const int* ptr1 = &var1;
          cout << "The old value of ptr1 is: " << *ptr1 << endl;
          int* ptr2 = const_cast <int*> (ptr1);
          *ptr2 = 3;
          cout << "The new value of ptr1 is: " << *ptr1 << endl;
          return 0;
        }
        ```
        ![螢幕擷取畫面 2024-06-12 162405](https://hackmd.io/_uploads/H1gBoALrR.png)
        
        4. *reinterpret_cast* 
        用於將一種**指標類型**轉換為另一種指標類型，無論這些類別是否相關。它不檢查指標類型和指標所指向的資料是否相同。
         主要用於處理位元。
         ex:
         ```c++=
         int main() {
              int* ptr = new int(98);

              char* ch = reinterpret_cast <char*> (ptr);

              cout << "The value of *ptr is: " << *ptr << endl;
              cout << "The value of ptr is: " << ptr << endl;
              cout << "The value of *ch is: " << *ch << endl;
              cout << "The value of ch is: " << ch << endl;
              return 0;
        }
        ```
        ![螢幕擷取畫面 2024-06-12 163907](https://hackmd.io/_uploads/ryQpR0LS0.png)
        
            在上面的例子中，我們聲明了一個指向值98的整數指標ptr。
            列印這些值後，我們可以觀察到*ch 列印“b”，
            因為“b”相當於 ASCII 中的 98。值ch包含98。
            
### 2. string .data()
     str.data() 直接以數組方式返回string的內容，
     其大小爲size()的返回值，結尾並沒有\0字符。
     
### 3. enum
ex:
```c++=
enum Tree {ASH, ELM, OAK} tree1, tree2;
//     代表  0    1    2 
tree1 = ASH // == (tree1 = 1)
```
* 用在case中能對choice取名字
ex:
    ```c++=
    switch(tree1)
    {
        case ASH: cout << "Ash";
                break;
        case ELM: cout << "Elm";
                break;
        case OAK: cout << "Oak";
                break;
    }

    ```
* enum class (又稱strong type enum)
    > https://viml.nchc.org.tw/archive_blog_720/
    ex:
    ![螢幕擷取畫面 2024-06-15 224807](https://hackmd.io/_uploads/SJ5TKXjr0.png)
    也就是說一般的enum可以在不同群之間使用(因為都會被翻成int)，但enum class只能在自己的小圈圈用


### 4. File operation
* **fstream** : 檔案操作的library
    >https://hackmd.io/@voidism/ry4GNk78-?type=view
    ex:
    ```c++=
    #include<fstream>
    ifstream inFile;
    ofstream outFile;
    //開檔
    inFile.open("inventory.dat");
    outFile.open("report.txt");
    //拿data
    while(!infile.eof()){
        infile.get(ch);
        cout << ch;
    }
    //關檔
    inFile.close();
    outFile.close();
    ```
    or 
    ex:
    ```c++=
    fstream file;
    file.open("myfile.dat", ios::in);
    file.open("myfile.dat", ios::out);
    //或者可以
    file.open("myfile.dat", ios::in|ios::out);
    ```
    開檔方式:
    ![螢幕擷取畫面 2024-06-16 150127](https://hackmd.io/_uploads/B1JNRZ3SC.png)

* **peek**:看inputstream但不拿出
    ex:
    ```c++=
    ifstream inFile; char ch;
    inFile.open("myFile");
    ch = inFile.peek();
    cout << "Got " << ch;
    ch = inFile.peek();
    cout << "Got " << ch;//same output
    ```
* **seek**
    ![螢幕擷取畫面 2024-06-16 173123](https://hackmd.io/_uploads/HJt6b4nHR.png)
![螢幕擷取畫面 2024-06-16 173438](https://hackmd.io/_uploads/SyF6W43HA.png)

* 結構化寫入寫出:
    ex: 
    store(write to file)
    ```c++=
    void menu::store(ofstream &out){
        //write string
	    int Length = item_description.length();
	    out.write(reinterpret_cast<char *>(&Length), sizeof(int));
	    out.write(item_description.data(), Length);
	    
        //write int
	    out.write(reinterpret_cast<char*>(&quantity_on_hand),
        sizeof(quantity_on_hand));
	    out.write(reinterpret_cast<char*>(&wholesale_cost), 
        sizeof(wholesale_cost));
	    out.write(reinterpret_cast<char*>(&retail_cost), 
        sizeof(retail_cost));
	    out.write(reinterpret_cast<char*>(&date_added), 
        sizeof(date_added));
    }
    ```
    load(read from file)
    ``` c++=
    void menu::load(ifstream &in){
        //read string 
	    static char buffer[256];
	    int Length;
	    in.read(reinterpret_cast<char *>(&Length), sizeof(int));
	    in.read(buffer, Length);
	    buffer[Length] = '\0';
	    item_description = buffer;
	
        //read int
	    in.read(reinterpret_cast<char*>(&quantity_on_hand), 
        sizeof(quantity_on_hand));
	    in.read(reinterpret_cast<char*>(&wholesale_cost), 
        sizeof(wholesale_cost));
	    in.read(reinterpret_cast<char*>(&retail_cost), 
        sizeof(retail_cost));
	    in.read(reinterpret_cast<char*>(&date_added), 
        sizeof(date_added));
    }
    ```
    用array儲存多筆資料
    ```c++=
    menu m[2];
    ifstream in("Menu.dat", ios::binary);
    in.close();
	ofstream out("Menu.dat", ios::binary);
    m[1].add(out, description, Quantity, Wholesale, Retail, Date);
	out.close();
    ```
    note:好像要先關一個再開另一個才不會錯
    
### 5. iomanip有關
![螢幕擷取畫面 2024-06-16 150631](https://hackmd.io/_uploads/ryYSJM2r0.png)
![螢幕擷取畫面 2024-06-16 150647](https://hackmd.io/_uploads/H1KByz2rR.png)


### 6. extern
> https://wucodingroad.blogspot.com/2017/05/Cplusplus-extern.html
``` 用來聲明此變數只是一個宣告，它的定義在別處，可能在同一個文件，也可能在別的文件，告知程式去尋找。 ```

### 7. volatile
> https://ithelp.ithome.com.tw/articles/10308388
* **修飾變數**
    強制編譯器直接讀取變數的記憶體value，而不是讀取其暫存器的值(防止變數變化太快而出錯)