CHAPTER 7 Implementing abstract data types 抽象数据类型实现 Introduction A data abstraction is a representation of information and the operations to be performed on the information. An abstract data type, or ADT, is a well- defined and complete data abstraction that uses the information-hiding principle. ADTs make it possible to create and manipulate objects in a natural manner. 数据抽象就是对信息表达并对信息执行的操作。抽象数据类型 (ADT) 按照信息屏蔽的原则,对数据抽象作意义明确完整的定义。 ADT 允许 用自然的方法创建和管理对象。
Fundamental-type 基本数据类型 Data abstraction 数据抽象 Information-hiding 信息隐蔽 Abstract data type(ADT) 抽象数据类型 7.1 INTRODUCING ABSTRACT DATA TYPES 抽象数据类型简介 Example, an Rational ADT : Rational a ( 1, 2 ) ;// a = 1 / 2 Rational b ( 2, 3 ) ;// b = 2 / 3 cout << a << “+” << b << “=” << ( a + b) << endl ;
Our goal in developing Rational is to create a type whose objects are as natural to use as objects defined using the fundamental types. 7.2 RATIONAL ADT BASICS 有理数 Rational ADT 的基础 The basic arithmetic operations : Addition: Subtraction: Mulitiplication: Division:
Data members: numerator int object denominator int object Member functions: Construct the rational number with default or particular attributes. Add, subtract, multiply, and divide the rational number to another rational number. Copy the value of the rational number to another rational number. Compare the rational number to another rational number. Display the value of the rational number. Extract the value of the rational number. Inspect the values of the numerator and the denominator. Set the values of the numerator and the denominator. Class Rational
This rule states that unless a behavior is needed, it should not be part of the ADT. A corollary to the rule of minimality is the class minimality principle. Rule minimality ( 最小化规则 )
// Program 8.1 Demonstrate Rational ADT #include #include "rational.h" using namespace std ; int main() { Rational r, s ; cout > r ; cout > s ; Rational t ( r ) ; Rational Sum = r + s ; Rational Product = r * s ; cout << r << " + " << s << " = " << Sum << endl ; cout << r << " * " << s << " = " << Product << endl ; return 0; } A client program using the rational library
// Program 8.1 Demonstrate Rational ADT #include #include "rational.h" using namespace std ; int main() { Rational r, s ; cout > r ; cout > s ; Rational t ( r ) ; Rational Sum = r + s ; Rational Product = r * s ; cout << r << " + " << s << " = " << Sum << endl ; cout << r << " * " << s << " = " << Product << endl ; return 0; } A client program using the rational library Use the default constructor for the class Rational
// Program 8.1 Demonstrate Rational ADT #include #include "rational.h" using namespace std ; int main() { Rational r, s ; cout > r ; cout > s ; Rational t ( r ) ; Rational Sum = r + s ; Rational Product = r * s ; cout << r << " + " << s << " = " << Sum << endl ; cout << r << " * " << s << " = " << Product << endl ; return 0; } A client program using the rational library Use the copy constructor to create a new object.
// Program 8.1 Demonstrate Rational ADT #include #include "rational.h" using namespace std ; int main() { Rational r, s ; cout > r ; cout > s ; Rational t ( r ) ; Rational Sum = r + s ; Rational Product = r * s ; cout << r << " + " << s << " = " << Sum << endl ; cout << r << " * " << s << " = " << Product << endl ; return 0; } A client program using the rational library copy constructor The copy constructor has a single constant reference parameter. The copy constructor is always present : It can be specified by designer or is automatically supplied by the compiler. copy constructor The copy constructor has a single constant reference parameter. The copy constructor is always present : It can be specified by designer or is automatically supplied by the compiler.
// Program 8.1 Demonstrate Rational ADT #include #include "rational.h" using namespace std ; int main() { Rational r, s ; cout > r ; cout > s ; Rational t ( r ) ; Rational Sum = r + s ; Rational Product = r * s ; cout << r << " + " << s << " = " << Sum << endl ; cout << r << " * " << s << " = " << Product << endl ; return 0; } A client program using the rational library They use the copy constructor too.
// Program 8.1 Demonstrate Rational ADT #include #include "rational.h" using namespace std ; int main() { Rational r, s ; cout > r ; cout > s ; Rational t ( r ) ; Rational Sum = r + s ; Rational Product = r * s ; cout << r << " + " << s << " = " << Sum << endl ; cout << r << " * " << s << " = " << Product << endl ; return 0; } A client program using the rational library Supply initialization parameters: The parameter list. The initialization expression. Supply initialization parameters: The parameter list. The initialization expression.
// Program 8.1 Demonstrate Rational ADT #include #include "rational.h" using namespace std ; int main() { Rational r, s ; cout > r ; cout > s ; Rational t ( r ) ; Rational Sum = r + s ; Rational Product = r * s ; cout << r << " + " << s << " = " << Sum << endl ; cout << r << " * " << s << " = " << Product << endl ; return 0; } A client program using the rational library Overloaded operators
Assignment operator and copy construction Rational v ( 6, 21 ) ;// v is 6 / 21 Rational w ;// w is 0 / 1 w = v ;// w is 6 / 21 by assignment Rational x = v ;// x is 6 / 21 by copy construction A client program using the rational library Overloaded construction Rational x ( 3, 4 ) ;// v is 3 / 4 Rational y ( 5 ) ;// y is 5 / 1
const object // the data members can not be modified const Rational OneHalf ( 1, 2 ) ; A client program using the rational library Overloaded operators >> and > and << Rational r ; cout << "Enter rational number (a/b): " ; cin >> r ; cout << r ;
const object // the data members can not be modified const Rational OneHalf ( 1, 2 ) ; A client program using the rational library Overloaded operators >> and > and << Rational r ; cout << "Enter rational number (a/b): " ; cin >> r ; cout << r ; If operator >> (or <<) is overloaded to be a member function, left operand must be an object of Rational type : operator >> Rational :: istream & operator >> ( istream &sin ) ; operator << Rational :: ostream & operator << ( ostream &sout ) ; r >> cin ; r << cout ; If they overloaded to be common function or friend function, we are free to define their left and right operands. operator >> istream & operator >> ( istream &sin, const Rational &r ) ; operator << ostream & operator << ( ostream &sout, const Rational &r ) ; cin >> r ; cout << r ; If operator >> (or <<) is overloaded to be a member function, left operand must be an object of Rational type : operator >> Rational :: istream & operator >> ( istream &sin ) ; operator << Rational :: ostream & operator << ( ostream &sout ) ; r >> cin ; r << cout ; If they overloaded to be common function or friend function, we are free to define their left and right operands. operator >> istream & operator >> ( istream &sin, const Rational &r ) ; operator << ostream & operator << ( ostream &sout, const Rational &r ) ; cin >> r ; cout << r ;
7.2.1 A client program using the rational library Operators +, * are overloaded to be common function or friend function Member function operator + Rational :: Rational operator + ( const Rational &r ) ; Rational u ( 3, 4 ), t ; t = u + 2 ;// OK t = 2 + u ; t = 2 + u ;// Error Common function or friend function operator + Rational operator + ( const Rational &r, const Rational &s ) ; t = u + 2 ;// OK t = 2 + u ;// OK Function name
// rational.h: declaration of Rational ADT #ifndef RATIONAL_H #define RATIONAL_H #include using namespace std; // … #endif 7.3 RATIONAL INTERFACE DESCRIPTION
// Rational ADT: class description class Rational { public: Rational(); // member functions default constructor Rational(int numer, int denom = 1); // a second constructor // some arithmetic and stream facilitators Rational Add(const Rational &r) const; Rational Multiply(const Rational &r) const; void Insert(ostream &sout) const; void Extract(istream &sin); protected: // inspectors int GetNumerator() const; int GetDenominator() const; // mutators void SetNumerator(int numer); void SetDenominator(int denom); private: // data members int NumeratorValue; int DenominatorValue; };
// Rational ADT: auxiliary operator description 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); #endif
public can be directly used protected can be use by other member functions of the class and by member functions from a derived class. private can be use only by other member functions of the class Access restrictions 访问权限
The prototypes of the two Rational constructors Rational(); Rational(int numer, int denom = 1); Constructor member functions A copy constructor and a member assignment operator are defaulted, the Rational class uses the definitions provided by the compiler.
Member functions: Inspector functions (检查器) provide methods to access representations of the date member. Mutator functions (转变器) provide methods to modify the representations of the data members. Facilitator functions (简化器) provide methods for achieving the operations intended with the object Facilitator member functions 简化器
Rational Add ( const Rational &r ) const ; Rational Multiply ( const Rational &r ) const ; void Insert ( ostream &sout ) const ; void Extract ( istream &sin ) ; Facilitator member functions 简化器
const Rational Add ( const Rational &r ) const ; const Rational Multiply ( const Rational &r ) const ; const void Insert ( ostream &sout ) const ; void Extract ( istream &sin ) ; Facilitator member functions 简化器 Const member functions can not change any of the invoking object’s data member. Const member functions and operators can be used by const and non- const objects. Non-const member functions con not be used by const objects.
const Rational Add ( const Rational &r ) const ; const Rational Multiply ( const Rational &r ) const ; const void Insert ( ostream &sout ) const ; void Extract ( istream &sin ) ; Facilitator member functions 简化器 For example const Rational OneHalf ( 1, 2 ) ; OneHalf. Insert ( cout ) ; // legal OneHalf. Extract ( cin ) ; OneHalf. Extract ( cin ) ; // illegal, Extract() is not const member function
Use the four Rational facilitators Rational r ; Rational s ; cout << "Enter rational number (a/b): " ; r.Extract ( cin ) ; cout << "Enter rational number (a/b): " ; s.Extract ( cin ) ; Rational t ( r ) ; Rational Sum = r.Add (s) ; Rational Product = r.Multiply (s) ; r.Inseral ( cout ) ; cout << " + " ; s.Inseral ( cout ) ; cout << " = " ; s.Inseral ( cout ) ; cout << endl ; r.Inseral ( cout ) ; cout << " * " ; s.Inseral ( cout ) ; cout << " = " ; Product.Inseral ( cout ) ; cout << endl ;
Use the four Rational facilitators Rational r ; Rational s ; cout << "Enter rational number (a/b): " ; r.Extract ( cin ) ; cout << "Enter rational number (a/b): " ; s.Extract ( cin ) ; Rational t ( r ) ; Rational Sum = r.Add (s) ; Rational Product = r.Multiply (s) ; r.Inseral ( cout ) ; cout << " + " ; s.Inseral ( cout ) ; cout << " = " ; s.Inseral ( cout ) ; cout << endl ; r.Inseral ( cout ) ; cout << " * " ; s.Inseral ( cout ) ; cout << " = " ; Product.Inseral ( cout ) ; cout << endl ; use Overloaded operators use
Use the four Rational facilitators Rational r ; Rational s ; cout << "Enter rational number (a/b): " ; r.Extract ( cin ) ; cout << "Enter rational number (a/b): " ; s.Extract ( cin ) ; Rational t ( r ) ; Rational Sum = r.Add (s) ; Rational Product = r.Multiply (s) ; r.Inseral ( cout ) ; cout << " + " ; s.Inseral ( cout ) ; cout << " = " ; s.Inseral ( cout ) ; cout << endl ; r.Inseral ( cout ) ; cout << " * " ; s.Inseral ( cout ) ; cout << " = " ; Product.Inseral ( cout ) ; cout << endl ; cin >> r ; cin >> s ; Rational Sum = r + s; Rational Product = r * s; cout << r << " + " << s << " = " << Sum << endl; cout << r << " * " << s << " = " << Product << endl;
Use the four Rational facilitators Rational r ; Rational s ; cout << "Enter rational number (a/b): " ; r.Extract ( cin ) ;// cin >> r ; cout << "Enter rational number (a/b): " ; // cin >> s ; s.Extract ( cin ) ; // cin >> s ; Rational t ( r ) ; Rational Sum = r.Add (s) ;// Rational Sum = r + s; Rational Sum = r.Add (s) ; // Rational Sum = r + s; Rational Product = r.Multiply (s) ;// Rational Product = r * s; r.Inseral ( cout ) ; cout << " + " ; s.Inseral ( cout ) ; cout << " = " ; s.Inseral ( cout ) ; cout << endl ; // cout << r << " + " << s << " = " << Sum << endl; r.Inseral ( cout ) ; cout << " * " ; s.Inseral ( cout ) ; cout << " = " ; Product.Inseral ( cout ) ; cout << endl ; // cout << r << " * " << s << " = " << Product << endl;
protected: int GetNumerator() const; int GetDenominator() const; Inspector member function 检查器
protected: void SetNumerator(int numer); void SetDenominator(int denom); Mutator member function 转变器
private: int NumeratorValue ; int DenominatorValue ; Data member 数据成员
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); Overloaded operators 运算符重载 Overloaded operators are the same as their conventional precedence and calling form. ExerciseP423-12
SCOPE OPERATOR ( 作用域运算符 ) void Rational :: SetNumerator(int numer) { NumeratorValue = numer; } 7.4 IMPLEMENTING THE RATIONAL CLASS
// default constructor Rational::Rational() { SetNumerator(0); SetDenominator(1); } // (numer, denom) constructor Rational::Rational(int numer, int denom) { SetNumerator(numer); SetDenominator(denom); } Constructor definitions
// default constructor Rational::Rational() { SetNumerator(0); SetDenominator(1); } // (numer, denom) constructor Rational::Rational(int numer, int denom) { SetNumerator(numer); SetDenominator(denom); } Use member functions Constructor definitions
// default constructor Rational::Rational() { SetNumerator(0); SetDenominator(1); } // (numer, denom) constructor Rational::Rational(int numer, int denom) { SetNumerator(numer); SetDenominator(denom); } // default constructor Rational::Rational() { NumeratorValue = 0; DenominatorValue = 1; // (numer, denom) constructor Rational::Rational(int numer, int denom) { NumeratorValue = numer; if (denom != 0) DenominatorValue = denom; else DenominatorValue = 1; }
// get the numerator int Rational::GetNumerator() const { return NumeratorValue; } // get the denominator int Rational::GetDenominator() const { return DenominatorValue; } Inspector definitions
// set the numerator void Rational :: SetNumerator(int numer) { NumeratorValue = numer; } // set the denominator void Rational :: SetDenominator(int denom) { if (denom != 0) { DenominatorValue = denom; } else { cerr << "Illegal denominator: " << denom<< "using 1" << endl; DenominatorValue = 1; } Mutator definitions Exception handling
// adding Rationals Rational Rational::Add(const Rational &r) const { int a = GetNumerator(); int b = GetDenominator(); int c = r.GetNumerator(); int d = r.GetDenominator(); return Rational(a*d + b*c, b*d); } // multiplying Rationals Rational Rational::Multiply(const Rational &r) const { int a = GetNumerator(); int b = GetDenominator(); int c = r.GetNumerator(); int d = r.GetDenominator(); return Rational(a*c, b*d); } Arithmetic facilitator definitions Rational x ( 1, 2 ) ; Rational y ( 1, 3 ) ; Rational z = x. Add ( y ) ; // 1/2 + 1/3 is 5/6 cout << z <<endl; Rational x ( 1, 2 ) ; Rational y ( 1, 3 ) ; Rational z = x. Add ( y ) ; // 1/2 + 1/3 is 5/6 cout << z <<endl;
// inserting a Rational void Rational::Insert(ostream &sout) const { sout << GetNumerator() << '/' << GetDenominator(); return; } // extracting a Rational void Rational::Extract(istream &sin) { int numer; int denom; char slash; sin >> numer >> slash >> denom; SetNumerator(numer); SetDenominator(denom); return; } Insertion and extraction definitions Rational x ; x. Extract ( cin ) ; Rational y ( 1, 3 ) ; Rational z = x. Add ( y ) ; z. Insert ( cout ) ; Rational x ; x. Extract ( cin ) ; Rational y ( 1, 3 ) ; Rational z = x. Add ( y ) ; z. Insert ( cout ) ; Can you Output the value of x+y directly ? Can you Output the value of x+y directly ?
// adding Rationals Rational operator+(const Rational &r, const Rational &s) { r. Add ( s return r. Add ( s ) ;// is r + s } // multiplying Rationals Rational operator*(const Rational &r, const Rational &s) { r. Multiply ( s ) return r. Multiply ( s ) ;// is r * s } Auxiliary arithmetic operator definitions Rational x ; x. Extract ( cin ) ; Rational y ( 1, 3 ) ; x + y Rational z = x + y ; z. Insert ( cout ) ; Rational x ; x. Extract ( cin ) ; Rational y ( 1, 3 ) ; x + y Rational z = x + y ; z. Insert ( cout ) ;
// inserting a Rational ostream& operator<<(ostream &sout, const Rational &r) {r.Insert(sout); return sout; } // extracting a Rational istream& operator>>(istream &sin, Rational &r) {r.Extract(sin); return sin; } Auxiliary stream operator definitions Rational x ; cin >> x cin >> x ; Rational y ( 1, 3 ) ; x + y Rational z = x + y ; cout << z cout << z << endl ; Rational x ; cin >> x cin >> x ; Rational y ( 1, 3 ) ; x + y Rational z = x + y ; cout << z cout << z << endl ;
// Rational : copy constructor Rational :: Rational ( const Rational &r ) { int a = r. GetNumerator() ; inr b = r. GetDenominator() ; SetNumerator(a) ; SetDenominator(b) ; } // Rational destructor ~ Rational :: ~Rational ( ) { /* no body needed */ } 7.5 COPY CONSTRUCTION, MEMBER ASSIGNMENT, AND DESTRUCTION Shallow copying ( 浅拷贝 ) The source’s data members are copied bit by bit to the corresponding data members of the target. Shallow copying ( 浅拷贝 ) The source’s data members are copied bit by bit to the corresponding data members of the target.
// Rational : copy constructor Rational :: Rational ( const Rational &r ) { int a = r. GetNumerator() ; inr b = r. GetDenominator() ; SetNumerator(a) ; SetDenominator(b) ; } // Rational destructor ~ Rational :: ~Rational ( ) { /* no body needed */ } 7.5 COPY CONSTRUCTION, MEMBER ASSIGNMENT, AND DESTRUCTION Destructor Cannot take a parameter. Cannot produce a return value. A class to a single destructor.
// Rational : assignment operator Rational & Rational :: operator= ( const Rational &r ) { int a = r. GetNumerator() ; inr b = r. GetDenominator() ; SetNumerator(a) ; SetDenominator(b) ; *this return *this ; } 7.5 COPY CONSTRUCTION, MEMBER ASSIGNMENT, AND DESTRUCTION
this About this pointer this is a key word this is a address of the object whose member function is being invoked. this is imparted to the member function when is being invoked by system. Object. mf actual parameter ClassType :: mf formal parameter this
this About this pointer this is a key word this is a address of the object whose member function is being invoked. this is imparted to the member function when is being invoked by system. Object. mf actual parameter ClassType :: mf formal parameter this &Object DM: FM: DM: FM: Object &Object this * this Outside Inside Object *this Object.dm (*this).dm this->dm Object.fm (*this).fm this->fm
#include using namespace std; string s="w"; class C { public: C() //defual constructor { name=s; cout<<name<<": default constructed"<<endl; } C(const C &c) //copy constructor { name=s; cout<<name<<": copy constructor using "<<c.name<<endl; } ~C() // destructor { cout<<name<<": destructed "<<endl; } C & operator=(const C &c) // assignment { cout<<name<<": assigned using "<<c.name<<endl; return *this; } private: string name; //data member }; int main(){ C w;s="x"; C x; { s = "y" ; C y ; } s = "z" ; C z(w) ; x = w = z ; return 0 ; } w: default constructed x: default constructed y: default constructed y: destructed z : copy constructor using w w: assigned using z x : assigned using w z: destructed x: destructed w: destructed