570 likes | 821 Views
Abstract Data Types (ADTs). by Briana Morrison adapted from Dale/Weems/Headington and Cahoon/Davidson. Topics. Abstraction Abstract Data Types (ADTs) Separate Compilation Rational Class Overloading Operators Member function vs. non-member function Good ADTs Namespaces.
E N D
Abstract Data Types (ADTs) by Briana Morrison adapted from Dale/Weems/Headington and Cahoon/Davidson
Topics • Abstraction • Abstract Data Types (ADTs) • Separate Compilation • Rational Class • Overloading Operators • Member function vs. non-member function • Good ADTs • Namespaces
Abstraction • is the separation of the essential qualities of an object from the details of how it works or is composed • focuses on what, not how • is necessary for managing large, complex software projects
Control Abstraction • separates the logical properties of an action from its implementation . . . Search (list, item, length, where, found); . . . • the function call depends on the function’s specification (description), not its implementation (algorithm)
Data Abstraction • separates the logical properties of a data type from its implementation LOGICAL PROPERTIES IMPLEMENTATION What are the possible values? How can this be done in C++? What operations will be needed? How can data types be used?
Data Type set of values (domain) allowable operations on those values FOR EXAMPLE, data type int has operations +, -, *, /, %, >>, << domain -32768 . . . 32767
Abstract Data Type (ADT) • a data type whose properties (domain and operations) are specified (what) independently of any particular implementation (how) FOR EXAMPLE . . .
ADT Specification Example TYPE TimeType DOMAIN Each TimeType 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
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
ADT Implementation means • choosing a specific data representation for the abstract data using data types that already exist (built-in or programmer-defined) • writing functions for each allowable operation
“10” “45” “27” 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
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 ; bool Equal ( TimeType otherTime ) const ; bool LessThan (TimeType otherTime ) const ; private : // 3 private data members int hrs ; int mins ; int secs ; } ;
TimeType Class Instance Diagrams currentTime endTime Set Set Private data: hrs mins secs Private data: hrs mins secs Increment Increment 18 30 0 17 58 2 Write Write LessThan LessThan Equal Equal
Client Code UsingTimeType #include “timetype.h” // includes specification of the class using namespace std ; int main ( ) { TimeType currentTime ; // declares 2 objects of TimeType TimeType endTime ; bool done = false ; currentTime.Set ( 5, 30, 0 ) ; endTime.Set ( 18, 30, 0 ) ; while ( ! done ) { . . . currentTime.Increment ( ) ; if ( currentTime.Equal ( endTime ) ) done = true ; } ; }
Implementation File for TimeType // IMPLEMENTATION FILE ( timetype.cpp ) // Implements the TimeType member functions. #include “ timetype.h” // also must appear in client code #include <iostream> . . . bool TimeType :: Equal ( /* in */ TimeType otherTime ) const // Postcondition: // Function value == true, if this time equals otherTime // == false , otherwise { return ( (hrs == otherTime.hrs) && (mins == otherTime.mins) && (secs == otherTime.secs) ) ; } . . .
timetype.h client.cpp timetype.cpp client.obj timetype.obj client.exe Separate Compilation and Linking of Files specification file main program implementation file #include “timetype.h” Compiler Compiler Linker
Avoiding Multiple Inclusion of Header Files • often several program files use the same header file containing typedef statements, constants, or class type declarations--but, it is a compile-time error to define the same identifier twice • this preprocessor directive syntax is used to avoid the compilation error that would otherwise occur from multiple uses of #include for the same header file #ifndef Preprocessor_Identifier #define Preprocessor_Identifier . . . #endif
Example Using Preprocessor Directive #ifndef // timetype .h FOR COMPILATION THE CLASS DECLARATION IN // SPECIFICATION FILE FILE timetype.h WILL BE INCLUDED ONLY ONCE #ifndef TIME_H #define TIME_H // timetype .cpp // client.cpp // IMPLEMENTATION FILE // Appointment program class TimeType { #include “timetype.h” #include “timetype.h” public: . . .. . . int main ( void ) { private: . . . . . . } } ; #endif
Rational Abstract Data Type • Consider Rational a(1,2); // a = 1/2 Rational b(2,3); // b = 2/3 cout << a << " + " << b << " = " << a + b; Rational s; // s = 0/1 cin >> s; cout << s << " * " << a << " = " << s * a; if (s == b) cout << “Equal” << endl; • Observation • Natural look that is analogous to fundamental-type arithmetic objects
Multiplication Division Rational number Ratio of two integers: a/b Numerator over the denominator Standard operations Addition Subtraction Rational Number Review
Rational Number Representation • Requirements • Represent a numerator and denominator • Implies in part a class representation with two int data members • NumeratorValue and DenominatorValue • Data members private to support information hiding • Public arithmetic behaviors (member functions) • Rational addition, multiplication and equality • Public relational behaviors • Equality and less than comparisons • Practice rule of class minimality
Rational Number Representation • Other requirements • Public object behaviors • Construction • Default construction • Specific numerator and denominator construction • Assignment (provided automatically) • Value reading and printing • Inspection/accessors and mutation of data members • Clients deal with a Rational object!
Rational Number Representation • Other requirements • Auxiliary operations (necessarily public) • Arithmetic, relational, reading, and printing operations • Provides the natural form we expect • Class definition provides a functional form that auxiliary operators use • Provides commutativity consistency • For C++ reasons 1 + r and r + 1 would not be treated the same if addition was a member operation
Rational Class Instance Diagrams a b SetNumerator SetNumerator Add Add SetDenominator SetDenominator Multiply Multiply Private data: Numerator value Denominator value Private data: Numerator value Denominator value Print Print 2 3 1 2 Read Read LessThan LessThan Equal Equal Numerator Numerator Denominator Denominator
Consider Rational r, s, Sum, Product; // requires default constructor cout << "Enter two rationals(a/b): " << endl; cin >> r >> s; // need I/O operations Sum = r + s; // need arithmetic operators Product = r * s; cout << r << " + " << s << " = " << Sum; cout << r << " * " << s << " = " << Product;
Class Rational Overview class Rational { public: // for everybody including clients // for Rational member functions private: // for hidden Rational memberfunctions // for Rational data members } ;
Rational Private Section private: // data members int NumeratorValue; int DenominatorValue;
Class Rational Interface public: // default constructor Rational(); // specific constructor Rational(int numer, int denom = 1); // second argument is defaulted if not supplied // arithmetic facilitators Rational Add (const Rational &r) const; Rational Multiply (const Rational &r) const; bool Equal (const Rational &r) const;
Class Rational Interface Cont. public cont. // stream facilitators void Print (ostream &sout) const; void Read (istream &sin); // inspectors int Numerator ( ) const; int Denominator ( ) const; // mutators void SetNumerator (int numer); void SetDenominator (int denom); };
Auxiliary Operator Prototyping //after the class definition in rational.h Rational operator+ (const Rational &r, const Rational &s); Rational operator* (const Rational &r, const Rational &s); Rational operator== (const Rational &r, const Rational &s); ostream& operator<< (ostream &sout, const Rational &s); istream& operator>> (istream &sin, Rational &r);
Rational r; Rational s; r.Read (cin); s.Read (cin); Rational t = r.Add (s); t.Print (cout); Rational r; Rational s; cin >> r; cin >> s; Rational t = r + s; cout << t; Natural look Should << be a member? Consider r << cout; Why Non-Member Operators
Const Power const Rational OneHalf (1,2); cout << OneHalf; // legal cin >> OneHalf; // illegal
Remember • Every class object • Has its own data members • Has its own member functions • When a member function accesses a data member • By default the function accesses the data member of the object to which it belongs! • No special notation needed • Auxiliary functions • Are not class members • To access a public member of an object, an auxiliary function must use the dot operator on the desired object object.member
Rational ADT Implementation #include <iostream> using namespace std; // default constructor Rational::Rational ( ) { SetNumerator (0); SetDenominator (1); } • Example Rational r; // r = 0/1 Which objects arebeing referenced?
Specific Constructor // (numer, denom) constructor Rational::Rational (int numer, int denom) { SetNumerator (numer); SetDenominator (denom); } • Example Rational u(2); // u = 2/1 (why?) Rational t(2,3); // t = 2/3 // we’ll be using t in future examples
Accessors / Inspectors int Rational::Numerator ( ) const { return NumeratorValue; } int Rational::Denominator ( ) const { return DenominatorValue; } • Where are the following legal? int a = Numerator ( ); int b = t.Numerator ( ); Which object isbeing referenced? Why the const?
Numerator Mutator void Rational::SetNumerator (int numer) { NumeratorValue = numer; } • Where are the following legal? SetNumerator (1); t.SetNumerator (2); Why no const?
Denominator Mutator void Rational::SetDenominator (int denom) { if (denom != 0) DenominatorValue = denom; else { cerr << "Illegal denominator: " << denom << "using 1" << endl; DenominatorValue = 1; } } • Example SetDenominator (5);
Addition Facilitator Rational Rational::Add (const Rational &r) const { int a, b, c, d; a = Numerator ( ); b = Denominator ( ); c = r.Numerator ( ); d = r.Denominator ( ); return Rational (a*d + b*c, b*d); } • Example cout << t.Add (u);
Multiplication Facilitator Rational Rational::Multiply(const Rational &r) const { int a, b, c, d; a = Numerator ( ); b = Denominator ( ); c = r.Numerator ( ); d = r.Denominator ( ); return Rational (a*c, b*d); } • Example t.Multiply (u);
Equality Facilitator bool Rational::Equal (const Rational &r) const { int a, b, c, d; a = Numerator ( ); b = Denominator ( ); c = r.Numerator ( ); d = r.Denominator ( ); return (a*d == b*c); } • Example t.Equal (u);
Print Facilitator void Rational::Print (ostream &sout) const { sout << Numerator ( ) << '/' << Denominator ( ); return; } • Example t.Print (cout); • Why is sout a reference parameter?
Basic Read Facilitator void Rational::Read (istream &sin) { int numer; int denom; char slash; sin >> numer >> slash >> denom; SetNumerator (numer); SetDenominator (denom); return; } • Example t.Read (cin);
Auxiliary Arithmetic Operators Rational operator+ (const Rational &r, const Rational &s) { return r.Add (s); } Rational operator* (const Rational &r, const Rational &s) { return r.Multiply (s); } • Example cout << (t + t) * t;
Auxiliary Equality Operator bool operator== (const Rational &r, const Rational &s) { return r.Equal (s); } • Example if (s == t) cout << “Equal” <<endl;
Auxiliary Output Operator ostream& operator<< (ostream &sout, const Rational &r) { r.Print (sout); return sout; } • Why a reference return? • Note we can do either t.Print (cout); cout << endl;// unnatural cout << t << endl;// natural
Auxiliary Input Operator istream& operator>> (istream &sin, Rational &r) { r.Read (sin); return sin; } • Why a reference return? • We can do either t.Read (cin); // unnatural cin >> t; // natural
Overloading Operators Rules 1. At least one argument must be of class type 2. May be a friend function 3. Cannot create a new operator 4. Cannot change the number of arguments for operator 5. Cannot change the precedence of operator 6. Cannot overload the following operators: • . (member selector) • :: (scope resolution) • .* (member indirection) • ?: (conditional if)
Separate Compilation Components • Header file • Define class and prototype library functions • rational.h • Rational class implementation • Define member functions • rational.cpp • Auxiliary function implementations • Define assisting functions that provide expected but non-member capabilities • rational.cpp • Usage or Application File • Contains main()
Rational ADT Header File • File layout • Class definition and library prototypes nested within preprocessor statements • Ensures one inclusion per translation unit • Class definition proceeds library prototypes #ifndef RATIONAL_H #define RATIONAL_H class Rational { // … }; // library prototypes …