Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Data Structures and Algorithms Week 3 Data Abstraction: Part II Structured Types, and Classes.

Similar presentations


Presentation on theme: "1 Data Structures and Algorithms Week 3 Data Abstraction: Part II Structured Types, and Classes."— Presentation transcript:

1 1 Data Structures and Algorithms Week 3 Data Abstraction: Part II Structured Types, and Classes

2 2 Part II Topics Meaning of a Structured Data Type Declaring and Using a struct Data Type C++ union Data Type Meaning of an Abstract Data Type Declaring and Using a class Data Type Using Separate Specification and Implementation Files Invoking class Member Functions in Client Code C++ class Constructors

3 3 C++ Data Types structured array address pointer reference simple integral enum char short int long bool floating float double long double struct union class

4 4 C++ Structured Type often we have related information of various types that we’d like to store together for convenient access under the same identifier, for example...

5 5 thisAnimal 5000 2037581 “giant panda” “Ailuropoda” “melanoluka” “China” 18 234.6 Good.id.name.genus.species.country.age.weight.health

6 6 anotherAnimal 6000 5281003 “llama” “Lama” “peruana” “Peru” 7 278.5 Excellent.id.name.genus.species.country.age.weight.health

7 7 struct AnimalType enum HealthType { Poor, Fair, Good, Excellent } ; struct AnimalType// declares a struct data type {// does not allocate memory long id ; string name ; string genus ; string species ; struct members string country ; int age ; float weight ; HealthType health ; } ; AnimalType thisAnimal ; // declare variables of AnimalType AnimalType anotherAnimal ;

8 8 struct type Declaration SYNTAX struct TypeName // does not allocate memory { MemberList } ; MemberList SYNTAX DataType MemberName ;.

9 9 struct type Declaration The struct declaration names a type and names the members of the struct. It does not allocate memory for any variables of that type! You still need to declare your struct variables.

10 10 Accessing struct Members Dot ( period ) is the member selection operator. After the struct type declaration, the various members can be used in your program only when they are preceded by a struct variable name and a dot. EXAMPLES thisAnimal.weight anotherAnimal.country

11 11 More about struct type declarations If the struct type declaration precedes all functions it will be visible throughout the rest of the file. If it is placed within a function, only that function can use it. It is common to place struct type declarations with TypeNames in a (.h) header file and #include that file. It is possible for members of different struct types to have the same identifiers. Also a non-struct variable may have the same identifier as a structure member.

12 12 Valid operations on a struct member depend only on its type thisAnimal.age = 18; thisAnimal.id = 2037581; cin >> thisAnimal.weight; getline ( cin, thisAnimal.species ); thisAnimal.name = “giant panda”; thisAnimal.genus[ 0 ] = toupper (thisAnimal.genus[ 0 ] ) ; thisAnimal.age++;

13 13 Aggregate Operation is an operation on a data structure as a whole, as opposed to an operation on an individual component of the data structure

14 14 Aggregate struct Operations I/O, arithmetic, and comparisons of entire struct variables are NOT ALLOWED! operations valid on an entire struct type variable: assignment to another struct variable of same type, pass to a function as argument (by value or by reference), return as value of a function

15 15 Examples of aggregate struct operations anotherAnimal = thisAnimal ; // assignment WriteOut(thisAnimal); // value parameter ChangeWeightAndAge(thisAnimal); // reference parameter thisAnimal = GetAnimalData( ); // return value of function NOW WE’LL WRITE THE 3 FUNCTIONS USED HERE...

16 16 void WriteOut( /* in */ AnimalType thisAnimal) // Prints out values of all members of thisAnimal // Precondition: all members of thisAnimal are assigned // Postcondition: all members have been written out { cout << “ID # “ << thisAnimal.id << thisAnimal.name << endl ; cout << thisAnimal.genus << thisAnimal.species << endl ; cout << thisAnimal.country << endl ; cout << thisAnimal.age << “ years “ << endl ; cout << thisAnimal.weight << “ lbs. “ << endl ; cout << “General health : “ ; WriteWord ( thisAnimal.health ) ; }

17 17 void ChangeAge ( /* inout */ AnimalType& thisAnimal ) // Adds 1 to age // Precondition: thisAnimal.age is assigned // Postcondition: thisAnimal.age == thisAnimal.age@entry + 1 { thisAnimal.age++ ; } Passing a struct Type by Reference

18 18 AnimalType GetAnimalData ( void ) // Obtains all information about an animal from keyboard // Postcondition: // Function value == AnimalType members entered at kbd { AnimalType thisAnimal ; char response ; do {// have user enter all members until they are correct. } while (response != ‘Y’ ) ; return thisAnimal ; }

19 19 Hierarchical Structures The type of a struct member can be another struct type. This is called nested or hierarchical structures. Hierarchical structures are very useful when there is much detailed information in each record. FOR EXAMPLE...

20 20 struct MachineRec Information about each machine in a shop contains: – an idNumber, – a written description, – the purchase date, – the cost, –and a history (including failure rate, number of days down, and date of last service).

21 21 struct DateType {int month ; // Assume 1.. 12 int day ;// Assume 1.. 31 int year ; // Assume 1900.. 2050 }; struct StatisticsType {floatfailRate ; DateTypelastServiced ; // DateType is a struct type intdownDays ; } ; struct MachineRec {int idNumber ; string description ; StatisticsType history ; // StatisticsType is a struct type DateType purchaseDate ; float cost ; } ; MachineRec machine ;

22 22 struct type variable machine 7000.idNumber.description. history.purchaseDate.cost.month.day.year 5719 “DRILLING…” 3 21 1995 8000.0.failrate.lastServiced.downdays.02 1 25.month.day.year machine.history.lastServiced.year has value 1999 4 1999

23 23 Data Abstraction Separation of a data type’s logical properties from its implementation. LOGICAL PROPERTIESIMPLEMENTATION What are the possible values? How can this be done in C++? What operations will be needed? How can data types be used?

24 24 Abstract Data Type (ADT) A data type whose properties (domain and operations) are specified independently of any particular implementation.

25 25 Data from 3 different levels Application (or user) level: modeling real-life data in a specific context. WHY Logical (or ADT) level: abstract view of the domain and operations. WHAT Implementation level: specific representation of the structure to hold the data items, and the coding for operations. HOW

26 26 Viewing a library from 3 different levels Application (or user) level: Library of Congress, or Baltimore County Public Library. Logical (or ADT) level: domain is a collection of books; operations include: check book out, check book in, pay fine, reserve a book. Implementation level: representation of the structure to hold the “books”, and the coding for operations.

27 27 Structured Data Type A structured data type (or data structure) is a type which stores a collection of individual data components under one variable name, has rules that determine how the individual data components can be accessed.

28 28 C++ Built-In Data Types Structured array struct union class Address pointer reference Simple IntegralFloating char short int long enum float double long double

29 29 Records A record is a linear, direct-access data structure with heterogeneous components called members or fields. For example....year 1999.maker ‘h’ ‘o’ ‘n’ ‘d’ ‘a’ ‘\0’....price 18678.92 myCar at Base Address 6000

30 30 C++ struct s C++ defines a struct to be a class whose members are all, by default, public. All operations that apply to C++ classes also apply to structs.

31 31 struct CarType { int year ; char maker[10]; float price ; } ; CarType thisCar; //CarType variables CarType myCar;

32 32 Accessing struct members The member selection operator (period. ) is used between the variable name and the member identifier to access individual members of a record (struct or class) type variable. EXAMPLES myCar.year thisCar.maker[4]

33 33 Aggregate struct operations Operations valid on an entire struct type variable: –assignment to another struct variable of same type, –pass as a parameter to a function (either by value or by reference), –return as the value of a function.

34 Pass-by-value CALLING BLOCK FUNCTION CALLED sends a copy of the contents of the actual parameter So, the actual parameter cannot be changed by the function. 34

35 Pass-by-reference sends the location (memory address) of the actual parameter can change value of actual parameter CALLING BLOCK FUNCTION CALLED 35

36 36 Using struct type Reference Parameter to change a member void AdjustForInflation(CarType& car, float perCent) // Increases price by the amount specified in perCent { car.price = car.price * perCent + car.price; } ; SAMPLE CALL AdjustForInflation(myCar, 0.03);

37 37 Using struct type Value Parameter to examine a member Boolean LateModel(CarType car, int date) // Returns true if the car’s model year is later than or // equal to date; returns false otherwise. { return ( car.year >= date ) ; } ; SAMPLE CALL if ( LateModel(myCar, 1995) ) cout << myCar.price << endl ;

38 38 Unions in C++ DEFINITION A union is a struct that holds only one of its members at a time during program execution. EXAMPLE union WeightType { long wtInOunces ; int wtInPounds; only one at a time float wtInTons; } ;

39 39 Using Unions union WeightType// declares a union type { long wtInOunces ; int wtInPounds; float wtInTons; } ; WeightType weight;// declares a union variable weight.wtInTons = 4.83 ; // Weight in tons is no longer needed. Reuse the memory space. weight.wtInPounds = 35;

40 40 Data Abstraction separates the logical properties of a data type from its implementation LOGICAL PROPERTIESIMPLEMENTATION What are the possible values?How can this be done in C++? What operations will be needed?How can data types be used?

41 41 Abstract Data Type (ADT) A data type whose domain and operations are specified (what) independently of any particular implementation (how). FOR EXAMPLE...

42 42 ADT Specification Example TYPE TimeType DOMAIN Each value is a time in hours, minutes, and seconds. OPERATIONS Set the time Print the time Increment by one second Compare 2 times for equality Determine if one time is “less than” another

43 43 Another ADT Specification TYPE ComplexNumberType DOMAIN Each value is an ordered pair of real numbers (a, b) representing a + bi. OPERATIONS Initialize the complex number Write the complex number Add Subtract Multiply Divide Determine the absolute value of a complex number

44 44 To implement an ADT means choosing a specific data representation for the ADT using existing data types (built-in or programmer-defined), and writing functions for each ADT operation.

45 45 10 45 27 Several Possible Representations of TimeType 3 int variables 3 strings 3-element int array actual choice of representation depends on time, space, and algorithms needed to implement operations 10 45 27 “10” “45” “27”

46 46 Some Possible Representations of ComplexNumberType struct with 2 float members 2-element float array -16.2 5.8 real.imag -16.2 5.18

47 47 C++ Data Types structured array struct union class address pointer reference simple integral enum char short int long bool floating float double long double

48 48 Creating a Class A class is like a type: we can create instances of this type One can now declare: class CookieType { public: void initToEmpty(); // Initialize the cookie to be empty void add(/* in */ int n); // Add n units to the cookie void quantity() const; // Return the current numbers of cookies private: int numUnits; }; CookieType cookie1; CookieType cookie2;

49 49 More about Class Each instance of CookieType is different – cookie1 's copy of numUnits is not the same copy as the one for cookie2. – Both copies may have different values – The functions will act on the correct data We can create as many instances as needed Built in operations (such as addition, subtraction) cannot be applied to user defined classes Two operations are valid – Member selection: (.) – Assignment ( = )

50 50 Using class A class is a programmer-defined type whose components (called class members) can be variables or functions. Class members are private by default. Compiler does not permit client code to access private class members. Class members declared public form the interface between the client and the class. In most classes, the private members contain data, and the public members are functions to manipulate that data.

51 51 Benefits of information hiding Data and details can be concealed from the client of the abstraction. Code can be changed witout affecting the client because the specification and interface are unchanged.

52 52 class TimeType Specification // SPECIFICATION FILE( timetype.h ) class TimeType {// declares a class data type // does not allocate memory public : // 5 public function members void Set ( int hours, int mins, int secs ) ; void Increment ( ) ; void Write ( ) const ; Boolean Equal ( TimeType otherTime ) const ; Boolean LessThan ( TimeType otherTime ) const ; private : // 3 private data members int hrs ; int mins ; int secs ; } ;

53 53 Use of C++ data type class Facilitates re-use of C++ code for an ADT. Software that uses the class is called a client. Variables of the class type are called objects or instances of the class. Client code uses public member functions to handle its class objects.

54 54 Member functions categorized by task CONSTRUCTOR -- a member function that actually creates a new instance and initialized some or all of its data members ACCESS FUNCTION or OBSERVER -- a member function that can inspect (use but not modify) the data members of a class without changing their values. Such a function is declared with const follwing the parameter list in both the specification and the implementation files.

55 55 Client Code Using TimeType #include “timetype.h” // includes specification of the class #include “bool.h” int main ( void ) { TimeType currentTime ; // declares 2 objects of TimeType TimeType endTime ; Boolean done = FALSE ; currentTime.Set ( 5, 30, 0 ) ; endTime.Set ( 18, 30, 0 ) ; while ( ! done ) {... currentTime.Increment ( ) ; if ( currentTime.Equal ( endTime ) ) done = TRUE ; } ; }

56 56 class type declaration The class declaration creates a data type and names the members of the class. It does not allocate memory for any variables of that type! Client code still needs to declare class variables.

57 57 C++ Data Type class represents an ADT 2 kinds of class members: –data members and function members class members are private by default data members are generally private function members are generally declared public private class members can be accessed only by the class member functions (and friend functions), not by client code.

58 58 Aggregate class operations Built-in operations valid on class objects are: member selection using dot (. ) operator, assignment to another class variable using ( = ), pass to a function as parameter (by value or by reference), return as value of a function. Other operations can be defined as class member functions.

59 59 2 separate files generally used for class type // SPECIFICATION FILE ( timetype.h ) // Specifies the data and function members. class TimeType { public:... private:... } ; // IMPLEMENTATION FILE ( timetype.cpp ) // Implements the TimeType member functions....

60 60 Implementation file for TimeType // IMPLEMENTATION FILE ( timetype.cpp ) // Implements the TimeType member functions. #include “ timetype.h”// also must appear in client code #include... Boolean TimeType :: Equal ( /* in */ TimeType otherTime ) const // POST: FCTVAL == true, if this time equals otherTime // == false, otherwise { return ( (hrs == otherTime.hrs) && (mins == otherTime.mins) && (secs == otherTime.secs) ) ; }...

61 61 Member selection operator. When a client uses a public member function, the function call requires a dot preceded by the name of the object. You can think of the function call as being sent to this object. ofstream outFile ; outFile.open (“a:\\my.out”) ;. outFile.close( ) ; class type variable, object, instance

62 62 Familiar Class Instances The member selection operator (. ) selects either data members or function members. Header files iostream.h and fstream.h declare the istream, ostream,and ifstream, ofstream I/O classes. Both cin and cout are class objects and get and ignore are function members. cin.get (someChar) ; cin.ignore (100, ‘\n’) ;

63 63 Information Hiding Class implementation details are hidden from the client’s view. This is called information hiding. Public functions of a class provide the interface between the client code and the class objects. client code specificationimplementation abstraction barrier

64 64 Scope Resolution Operator ( :: ) Different classes can have member functions with the same identifer, like Write( ). Member selection operator is used to determine the class whose member function Write( ) is invoked. currentTime.Write( ) ;// class TimeType In the implementation file, the scope resolution operator is used in the heading before the function member’s name to specify its class. void TimeType :: Write ( ) const {... }

65 65 TimeType Class Instance Diagrams Private data: hrs mins secs Set Increment Write LessThan Equal 17 58 2 Private data: hrs mins secs Set Increment Write LessThan Equal 18 30 0 currentTime endTime

66 66 const member functions When a member function does not modify the private data members, use const in both the function prototype (in specification file) and the heading of the function definition (in implementation file).

67 67 A const member function void TimeType :: Write ( ) const // POST: Time has been output in form HH:MM:SS {if ( hrs < 10 ) cout << ‘0’ ; cout << hrs << ‘:’ ; if ( mins < 10 ) cout << ‘0’ ; cout << mins << ‘:’ ; if ( secs < 10 ) cout << ‘0’ ; cout << secs ; }

68 68 Separate Compilation and Linking of Files timetype.h client.cpptimetype.cpp client.obj client.exetimetype.obj Compiler Linker #include “timetype.h” implementation file specification file main program

69 69 Class Constructors A class constructor is a member function whose purpose is to initialize the private data members of a class object. The name of a constructor is always the name of the class, and there is no return type for the constructor. A class may have several constructors with different parameter lists. A constructor with no parameters is the default constructor. A constructor is implicitly invoked when a class object is declared. If there are parameters, their values are listed in parentheses in the declaration.

70 70 Specification of TimeType Class Constructors class TimeType {// timetype.h public : // 7 function members void Set ( int hours, int minutes, int seconds ) ; void Increment ( ) ; void Write ( ) const ; Boolean Equal ( TimeType otherTime ) const ; Boolean LessThan ( TimeType otherTime ) const ; TimeType ( int initHrs, int initMins, int initSecs ) ; // constructor TimeType ( ) ; // default constructor private : // 3 data members int hrs ; int mins ; int secs ; } ;

71 71 Implementation of TimeType Default Constructor TimeType :: TimeType ( ) // Default Constructor // POST: hrs == 0 && mins == 0 && secs == 0 { hrs = 0 ; mins = 0 ; secs = 0 ; }

72 72 Implementation of Another TimeType Class Constructor TimeType :: TimeType ( /* in */ int initHrs, /* in */ int initMins, /* in */ int initSecs ) // Constructor // PRE: 0 <= initHrs <= 23 && 0 <= initMins <= 59 // && 0 <= initSecs <= 59 // POST: //hrs == initHrs && mins == initMins && secs == initSecs { hrs = initHrs ; mins = initMins ; secs = initSecs ; }

73 73 Automatic invokation of constructors occurs TimeType departureTime ; // default constructor invoked TimeType movieTime (19, 30, 0 ) ; // parameterized constructor departureTime movieTime Private data: hrs mins secs Set Increment Write LessThan Equal 000000 Private data: hrs mins secs Set Increment Write LessThan Equal 19 30 0

74 74 Array of class objects const int MAX_SIZE = 50 ; // declare array of class objects TimeType trainSchedule[ MAX_SIZE ] ; The default constructor, if there is any constructor, is invoked for each element of the array.

75 // SPECIFICATION FILE( jar2.h ) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class JarType { // declares a class data type public : // public function members void Add ( /* in */ int n ) ; // PRE: n >= 0 // POST: n units have been added to jar int Quantity ( ) const ; // POST: FCTVAL == number of units in jar JarType ( /* in */ int n ) ; // 2 constructors // PRE: n >= 0 // POST: numUnits == n JarType ( ) ; // POST: numUnits == 0 private :// 1 private data member int numUnits ; } ;

76 76 Client Code Using JarType #include “jar.h” // includes specification of the class #include “bool.h” int main ( void ) { JarType myJar (20) ; // declares 2 objects of JarType JarType anotherJar ; // constructors implicitly called int number ;... cin >> number ; anotherJar.Add ( number ) ; if ( anotherJar.Quantity( ) == myJar.Quantity( ) ). }

77 77 Class Invariant is a special assertion about the current state of a class instance. Typically, it refers only to data members of the class. The class invariant is an implicit precondition for each member function (except a constructor). The class invariant is an implicit postcondition for each member function (including constructors).

78 78 // CLASSINV is a comment describing a condition, generally about the data members of the class, which must be true before any member function (except constructor) is called, and which also must be true after each member function is called. It is the task of the constructor to insure that the class invariant is true.

79 // IMPLEMENTATION FILE ( jar2.cpp ) // Implements the JarType member functions. #include “ jar2.h” // also must appear in client code #include “bool.h” // CLASSINV: numUnits >= 0 JarType :: JarType ( /* in */ int n ) // Parameterized Constructor // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // PRE: n >= 0 // POST: numUnits == n // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { numUnits = n ; } JarType :: JarType ( ) // Default Constructor // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // POST: numUnits == 0 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { numUnits = 0 ; }

80 // IMPLEMENTATION FILE continued ( jar2.cpp ) int JarType :: Quantity ( ) const // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // POST: FCTVAL == numUnits // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { return numUnits ; } void JarType :: Add ( /* in */ int n ) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // PRE: n >= 0 // POST: numUnits == numUnits + n // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { numUnits += n ; }

81 81 Equal implemented as a member function Boolean JarType :: Equal ( /* in */ JarType otherJar ) const // POST: FCTVAL == (This jar and otherJar contain // the same number of units) { return ( numUnits == otherJar.numUnits ) ; } // CLIENT CODE( mainprog.cpp )... if ( myJar.Equal ( anotherJar ) )// uses dot notation.

82 82 friend functions A friend is a specially-designated function that is not a member of a class, but still can access the class private data members for its parameters. The function must be declared to be a friend in the class declaration (specification file) in the function prototype. The client does not use the dot operator to invoke the friend function. A friend function is considered part of the public interface.

83 // SPECIFICATION FILE( jar2.h ) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class JarType { public : // 4 public function members void Add ( /* in */ int n ) ; int Quantity ( ) const ; JarType ( /* in */ int n ) ; // 2 constructors JarType ( ) ; friend Boolean Equal ( /* in */ JarType firstJar, /* in */ JarType secondJar ) ; private : int numUnits ; } ;

84 84 Equal implemented as a friend function Boolean Equal ( /* in */ JarType firstJar, /* in */ JarType secondJar ) // POST: FCTVAL == ( firstJar and secondJar contain // the same number of units) { return ( firstJar.numUnits == secondJar.numUnits ) ; } // CLIENT CODE( mainprog.cpp )... if ( Equal ( myJar, anotherJar ) ) // NO dot notation used.

85 85 Aside from. and = Other operators like +, -, ==, * cannot be used by a class unless they are first defined as either member functions or friends of the class. The name of the function defining == must be operator == The name of the function defining + must be operator +

86 86 Operator overloading means the operator has different meanings for different types of operands. You can overload any existing C++ operator for a class except sizeof ?: ::. To overload an operator, say +, for a class, you need to define a member function, or a friend function, named operator+

87 // SPECIFICATION FILE( jar3.h ) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class JarType { public : // 5 public function members void Add ( /* in */ int n ) ; int Quantity ( ) const ; JarType ( /* in */ int n ) ; // 2 constructors JarType ( ) ;// overloaded operator Boolean operator== ( /* in */ JarType otherJar ) const ; private : int numUnits ; } ;

88 88 operator== implemented as a member function Boolean JarType::operator== ( /* in */ JarType otherJar ) const // POST: FCTVAL == ( This Jar and otherJar contain // the same number of units) { return ( numUnits == otherJar.numUnits ) ; } // CLIENT CODE( mainprog.cpp )... if ( myJar == anotherJar )// uses familiar notation.

89 // SPECIFICATION FILE( jar3.h ) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - class JarType { public : // 6 public function members void Add ( /* in */ int n ) ; int Quantity ( ) const ; JarType ( /* in */ int n ) ; // 2 constructors JarType ( ) ;// overloaded operators Boolean operator== ( /* in */ JarType otherJar ) const ; JarType operator+ ( /* in */ JarType otherJar ) const ; private : int numUnits ; } ;

90 90 operator+ implemented as a member function JarType JarType :: operator+ ( /* in */ JarType otherJar ) const // POST: FCTVAL == this Jar + otherJar // with combined number of units { int resultUnits = numUnits + otherJar.numUnits ; JarType resultJar (resultUnits) ; // invokes constructor return resultJar ; }

91 91 2 ways to use overloaded operator+ // CLIENT CODE( mainprog.cpp )... JarType myJar ( 10 ) ; JarType yourJar ( 56 ) ; JarType thirdJar ; thirdJar = myJar + yourJar ; // uses familiar notation OR USE thirdJar = myJar.operator+ (yourJar) ; // member notation


Download ppt "1 Data Structures and Algorithms Week 3 Data Abstraction: Part II Structured Types, and Classes."

Similar presentations


Ads by Google