1.14k likes | 1.39k Views
http://www.csie.nctu.edu.tw/~tsaiwn/cpp/. C++ 物件導向程式設計 Introduction to C++ with OOP. 蔡文能 tsaiwn@csie.nctu.edu.tw tsaiwn@cs.nctu.edu.tw 交通大學資訊工程學系. 01_oop.ppt. Agenda. From C to C++ (C++ == a better C + Objec-Oriented support) a. I/O stream, b. pass-by-reference
E N D
http://www.csie.nctu.edu.tw/~tsaiwn/cpp/ C++ 物件導向程式設計Introduction to C++ with OOP 蔡文能 tsaiwn@csie.nctu.edu.tw tsaiwn@cs.nctu.edu.tw 交通大學資訊工程學系 01_oop.ppt 交通大學資訓工程學系 蔡文能
Agenda • From C to C++ (C++ == a better C + Objec-Oriented support) a. I/O stream, b. pass-by-reference c. function name overloading, d. operator overloading, e. default parameter, f. inline function, g. template function • Data Abstraction: Why using struct? Why using class? • An ADT example: How to design/construct/use a Stack? next topic: Introduction to OOA, OOD, and UML http://www.csie.nctu.edu.tw/~tsaiwn/cpp/ 交通大學資訓工程學系 蔡文能
From C to C++ • C++ 最重要的當然是 class (類別) • C++ 除了 class 外還有一些雕蟲小技 • I/O stream facility and other Class Library • Parameter passing? (C++可指定call by reference) • function name overloading (函數名稱重複使用) • Operator overloading, … n= 5+38; x= 25.8+3.69; • inline function ? (只影響編譯與執行效率, 不影響答案) • template function, template class, … 交通大學資訓工程學系 蔡文能
C++ Input/Output Stream read(0, …); write(1, …); write(2, …); /* system call */ • In C, • fscanf(stddin, …); fprintf(stdout, … ); fprintf(stderr, …); printf("Enter new yy: "); /* where yy is a float */scanf("%f", &yy); /* what if yy is a double?*/ printf("The new yy is: %f\n", yy); • In C++, I/O devices 用起來像 Object (物件) cout << "Enter new yy: ";cin >> yy;cout << "The new yy is : " << yy << endl; • In Java, System.out.print("The answer is " + ans + "\n" ); 交通大學資訓工程學系 蔡文能
C and C++ I/O compared C-style I/O: • No type safety. What happens with printf(“%d”, ‘c’);? • Conversion specifications have a high learning curve. • Almost all the state of the I/O is contained in the function call. C++ style I/O: • Manipulators are very verbose/annoying • Global state gets changed. When you do “cout << 2.4555”, what precision are you set at? You don’t know. • You get more customizability since C++ I/O is classed based. NEVER mix C and C++ I/O...until you know what ios::sync_with_stdio() does. 交通大學資訓工程學系 蔡文能
Pass-By-Reference • A reference parameter in a function "references" the same physical memory location as the argument passed in • Changing the value of a reference parameter: • Does not change the memory associated with the parameter • Does change the memory associated with the argument passed in • Therefore – argument's memory must not be constant or literal void refFunc(float &val) { val = 50; } int main() { int mainVal = 9; refFunc(mainVal); cout << "mainVal: " << mainVal << endl; return (0); } This assignment changes the memory associated with this variable! mainVal: 50 交通大學資訓工程學系 蔡文能
? 參數傳遞(parameter passing) /* 寫一個函數可以將傳入的兩整數參數對調*/ /* 函數如何寫? */ return_type function_name( parameters ) { local variables; statements; } /* 如何叫用? */ function_name( actual arguments ) ; C語言參數是pass by value C++語言參數則可以pass by Reference 不過, 這違反了C的設計者所謂的“怎麼宣告就怎麼用”; 例如:看到 int *x ; 所以 *x 就當 int 來用! 而 x 則是 int* ; 就是說 x 是一個指向整數的指標! 交通大學資訓工程學系 蔡文能
(錯) 參數(parameter)傳遞 (錯) /* 寫一個函數可以將兩整數對調, wrong version */ #include<stdio.h> void swap( int x, int y) { int temp; temp=x; x = y; y = temp; } int m=38, n=49; int main( ) { swap(m, n); /* 沒有用的!回來後m, n 不變 */ printf("m=%d, n=%d\n", m, n); } 因為C語言參數是pass by value (錯) (錯) 交通大學資訓工程學系 蔡文能
(正確) 參數會被函式改變的傳遞法 /* 寫一個函數可以將兩整數對調, correct version */ #include<stdio.h> void swap( int * x, int* y) { /* 注意參數寫法 */ int temp; temp = *x; *x = *y; *y = temp; } /* 註: C++ 則有 pass by reference 寫法 */ int m=38, n=49; int main( ) { swap(&m, &n); /* 注意 &m和&n把address傳過去 */ printf("m=%d, n=%d\n", m, n); } 注意不要在temp左邊寫星號, 意思不同 參考K&R課本5.2節 Call by address to pointer &m, &n : address of m 和address of n 交通大學資訓工程學系 蔡文能
(C++專有) Call by Reference參數傳遞 /* 寫一個函數可以將兩整數對調, in C++ */ #include<stdio.h> void swap( int & x, int & y) { int temp; temp=x; x = y; y = temp; } int m=38, n=49; int main( ) { swap(m, n); /* 注意!看起來好像不會變 */ printf("m=%d, n=%d\n", m, n); } C++才可以用pass by Reference 前面所說的 C language 可用之方法仍可以用於 C++. 交通大學資訓工程學系 蔡文能
(C++專有) Function name Overloading /*寫個函數可將兩 int數對調, 再寫一個函數可以將兩double數對調, 名稱?*/ #include<stdio.h> void swap( int & x, int & y) { /* by reference */ int temp; temp=x; x = y; y = temp; } void swap( double & x, double & y) { double temp; temp=x; x = y; y = temp; } C++允許同名的 function, 但注意參數 交通大學資訓工程學系 蔡文能
C++ STL 中的 swap( )是 template template <class T> void swap( T & x, T & y) { T temp; temp=x; x = y; y = temp; } 此即所謂的 template function (樣版函數) STL = Standard Template Library 交通大學資訓工程學系 蔡文能
再談 function name overloading • Function name overloading 不一定在class內! 請注意 它與 Object Oriented 並沒有關係! • function name overloading 是指很多個函數都用同一個名稱 例如: int m=2, n=3; double x=3.8, y=4.9; swap(m, n); swap(x, y); 顯然以上兩個 swap 應該是不同函數, 這是由它們的參數不同得知的!這在 compile time 就可以決定是用哪一個 swap, 此稱之為 static binding (靜態繫結)! 如何做? (next slide) ? 何謂 dynamic binding? (next slide) C++允許同名的 function, 但注意參數 交通大學資訓工程學系 蔡文能
C++ How to …overloading/polymorphism • C++ 到底是用了什麼技術辦到 function name overloading ?事實上只是用了一個超級簡單的 idea: • C++只是把參數的型別納入函數名稱中而已, Compiler會偷換 function name, 參數的type也變成 function_name 的一部份: ( static binding) 例如: void swap(int&, int&); 會被譯為(可能!): __swap_F2RiRi • 如何達成 polymorphism ? • 透過 virtual function dynamic binding • p-> draw( ); 譯成去執行 p 指過去之物件內有個指標指過去的函數表中draw的項目位置指過去的那個函數! (相關指標在 new 出物件時填入) 交通大學資訓工程學系 蔡文能
Tips about Dynamic binding • Dynamic binding(動態繫結)是指在 執行階段(run time) 才確定! • 動態繫結是一種被 Compiler 使用的技術, 它也不是 OO 才有的, C語言的 Auto 變數(函數中沒有宣告 static 的 Local 變數)就是使用Dynamic binding;在執行期(Run time)時才安排於堆疊(Stack)中! Static binding? vs. Dynamic binding? 交通大學資訓工程學系 蔡文能
Operator overloading (1/4) • Operator overloading • Use traditional operators with user-defined objects • A straightforward and natural way to extend C++ • Requires great care • When overloading misused, program difficult to understand • Format of the operator function • Function name is keyword operator followed by the symbol for the operator being overloaded. • operator+ would be used to overload the addition operator (+) 交通大學資訓工程學系 蔡文能
Operator overloading (2/4) • You can NOT invent operator • No new operators can be created, use only existing operators • Arity (number of operands) canNot be changed • Unary operators remain unary, and binary operators remain binary • Operators &, *, + and - each have unary and binary versions • Unary and binary versions can be overloaded separately • Can NOT overload operators for Built-in types • You cannot change how two integers are added 交通大學資訓工程學系 蔡文能
Operator overloading (3/4) • Operator functions • Can be member or non-member functions (i.e., friend) • Operator functions for the assignment operators must be a member function • i.e: (), [], ->,= • Member function vs. non-member function • Leftmost operand must be an object (or reference to an object) of the class • If left operand of a different type, operator function must be a non-member function • A non-member operator function must be a friend if private or protected members of that class are accessed directly 交通大學資訓工程學系 蔡文能
Operator overloading (4/4) • Overloaded binary operators • Non-static member function, one argument • Non-member function, two arguments • Leftmost operand must be an object (or reference to an object) of the class • If left operand is an object of a different type, operator function must be a non-member operator function • A non-member operator function must be a friend if private or protected members of that class are accessed directly 交通大學資訓工程學系 蔡文能
Operators in C / C++ / Java(1/3): 交通大學資訓工程學系 蔡文能
Operators in C / C++ / Java (2/3): 交通大學資訓工程學系 蔡文能
Operators in C / C++ / Java (3/3): 交通大學資訓工程學系 蔡文能
表示不會改member data, 此例顯然不該寫這個 const, Why? Operator Overloading Examples(1/3) • As a member function ( 寫成自己人) • class Haha { public: const Haha &operator+=( const Haha & p) const { • /*** mutable member 是例外 ***/ • } //...}; • Haha x, y, z; // … • // then: • y += z; • // equivalent to • y.operator+=( z ); //operator+= is a member 交通大學資訓工程學系 蔡文能
Operator Overloading Examples(2/3) • As friend function (不好, 但文法正確) • class Haha { public: friend const Haha &operator+=( Haha&, const Haha & ) ; • //...}; • const Haha& operator+=(Haha&x, const Haha&y){ /*…*/ } • Haha x, y, z; // … • // then: • y += z; • // equivalent to • operator+=( y, z ); // operator+= is a friend operator+=應寫成自己人比較好 交通大學資訓工程學系 蔡文能
Operator Overloading Examples(3/3) • As friend function again (可以, 很好) • class Haha { • long data_; • public: friend ostream& operator<<(ostream&, const Haha & ) ; • //...}; • ostream& operator<<(ostream&river, const Haha&y){ • river << y.data_; /*…*/ } • Haha x; // … • // then: • cout << x; • // equivalent to • operator<<( cout, x); // operator<< is a friend Operator<<一定要寫成朋友! 無法寫成自己人! Why? 交通大學資訓工程學系 蔡文能
Default parameter void setNum(int x = 3388); void setNum(int x) { cout << "You gave me " << x << endl; // … } setNum(123); setNum( ); /* compiler 會自動填入 3388 */ setNum(456); 交通大學資訓工程學系 蔡文能
inline Functions • Inline function is an important addition to C++ because it can allow you to create very efficient code. • They are especially important in classes, because a lot of functions, such as the constructor or accessors are executed very often. • Inline is actually just a request to the compiler, not a command. (eg. recursive functions often not set inline) • inline functions = faster processing – larger code size 寫了 inline 的函數, 用到時用展開的(類似 macro), 不是譯成呼叫; • 在 class內就寫完的function會自動變 inline function; 在 class 之外寫的 function 要寫明 inline 才是 inline function. (C99 也可用) 只要在原來 function 之前面寫 inline, 就可能使得 function 變成 inline function. 這是要求 Compiler 採用類似 Macro (巨集) 展開方式來翻譯該函數呼叫! 所以通常機器碼較佔空間, 但執行起來比較快 (用空間換時間);但是它仍然具有 function 的效果! 注意: 含有某些 statements 的functions無法成為 inline, compiler會把關! 交通大學資訓工程學系 蔡文能
template function template <class T> void swap( T & x, T & y) { T temp; temp=x; x = y; y = temp; } int a=38, b=49, m=123, n=456; double x=23.5, y = 33.88; swap( a, b); /* 會生出一份 swap function */ swap(x, y); swap(m, n); /* 不會再生出一份 function */ swap( ) in STL (Standard Template Library) 交通大學資訓工程學系 蔡文能
再 談 變數 Variable 變 變 變 • 變數當然會變才叫變數– 廢話! • 變數命名規則與慣例? averageScore,n, x • 變數放在電腦的記憶體 – 何處? • 與程式一起, 與程式分離? –由Linker 負責 • 堆疊區 (STACK) ? 嘿洗蝦密碗糕啊? • 變數的能見範圍(Scope)? 或說有效範圍 • 函數(函式 )內的變數:Local variable 局部(區域)變數 • 函數外的變數: Global variable整體變數 • 變數何時生出?何時死掉? 生命期(Life time) ? 交通大學資訓工程學系 蔡文能
變數分類 • 依能見範圍(Scope, 或說有效範圍)? • Local 區域 vs. Global 整體 • 依何時給它記憶體位置(稱作binding) • Static variable : 靜態變數, Run 之前 (compile / Link) • Dynamic variable: 動態變數, Run 之後才會做 binding(就是Run 之後才給它位置) • 自動要自動還: auto 變數 (function內沒寫static) • 手動要:使用malloc 或 calloc 要, 用free還 (C++用new 和delete) • auto變數被安排在 stack (堆疊) • 手動要的(malloc, calloc)在 Heap (堆積) 交通大學資訓工程學系 蔡文能
變數 (Variable)的 Scope, Life time • 變數的能見範圍(Scope, 或說有效範圍) • 函數(函式 )內的變數:Local variable 局部(區域)變數 : 只有在函數內有效 • 函數外的變數: Global variable (整體變數) • Global variable : 宣告之後就一直有效 • 變數生命期(Life time) ? • 靜態變數從程式開始 Run 就“出生” • Auto 變數在進入函數時生出, 離開函數時死掉(把記憶體還給系統) • 沒有宣告 static 的:Local變數就是Auto 變數 交通大學資訓工程學系 蔡文能
(1/2) Global 變數 vs. Local變數 #include <iostream.h> int x = 38, y=250; /* Global */ void sub1(int); /* 見後面程式 */ int main( ) { int x=49; /* Local */ sub1(::x); /* Global 的 x == 38 */ sub1(x); /* Local 的 x == 49 */ cout << "x=" << x << endl; cout << "outside x=" << ::x << endl; cout << " y=" << y << endl; return 0; /* 0 in main( ) means OK */ } 交通大學資訓工程學系 蔡文能
(2/2) Global 變數 vs. Local變數 void sub1(int y){ cout << "y=" << y << endl; x++; /* Global 的 x , 因為 Local 沒有 x*/ ::x++; /* 也是 Global 的 x */ y++; /*因為y是 pass by value, 回去不會變*/ ::y++; /* 是 Global 的 y */ return ; /* 不寫也可以 */ } pass by value 就是 call by value 講法不同而已 交通大學資訓工程學系 蔡文能
(1/2) Static Local變數 #include <iostream.h> // #include<iostream> int fa( ) { int x = 1; return x++; /*先取其值, 再做 ++ */ } int fb( ) {static int x = 1; /*注意 static int x = 1; */ return x++; } int main( ) { cout << "fa( )=" << fa( )<<fa( )<<fa( ) << endl; cout << "fb( )=" << fb( )<<fb( )<<fb( ) << endl; return 0; /* 0 in main( ) means OK */ } return x++; 和return ++x;不同! 交通大學資訓工程學系 蔡文能
(2/2) Static Local變數 int fa( ) { int x = 1; return x++; /*先取其值, 再做 ++ */ } int fb( ) { static // 把 static 寫在下列左方也一樣 int x = 1; // 注意 static int x = 1; return x++; } 交通大學資訓工程學系 蔡文能
Static Local變數 , evaluation 順序 #include <stdio.h> int fa( ); /*宣告*/ int fb( ); int main( ) { /* 不同系統可能不同答案*/ printf( "fa( )=%d %d %d \n", fa( ), fa( ), fa( ) ); printf( "fb( )=%d %d %d \n", fb( ), fb( ), fb( ) ); return 0; /* 0 in main( ) means OK */ } // int fa( ) … 也可以寫在另一個檔案內 交通大學資訓工程學系 蔡文能
Evaluation 順序 #include <stdio.h> int gg(int x){ static ans=0; ans = x + ans*ans; return ans; } int main( ) { /* 不同系統可能不同答案 !*/ int haha = gg(1) + gg(2) + gg(3); /*先做哪個gg( ) ?*/ printf("haha=%d\n", haha); return 0; } expression中有多個函數叫用會先做哪個 gg( )? C/C++ 沒有規定! 所以看寫 compiler的人高興 交通大學資訓工程學系 蔡文能
Auto 變數不可佔太多memory • Auto 變數就是沒寫 static的 Local 變數 • Auto 變數是在進入函數時才在STACK區安排記憶體, 在離開函數(return)時就還掉(改變 Stack Pointer) • STACK區一般不會很大(幾十 K Bytes) • Auto 變數用STACK區, 所以太大的array不能用 • 叫用函數時, return address 也會被推入STACK • 參數傳遞也是用 STACK區 • C/C++推入參數時是先推入最後一個參數, 這使得第一個參數會在堆疊的最上方, 進入函數時, STACK中return address 之下就是第一個參數 • C/C++離開函數時, 函數不負責拿掉STACK中的參數, 那是叫用函數那個程式的責任! (與其它語言不同) 交通大學資訓工程學系 蔡文能
Auto 變數佔用STACK區memory address 0 系統區 • Auto 變數就是沒寫 static的 Local 變數 Instruction Pointer CPU IP 程式+靜態data SP HEAP堆積 malloc( ), new( ) Stack Pointer STACK (參數與Auto變數) Heap 由上往下長 Stack 由下往上長 系統區 交通大學資訓工程學系 蔡文能
Static變數? • Global 變數都是static的 變數 • Local 變數就是寫在函數內的變數 • 有補 static 修飾詞則為 static變數 (靜態變數) • 沒有補 static 修飾詞則為 Auto 變數 (自動變數) • static的 變數在程式開始 RUN 之前就存在, 且已經設好初值, 程式結束後才會還掉所佔記憶體(生命期) • 寫了 extern 表示只是 宣告(declare), 不是定義(define) • Local 變數就只能在該函數(function)內存取(access) • Global 變數則只要看得見它的任一函數都能存取它 • 宣告之後就看得見, 沒宣告就定義 則看作 同時宣告了 • 注意 main( ) 也是函數, 沒有特別偉大! 應寫成 int function. 交通大學資訓工程學系 蔡文能
Global, Static Local, Auto 變數 #include <stdio.h> extern int x; /* 只有宣告 , 還不知道位置在何處?*/ int fa( ) ; int fb( ) { int ans=0; return ++ans; } int main( ) { int kk=123; cout << "fa( )=" << fa( )<<fa( )<<fa( ) << kk<<endl; cout << "fb( )=" << fb( )<<fb( )<<fb( ) << endl; return 0; /* 0 in main( ) means OK */ } int x, y; /* 真的 x 在這, 也可以寫在另一個 file 中*/ int fa ( ) { /*…* } 寫了 extern 表示只是 宣告, 不是定義(define) 交通大學資訓工程學系 蔡文能
Functions in another file can NOT see these staticvariable Static Global 變數 Information Hiding? #include <stdio.h> #define BUFSIZE 100 static char buf[BUFSIZE]; static int bufp = 0; int getch( ) { /* . . . */ } void ungetch(int c) { /* . . . */ } 也參考stack的push和pop寫在同一獨立 file 中, push和pop共享 data 交通大學資訓工程學系 蔡文能
再談Static Global 變數 Information Hiding? #include <stdio.h> #define RAND_MAX 65535 static unsigned long seed=0; /* global */ int rand( ) { seed = seed * 1103515245 + 12345; return seed % (RAND_MAX+1); } void srand(int newseed) { seed = newseed; } 只有rand 和srand 看得見 seed 程式庫中的 Pseudo Random Number Generator (PRNG) 交通大學資訓工程學系 蔡文能
register 變數 , volatile 變數 #include <stdio.h> enum {BUFSIZE=100, NSTU=60}; register int wrong; /* this is wrong, global不可*/ volatile int haha; void myfun(register int x ) { register int yy, i; /* OK */ int * p; /* . . . */ p = &yy; /* this is wrong */ } 拜託Compiler儘可能安排在CPU內的暫存器 參考K&R課本4.7節 交通大學資訓工程學系 蔡文能
volatile 變數 #include <stdio.h> volatile int haha ; /* tell compiler … */ int main( ) { int k; double ans; for(k=1; k<=99; ++k) { /* . . . */ ans = haha * haha; /* do NOT optimize*/ printf(" ans=%f\n ", ans); } } 警告Compiler這變數可能會被別的程式改變 參考K&R課本4.7節 交通大學資訓工程學系 蔡文能
ADT --- Data Abstraction • An Abstract Data Type (ADT) is a user-defineddata type that satisfies the following two conditions: (Encapsulation +Information Hiding) • The representation of, and operations on, objects of the type are defined in a single syntactic unit; also, other program units can create objects of the type. • The representation of objects of the type is hidden from the program units that use these objects, so the only operations (methods) possible are those provided in the type's definition which are known as interfaces. 交通大學資訓工程學系 蔡文能
ADT in C_plus_plus • class / struct can be used as the encapsulation device. (只有一開始default access屬性不同) • All of the class instances of a class share a single copy of the member functions. • Each instance of a class has its own copy of the class data members (except static data) • Instances can be static, stack dynamic (auto), or heap dynamic; this is similar to built-in types. class instance of a class = Object Object is an instance of some class 交通大學資訓工程學系 蔡文能
C++ = a better C + classes • Why using struct in C ? • Group related data together (後面講) • C++ 最重要的就是 class (類別) • class 其實是 struct的延伸 • In C++, we can put relatedfunctions with the relateddata in struct ( class ) • 所以 C++ 的 class就是 C 的 struct加上一些規定 • Java 把 struct 拿掉了! 且 union 也沒了! • class有何用? (後面講) 交通大學資訓工程學系 蔡文能
Object Oriented Concept (1/3) • Why using class ? (先考慮 why using struct ?) • 支援 OOP (物件導向Object Oriented Programming) • 又譯作個體導向程式設計 • 考慮 Stack 堆疊 : 讓東西用起來更像東西 • ADT (Abstract Data Type) • 把 data 以及對 該些 data 有關的方法(method)或稱函數(function, 函式)封裝(encapsulate)在一個程式單元方便使用 交通大學資訓工程學系 蔡文能
Object Oriented Concept (2/3) • Object-Oriented Analysis (OOA) • Goal: Understand the domain • Object-Oriented Design (OOD) • Goal: Design a solution, a model of the domain in which the desired activities occur • Object-Oriented Programming (OOP) • Goal: Implement the solution • Note: A Good Design is 2/3 Before You Hit the Keyboard 交通大學資訓工程學系 蔡文能