logistics
play

Logistics Project IOStreams III Part 2 (water) due Sunday, Oct 16 - PDF document

Logistics Project IOStreams III Part 2 (water) due Sunday, Oct 16 th Feedback by Monday Part 3 (block) due Sunday, Oct 30 Inserters and Extractors, Questions? Manipulators, and friends Exam Exam 2 Exam 2 What


  1. Logistics • Project IOStreams III – Part 2 (water) due Sunday, Oct 16 th • Feedback by Monday – Part 3 (block) due Sunday, Oct 30 Inserters and Extractors, • Questions? Manipulators, and friends Exam Exam 2 • Exam 2 • What it will cover – Thursday, October 27. – C++ classes • constructors • Inheritance • Operator overloading – Review Session – Templates • Tuesday, Oct 25 th / 9-10am (70-3435) – STL • Wednesday, Oct 26 th / 8-9pm (70-3445) – Memory Management Logistics Plan for this week • Final exam • I/O Week – Good news…bad news – Today: IOStreams 1 – Good news – Tomorrow: IOStreams 2 • Last day of finals, November 18 th – Thursday: IOStreams 3 – Bad news • Friends • 8am-10am • Review of inserters/extractors • Manipulators (FYI) – Room • 01-3338 1

  2. IOStream Class Hierarchy Insertion and Extraction • Recall: – Insertion and Extraction is the standard means for writing / reading data and objects to / from text form. • Insertion (output) – operator<< • Extraction (input) – operator>> int i = 5; cout << i; cin >> i; Insertion and Extraction Insertion and Extraction int i=5; • Inserters and extractors for built-in datatypes (like int, double, float , double d = 7.0; etc.) are predefined member functions of the myClass foo (7); IOStream classes. • It would be nice if we can do I/O on objects cout << i << d << foo; of our own classes in the same manner as the basic datatypes. Insertion and Extraction Insertion and Extraction Signature • Since the operators are being defined • We can do so by overloading the outside of a class, the operator will take the operator>> and operator<< for our classes. 2-argument form: istream & operator>> (istream &is, myClass& m); • Note: these operators must be defined ostream & operator<< (ostream &os, myClass& outside of any class. m); Very often, these operators will need access to private members of myClass thus are usually declared as friend . Note that the operators return a reference to the stream acted upon. 2

  3. Sidebar: friend Example • By using friend , a class can grant access to class date { non-member functions or to another class. public: date (int d, int m, int y); • Friend functions can be declared anywhere within date(); a class declaration, but it is common practice to private: int day; list friends at the beginning of the class. int month; int year; • The public and protected keywords do not apply to friend functions friend istream &operator>> (istream& is, date& d); friend ostream &operator<< (ostream& os, date &d); }; Using existing operators Friends and inheritance • The simplest approach is to decompose your class • You cannot have virtual friend into a set of objects/variables that have inserters functions. and extractors defined. friend istream &operator>> (istream& is, date& d) { is >> d.day >> d.month >> d.year; return is; } friend ostream &operator<< (ostream& os, date &d) { os << d.day << ‘ ‘ << d.month << ‘ ‘ << d.year; return os; } This is why operators are declared as friends Friends and inheritance Friends and inheritance class Performer Musician M (“Ringo”) { public: cout << “Info on the drummer for the Beatles: “ << M; Performer (char *name, char *talent); virtual void calculatePay(); friend ostream &operator<< (ostream& os, Performer &P) Calls operator<< (ostream& os, Performer &P) } class Musician : public Performer displays only Performer data. { public: Musician (char *name); void calculatePay(); } 3

  4. Friends and inheritance Friends and inheritance class Performer ostream &operator<< (ostream& os, Performer &P) { { public: return P.display (os); Performer (char *name, char *talent); } virtual void calculatePay(); virtual ostream &display(ostream &out); Musician M (“Ringo”) friend ostream &operator<< (ostream& os, Performer &P) cout << “Info on the drummer for the Beatles: “ << M; } class Musician : public Performer { Calls operator<< (ostream& os, Performer &P) public: Musician (char *name); calls Musician::display void calculatePay(); displays only Musician data. virtual ostream &display(ostream &out); } Friend classes Friend classes // Forward declaration of friend class. • A class can declare a member function of class PointCollection; another class as a friend // Point class. class Point • A class can declare an entire other class as a { friend PointCollection; friend. public: Point(const double x, const double y); ~CPoint(void) • Useful where one class is tightly coupled to // ... another class. private: double x; double y; }; Friend classes Friend classes void PointCollection::set(const double x, const • Friendship is not mutual double y) { // Get the number of elements in the void Point::illegallyAccessCollection (PointCollection collection. PC, int i) const int nElements = vecPoints.size(); { cout << “Point “ << i << “ is “<< // Set each element. PC.vecPoints[i]; for(int i=0; i<nElements; i++) } { vecPoints[i].x = x; vecPoints[i].y = y; } } 4

  5. Friend classes Friends • Friendship is not transitive • Questions? – Will not travel down class heirarchy // Forward declaration of friend class. class PointCollection; // Point class. class Point { friend PointCollection; // subclasses of PointCollection cannot access // Point’s data members public: Point(const double x, const double y); ~CPoint(void) // ... private: double x; double y; }; Using existing operators Writing an inserter ( operator<< ) • Good safety tip: 1. The first argument should be a reference to an ostream . The second argument should be a constant – It is usually a good idea to make extraction and reference to your class. insertion complementary operations. The function should return a reference to an ostream 2. so that insertions can be chained. – Thus, 3. The body of the function should perform whatever date d (10, 10, 2003); output is appropriate for your class, but nothing more! date dd; 4. If you need to access the private data members of your cout << d; class directly, then your class must declare this function cin >> dd; to be a friend // dd == d Writing an inserter ( operator<< ) Writing an extractor ( operator>> ) friend ostream &operator<<( ostream &out, const • Like inserter except: Point &p ) – Must handle possible errors { out << ’(’ << p.x << ’,’ << p.y << ’)’; – Argument cannot be const reference. return out; – Almost surely will have to declare as a } friend . Output: (0,0) 5

  6. Writing an extractor ( operator>> ) Writing an extractor ( operator>> ) friend istream &operator>> (istream &in, Point &p) • Things to note: { char c; – Checks to see if in same format as output. int ok = FALSE; – Stops reading as soon as an error is found. in >> c; if (c == ‘(‘)) { – Sets failbit if format is not correct. in >> p.x >> c; if (c == ‘,’) { in >> p.y >> c; if (c == ‘)’) ok = TRUE; } } • Questions? if (!ok) in.clear (in.rdstate() | ios::failbit return in; } Inserters / Extractors Manipulators • Questions • What’s the deal with manipulators? cout << setw(5) << setfill (‘0’) << 345; How does C++ know what to do with setw and set_fill Manipulators Manipulators • The iostreams have a version of operator<< • Example: and operator>> that take a function pointer – cout << flush as an argument: – Note that there is a non-member function ostream & operator<< (ostream& (*f)(ostream&)) { return (*f)(*this); } ostream & flush (ostream& os) { return os.flush(); } 6

  7. Manipulators Manipulators When the compiler sees: • Let’s kick it up a notch cout << flush; It will convert to cout.operator<< (flush); • What if your manipulator takes arguments? cout << setw(5) << 123; Which will call flush (cout) Which will result in There is no operator<< with a function pointer cout.flush(); and an argument And all this is done at compile time!! Manipulators Manipulator class smanip • functor!!! { public: ostream & (*f) (ostream &os, int); // function to call int intarg; // integer argument • Recall: what differentiates functors from smanip (ostream & (*ff)(ostream&, int), int ii) : pointers to function is that functors are f (ff), intarg(ii) {} ostream& operator(ostream &os) { return (*f)(os, intarg); objects } } – They can retain state. ostream& operator<< (ostream& os, smanip& sm) { return sm(os); } Manipulator Manipulator When the compiler sees: • Assume there is a non-member function cout << setw(5); It will convert to ostream & setw (ostream& os, int w) //lets call smanip (setw, 5), setsm cout << smanip (setw, 5); { then cout.operator<< (setsm); return os.width(w); Which will call } setsm(cout); Which will result in setw(os, 5) smanip setw(int i) Which will call { os.setw(5); return smanip(setw, i); And all this is done at compile time!! } 7

Recommend


More recommend