可以參照這一篇
https://hackmd.io/@Chunghao/rJBkfDQ1T
針對基礎輸出輸入
- #include <stdio.h>為C語言當中的標頭檔,表示輸出與輸入
- printf or scanf 為C語言的輸出方法
- 需要有修飾子進行資料型態判別
- | + | %c |
---|---|---|
向左靠齊 | 印出正負號 | 字元 |
%s | %d | %f |
---|---|---|
字串 | 十進位整數 | 浮點數 |
%l | %u | %e |
---|---|---|
長整數,加在d,u之前 | 無號 十進位整數 | 浮點數(指數) |
C語言必須要使用,C++則沒有必要使用
針對基礎輸出輸入
- 這段程式碼是基礎語法中最常見的。
- #include <iostream> 是指引入標準庫中的輸入跟輸出,為標頭檔。
- using namespace std; std指得是逼準時是庫的命名空間。
- cout 為輸出指令。
- return 0 為回傳0給作業系統
std:: 與 namespace std; 差別
- using namespace std;拿掉
- std:: 語法上可以取代
\n 與 endl 差異
此時輸出分別為51, 5.2, 5.2, F, project, 1
如果在int 前面新增一個const 代表這個值無法變動,如果再賦值給name的話就會報錯。
\n |
---|
換行 |
\f | \t | \b |
---|---|---|
換頁 | 跳格 | 倒退 |
" | ' | / |
---|---|---|
雙引號 | 單引號 | 斜線 |
\ | \x | \d |
---|---|---|
反斜線 | ASCII(16進位) | ASCII(8進位) |
+ | - | * | / | %(取餘數) |
---|---|---|---|---|
a+b | a-b | a*b | a/b | a%b |
> | >= | < | <= | == | != | += | -= | *= | /= | %= |
---|---|---|---|---|---|---|---|---|---|---|
2>3 =false | 2>=3 =false | 2<3 =true | 2<=3 =true | 2==3 =false | 2!=3 =true | a=a+b -> a+=b | a=a-b -> a-=b | a=ab -> a=b | a=a/b -> a/=b | a=a%b -> a%=b |
C++運算輸出練習
C運算輸出練習
可以看得出來C/C++語法上有些許上的差異。
&& | || | ! |
---|---|---|
AND or 且 | OR or 或 | NOT or 否 |
i++ | i- - | ++i | - -i |
---|---|---|---|
表示先輸出i,再對i做出加法 | 表示先輸出i,再對i做出減法 | 先對i進行加法,再輸出i | 先對i進行減法,再輸出i |
C++資料型態的轉換
C資料型態的轉換
C語言沒有查閱型別的函式庫
結果回傳:
C++撰寫數學函式庫
結果回傳:
C撰寫數學函式庫
C語言沒有max,min的函數,因此要使用這種比大小方法回傳最大值。
- 這個意思是指定義一個簡單的宏定義PI的值為3.14,因此在main當中調用PI就可以代表3.14這個數值。
- Ans:
請輸入半徑:2
圖的面積是:12.56
圖的周長是:12.56
- 這個意思是指定義一個帶有參數的宏定義SQUARE,其參數x的方法為x*x,在main當中宣告num = 5,帶入SQUARE的方法,再將結果賦值給squared。
- Ans:數字5的平方是25
i=層數, j=*數,C++基本上只有輸出入的部分改掉。
while(ture) or while(1),都代表為真的意思,都會執行無限迴圈。
- 介紹
- 宣告
- 函式中的參數
- 變數的範圍
- 靜態變數
一段程式碼,執行特別的工作。
可重複使用
讓程式變得淺顯易懂
在呼叫函式不變的狀況下,可以直接修改程式。
- global (全域變數)整個程式中皆可以使用此變數
- local (區域變數)只能在部分函式中使用
範例如下:
- static變數,是一個區域變數,但不會因為函式執行結束,變數內的資料就不見。
上面的for迴圈,是為了要進入此函式五次才設定的。函式內部的X沒有因為離開函式後,其數字重新歸零,而是繼續累加。這就是static變數的最大特色。要等到程式全部結束後,X才會回到原本預設的狀態。
指標是用來儲存"記憶體位址"的變數,設計師可以透過指標來管理記憶體,包含:配置,存值,取值,釋放。
- & : 取得已存在的變數位址
- * : 表示為指標變數
- new : 配置指定型別的記憶體位址
- 另一個指標:將已經存在的指標所儲存的記憶體位址指派給另一個指標
- 釋放記憶體位址
- 用 new 配置給指標的記憶體可以用delete釋放
- 限制指標or指標所管理的記憶體為 read-only
- type * const name;
- const type * name;
因此可得出const 只可讀取
這樣寫n還沒定義值就先報錯無改給值,你可以得很奇怪,因此這邊不能這樣賦予他一個新的記憶體空間。
- 以指標為參數 pass by pointer
- 呼叫function
- pass by value
- pass by point
解釋第一部分為何輸出1
解釋第二部分為何輸出=101
呼叫敘述是一個記憶體位址
不應return 區域變數的記憶體位址
可以宣告為const
- 宣告 type** name;
- 存取值 **name;
- 指派
- casting
- 宣告
- 存取
執行環境依照類別中的宣告,所配置的記憶體群組。它可以儲存一群資料,而該群資料可以完整的描述一個特定的運算單位。例如:一群可以完整描述一張訂單的資料、一群可以完整描述購買者的資料、一群可以完整描述一件商品的資料、一群可以完整描述日期時間的資料、一群可以完整描述信用卡付款的資料…。
也就是說:一個記憶體群組,代表一個特定運算單位的完整資料。這一個記憶體群組,我們就稱之為物件。
所以就程式語言的角度上也可以說:物件一群記憶體的集合。
物件擁有什麼
資料成員(Data Members) => 儲存資料(變數)。
很多文件的解說中稱之為屬性或狀態。在 Java 中稱之為欄位。
成員函式 (Member Functions) => 運算資料。
很多文件的解說中稱之為行為或能力。在 Java 中稱之為方法。
為什麼要使用物件導向
在物件導向之前是函式導向。隨著運算複雜度的提升,各語言也逐一的支援物件導向。物件導向與函式導向的基本差異是:物件儲存資料,物件運算資料。
以 C / C++ 語言為例,在函式導向時期(C 語言時期),雖然可以用結構(struct)宣告一個新型別,集合一群資料。但是,那一群資料本身並不具有運算能力,它只能當參數讓函式運算。所以,資料與運算資料的函式是沒有關係的。
到了物件導向時期(C++ 時期),改用類別(class)來宣告新型別。依照類別的宣告建立的物件,除了是一群資料的集合之外,本身也具有運算的能力。也就是說:資料與運算資料的函式是屬於同一個物件的成員。
相同類別的物件,一定擁有相同的成員
相同名稱的資料成員,但它的值不見得一樣。
相同名稱的成員函式,但它運算的結果不一定一樣。
每一個物件獨立管理與運算自己的資料
除非特殊的設計需求。基本上,每個物件運算自己的資料。
- 物件儲存資料,運送資料
- 物件導向不能用靜態觀點,不可看單一程式碼,要看真的主函式中真正配置的記憶體位址
- 環境依照類別做出來物件,類別是說明書,材料是記憶體,配出來的記憶體是物件
像 int 一樣,是 C++ 中合法的型別。
因為程式有物件的需求,所以依照物件的需求開發類別
宣告變數
宣告指標
宣告參考
物件轉型
物件識別
執行環境製做物件的說明書
物件成員=> 物件資料成員,物件成員函式
類別成員=> 類別資料成員,類別成員函式
建構函式(建構子)
其他
ClassName objectName;
變數宣告時,環境會依照類別中的宣告來建立物件。並把物件的記憶體位址指派給變數。
標黃色代表他們是一體的,記憶體一定是一格一格的,不是一群物件,是一群記憶體,以群為單位配送記體位址複製給c1
到這裡,執行main函式,radius記憶體位址變數變成10,並且執行getGirth,再將結果複製給0x123(c1)
接著main函式當中,執行第二個c2,為何執行第二個c2,原本的記憶體位址不會消失呢?由下圖解釋:
objectName.dataMember
objectName.memberFunction()
用 變數.成員 的方式,存取物件成員。
objectName = otherObjectName;
變數和物件是挷定的,也就是說這個變數不能再指派另一個物件的記憶體位址給它。指派時是將 '=' 右邊的物件的資料成員的值,複製給 '=' 左邊的物件的資料成員。
函式原型 : void function(ClassName objectName)
呼叫敍述 : function(objectName);
在函式呼叫敍述的小括號中放物件變數時,是把本物件的成員變數的值,複製給函式的物件變數參數。
- int compare(Circle c) :
- c1.compare(c2) : 在c1中執行compare,所以將其記憶體位建立在c1中,並將物件的值指派一份給c
- c2物件的值指派給c的值
- 接著改變c2的值就會改變c.radius的值
- c2的值不會被改變,他是複製一份給c,並指派參數給c.radius,如果改變c.radius的值,c2依然為20
函式原型 : ClassName function()
呼叫敍述 : ClassName objectName = function();
代表返回值是這個類別的物件變數
不過這樣有個壞處,這個寫法會多佔用一個記憶體位址,如果是大型運算會佔太多不必要的空間
ClassName * pointerName;
Or
ClassName * pointerName = new ClassName;
new ClassName
new ClassName()
這邊代表新增了兩個物件分別創建出一個記憶體位址
pointerName = memory address;
Ex:
pointerName = new ClassName;
Or
pointerName = &objectName;
Or
pointerName = otherPointerName;
pointerName -> dataMember
pointerName -> memberFunction()
用 指標 -> 成員 的方式,存取物件成員。
函式原型 : void function(ClassName* pointer)
呼叫敍述 : function(memory address)
函式原型 : ClassName * function()
呼叫敍述 : ClassName * pointer = function();
物件導向中用來實作資訊隱藏的機制,確保物件的安全。其作法為:隱藏不想讓外界碰觸的成員,只公開接受外界存取的成員。
一般而言,類別開發者為了物件的安全,會把資料成員全部隱藏起來,只公開存取或運算資料成員的函式成員。讓物件資料的修改,完全由函式成員掌控其值的變化,避免物件產生預期外的值。
成員存取的控制以存取修飾詞宣告的段落為單位。在宣告某一個存取修飾詞之後,另一個存取修飾詞出現之前為一個段落。若都沒有宣告,預設為 private 。
1.private
:只允許本類別中的其他成員存取。
2.protected
:允許本類別的子類別存取。
3.public
:允許所有類別存取。
物件導向中用來避免程式碼重複撰寫與減低維護困難度的機制。子類別可以繼承父類別中的所有成員。也就是說,把多個類別都會用到的成員,寫在父類別中,子類別只要繼承父類別,不必再寫,就可以擁有那群成員。不但避免了程式寫的重複撰寫,也減少了日後維護的困難度。因為若有程式碼要修改,只需要修改一個類別。
當我們寫一個新類別,指定繼承某一個或多個己存在的類別時,就是在使用那一個或多個己存在的類別。新類別稱之為衍生類別 (Derived class) 或子類別 (Child class),己存在的類別稱之為基礎類別 (Base class) 或父類別 (Parent class)。子類別繼承父類別中的所有成員。但繼承了不代表可以存取,子類別不能存取父類別中宣告為 private 的成員,只能存取宣告為 protected 或 public 的成員。
當你是類別開發者時,不接受子類別與物件存取的,宣告為 private。不接受物件存取,但接受子類別存取的,宣告為 protected。接受物件存取的才宣告為 public。
繼承運算符號
:
繼承是為了在父類別的基礎之上,做進一步的開發。所以繼承不是重點,重點是繼承後的子類別可以做什麼?
子類別中可以:
隱藏父類別的成員
在子類別中可以宣告父類中己宣告過的成員,新宣告的成員會遮蔽父類別中相同名稱的成員。
若子類別中宣告與父類別中名稱相同的資料成員,子類別中的函式存取的是子類別中的資料成員。但父類別中的函式存取的是父類別中的資料成員。
若子類別中宣告與父類別名稱相同但參數列不同的函式,不是 Overloading,一樣是遮蔽了父類別的成員函式。
主要必須記得要讓子類碰的不是成員變數,而是成員函式。這樣的寫法比較正確,確保製作出來的類別符合封裝的原則
物件建立時,環境會在配置記憶體之後呼叫類別中定義的建構函式。類別開發者會在建構函式中撰寫物件初始化的程式碼,一般是指定資料成員的初值。建構函式的名稱必須與類別名稱一樣,可以有參數列,但不可以有返回型別。參數列可以宣告參數預設值。
- 預設的建構函式
建立物件時,若建立物件的敍述中沒有指定建構函式。環境預設會呼叫沒有參數的建構函式。所以沒有參數的建構函式就是預設的建構函式。
類別中若沒有撰寫建構方法,編譯器會自動產生沒有參數的建構方法。但是,自動產生的建構方法並不會自動指派資料成員的初值,所以建構出來的物件是不安全的。而且,若類別中有撰寫任何建構方法,編譯器就不會自動產生沒有參數的建構方法。
- Overloading 建構函式
類別中除了沒有參數的建構函式,也可以視需求,Overloading 多個建構函式。
- this
寫法: this -> 建構函式中指向的方法
每一個成員函式中都有一個隱含的指標 this。this可以指向呼叫此函式的物件,用來取存物件成員。
主要用途有二:
在專業編輯環境中快速找到要存取的成員
解決成員變數與參數名稱重複的問題。
- 子類別的建構函式指定呼叫父類別的建構函式
若父類別沒有預設的建構函式或 Overloading 多個建構函式,子類別的建構函式可以指定呼叫。