[筆記]介面與實作、運算子多載、左值右值、參數傳遞、回傳多值|C++

2021年7月3日 16:00
運算子多載如何執行?int a = 10; ++a—;這串程式碼為什麼會出錯?居然跟左值右值有關!左值右值真的是一左一右嗎?參數傳遞中的傳指標和傳參考差在哪邊?C++居然無法回傳多值,那我該怎麼回傳多值? 這是一篇中山資工所 江明朝老師 物件導向程式設計 課程筆記,如內容有錯,歡迎留言交流~ 還是很困惑嗎?文章裡有答案喔~😎 好讀版
一、介面 (interface)與實作 (implementation)分離 實務上,會建議介面和實作分離,一個粗糙的分法是.h檔為介面,.cpp檔為實作,但這樣的分法不完全正確。 介面是指使用者會使用到的東西,例如:public函數的標頭、class的標頭。而function的實作和private (member data)裡的東西,都不屬於是介面,因為使用者不會直接使用到這些東西。
 因此通常#include進來的檔案是介面,檔案中不會看太多實作的細節。這樣有些好處:第一、使用者不用知道如何實作,只要學會如何使用介面,即可使用這些功能,所以套件也是介面與實作分開的例子。第二、如果套件的更新只更新實作部分,而不更動到介面部分,這樣使用者的程式碼不需要變動,也能更新套件的功能。而如果套件的介面與實作是合在一起的,每次套件更新,使用者就可能要再更新自己的程式碼,這樣的套件是不會有人想用的。 介面與實作分開並不會影響到編譯器 (complier)的運作,因為編譯器只需要知道函式名、回傳值、參數列,這也剛好是函式的標頭 (header)內容。只有linker or loader (OS的程式,loader也可以包含linker的工作)才需知道實作內容。 至於哪些東西要放在介面?哪些要放在實作?基本上沒有一個有系統的規則,主要以經驗談。大方就是Public的介面更動相對難,Private的實作更動相對簡單。inline, explicit, default argument, virtual, override要放在.h中,.cpp不用放。 二、函式 (Function) 運算子 (operator)、函式 (procedure)、函數 (function),本質上無太大的差別,只不過運算子可以使用運算子符號來呼叫函式,當然也可以用函式形式來呼叫函式;而函式 (procedure)是指無回傳值 (void)的;函數 (function)則是指有回傳值的。不過函式與函數的區分並沒有太大的意義,因此也常會混用。 (一)運算子多載 (Operator overloading) 函式多載有些前提:(1)需要在同一個scope內,不同scope就不是overloading。(2) 函式名相同,但簽章 (signature)不同。因此對於C++來說,每個多載函式都是獨立的函式,他們都是不同的函式,因為各自有獨特的簽章。函式簽章通常包含:函式名、參數型態、參數排序。 然後也不是所有的程式語言都支援運算子多載,C++有支援,但JAVA不支援,所以在JAVA中必須用函式多載。運算子多載如何運作?以輸入為例:cout << int << double << string; 1. 先overload operator cout << int == cout.operator<<(int),這會回傳cout (ostream&),使得可以連續輸出。cout << 之所以可以輸入不同型態的變數,是因為<<為一個多載運算子。 2. 決定優先順序: (1) Precedence (優先順序) (2) Associativity (結合性,左右順序) Cout << int << double << string; == ( ( (Cout << int) << double) << string); a<b<c必須拆成a<b && b<c,否則會有問題,因為這攸關結合性問題。a<b<c == ((a<b)<c),如果(a<b)為真,即會回傳1,因此((a<b)<c) == (1<c),顯然這不是我們要的結果。 && 和 || 這兩個operator如果要overloading必須小心,e1 && e2 && e3 && e4……,原本如果e1為false,判斷就會結束,但如果overloading,此性質就會消失。 更多運算子優先順序的例子可以看期中考第8題 (二)左值 (lvalue)與右值 (rvalue) 左值與右值明顯的議題會出現在賦值 (assignment)這一動作,如:a = 1、b = c。首先何謂左值?何謂右值?左值通常是等號左邊的那個變數,也就是a和b都是左值,變數的本質是有名有記憶體位置的,而左值必須為變數,因此左值一定是有名字的;右值通常是等號右邊的數,也就是1和c都是右值,1本身是一個樣板數字 (literal number),是一個暫時且沒有名字的東西,因此右值可以是沒有名字的東西。因此一個簡單的判斷左右值的方法即為,左值需有名,右值可無名。 有些運算子是涉及到賦值,如:=, ++, --, +=, -=, .......。++a == a = a + 1、—b == b = b - 1。以下有一個涉及到左右值的運算子問題: int a = 10; ++a—; // == (++(a—)) 請問上面的a值為何?9?10?11?錯誤?答案是Compiling error。 因為++a需要一個rvalue,因為++a內含一個assignment,但a--會給lvalue 然後++, —盡量不要和macro(文取代)一起使用,因為Macro是copy整串的指令,容易會有意外的side effect,而不是copy計算值,所以指令會在copy後才執行運算。 更多左值右值的例子可以看期中考第6題 (三)參數傳遞 C語言的參數傳遞都是call-by-value,而pointer可以call-by-address。C++的call-by-reference和C的call-by-address很像,只不過C中的& (get address) and * (dereference)在C++中,編譯器自動幫你做。
 call-by-value的缺點就是效率不好,因為它是用複製的方式在傳參數,但優點就是原本的參數不會因為函數內對引數做任何改變,而有所影響。call-by-reference的效率就會比較好,因為它是傳參考,參考可以視為變數的別名,因此只要改變引數,就會改變原本的變數。有時為了追求效能,但要沒有改變資料,就可以使用const reference 。 (四)回傳多值 C/C++只能回傳一個值,無法回傳多值。所以可能的方法有: 回傳指標(如:陣列):蠻危險的,因為要避免指到區域變數,或是被區域指標指到,區域變數或指標皆會因為block結束,而跟著被回收,此時的指標會指向空。 回傳struct / class:要先自己建立struct / class,將多個變數包在struct / class,struct / object可用call-by-value傳出去。 reference:比較安全,但如果回傳值太多,就可能會需要有多個變數,或是用陣列/物件承載多個值。 三、相關文章 1. 物件導向程式設計|模擬真實世界的方式|江明朝
江老師物件導向程設,評分、老師、課程簡介。 2. AOOP Homework source code
3. [筆記]109-2高等物件導向程式設計 期中考
4. [筆記]介面與實作、運算子多載、左值右值、參數傳遞、回傳多值|C++
運算子多載如何執行?int a = 10; ++a—;這串程式碼為什麼會出錯?居然跟左值又值有關!左值右值真的是一左一右嗎?參數傳遞中的傳指標和傳參考差在哪邊?C++居然無法回傳多值,那我該怎麼回傳多值? 5. [筆記]陣列與指標|C++
我以為我傳的是陣列,但居然傳的是指標?為什麼我無法回傳陣列?只能回傳指標?所以陣列和指標是什麼關係?指標運算怎麼算?釋放動態記憶體時,指標變數會不會也被釋放? 6. [筆記]類別、特殊函式、內嵌函式、函式物件|C++
程序導向的C語言也能實作物件導向?C語言要如何模擬類別?C struct與C++ struct與C++ class這三者有什麼差別?類別中有哪六個特殊函式?初始化和賦值有什麼差別?內嵌函式和巨集很像?物件居然可以拿來當成函式?為什麼C++宣告無參數物件時,不用加()? 7. [筆記]繼承模式與存取權限|C++
繼承模式和存取權限有什麼關係?private繼承不是讓所有存取權限變成private嗎?為什麼衍生類別依舊可以存取基礎類別?類別開發者和使用者有什麼區分?特殊函式的繼承會和一般函式一樣嗎? 8. [筆記]多型與繼承的關係|C++
多型的出現是為了要解決什麼問題?多型觸發的條件是什麼?為什麼多型要和繼承一起使用?多型能保有繼承的優點嗎?多型比繼承又多了什麼功能?特殊函式也能多型嗎? 9. [筆記]static / const成員資料與函式|C++
non-const static成員資料無法在類別內初始化,也無法使用初始化列,那到底該如何初始化?static成員是什麼概念?可以將自己宣告為自己的成員資料嗎?如果可以,該如何實現?如果不行,會發生什麼問題? 10. [筆記]夥伴函式與類別、不夠朋友問題|C++
夥伴函式和成員函式差在哪裡?為什麼輸入/輸出的多載運算子一定要為夥伴函式?如果A類別把B函式當作夥伴,但B函式的參數中沒有A類別,顯然這個B不把A當夥伴,就會造成main()無法找到B函式。
13
留言 5
文章資訊
85 篇文章294 人追蹤
Logo
每天有 10 則貼文
共 5 則留言
國立中山大學
考試會出現一串很繞口令的關於指標的敘述然後要寫code(一行)@@
國立中山大學 資訊工程學系
macro 台灣應該翻作巨集(?) 文取代倒是第一次聽到這用法 然後 macro 沒有做任何的 copy,精確來說是 replacement SCC
國立中山大學 資訊工程學系
回傳值那段,不要回傳 ref,這會造成 uaf 請愛用 smart pointer
b1 對,期中考我還真無法理解題意,所以就考了一個平均值的分數XDDD b2 啊啊啊啊啊啊,我打錯了,應該要打macro (文字取代),()內是要形容macro的功能,中文是巨集。 replace比copy更恰當沒錯 晚點我再修正這些錯誤,謝謝 b3 回傳值那邊,我會在寫清楚,我發現我筆記當下寫太少,會產生一些誤會。
國立中山大學
理解題意也不會寫吧(?