EECS 204002 Data Structures 資料結構 Prof. REN-SONG TSAY 蔡仁松 教授 NTHU C++ QUICK REVIEW www.tutorialspoint.com/cplusplus/cpp_quick_guide.htm 2023/9/8 Data Structures © Prof. Ren-Song Tsay 2 1.2.3 History of C++ C is widely-used in industry because: ◦ Efficient: Support low-level features which utilize hardware more efficiently. ◦ Flexible: Can be used to solve problem in most application areas. ◦ Available: C Compilers are readily available for most platforms. C++ is an enhanced version of C C++ = Object-oriented paradigm + C 2023/9/8 Data Structures © Prof. Ren-Song Tsay 3 Review of C 2023/9/8 Data Structures © Prof. Ren-Song Tsay 7 Auto and Static Variables Automatic ◦ The variable will lose its storage (and value) when the program exits the block Static ◦ The variable is initialized only once. ◦ The value can be changed during run time. ◦ The value remains until the program exits. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 11 Quiz 1: Static Variables Show the output If take out “static” what will be the output? #include <stdio.h> /* function declaration */ void func(void); static int count = 5; /* global variable */ main() { while(count--) { func(); } return 0; } /* function definition */ void func( void ) { static int i = 5; /* local static variable */ i++; printf("i is %d and count is %d\n", i, count); } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 12 Quiz 2: Block Scope Show the output int main() { { int x = 10, y = 20; { printf("x = %d, y = %d\n", x, y); { int y = 40; x++; // Changes the outer block variable x to 11 y++; // Changes this block's variable y to 41 } printf("x = %d, y = %d\n", x, y); printf("x = %d, y = %d\n", x, y); } } return 0; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 13 Example: extern global variable //file : main.cpp // file: int x = 100; // auto global defined in other file extern int x; //static global only within a file static int size=10; int main() { func(); func.cpp void func () { printf(“x=%d\n”, x ); } return 0; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 14 typedef: a new name for a type typedef int Integer ; Integer x; // = int x typedef struct Books { char title[50]; … } Book; int main( ) { Book book; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 18 typedef Function Pointer typedef int (*t_somefunc)(int, int); int product(int u, int v) { return u*v; } t_somefunc afunc = &product; ... int x2 = (*afunc)(123, 456); // call product() to calculate 123*456 2023/9/8 Data Structures © Prof. Ren-Song Tsay 19 1.2 Object Oriented Design 2023/9/8 Data Structures © Prof. Ren-Song Tsay 24 From C to C++ Data type and operations in C Extend to user-defined data types? ◦ int i,j; x = i+j; typedef struct { double long; // Longitude of building double lati; // Latitude of building char* owner; // owner of the building } building; building A,B; ◦ A+B? (Data abstraction) How to describe a house as a building with an additional attribute of a number of rooms? (Object Inheritance) 2023/9/8 Data Structures © Prof. Ren-Song Tsay 25 1.2.1 C: Algorithmic Decomposition Software is viewed as a process and decomposed into steps. Steps are implemented as functions ◦ e.g., in C or Pascal Data structures are a secondary concern ◦ Data is visible and accessible to potentially all steps ◦ Unclear by which function the data is manipulated ◦ No way to prevent irrelevant code to access the data Difficult to reuse code 2023/9/8 Data Structures © Prof. Ren-Song Tsay 26 1.2.1 C++: Object-Oriented Decomposition Software is viewed as a set of well-defined objects that interact with each other to solve the problem. ◦ Objects are entities that contain data (local state) and operations (functions) to perform computation and are instances of some classes (vs. struct in C). ◦ Focus on the design of data. ← Data Structure! Benefits ◦ Intuitive to develop software ◦ Easy to maintain ◦ High reusability and flexibility 2023/9/8 Data Structures © Prof. Ren-Song Tsay 27 struct V.S. class In C, use “struct” to define custom data types In C++ and OOP, introduces “class” to define custom data types ◦ Each class contains NOT just data but also “operations” With concrete data representation of the class object. A set of operations to manipulate object data. Other operations or codes cannot access the objects. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 28 1.2.2 Object-Oriented Programming C++ fully supports object-oriented programming, including the four pillars of object-oriented development − Encapsulation Data hiding (abstraction) Inheritance Polymorphism (多型性) 2023/9/8 Data Structures © Prof. Ren-Song Tsay 29 The Object in OOP Contains data and procedural elements (functions) Is the basic unit for computation Is a fundamental building block Each object is an instance of some type (class) Classes are related to each other by inheritance relationships 2023/9/8 Data Structures © Prof. Ren-Song Tsay 30 1.3 Data Abstraction and Encapsulation 2023/9/8 Data Structures © Prof. Ren-Song Tsay 32 Data Abstraction User manual only tells what the player and buttons will do (Specification) No need to know how the machine does it (Implementation) Data Encapsulation Interact only through buttons (PLAY, STOP and PAUSE) Do not interact with internal circuitry Internal representation (circuitry) is hidden 2023/9/8 Data Structures © Prof. Ren-Song Tsay 33 Abstraction & Encapsulation Data Abstraction: separate interface (specification) from implementation. ◦ Public methods ◦ Private data Or protected data for heirs Data Encapsulation (Information Hiding): Conceal the implementation details. E.g., “sort” can have many different implementations. • Advantages: ◦ Simplification of software development ◦ Easy to test and debug 2023/9/8 Data Structures © Prof. Ren-Song Tsay 34 Illustrate the Difference https://techdifferences.com/difference-between-abstraction-and-encapsulation.html 2023/9/8 Data Structures © Prof. Ren-Song Tsay 37 1.4 Basic of C++ 2023/9/8 Data Structures © Prof. Ren-Song Tsay 39 C++ Basics Object: a specific dog ◦ States: color, name, breed … ◦ Behaviors: wagging, barking, eating … Class − describes the behaviors/states that object of its type support. Methods − each method describes a behavior (function). Instance Variables − Each variable with a value describes a state. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 40 1.4.1 Program Organization Header files (*.h) store declarations Source files (*.cpp) store source code System-defined header #ifndef _HELLO_WORLD_H_ #define _HELLO_WORLD_H_ void Hello_World(void); // insert other declarations here // … #include <iostream> #include <Hello_World.h> void Hello_World(void) { std::cout << "Hello" << std::endl; } #endif 2023/9/8 Data Structures © Prof. Ren-Song Tsay 41 1.4.2 Scope in C++ Local scope A name declared in a block void Hello_World(void) { int a = 2; { int b = 3; } } Class scope Declaration associated with a class definition class Obj { Obj(void) {m_a=2; m_b=3; } int m_a; int m_b; }; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 42 1.4.2 Scope in C++ Namespace scope namespace Yahoo{ char* homePageURL; } namespace Google{ char* homePageURL; } //access Yahoo::homePageURL=. .. //access Google::homePageURL= ... http://www.cplusplus.com/doc/tutorial/namespaces/ 2023/9/8 Data Structures © Prof. Ren-Song Tsay 43 1.4.2 Namespace A mechanism to group related variables and functions Access the members using scope operator “::” For the repeated usage of members, use the “using” declaration. Avoid namespace pollution. namespace Google{ char* homePageURL; } //access Google::homePageURL=... using namespace Google; //access homePageURL=... 2023/9/8 Data Structures © Prof. Ren-Song Tsay 44 1.4.2 Scope in C++ A variable is uniquely identified by its scope and its name Scenario 1: What if a local variable reuses the name of a global variable? Ans: use scope operator :: Scenario 2: A global variable is defined in file1.cpp, but used in file2.cpp. Ans: as in C, use extern. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 45 1.4.2 Quiz: show the result #include <iostream> using namespace std; namespace first { int x = 5; int y = 10; } namespace second { double x = 3.1416; double y = 2.7183; } int main () { using first::x; using second::y; cout << x << '\n'; cout << y << '\n'; cout << first::y << '\n'; cout << second::x << '\n'; return 0; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 46 1.4.3 Same as in C, except ::, new, delete, throw, … http://en.cppreference.com/w/cpp/language/operator_precedence 2023/9/8 Data Structures © Prof. Ren-Song Tsay 48 1.4.4 Initialization of Variables #include <iostream> using namespace std; int main () { int a=5; int b(3); int result; // initial value: 5 // initial value: 3 // initial value undetermined a = a + 2; result = a - b; cout << result; } return 0; http://www.cplusplus.com/doc/tutorial/variables/ 2023/9/8 Data Structures © Prof. Ren-Song Tsay 50 1.4.4 Data Declaration in C++ Constant variables (const): ◦ Fixed values during their lifetime. ◦ Must be initialized at the time declared Enumeration types (enum): ◦ Declaring a series of integer constants const int MAX = 500; enum semester {SUMMER=0, FALL, SPRING}; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 51 1.4.4 Pointer and Reference Pointer (*): ◦ the memory address of an object Reference type (&): ◦ an alternative name to an object (C++ only). int i = 25; int* np; np = &i; int i=5; int& j=i; i = 7; cout << j << endl; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 52 1.4.5 Comments in C++ Single line comment: // ooxx Multiple Line comment: /* ooxx */ 2023/9/8 Data Structures © Prof. Ren-Song Tsay 56 1.4.6 I/O in C++ C C++ #include <stdio.h> int main(){ int x=100, y=99; #include <iostream> using namespace std; int main(){ int x=100, y=99; printf(“%d%d\n”,x,y); scanf(“%d %d”, &x , &y); cout << x << y << endl; cin >> x >> y ; return 0;} return 0; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 57 1.4.6 I/O in C++ Include the system-defined header file: #include <iostream> ◦ need to specify namespace “std” Keyword “cout” + “<<“ operator: ◦ output to the standard output device. Keyword “cin” + “>>“ operator: ◦ input a value to an object. Keyword “endl” : ◦ Inserts a new-line(‘\n’) character. http://www.cplusplus.com/reference/ostream/endl/?kw=endl 2023/9/8 Data Structures © Prof. Ren-Song Tsay 58 1.4.6 File I/O in C++ Include the system-defined header file: #include <fstream> ◦ Namespace is ios Declare file objects using the following keywords ◦ ofstream: write to file ◦ ifstream: read from file ◦ fstream: read to/write from file Specify the I/O mode when opening the file ◦ ios::out, ios::in, …etc Use shift operator “<<” and “>>” to write to and read from a file. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 59 1.4.6 File I/O in C++ #include <iostream> #include <fstream> using namespace std; #include <iostream> #include <fstream> using namespace std; int main(){ int main(){ ofstream outFile(“my.out”, ios::out); if(! outFile) { cout << “cannot open my.out” << endl; return 1; } ifstream inFile(“my.out”, ios::in); if(! inFile) { cout << “cannot open my.out” << endl; return 1; } int n = 50; float f = 20.3; outFile << “n: ” << n << endl; outFile << “f: ” << f << endl; Int x; while (! inFile.eof()){ inFile >> x; cout << x << endl; } return 0; } return 0; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 60 1.4.6 I/O Operator Overloading ostream& operator <<(ostream &os, const dataType &obj); Class Ferrari { public: int W, H, L; char* model; } #include <iostream> using namespace std; int main(){ Ferrari myCar; cout <<“Car info:”<<endl; cout << myCar << endl; return 0; } 2023/9/8 Car info: *********** Ferrari 250 GTO W=160 H=121 L=433 *********** Data Structures © Prof. Ren-Song Tsay 61 1.4.6 I/O Operator Overloading using namespace std; ostream& operator <<(ostream &os, const Ferrari &obj) { } os os os os os os << << << << << << “***********” “Ferrari ” << “W=” << obj.W “H=” << obj.H “L=” << obj.L “***********” << endl; obj.model << endl; << endl; << endl; << endl; << endl; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 62 1.4.7 Functions in C++ Function declaration( function prototype ) int sum( int , int ); Function definition int sum( int a, int b){ return a+b; } Inline function: compiler replaces each function call using its function body. inline int sum( int a, int b){ return a+b; } http://www.cplusplus.com/doc/tutorial/functions/ 2023/9/8 Data Structures © Prof. Ren-Song Tsay 63 1.4.8 Parameter Passing by Value Call by value int special_add(int a , int b) { a = a+5; return a+b; } Object’s value is copied into function’s local storage (storage overhead). Any change in ‘a’ and ‘b’ won’t modify the original copies. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 64 1.4.8 Parameter Passing by Pointer Call by pointer void swapnum(int *a , int *b){ int temp=*a; *a=*b; *b=temp; } Any change in ‘*a’ and ‘*b’ will modify the original objects 2023/9/8 Data Structures © Prof. Ren-Song Tsay 65 1.4.8 Parameter Passing by Reference Call by reference void swapnum(int &a, int &b) { int temp = a; a = b; b = temp; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 66 1.4.8 Passing const arguments The referenced arguments cannot be modified Any attempt for modification will cause a compile error. void func1(const dataType& a) { a = …; // ← Compile time error! } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 67 1.4.9 Function Overloading in C++ In C++, we can have the following functions: int Max(int, int); int Max(int, int, int); int Max(int*, int); int Max(float, int); int Max(int, float); In C, it’s impossible to define two functions of same function name. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 68 1.4.9 Function Overloading by Signatures C defines a function signature by function name. C++ defines a function signature by 1. Function name 2. Type & number of parameters 3. Order of parameters 2023/9/8 Data Structures © Prof. Ren-Song Tsay 69 Polymorphism in C++ Occurs when there is a hierarchy of classes and they are related by inheritance. A virtual function defined in a base class is dynamically linked to the version in a derived class 2023/9/8 Data Structures © Prof. Ren-Song Tsay 71 An Example class Shape { protected: int width, height; public: Shape( int a = 0, int b = 0){ width = a; height = b; } virtual int area() = 0; }; class Rectangle: public Shape { public: Rectangle( int a = 0, int b = 0): Shape(a, b) { } int area () { return (width * height); } }; class Triangle: public Shape { public: Triangle( int a = 0, int b = 0):Shape(a, b) { } int area () { return (width * height / 2); } }; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 72 1.4.11 Dynamic Memory Allocation in C++ Dynamic Memory Allocation in C ◦ malloc, delete, realloc, memset, memcopy ◦ Causes memory leak and memory fragmentation problems New dynamic memory allocation mechanism in C++ ◦ Use keywords “new” and “delete” ◦ The “new” operator in C++ is more powerful than “malloc” in C. ◦ Use ‘delete’ for pointer generated by ‘new’. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 74 1.4.11 Dynamic Memory Allocation in C++ C C++ #include <cstdio> #include <iostream> int main () { int main () { int * x = (int*) malloc ( sizeof(int) ); free(x); int * y = new int ; delete y ; return 0; // allocate an int array. int * data = new int [10]; /* make sure you use ‘delete’ for pointer generated by ‘new’. */ delete [] data ; } return 0; } http://www.cplusplus.com/reference/new/operator%20new[]/ 2023/9/8 Data Structures © Prof. Ren-Song Tsay 75 1.4.12 Handling Exceptions try-catch block ◦ ◦ ◦ ◦ Exceptions are thrown by a piece of code within the try block. Each try block is followed by zero or more catch blocks. Each catch block is visited sequentially until the matched block is found. Each catch block has a parameter whose type determines the type of exception to be caught. catch (char* e){} ◦ Catch exceptions of type char*. catch (bad_alloc e){} ◦ Catch exceptions of type bad_alloc (system-defined type). catch (…){} ◦ Catch all exceptions regardless of types. http://www.cplusplus.com/doc/tutorial/exceptions/ 2023/9/8 Data Structures © Prof. Ren-Song Tsay 80 1.4.12 P1.6 Example int DivZero(int a, int b, int c){ if(a <= 0 || b <=0 || c <= 0) throw “All parameters should be > 0”; return a+b*c+b/c; } int main () { try { cout << DivZero(2, 0, 4) << endl; } catch (const char* e) { cout << “The parameters to DivZero were 2, 0, 4" << endl; cout << “An exception has been thrown" << endl; cout << e << endl; } catch (…) { cout << “An unknown exception has been thrown" << endl; } return 0; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 84 2.1 Abstract Data Type and the C++ Class 2023/9/8 Data Structures © Prof. Ren-Song Tsay 86 Reviews of Data Type A data type is a collection of objects and a set of operations that act on objects Fundamental data type in C++: ◦ char, int, float, double, …etc. ◦ Modifiers: short, long, signed, unsigned Example: int data type ◦ Objects: {0, +1, -1, +2, -2, …, MAXINT, MININT} ◦ Operations: {+, -, *, /, ==, <=, …etc.} 2023/9/8 Data Structures © Prof. Ren-Song Tsay 87 Reviews of Data Type How to group data together? Arrays: int x[10]; ◦ Collection of elements of the same basic data type. structs (C) and classes (C++) ◦ Collection of elements whose data types need not be the same. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 88 Abstract Data Type (ADT) A data type that separates ◦ The specification of objects from their representation ◦ The specification of operation from their implementation. Major advantages ◦ ◦ ◦ ◦ Simplification Testing and debugging Reusability Flexibility 2023/9/8 Data Structures © Prof. Ren-Song Tsay 89 Example Data Type 1 Data Type 2 Objects: int data; Objects: float data; Operations: int Value(void) { return data; } Operations: float Value(void) { return data; } void Calculate(void) {data = 100; } void Calculate(void) {data= exp(-10); } 2023/9/8 Data Type 3 Objects: Type1 data; int data2; Operations: int Value(void) { return data.Value()+data2; } void Calculate(void) {data. Calculate(); data2 = 128; } Data Structures © Prof. Ren-Song Tsay 90 Object Representation? Data Type 1 Data Type 2 Objects: int data; Objects: float data; Operations: int Value(void) { return data; } Operations: float Value(void) { return data; } void Calculate(void) {data = 100; } void Calculate(void) {data= exp(-10); } 2023/9/8 Data Type 3 Objects: Type1 data; int data2; Operations: int Value(void) { return data.Value()+data2; } void Calculate(void) {data. Calculate(); data2 = 128; } Data Structures © Prof. Ren-Song Tsay 91 Object Specification? Data Type 1 Data Type 2 Objects: int data; Objects: float data; Operations: int Value(void) { return data; } Operations: float Value(void) { return data; } void Calculate(void) {data = 100; } void Calculate(void) {data= exp(-10); } 2023/9/8 Data Type 3 Objects: Type1 data; int data2; Operations: int Value(void) { return data.Value()+data2; } void Calculate(void) {data. Calculate(); data2 = 128; } Data Structures © Prof. Ren-Song Tsay 92 Operation Specification? Data Type 1 Data Type 2 Objects: int data; Objects: float data; Operations: int Value(void) { return data; } Operations: float Value(void) { return data; } void Calculate(void) {data = 100; } void Calculate(void) {data= exp(-10); } 2023/9/8 Data Type 3 Objects: Type1 data; int data2; Operations: int Value(void) { return data.Value()+data2; } void Calculate(void) {data. Calculate(); data2 = 128; } Data Structures © Prof. Ren-Song Tsay 93 Operation Implementation? Data Type 1 Data Type 2 Objects: int data; Objects: float data; Operations: int Value(void) { return data; } Operations: float Value(void) { return data; } void Calculate(void) {data = 100; } void Calculate(void) {data= exp(-10); } 2023/9/8 Data Type 3 Objects: Type1 data; int data2; Operations: int Value(void) { return data.Value()+data2; } void Calculate(void) {data. Calculate(); data2 = 128; } Data Structures © Prof. Ren-Song Tsay 94 A Software that uses ADTs Type3 Obj3 Type1 Obj1 Type2 Obj2 double Calculate1(void); double Calculate2(void); double Calculate3(void); double Calculate1(void) { Obj1.Calculate(); Obj2.Calculate(); return (double)Obj1.Value()+ (double)Obj2.Value();} double Calculate2(void) { Obj2.Calculate(); Obj3.Calculate(); return (double)Obj2.Value()+ (double)Obj3.Value();} 2023/9/8 Data Structures © Prof. Ren-Song Tsay 95 Introduction to C++ Class C++ provides new mechanism, class, to support data abstraction and encapsulation. // In the header file Rectangle.h #ifndef RECTANGLE_H #define RECTANGLE_H class Rectangle { public: // the following members are public // the next four members are member functions Rectangle ( ); // constructor ~Rectangle( ); // destructor int GetHeight ( ); // return the height of the rectangle int GetWidth ( ); // return the width of the rectangle private: // the following members are private // the following members are data member int xLow, yLow, height, width; // (xLow, yLow) are the coordinates of the bottom left corner of rec. }; #endif 2023/9/8 Data Structures © Prof. Ren-Song Tsay 98 Class Architecture A class name: (e.g., Rectangle) Data members: ◦ The data that makes up the class (e.g., xLow, yLow, height, width) Member functions: ◦ The set of operations that apply to the objects (e.g., GetHeight(), GetWidth() ) Levels of program access (data encapsulation): ◦ public: data member (function) can be accessed from anywhere in the program. ◦ private: data member (function) can be accessed only within its class or by a friend class ◦ protected: data member (function) can be accessed only within its class, by a friend class or from its subclass (class inheritance) 2023/9/8 Data Structures © Prof. Ren-Song Tsay 99 2.1.2 Data Abstraction and Encapsulation // In the header file Rectangle.h #ifndef RECTANGLE_H Data abstraction #define RECTANGLE_H Implementation? (Specification) class Rectangle { public: // the following members are public // the next four members are member functions Rectangle ( ); // constructor ~Rectangle( ); // destructor int GetHeight ( ); // return the height of the rectangle int GetWidth ( ); // return the width of the rectangle private: // the following members are private // the following members are data member int xLow, yLow, height, width; // (xLow, yLow) are the coordinates of the bottom left corner of rec. }; Data encapsulation #endif 2023/9/8 Data Structures © Prof. Ren-Song Tsay 100 Data Abstraction Specification is placed in header file (e.g., Rectangle.h) Implementation is placed in source file (e.g., Rectangle.cpp) // In the source file Rectangle.cpp #include “Rectangle.h” /* The prefix ”Rectangle::” identifies GetHeight() and GetWidth() are member function of class Rectangle. It is required because the member functions are implemented outside the class definition*/ int Rectangle::GetHeight() {return height;} int Rectangle::GetWidth() {return width;} 2023/9/8 Data Structures © Prof. Ren-Song Tsay 101 Class Usage // In a source file main.cpp #include <iostream> #include “Rectangle.h” main() { Rectangle r, s; // r and s are objects of class “Rectangle” Rectangle *t = &s; // t is a pointer to class object s . . // use “.” operator to access members of class objects. // use “®“ operator to access members of class objects through pointers. If ( r.GetHigh ( ) * r.GetWidth ( ) > t®GetHeight ( ) * t®GetWidth ( ) ) cout << “r”; else cout << “s”; cout << “has the greater area “ << endl; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 102 Data Encapsulation C++ C class Foo{ private: int x; public: int y; }; struct Foo{ int main(void){ Foo obj1 ; obj1.x = 11; // compile ERROR obj1.y = 22; // access y } int main(void){ struct Foo obj1 ; obj1.x = 11; // access x obj1.y = 22; // access y } int x; int y; }; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 103 Constructors and Destructors // In the source file Rectangle.cpp #include “Rectangle.h” // constructor Rectangle::Rectangle (void) { xLow = 0; yLow = 0; height = 1; width = 1; } // destructor Rectangle::~Rectangle (void) { xLow = yLow = height = width = 0; } int Rectangle::GetHeight() {return height;} int Rectangle::GetWidth() {return width;} 2023/9/8 Data Structures © Prof. Ren-Song Tsay 104 Constructors A member function to initialize the data members. Constructor (if defined) is invoked when an object is created, otherwise only the memory of data member is allocated. Must be declared as a public member. Must have the same name as the class. No return type or return value. A class can have multiple constructors, as long as their signature (the parameters they take) are not the same. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 105 Type of Constructors Default constructor ◦ A constructor with no arguments Rectangle ( ); // default constructor Augmented constructor ◦ A constructor with arguments Rectangle (int, int, int, int); // augmented constructor Copy constructor ◦ Must be specified if the STL containers are used to store your class object. Rectangle (const Rectangle&); // copy constructor 2023/9/8 Data Structures © Prof. Ren-Song Tsay 106 Augmented Constructor Implementation Rectangle::Rectangle (int x, int y, int h, int w) { xLow = x; yLow = y; height = h; width = w; } May use member initialization list (more efficient) Rectangle::Rectangle ( int x, int y, int h, int w ) : xLow (x), yLow (y), height (h), width (w) {} 2023/9/8 Data Structures © Prof. Ren-Song Tsay 107 Copy Constructor Implementation Rectangle::Rectangle (const Rectangle& _src) { xLow = _src. xLow; yLow = _src. yLow; height = _src. height ; width = _src. width ; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 108 A Constructor Example // In a source file main.cpp #include <iostream> #include “Rectangle.h” main() { // r1 and r2 are initialized using default constructor Rectangle r1; Rectangle *r2 = new Rectangle; // r3 and r4 are initialized using augmented constructor Rectangle r3(1, 3, 6, 6); Rectangle *r4 = new Rectangle(0, 0, 3, 4); // r5 is initialized using r4 through copy constructor Rectangle r5(*r4); } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 109 Frequently Made Mistakes To specify an augmented constructor, one MUST also specify a default constructor. /* The following statement results in a compile time error if an augmented constructor is defined but default constructor is missing */ Rectangle t; Possible solution: use default value for arguments. Rectangle::Rectangle ( int x = 0, int y = 0, int h = 0, int w = 0 ) : xLow (x), yLow (y), height (h), width (w) {} 2023/9/8 Data Structures © Prof. Ren-Song Tsay 110 Destructor A member function to delete data members when the object disappears. The destructor is automatically invoked when a class object is out of scope or is deleted. Must be declared as a public member. Must have the same name as the class with the prefix “~”. No return type or return value. Take no arguments. Only one destructor for a class. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 111 Operator Overloading C++ can define customized “operators” for a class object. // In a source file main.cpp #include <iostream> #include “Rectangle.h” main() { Rectangle r1, r2(1, 3, 6, 6), r3(0, 0, 3, 4); r1 = r2; // compile time error, no operator “=” is defined for Rectangle class if(r2==r3) // compile time error, no operator “==” is defined for Rectangle class {…} } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 113 Operator Overloading // In the header file Rectangle.h #ifndef RECTANGLE_H #define RECTANGLE_H class Rectangle { public: Rectangle ( ); // constructor ~Rectangle( ); // destructor int GetHeight ( );// return the height of the rectangle int GetWidth ( ); // return the width of the rectangle // the function prototype for operator overloading is fixed bool operator== (const Rectangle&); // overloading operator “==” Rectangle& operator= (const Rectangle&); // overloading operator “=” private: int xLow, yLow, height, width; }; #endif http://en.wikipedia.org/wiki/Operator_overloading 2023/9/8 Data Structures © Prof. Ren-Song Tsay 114 Operator Overloading bool Rectangle::operator == (const Rectangle& _rhs) { if (this == &_rhs) return true; if ((xLow == _rhs.xLow) && (yLow == _rhs.yLow) && (height == _rhs.height) && (width == _rhs.width) ) return true; else return false; } Rectangle& Rectangle::operator = (const Rectangle& _rhs) { Important Note!!! if (this == &_rhs) return (*this); “this” is a reserved keyword xLow = _rhs. xLow; indicating a pointer to the class yLow = _rhs. yLow; object itself height = _rhs. height ; width = _rhs. width ; return (*this); } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 115 I/O Operator Overloading ostream& operator <<(ostream &os, const Rectangle &r); { // need to implement additional GetX() and GetY() member functions os << “Position is : “ << r.GetX() << “ “; os << r.GetY() << endl; os << “Height is: “ << r.GetHeight() << endl; os << “Width is: “ << r.GetWidth() << endl; return os; } main() { Rectangle r1, r2(1, 3, 6, 6), r3(0, 0, 3, 4); std::cout << r1 << r2 << r3 << std::endl; } Ref: C++ Primer 5th chapter 14 2023/9/8 Data Structures © Prof. Ren-Song Tsay 116 3.1 Templates in C++ 2023/9/8 Data Structures © Prof. Ren-Song Tsay 120 3.1 Template in C++ A mechanism to parameterize the target data type and instantiate it to a proper data type at compile time. Using the keyword template followed by parameter type list <typename T> or <class T>. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 121 3.1.1 Function Template Ordinary function Template function int sum(int * data, const int SIZE) { int sum=0 ; for( int i =0; i < SIZE; i++) { sum += data[i]; } return sum; } template < class T > T sum(T * data, const int SIZE) { T sum=0 ; for( int i =0; i < SIZE; i++) { sum += data[i]; } return sum; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 122 3.1.1 Function Template The compiler will insert the code with proper data type at compile time. The source code is visible to everyone! int main(){ int data1[100] = …; sum( data1 ) ; After compiling int main(){ int data1[100] = …; {int sum=0 ; for( int i =0; i < SIZE; i++ ){ sum += data1[i];}} float data2[100] = …. ; { float sum=0 ; for(int i =0; i < SIZE; i++){ sum += data2[i];}} float data2[100] = …; sum( data2 ) ; } source code } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 123 3.1.2 P3.4 The Class Bag Containing int class Bag { public: Bag(int bagCapacity = 10); ~Bag(); // Constructor // Destructor int Size() const; // Return the number of elements bool IsEmpty() const; // Check if bag is empty int Element() const; // Return an element in the bag void Push(const int); void Pop() // Insert an integer into the bag // Delete an integer from the bag private: int *array; int capacity; int top; }; // Integer array that stores the data // Capacity of array // Position of top element 2023/9/8 Data Structures © Prof. Ren-Song Tsay 124 3.1.2 P3.5 Implement Bag Operations Bag::Bag( int bagCapacity):capacity( bagCapacity ) { if(capacity < 1) throw “Capacity must be > 0”; array = new int [ capacity ]; top = -1; } Bag::~Bag(){ delete [] array; } inline int Bag::Size() const { return top + 1; } inline bool Bag::IsEmpty() const { return Size() == 0; } inline int Bag::Element() const { if(IsEmpty()) throw “Bag is empty”; return array [0]; // Always return the first element } void Bag::Push(const int x) { if(capacity == top+1) ChangeSize1D(array,capacity,2*capacity); capacity *= 2; array[++top]=x; } void Bag::Pop( ) { if(IsEmpty()) throw “Bag is empty, cannot delete”; int deletePos = top / 2; // Always delete the middle element copy (array+deletePos+1, array+top+1, array+deletePos); top--; } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 125 3.1.2 P3.6 Define Class Template Bag template<class T> class Bag { public: Bag(int bagCapacity = 10); // Constructor ~Bag(); // Destructor int Size() const; // Return the number of elements bool IsEmpty() const; // Check if bag is empty T& Element() const; // Return an element in the bag void Push(const T&); void Pop() // Insert an element into the bag // Delete an element from the bag private: T *array; int capacity; int top; }; // Data array // Capacity of array // Position of top element 2023/9/8 Data Structures © Prof. Ren-Song Tsay 126 3.1.2 P3.7 Implementation of Some Bag Operations template<class T> Bag<T>::Bag( int bagCapacity):capacity( bagCapacity ) { if(capacity < 1) throw “Capacity must be > 0”; array = new T [ capacity ]; top = -1; } template<class T> void Bag<T>::Push(const T& x) { if(capacity == top+1) ChangeSize1D(array,capacity,2* capacity); capacity *= 2; array[++top]=x; } template<class T> void Bag<T>::Pop() { if(IsEmpty()) throw “Bag is empty, cannot delete”; int deletePos = top/2; // Always delete the middle emelent copy (array+deletePos+1, array+top+1, array+deletePos); array[top--].~T(); 2023/9/8 Data Structures © Prof. Ren-Song Tsay } 127 3.1.2 An Example Using Template int main() { // T is instantiated as int Bag<int> Bag1; Bag1.Push(10); … // T is instantiated as MyData Bag<MyData> Bag2; Bag2.Push(MyData()); … } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 128 3.4 Subtyping and Inheritance in C++ 2023/9/8 Data Structures © Prof. Ren-Song Tsay 130 Object Inheritance An object A could be used to define another object B. Both objects and operations of A are automatically inherited by B. ◦ house can inherit from building • Advantages: ◦ Simplification of software development ◦ Easy to test and debug ◦ Reusability ◦ Flexibility 2023/9/8 house Building Data Structures © Prof. Ren-Song Tsay 131 C++ Inheritance Define a class in terms of another class ◦ easier to create and maintain an application. The existing class = base class, the new class = derived class. The derived class is a base class derived base ◦ dog IS-A mammal A class can be derived from more than one classes, i.e. inherit data and functions from multiple base classes. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 132 Process Geometry If to develop a program to process various types of geometry. … Triangle Rectangle Trapezoid Operations on these primitives: ◦ Get number of vertices. ◦ Calculate the area of the primitive. ◦ Check whether it is convex or not. 2023/9/8 Data Structures © Prof. Ren-Song Tsay 133 Implement Using Classes Triangle class Triangle { public: Triangle ( ){ m_VN = 3; mp_V = new Point [m_VN]; } ~Triangle ( ){ delete [] mp_V; mp_V = NULL; } double CalArea ( ); bool isConvex(); int vtxNum() { return m_VN; } private: int m_VN; Point* mp_V; }; class Rectangle { public: Rectangle ( ){ m_VN = 4; mp_V = new Point [m_VN]; } ~Rectangle( ){ delete [] mp_V; mp_V = NULL; } double CalArea ( ); bool isConvex(); int vtxNum() { return m_VN; } private: int m_VN; Point* mp_V; }; 2023/9/8 Data Structures © Prof. Ren-Song Tsay Rectangle 134 What’s the Problem? Duplicated codes in both classes! If need to design 100 or more types of geometry? If need to add another “common” data member or function? Will need to maintain all the classes! 2023/9/8 Data Structures © Prof. Ren-Song Tsay 135 Polygon Base Class Polygon is an abstract type of geometry. Triangle and rectangle are special polygons. But how do we let the triangle and rectangle classes share the same code by using polygon? Don’t worry! C++ will be your lifesaver! 2023/9/8 Data Structures © Prof. Ren-Song Tsay 136 Class Inheritance in C++ A mechanism to relate one class object to another one. Define a “IS-A” relationships between objects. B ◦ Type B IS-A data type of Type A if B is a specialized version of A and A is more general than B, e.g., Triangle IS-A Polygon and Rectangle IS-A Polygon. A Members (data and functions) in Type A are implicitly copied to Type B. Reusability of code 2023/9/8 Data Structures © Prof. Ren-Song Tsay 137 3.4 Class Diagram of Inheritance class Polygon Base class “IS-A” relationships class Triangle class Rectangle Derived class 2023/9/8 Data Structures © Prof. Ren-Song Tsay 138 3.4 Inherit the Polygon Class class Polygon { public: Polygon ( ){ m_VN = 0; mp_V = NULL; } ~Polygon ( ){ delete [] mp_V; mp_V = NULL; } double CalArea ( ) { return 0.0;} bool isConvex() { return true; } int vtxNum() { return m_VN; } protected: int m_VN; Point* mp_V; }; class Triangle: public Polygon { public: Triangle ( ){ m_VN = 3; mp_V = new Point [m_VN]; } ~Triangle ( ){} double CalArea ( ); }; Triangle Class Rectangle: public Polygon { public: Rectangle ( ){ m_VN = 4; Rectangle mp_V = new Point [m_VN]; } ~Rectangle ( ){} double CalArea ( ); }; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 139 Access Specifier of Inheritance “class Triangle: public Polygon” indicates the triangle class inherits all the non-private members (data and functions) from Polygon The access specifier could be public, protected and private. https://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/ 2023/9/8 Data Structures © Prof. Ren-Song Tsay 140 Access Specifier: public Base Class Derived Class class Triangle : public Polygon { class Polygon { private: int x; protected: X private: //CANNOT ACCESS private member of base class protected: Int y; int y; public : public : Int z; int z; }; }; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 141 Access Specifier: protected Base Class Derived Class class Triangle : protected Polygon { class Polygon { private: int x; protected: X private: protected: Int y; int y; Int z; public : int z; public : }; }; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 142 Access Specifier: private Base Class Derived Class class Triangle : private Polygon { class Polygon { private: int x; X private: Int y; protected: Int z; int y; public : int z; }; protected: public : }; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 143 Specialization Some members (data and functions) are specialized in different class. ◦ Triangle and Rectangle use different area calculation, e.g., specialized CalArea() function. Put these non-common members in private block of base class. Derived class thus cannot access these members (Optional) Re-declare the members (data and functions) in the derived class. (overriding) 2023/9/8 Data Structures © Prof. Ren-Song Tsay 144 Overriding class Polygon { public: … double CalArea ( ) { return 0.0;} … }; class Triangle : public Polygon { public: … // overriding CalArea function double CalArea () { // calculate triangle area } }; Class Rectangle : public Polygon { public: … // overriding CalArea function double CalArea ( ){ // calculate rectangle area /* if you want to access the original base class function*/ Polygon::CalArea(); } }; 2023/9/8 Data Structures © Prof. Ren-Song Tsay 145 Overloading v.s. Overriding Function overloading: (超載) ◦ Two or more functions with the same name but different signatures in the same scope or one in base class and another in derived class. Function overriding:(覆蓋) ◦ A different implementation of the same function in the inherited class. ◦ Functions would have the same signature, but different implementation. ◦ Only exist in class inheritance. http://www.codeproject.com/Articles/16407/METHOD-Overload-Vs-Overriding 2023/9/8 Data Structures © Prof. Ren-Song Tsay 146 Initialization The order of calling constructors: Base class 2nd derived class Last derived class The order of calling destructors: Last derived class 1st derived class 2nd derived class 1st derived class Base class Use Initialization Lists to initialize base class in derived class via constructor 2023/9/8 Data Structures © Prof. Ren-Song Tsay 147 A Constructor Example class Foo { public: Foo() { std::cout << "Foo's constructor" << std::endl; } }; class Bar: public Foo { public: Bar() { std::cout << "Bar's constructor" << std::endl; } }; int main(){ Bar bar; } Output: Foo's constructor Bar's constructor 2023/9/8 Bar Foo Data Structures © Prof. Ren-Song Tsay 148 Polymorphism (多態性) A mechanism allow you to manipulate different objects through the common interface. Why not function overloading? class Foo { public: char* getName() { return “foo”; } }; class Bar: public Foo { public: char* getName() { return “Bar”; } }; 2023/9/8 class Car: public Foo { public: char* getName() { return “Car”; } }; Data Structures © Prof. Ren-Song Tsay 151 Review Function Overloading int main(){ Foo myFoo; Bar myBar; Car myCar; processObj(Foo _obj) {… _obj.getName()…} processObj(Bar _obj) {… _obj.getName()…} processObj(myFoo); processObj (myBar); processObj (myCar); processObj(Car _car) {… _obj.getName()…} } Each function performs the same algorithm and works only on different data type of object . Duplicated code. What if need to modify the algorithm? 2023/9/8 Data Structures © Prof. Ren-Song Tsay 152 Polymorphism class Foo { public: char* getName() { return “foo”; } }; class Bar : public Foo { public: char* getName() { return “Bar”; } }; int main(){ Foo* myFoo = new Foo; Foo* myBar = new Bar; Foo* myCar = new Car; class Car : public Foo { public: char* getName() { return “Car”; } }; processObj(Foo* _obj) {… _obj->getName()…} processObj(myFoo); processObj(myBar); processObj(myCar); } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 153 Polymorphism class Foo { public: char* getName() { return “foo”; } }; class Bar : public Foo { public: char* getName() { return “Bar”; } }; int main(){ Foo* myFoo = new Foo; Foo* myBar = new Bar; Foo* myCar = new Car; class Car : public Foo { public: char* getName() { return “Car”; } }; processObj(Foo* _obj) {… _obj->getName()…} processObj(myFoo); processObj(myBar); processObj(myCar); } 2023/9/8 Data Structures © Prof. Ren-Song Tsay 154 Polymorphism Function Overloading Data type is determined in compiler time. int main(){ Foo myFoo; Bar myBar; Car myCar; Dynamic Binding Data type is determined in run time. int main(){ Foo* myFoo = new Foo; Foo* myBar = new Bar; Foo* myCar = new Car; processObj (myFoo); processObj (myBar); processObj (myCar); } processObj(myFoo); processObj(myBar); processObj(myCar); } Use the keyword “virtual” as a prefix of your member function 2023/9/8 Data Structures © Prof. Ren-Song Tsay 155