Maskedbard.altervista.org



Advanced C++Northeastern State-of-the-ArtProgram COM5628Instructor: Dan LeachCourse materials copyright ? 2004 by Dan LeachAll rights reserved.dan.leach@alum.mit.eduRevision 1.24January, 2004 TOC \o "1-3" \h \z 1.Notes PAGEREF _Toc532646121 \h 1-11.1Language overview PAGEREF _Toc532646122 \h 1-11.1.1Keywords inherited from C PAGEREF _Toc532646123 \h 1-11.1.2Keywords new to C++ PAGEREF _Toc532646124 \h 1-21.2Hungarian Notation PAGEREF _Toc532646125 \h 1-41.3Other Coding Conventions PAGEREF _Toc532646126 \h 1-51.4Namespaces PAGEREF _Toc532646127 \h 1-61.5Operator overloading PAGEREF _Toc532646128 \h 1-81.5.1Interface to Complex class PAGEREF _Toc532646129 \h 1-81.5.2Implementation of Complex class PAGEREF _Toc532646130 \h 1-101.5.3Test program for Complex class PAGEREF _Toc532646131 \h 1-141.6Orthodox Canonical Form Idiom PAGEREF _Toc532646132 \h 1-221.6.1Interface to String class PAGEREF _Toc532646133 \h 1-221.6.2Implementation of String class PAGEREF _Toc532646134 \h 1-231.6.3Test program for String class PAGEREF _Toc532646135 \h 1-241.7Constructors, Destructors, and Assignment operators PAGEREF _Toc532646136 \h 1-261.7.1c_ds.cpp PAGEREF _Toc532646137 \h 1-271.7.2c_cds.cpp PAGEREF _Toc532646138 \h 1-291.7.3c_cdas.cpp PAGEREF _Toc532646139 \h 1-321.8Inheritance PAGEREF _Toc532646140 \h 1-361.9Virtual Functions PAGEREF _Toc532646141 \h 1-391.10Virtual Destructors PAGEREF _Toc532646142 \h 1-421.11Multiple Inheritance PAGEREF _Toc532646143 \h 1-461.11.1Simple multiple inheritance example PAGEREF _Toc532646144 \h 1-461.11.2Multiple inheritance example with a common ancestor PAGEREF _Toc532646145 \h 1-481.11.3Multiple inheritance example using virtual inheritance PAGEREF _Toc532646146 \h 1-521.12Cast operators PAGEREF _Toc532646147 \h 1-561.12.1C style casting PAGEREF _Toc532646148 \h 1-561.12.2static_cast PAGEREF _Toc532646149 \h 1-561.12.3dynamic_cast PAGEREF _Toc532646150 \h 1-561.12.4reinterpret_cast PAGEREF _Toc532646151 \h 1-561.12.5const_cast PAGEREF _Toc532646152 \h 1-561.13Handle/Body paradigm PAGEREF _Toc532646153 \h 1-571.13.1Complex - basic version PAGEREF _Toc532646154 \h 1-571.13.2Complex - handle/body version PAGEREF _Toc532646155 \h 1-601.13.3Complex - handle/body version with use counting PAGEREF _Toc532646156 \h 1-671.14Templates PAGEREF _Toc532646157 \h 1-731.14.1swap.h PAGEREF _Toc532646158 \h 1-731.14.2findex.h PAGEREF _Toc532646159 \h 1-731.14.3list.h PAGEREF _Toc532646160 \h 1-741.14.4fet.cpp PAGEREF _Toc532646161 \h 1-771.15STL Overview PAGEREF _Toc532646162 \h 1-801.15.1Containers PAGEREF _Toc532646163 \h 1-801.15.2Iterators PAGEREF _Toc532646164 \h 1-801.15.3Algorithms PAGEREF _Toc532646165 \h 1-811.15.4Functors PAGEREF _Toc532646166 \h 1-811.15.5Adaptors PAGEREF _Toc532646167 \h 1-811.16STL Container Examples PAGEREF _Toc532646168 \h 1-821.16.1reunion.txt PAGEREF _Toc532646169 \h 1-821.16.2listwrds.cpp PAGEREF _Toc532646170 \h 1-821.16.3answer.txt PAGEREF _Toc532646171 \h 1-841.16.4countw.cpp PAGEREF _Toc532646172 \h 1-851.16.5mapex.cpp PAGEREF _Toc532646173 \h 1-871.16.6mmex.cpp PAGEREF _Toc532646174 \h 1-881.16.7listex.cpp PAGEREF _Toc532646175 \h 1-901.16.8stackex.cpp PAGEREF _Toc532646176 \h 1-911.16.9dequeex.cpp PAGEREF _Toc532646177 \h 1-911.17A Larger Example of Using Containers in the STL PAGEREF _Toc532646178 \h 1-931.17.1graph.h PAGEREF _Toc532646179 \h 1-931.17.2shortest.h PAGEREF _Toc532646180 \h 1-971.17.3shorttst.cpp PAGEREF _Toc532646181 \h 1-1011.18Algorithms examples PAGEREF _Toc532646182 \h 1-1031.18.1vs.h PAGEREF _Toc532646183 \h 1-1031.18.2EX05-01.CPP PAGEREF _Toc532646184 \h 1-1031.18.3EX05-02.CPP PAGEREF _Toc532646185 \h 1-1041.18.4EX05-03.CPP PAGEREF _Toc532646186 \h 1-1041.18.5EX05-04.CPP PAGEREF _Toc532646187 \h 1-1051.18.6EX05-05.CPP PAGEREF _Toc532646188 \h 1-1051.18.7EX05-06.CPP PAGEREF _Toc532646189 \h 1-1061.18.8EX05-07.CPP PAGEREF _Toc532646190 \h 1-1071.18.9EX05-08.CPP PAGEREF _Toc532646191 \h 1-1071.18.10EX05-08A.CPP PAGEREF _Toc532646192 \h 1-1081.18.11EX05-09.CPP PAGEREF _Toc532646193 \h 1-1091.18.12EX05-10.CPP PAGEREF _Toc532646194 \h 1-1101.18.13EX05-11.CPP PAGEREF _Toc532646195 \h 1-1111.18.14EX05-12.CPP PAGEREF _Toc532646196 \h 1-1111.18.15EX05-13.CPP PAGEREF _Toc532646197 \h 1-1121.18.16EX05-14.CPP PAGEREF _Toc532646198 \h 1-1131.18.17EX05-15.CPP PAGEREF _Toc532646199 \h 1-1131.18.18EX05-16.CPP PAGEREF _Toc532646200 \h 1-1141.18.19EX05-17.CPP PAGEREF _Toc532646201 \h 1-1141.18.20EX05-18.CPP PAGEREF _Toc532646202 \h 1-1151.18.21EX05-19.CPP PAGEREF _Toc532646203 \h 1-1151.18.22EX05-20.CPP PAGEREF _Toc532646204 \h 1-1161.18.23EX05-21.CPP PAGEREF _Toc532646205 \h 1-1161.18.24EX05-22.CPP PAGEREF _Toc532646206 \h 1-1171.18.25EX05-23.CPP PAGEREF _Toc532646207 \h 1-1181.18.26EX05-24.CPP PAGEREF _Toc532646208 \h 1-1191.18.27EX05-25.CPP PAGEREF _Toc532646209 \h 1-1201.18.28EX05-26.CPP PAGEREF _Toc532646210 \h 1-1211.18.29EX05-27.CPP PAGEREF _Toc532646211 \h 1-1221.18.30EX05-28.CPP PAGEREF _Toc532646212 \h 1-1231.18.31EX05-29.CPP PAGEREF _Toc532646213 \h 1-1231.18.32EX05-30.CPP PAGEREF _Toc532646214 \h 1-1241.18.33EX05-31.CPP PAGEREF _Toc532646215 \h 1-1251.18.34EX05-32.CPP PAGEREF _Toc532646216 \h 1-1251.18.35EX05-33.CPP PAGEREF _Toc532646217 \h 1-1261.18.36EX05-34.CPP PAGEREF _Toc532646218 \h 1-1261.19String stream examples PAGEREF _Toc532646219 \h 1-1281.19.1iss.cpp PAGEREF _Toc532646220 \h 1-1281.19.2oss.cpp PAGEREF _Toc532646221 \h 1-1281.20Exceptions -- Overview PAGEREF _Toc532646222 \h 1-1291.21Basic Try-Catch-Throw Examples PAGEREF _Toc532646223 \h 1-1311.21.1tct1.cpp PAGEREF _Toc532646224 \h 1-1311.21.2tct2.cpp PAGEREF _Toc532646225 \h 1-1311.21.3tct3.cpp PAGEREF _Toc532646226 \h 1-1321.21.4tct4.cpp PAGEREF _Toc532646227 \h 1-1331.21.5tct5.cpp PAGEREF _Toc532646228 \h 1-1341.21.6tct6.cpp PAGEREF _Toc532646229 \h 1-1361.22SEH Examples PAGEREF _Toc532646230 \h 1-1391.22.1sehfin.cpp PAGEREF _Toc532646231 \h 1-1391.22.2sehfinzd.cpp PAGEREF _Toc532646232 \h 1-1391.22.3sehfilt.cpp PAGEREF _Toc532646233 \h 1-1401.22.4sehtct.cpp PAGEREF _Toc532646234 \h 1-1411.23Larger Try-Catch-Throw Example PAGEREF _Toc532646235 \h 1-1451.23.1queuet.h PAGEREF _Toc532646236 \h 1-1451.23.2queuett.cpp PAGEREF _Toc532646237 \h 1-1491.24Design Techniques PAGEREF _Toc532646238 \h 1-1541.24.1Waterfall Model PAGEREF _Toc532646239 \h 1-1541.24.2Object Oriented Design PAGEREF _Toc532646240 \h 1-1541.24.3CRC cards PAGEREF _Toc532646241 \h 1-1551.24.4Prototyping PAGEREF _Toc532646242 \h 1-1551.25Designing for Reuse PAGEREF _Toc532646243 \h 1-1571.25.1Anticipate Base Classes PAGEREF _Toc532646244 \h 1-1571.25.2Solve Problems in General PAGEREF _Toc532646245 \h 1-1571.25.3Consider a handle body design PAGEREF _Toc532646246 \h 1-1571.25.4Reusing the Design PAGEREF _Toc532646247 \h 1-1571.25.5Reusing the Code PAGEREF _Toc532646248 \h 1-1571.26Code Instrumentation PAGEREF _Toc532646249 \h 1-1581.26.1Debugging in engineering before releasing the product PAGEREF _Toc532646250 \h 1-1581.26.2Debugging in situ after releasing the product PAGEREF _Toc532646251 \h 1-1581.26.3Performance analysis PAGEREF _Toc532646252 \h 1-1591.26.4Determining testing coverage PAGEREF _Toc532646253 \h 1-1601.26.5Test drivers PAGEREF _Toc532646254 \h 1-1602.Homeworks for Advanced C++ PAGEREF _Toc532646255 \h 2-12.1Homework 1 PAGEREF _Toc532646256 \h 2-12.2Homework 2 PAGEREF _Toc532646257 \h 2-22.3Homework 3 PAGEREF _Toc532646258 \h 2-52.4Homework 4 PAGEREF _Toc532646259 \h 2-112.5Homework 5 PAGEREF _Toc532646260 \h 2-132.6Homework 6 PAGEREF _Toc532646261 \h 2-182.7Homework 7 PAGEREF _Toc532646262 \h 2-222.8Homework 8 PAGEREF _Toc532646263 \h 2-24NotesLanguage overviewKeywords inherited from CStorage allocation and name scopeautodefault; allocate variable on stack on entry to defining block and deallocate it on exit from the blockstaticallocate space for variable at the beginning of the program run and don't deallocate it until the end of the program run; at the module level, this has the effect of hiding the name from the global name scoperegisterkeep the indicated variable in a register if at all possible for its life; this request is not honored by newer compilers including Microsoft’s 32-bit compilersexterndon't allocate storage if data member (this can be applied to function names as well); the name tagged with this attribute is merely described here and is defined elsewhere either in this module or another moduleconstthe indicated variable is unchanged by the function or any functions it is passed to by this functionvolatilethe indicated variable may be changed by the OS or another thread; reload the variable each time its valueis requested rather than trying to optimize usageControl structuresif conditional executionelsewhat to do if the associated if was not trueswitchmultiway conditional execution; a selection statementcasea case within a selection statement (switch)defaultdescribes the else condition in a selection statement; switch will do nothing if a default is not present and none of the conditions are truecontinuestart the next iteration of the enclosing loopbreakexit the enclosing loop or case statementforiterative loop which describes both an initial step and an iterative step in addition to a termination condition and a body; termination condition is tested before execution of bodydomay be used with the while statement to describe a do-until situation; that is, the body is executed before testing the termination condition; sometimes called a test last loop structurewhileused to indicated a test in a loopgotowe won't use this four letter word in this coursereturnreturn from function; pass argument to caller if presentData typescharholds an ASCII characterdoubleholds a floating point number (usually twice the size of a normal float)enuman enumerated variablefloatholds a floating point numberintholds an integerlongholds an integer (usually twice the size of a normal int) shortholds an integer (usually half the size of a normal int) voiduntyped if applied to data; can also be used to indicate that there will be no value returned from a functionData attributessigneddefault; store a signed number in the indicated variableunsignedstore an unsigned number in the indicated variablestructaggregate data typetypedefdefine the indicated name as a data typeunionallocate storage associated with the largest of the specified members but allow that storage to be used in all specified waysBuilt in functionsizeofreturn the size of the indicated variable or data type (either basic or user defined) in bytesOtherasmused to indicate that assembler has been inserted inlineKeywords new to C++boolboolean data typetrue, falseconstant boolean valueswchar_twide character typethrowraise an exceptiontryindicates a block that may throw an exceptioncatchindicates a block which will handle an exceptionclassindicates a definition of an encapsulated user-defined data type (both data and functions to process that data)thisa pointer to the current instance of this classconstthis is not a new keyword but has other uses in C++const_cast,dynamic_cast,reinterpret_cast,static_cast new cast operatorsnewallocates storage for a type and calls the appropriate constructorsdeletereturns storage allocated by new; also calls destructorexplicitindicates that a constructor is not to be called implicitlyexportindicates that a symbol is to be made external from a libraryfriendindicates a function that may access private members that was not encapsulated with this classinlinedon’t generate a separate function for the indicated code; instead, treat it as a macro with its own namescope and generate object code for each use of it at the point of usemutableoverrides const nature of a member variablenamespacedefines a set of symbols to be used togetherusingused to indicate a namespace that will be treated as though it were part of the global namespace (symbols in it can be referenced without using the scope operatoroperatorindicates that a function is being defined whose name is a special character or sequence of special characters (e.g., ‘+’)privatemay only be used by this class and its friends; may also be used in a different way in inheritancepublicmay be used by all users of this class; may also be used in a different way in inheritanceprotectedmay only be used by this class, classes that use this class as a direct base, and friends; may also be used in a different way in inheritancevirtualindicates that a function may be replaced in classes that inherit from this class; can also be used to specify that only one class of the base type is be instantiated if there are multiple of the indicated basetemplateused to define generic codetypenameused in a template interface definition to indicate a generic typetypeidonly available when using the typeinfo header; allows you to determine other information about the type (generic or otherwise)Hungarian NotationBased on Short Course in Hungarian NotationIn general, Hungarian notation names a variable with a lower-case prefix to identify the class or usage of the variable. There is no such thing as standard HN, so the point here is to create a consistent notation system. In this class, we'll use the following standards. c: character uc: unsigned character i: integer ui: unsigned integer f: float d: double sz: string of characters, terminated by a null character b: Boolean value p: pointer to a structure or general void pointer px: pointer to a variable of class x, e.g. pi, pf, pStudent m_: member data, e.g., m_pSutdent, m_iUniqueIDThese prefixes are combined with an identifying name where each significant part begins with a capital letter: iUserChoice - holds the selection from a numeric menu cUserChoice - holds the selection from an alphabetic menu szFileName - a zero-terminated string with a file name in it pfsUnsortedNumbers - file pointer to a data file Function names (other than main) also follow this pattern of upper/lower case: ProcessRecord() GetUserChoice() HandleError() As the semester goes along, we may add more standard notations. If you find you need a variable that does not fit in these classes, create a new prefix and use it consistently.Other Coding ConventionsClass definitions should be in a separate header file (usually one per class).Similarly, implementation of classes should be in separate cpp files (usually one per class).Your test program should always be in a separate file from the class ment liberally. Each function other than accessor functions should start with a one line comment or short block comment explaining the function’s purpose. Major blocks of code (or even short blocks if you’re doing something that is less than obvious) within functions should contain similar comments.Names of both functions and variables should be descriptive. Non-descriptive variable names (especially one character variable names and variable names containing only one character and a number) should be used sparingly and only where it is obvious what their purpose is (such as counters, temporary storage, and certain input parameters to functions).Member variables should have the additional prefix “m_”. Examples:unsigned int m_uiLength;char * m_szString;CString m_strNameOfEmployee;String m_sNameOfCompany;int m_iOption;Member data should be “private” (“protected” will not be used in this class). Always use accessor functions to get and set member data outside of the class. Inside of the class, you may use either convention.Use const where appropriate. See item 21 in SM.NamespacesA namespace is used to define a set of symbols that are intended to be used together. Placing them together in a namespace allows you to keep them separate from those in other namespaces and from the global namespace. Namespace definitions may be spread across several namespace statements and hence across several files. The scope operator (::) is used to disambiguate between namespaces. If you wish to referenced the symbols as though they were part of the global namespace, you should use the ‘using’ statement. Note that several namespaces may be used at the same time. In the following example, two namespaces are used in main: std (that of the standard library) and CommVariables (which is defined local to this file).Example:// ns.cpp// example namespace#include <iostream>using namespace std;namespace CommVariables {enum DataBits { DATA_BITS_5 =5, DATA_BITS_6 =6, DATA_BITS_7 =7, DATA_BITS_8 =8};DataBits dbCurrent = DATA_BITS_8; enum StopBits { STOP_BITS_1 =1, STOP_BITS_1_5, STOP_BITS_2};StopBits sbCurrent = STOP_BITS_1; enum Parity { PARITY_ODD ='O', PARITY_EVEN ='E', PARITY_SPACE='S', PARITY_MARK ='M', PARITY_NONE ='N'};Parity parCurrent = PARITY_NONE;}CommVariables::StopBits sbStop = CommVariables::sbCurrent;int main(){cout << CommVariables::sbCurrent << endl;using namespace CommVariables;cout << sbCurrent << endl;return 0;}/* output:11*/There are two special namespaces: the global namespace and the unnamed (local) namespace. By default, symbols are placed in the global namespace if they are declared at the top level of a source file. This also means that they are known externally to the linker and may be used in other source modules. You would reference something in the global namespace by use of the scope operator if it became ambiguous (e.g., ::cout to reference the cout defined in iostream.h) The unnamed namespace is used to replace the function of suppressing membership in the global namespace previously only available by use of the ‘static’ keyword.Operator overloadingRules for overloading operators:(), [], ->, and = (in all forms) must be membersunary operators should generally be membersall others should be friend functions if implicit conversion is to be allowedInterface to Complex class// cxo.h// interface to Complex class// illustrates operator overloading#ifndef __cxo_h__#define __cxo_h__// NOTE: the following pragmas are specific to Microsoft// don't report warning that names are too long#pragma warning(disable:4786)// don't report warning that C++ Exception Specification ignored#pragma warning(disable:4290)#include <iostream>#include <string>#include <new>#include <typeinfo>using namespace std;// definition of Complex classclass Complex {public:// ctorComplex(double dReal = 0, double dImaginary = 0);// copy ctorComplex(const Complex& cx);// dtor~Complex();// assignment opsComplex& operator = (const Complex& cx);Complex& operator += (const Complex& cx);Complex& operator -= (const Complex& cx);// outputvoid Output(const char * szMessage) const;// ++ and -- opsComplex operator ++ ();Complex operator ++ (int);Complex operator -- ();Complex operator -- (int);// new opsvoid *operator new(size_t size) throw (bad_alloc);void *operator new[](size_t size) throw (bad_alloc);// delete opsvoid operator delete(void *pv);void operator delete[](void *pv);// accessorsinline double Real() const {return m_dReal;}inline double Imaginary() const {return m_dImaginary;}inline void SetReal(double dReal){m_dReal=dReal;}inline void SetImaginary(double dImaginary){m_dImaginary=dImaginary;}// call operatorComplex& operator()(double dReal, double dImaginary);// conversion operatoroperator double();// index operatordouble& operator[](int i);template <typename T>// , operatorT operator , (T t) const{cout << "in template Complex , op: " << typeid(t).name() << ":" << t << endl;return t;}private:double m_dReal;double m_dImaginary;};// global binary operatorsComplex operator + (const Complex& cx1, const Complex& cx2);Complex operator - (const Complex& cx1, const Complex& cx2);bool operator == (const Complex& cx1, const Complex& cx2);bool operator != (const Complex& cx1, const Complex& cx2);// << operatortemplate <typename OS>OS& operator << (OS& os, const Complex& cx){os << '(' << cx.Real() << ',' << cx.Imaginary() << ')';return os;}// >> operatortemplate<typename IS>IS& operator >> (IS& is, Complex& cx){char cTemp;double dTemp;is >> cTemp;is >> dTemp;cx.SetReal(dTemp);is >> cTemp;is >> dTemp;cx.SetImaginary(dTemp);is >> cTemp;return is;}#endifImplementation of Complex class// cxo.cpp// implementation of Complex class// illustrates operator overloading#include <iostream>#include <cmath>using namespace std;#include "cxo.h"// constructor from a pair of doublesComplex::Complex(double dReal, double dImaginary) : m_dReal(dReal), m_dImaginary(dImaginary){Output("Constructor");}// copy constructorComplex::Complex(const Complex& cx) : m_dReal(cx.m_dReal), m_dImaginary(cx.m_dImaginary){Output("Copy constructor");}// destructorComplex::~Complex(){Output("Destructor");}// = operatorComplex& Complex::operator =(const Complex& cx){if (this != &cx) {cx.Output("Assigning");m_dReal = cx.m_dReal;m_dImaginary = cx.m_dImaginary;}return *this;}// += operatorComplex& Complex::operator +=(const Complex& cx){*this = *this + cx;return *this;}// -= operatorComplex& Complex::operator -=(const Complex& cx){*this = *this - cx;return *this;}// call operatorComplex& Complex::operator()(double dReal, double dImaginary){cout << "in call op" << endl;m_dReal+=dReal;m_dImaginary*=dImaginary;Output("Leaving call op");return *this;}// conversion operatorComplex::operator double(){Output("in double conversion op");return sqrt(m_dReal*m_dReal + m_dImaginary*m_dImaginary);}// index operatordouble& Complex::operator[](int i){Output("in index op");if (i==0)return m_dReal;elsereturn m_dImaginary;}// output a Complex number and a messagevoid Complex::Output(const char * szMessage) const{cout<<szMessage<<':'<<*this<<endl;}// prefix ++ operatorComplex Complex::operator ++(){*this = *this + Complex(1,1);return *this;}// postfix ++ operatorComplex Complex::operator ++(int iUnused){Complex cx = *this;*this = *this + Complex(1,1);return cx;}// prefix -- operatorComplex Complex::operator --(){*this = *this - Complex(1,1);return *this;}// postfix -- operatorComplex Complex::operator --(int iUnused){Complex cx = *this;*this = *this - Complex(1,1);return cx;}// new overloaded relative to Complex.void *Complex::operator new(size_t size) throw(bad_alloc){void *pv;cout << "Allocating Complex object.\n";pv = malloc(size);// throw an exception on failureif(!pv) {bad_alloc ba;throw ba;}return pv;}// new overloaded relative to arrays of Complex.void *Complex::operator new[](size_t size) throw(bad_alloc){void *pv;cout << "Allocating array of Complex objects.\n";// throw an exception on failurepv = malloc(size);if(!pv) {bad_alloc ba;throw ba;}return pv;}// delete overloaded relative to Complex.void Complex::operator delete(void *pv){cout << "Deleting Complex object.\n";if (pv)free(pv);}// delete overloaded relative to arrays of Complex.void Complex::operator delete[](void *pv){cout << "Deleting array of Complex objects.\n";if (pv)free(pv);}// + operatorComplex operator + (const Complex& cx1, const Complex& cx2){cx2.Output("Adding");cx1.Output("to");return Complex(cx1.Real()+cx2.Real(), cx1.Imaginary()+cx2.Imaginary());}// - operatorComplex operator - (const Complex& cx1, const Complex& cx2){cx2.Output("Subtracting");cx1.Output("from");return Complex(cx1.Real()-cx2.Real(), cx1.Imaginary()-cx2.Imaginary());}// == operatorbool operator == (const Complex& cx1, const Complex& cx2){cx2.Output("Comparing");cx1.Output("with");return ((cx1.Real()==cx2.Real()) &&(cx1.Imaginary()==cx2.Imaginary()));}// != operatorbool operator != (const Complex& cx1, const Complex& cx2){return !(cx1==cx2);}Test program for Complex class// cxomain.cpp// test of Complex class// illustrating operator overloading#include <iostream>#include <string>using namespace std;#include "cxo.h"// test programvoid main() {// testing ctorscout << "before Constructors" << endl;Complex cx1(1,1);Complex cx2(1),cx3(5);Complex cx4;cout << "after Constructors" << endl;cout << "cx4:" << cx4 << endl; cout << "cx3:" << cx3 << endl; cout << "cx2:" << cx2 << endl; cout << "cx1:" << cx1 << endl << endl; // testing extractorcin >> cx4;cin >> cx3;cin >> cx2;cin >> cx1;cout << "after inputs" << endl;cout << "cx4:" << cx4 << endl; cout << "cx3:" << cx3 << endl; cout << "cx2:" << cx2 << endl; cout << "cx1:" << cx1 << endl << endl; // testing + and =cx4=cx1+cx2;cout << "after +" << endl;cout << "cx4:" << cx4 << endl; cout << "cx3:" << cx3 << endl; cout << "cx2:" << cx2 << endl; cout << "cx1:" << cx1 << endl << endl; // testing - and =cx3=cx4-cx2;cout << "after -" << endl;cout << "cx4:" << cx4 << endl; cout << "cx3:" << cx3 << endl; cout << "cx2:" << cx2 << endl; cout << "cx1:" << cx1 << endl << endl; // testing ==if (cx1==cx2)cout << "cx1 == cx2" << endl;elsecout << "cx1 != cx2" << endl;cout << "after 1st ==" << endl << endl;if (cx1==cx3)cout << "cx1 == cx3" << endl;elsecout << "cx1 != cx3" << endl;cout << "after 2nd ==" << endl << endl;// testing !=if (cx1!=cx2)cout << "cx1 != cx2" << endl;elsecout << "cx1 == cx2" << endl;cout << "after 1st !=" << endl << endl;if (cx1!=cx3)cout << "cx1 != cx3" << endl;elsecout << "cx1 == cx3" << endl;cout << "after 2nd !=" << endl << endl;// testing +=cx4+=cx1+cx2;cout << "after +=" << endl;cout << "cx4:" << cx4 << endl; cout << "cx3:" << cx3 << endl; cout << "cx2:" << cx2 << endl; cout << "cx1:" << cx1 << endl << endl; // testing -=cx4-=cx1+cx2;cout << "after +=" << endl;cout << "cx4:" << cx4 << endl; cout << "cx3:" << cx3 << endl; cout << "cx2:" << cx2 << endl; cout << "cx1:" << cx1 << endl << endl; // testing contiued = and +=cx4 = cx3 = cx2 += cx1;cout << "after continued =" << endl;cout << "cx4:" << cx4 << endl; cout << "cx3:" << cx3 << endl; cout << "cx2:" << cx2 << endl; cout << "cx1:" << cx1 << endl << endl; // testing ++cout << "cx2 = cx1++" << endl;cx2 = cx1++;cout << "cx1:" << cx1 << endl; cout << "cx2:" << cx2 << endl << endl; cout << "cx2 = ++cx1" << endl;cx2 = ++cx1;cout << "cx1:" << cx1 << endl; cout << "cx2:" << cx2 << endl << endl; // testing --cout << "cx2 = cx1--" << endl;cx2 = cx1--;cout << "cx1:" << cx1 << endl; cout << "cx2:" << cx2 << endl << endl; cout << "cx2 = --cx1" << endl;cx2 = --cx1;cout << "cx1:" << cx1 << endl; cout << "cx2:" << cx2 << endl << endl;// testing newcout << "allocating one complex number\n";Complex* pcx = new Complex(1,2);cout << "pcx:" << *pcx << endl << endl;// testing new[]cout << "allocating an array of 4 complex numbers\n";Complex* pcxa = new Complex[4];cout << "pcxa[0]:" << pcxa[0] << endl << endl;// testing deletecout << "deleting one complex number\n";delete pcx;cout << endl;// testing delete[]cout << "deleting array of complex numbers\n";delete [] pcxa;Complex cx5(1,2);cout << "comma op:" ;cout << (cx5, 42, cx5, "this is a test\n");cout << endl;cout << "call op:" << cx5(3,6) << endl;cout << "double conversion op:" << (double)cx5 << endl;cout << "index op[0]:" << cx5[0] << endl;cout << "index op[33]:" << cx5[33] << endl;cx5[0]=11;cx5[8]=22;cout << "after assigments through index op:" << cx5 << endl;cout << "end of main" << endl << endl;}/*after running cxomain < cxomain.inwhere cxomain.in contained the following:(1,2) (2,3) (3,4) (4,5)the output was:before ConstructorsConstructor:(1,1)Constructor:(1,0)Constructor:(5,0)Constructor:(0,0)after Constructorscx4:(0,0)cx3:(5,0)cx2:(1,0)cx1:(1,1)after inputscx4:(1,2)cx3:(2,3)cx2:(3,4)cx1:(4,5)Adding:(3,4)to:(4,5)Constructor:(7,9)Assigning:(7,9)Destructor:(7,9)after +cx4:(7,9)cx3:(2,3)cx2:(3,4)cx1:(4,5)Subtracting:(3,4)from:(7,9)Constructor:(4,5)Assigning:(4,5)Destructor:(4,5)after -cx4:(7,9)cx3:(4,5)cx2:(3,4)cx1:(4,5)Comparing:(3,4)with:(4,5)cx1 != cx2after 1st ==Comparing:(4,5)with:(4,5)cx1 == cx3after 2nd ==Comparing:(3,4)with:(4,5)cx1 != cx2after 1st !=Comparing:(4,5)with:(4,5)cx1 == cx3after 2nd !=Adding:(3,4)to:(4,5)Constructor:(7,9)Adding:(7,9)to:(7,9)Constructor:(14,18)Assigning:(14,18)Destructor:(14,18)Destructor:(7,9)after +=cx4:(14,18)cx3:(4,5)cx2:(3,4)cx1:(4,5)Adding:(3,4)to:(4,5)Constructor:(7,9)Subtracting:(7,9)from:(14,18)Constructor:(7,9)Assigning:(7,9)Destructor:(7,9)Destructor:(7,9)after +=cx4:(7,9)cx3:(4,5)cx2:(3,4)cx1:(4,5)Adding:(4,5)to:(3,4)Constructor:(7,9)Assigning:(7,9)Destructor:(7,9)Assigning:(7,9)Assigning:(7,9)after continued =cx4:(7,9)cx3:(7,9)cx2:(7,9)cx1:(4,5)cx2 = cx1++Copy constructor:(4,5)Constructor:(1,1)Adding:(1,1)to:(4,5)Constructor:(5,6)Assigning:(5,6)Destructor:(5,6)Destructor:(1,1)Copy constructor:(4,5)Destructor:(4,5)Assigning:(4,5)Destructor:(4,5)cx1:(5,6)cx2:(4,5)cx2 = ++cx1Constructor:(1,1)Adding:(1,1)to:(5,6)Constructor:(6,7)Assigning:(6,7)Destructor:(6,7)Destructor:(1,1)Copy constructor:(6,7)Assigning:(6,7)Destructor:(6,7)cx1:(6,7)cx2:(6,7)cx2 = cx1--Copy constructor:(6,7)Constructor:(1,1)Subtracting:(1,1)from:(6,7)Constructor:(5,6)Assigning:(5,6)Destructor:(5,6)Destructor:(1,1)Copy constructor:(6,7)Destructor:(6,7)Assigning:(6,7)Destructor:(6,7)cx1:(5,6)cx2:(6,7)cx2 = --cx1Constructor:(1,1)Subtracting:(1,1)from:(5,6)Constructor:(4,5)Assigning:(4,5)Destructor:(4,5)Destructor:(1,1)Copy constructor:(4,5)Assigning:(4,5)Destructor:(4,5)cx1:(4,5)cx2:(4,5)allocating one complex numberAllocating Complex object.Constructor:(1,2)pcx:(1,2)allocating an array of 4 complex numbersAllocating array of Complex objects.Constructor:(0,0)Constructor:(0,0)Constructor:(0,0)Constructor:(0,0)pcxa[0]:(0,0)deleting one complex numberDestructor:(1,2)Deleting Complex object.deleting array of complex numbersDestructor:(0,0)Destructor:(0,0)Destructor:(0,0)Destructor:(0,0)Deleting array of Complex objects.Constructor:(1,2)comma op:in template Complex , op: int:42in template Complex , op: char *:this is a testthis is a testin call opLeaving call op:(4,12)call op:(4,12)in double conversion op:(4,12)double conversion op:12.6491in index op:(4,12)index op[0]:4in index op:(4,12)index op[33]:12in index op:(4,12)in index op:(11,12)after assigments through index op:(11,22)end of mainDestructor:(11,22)Destructor:(7,9)Destructor:(7,9)Destructor:(4,5)Destructor:(4,5)*/Orthodox Canonical Form IdiomA String using the Orthodox Canonical Form Idiom based on Figure 3-1 in Coplien's Advanced C++.Interface to String class// str.h// A String using the Orthodox Canonical Form Idiom// based on Figure 3-1 in Coplien's Advanced C++#ifndef __str_h__#define __str_h__class String {public:// public user interface to a String// boilerplate member functions:// default ctorString();// copy ctorString(const String&);// assignment operatorString& operator = (const String&);// dtor~String();// class specific member functions// ctor from a const char *String(const char*);// conversion operator to a const char *operator const char*() const;// length member functionunsigned int Length() const;private:// implementation data and internal functions// here, the rep is a C style stringchar *m_sz;};// concatenationString operator + (const String &, const String &);// << operatortemplate <typename OS>OS& operator << (OS& os, const String& s){os << '"' << (const char *)s << '"';return os;}#endifImplementation of String class// str.cpp// this file contains the implementation of the String class// defined in str.h#include <iostream>using namespace std;#include <cstring>#include "str.h"// concatenationString operator + (const String& s1, const String& s2){char *sz = new char[s1.Length() + s2.Length() + 1];strcpy(sz, (const char *)s1);strcat(sz, (const char *)s2);String sReturn(sz);delete [] sz;return sReturn;}// default ctorString::String(): m_sz(new char[strlen("")+1]){strcpy(m_sz, "");}// copy constructorString::String(const String& s) : m_sz(new char[s.Length()+1]){strcpy(m_sz, s.m_sz);}// assignment operatorString& String::operator = (const String& s) {if (this!=&s) {delete [] m_sz;m_sz = new char[s.Length() + 1];strcpy(m_sz, s.m_sz);}return *this;}// dtorString::~String() {// scribble on the datafor (int i = 0; i<Length(); i++)m_sz[i]='X';// free the repdelete [] m_sz;}// ctor from a const char *String::String(const char* sz): m_sz(new char[strlen(sz)+1]){strcpy(m_sz, sz);}// conversion operator to a const char *String::operator const char*() const{ return m_sz; }// length member functionunsigned int String::Length() const { return strlen(m_sz); }Test program for String class// strmain.cpp// test procedure for String defined in str.h#include <iostream>using namespace std;#include "str.h"void main() {String s1("This is a test.");String s2("So is this.");String s3("This");String s4("this");String s5("is");String s6,s7,s8;String s9 = s5;s7=s8=s1+ " " + s2;cout<<s7<<endl;// "This is a test. So is this."cout<<s4+s6<<endl;// "this"cout<<s6.Length()<<endl;// 0cout<<s5.Length()<<endl;// 2cout<<s9<<endl;// "is"s9 = s9;cout<<s9<<endl;// "is"s9 = s3;cout<<s9<<endl;// "This"}/* output:"This is a test. So is this.""this"02"is""is""This"*/Constructors, Destructors, and Assignment operatorsThe rule of three states that: if you provide definitions for any of the following features, you generally have to provide all of them: copy constructor, assignment operator, destructor.The copy constructor is used when variables are initialized, when arguments are passed by value, and when arguments are returned by value. The default copy constructor for built-in types performs a bit-wise copy. The default copy constructor for user defined classes calls the copy constructors for each member. If all of the member data are built-in types, this degenerates to a bit-wise copy of the data. If your class acquires resources (such as dynamic memory or handles to other resources) on a per instance basis, then the default copy constructor will not do the right thing in that it will copy those pointers or handles. The problem actually arises when the copied objects are destructed as the destructors for each instance will be returning resources that really were allocated for the original.The default assignment operator behaves in a manner similar to the default assignment operator in that the assignments of built-in types is just a bit-wise copy. The default assignment operator for user defined classes calls the assignment operators for each member. Thus, as with the copy constructor, if all of the member data are built-in types, this degenerates to a bit-wise copy of the data. Again, if your class acquires resources on a per instance basis, this will lead to multiple copies of pointers and handles which will result in the same resource being returned more than once and will generally manifest as bugs that are using dangling pointers.The default destructor will call the destructors for all the member data. The default destructor for built-in types will simply free the memory allocated to hold that data item. That is to say, that if the data were a pointer, it would free the pointer but no what is pointed to by the pointer. If your program allocates resources on a per instance basis, it will leak resources if you do not define a destructor.c_ds.cpp// c_ds.cpp// this version contains a dtor, but not a copy ctor or assignment op#include <iostream>using namespace std;#include <cstring>class String {public:// dtor~String();// class specific member functions// ctor from a const char *String(const char* = "");// length member functionunsigned int Length() const;// conversion operator to a const char *operator const char*() const;// idinline unsigned int Id() const{return m_uiId;}private:char *m_sz;static unsigned int m_uiNextId;unsigned int m_uiId;};// << operatortemplate <typename OS>OS& operator << (OS& os, const String& s){os << s.Id() << ':' << '"' << (const char *)s << '"';return os;}// dtorString::~String() {cout << "destructing object:" << *this << endl;// scribble on the datafor (int i = 0; i<Length(); i++)m_sz[i]='X';// // free the rep// should do this, but it will cause unacceptable// behavior when build with MSVC 6.0 in this program// // delete [] m_sz;}// ctor from a const char *String::String(const char* sz): m_sz(new char[strlen(sz)+1]),m_uiId(m_uiNextId++){cout << "in const char * ctor" << endl;strcpy(m_sz, sz);cout << *this << endl;}// length member functionunsigned int String::Length() const { return strlen(m_sz); }// conversion operator to a const char *String::operator const char*() const{ return m_sz; }unsigned int String::m_uiNextId = 1;void Reminder(String s){cout << "Remember to call contact..." << s << endl;}void main () {String s1("Mummy"),s2("Dracula"),s3;Reminder(s1);Reminder(s2);Reminder(s3);cout << "after calls to reminder" << endl;cout << "s1:" << s1 << endl;cout << "s2:" << s2 << endl;cout << "s3:" << s3 << endl;s1 = s2;s3 = s2;cout << "after assignments" << endl;cout <<"s1:" << s1 << endl;cout <<"s2:" << s2 << endl;cout <<"s3:" << s3 << endl;Reminder(s1);Reminder(s2);Reminder(s3);}/* output:in const char * ctor1:"Mummy"in const char * ctor2:"Dracula"in const char * ctor3:""Remember to call contact...1:"Mummy"destructing object:1:"Mummy"Remember to call contact...2:"Dracula"destructing object:2:"Dracula"Remember to call contact...3:""destructing object:3:""after calls to reminders1:1:"XXXXX"s2:2:"XXXXXXX"s3:3:""after assignmentss1:2:"XXXXXXX"s2:2:"XXXXXXX"s3:2:"XXXXXXX"Remember to call contact...2:"XXXXXXX"destructing object:2:"XXXXXXX"Remember to call contact...2:"XXXXXXX"destructing object:2:"XXXXXXX"Remember to call contact...2:"XXXXXXX"destructing object:2:"XXXXXXX"destructing object:2:"XXXXXXX"destructing object:2:"XXXXXXX"destructing object:2:"XXXXXXX"*/c_cds.cpp// c_cds.cpp// this version contains a dtor and a copy ctor, but no assignment op#include <iostream>using namespace std;#include <cstring>class String {public:// dtor~String();// copy ctorString(const String&);// class specific member functions// ctor from a const char *String(const char* = "");// length member functionunsigned int Length() const;// conversion operator to a const char *operator const char*() const;// idinline unsigned int Id() const{return m_uiId;}private:char *m_sz;static unsigned int m_uiNextId;unsigned int m_uiId;};// << operatortemplate <typename OS>OS& operator << (OS& os, const String& s){os << s.Id() << ':' << '"' << (const char *)s << '"';return os;}// dtorString::~String() {cout << "destructing object:" << *this << endl;// scribble on the datafor (int i = 0; i<Length(); i++)m_sz[i]='X';// // free the rep// should do this, but it will cause unacceptable// behavior when build with MSVC 6.0 in this program// // delete [] m_sz;}// copy constructorString::String(const String& s) : m_sz(new char[s.Length()+1]),m_uiId(m_uiNextId++){strcpy(m_sz, s.m_sz);}// ctor from a const char *String::String(const char* sz): m_sz(new char[strlen(sz)+1]),m_uiId(m_uiNextId++){cout << "in const char * ctor" << endl;strcpy(m_sz, sz);cout << *this << endl;}// length member functionunsigned int String::Length() const { return strlen(m_sz); }// conversion operator to a const char *String::operator const char*() const{ return m_sz; }unsigned int String::m_uiNextId = 1;void Reminder(String s){cout << "Remember to call contact..." << s << endl;}void main () {String s1("Mummy"),s2("Dracula"),s3;Reminder(s1);Reminder(s2);Reminder(s3);cout << "after calls to reminder" << endl;cout << "s1:" << s1 << endl;cout << "s2:" << s2 << endl;cout << "s3:" << s3 << endl;s1 = s2;s3 = s2;cout << "after assignments" << endl;cout <<"s1:" << s1 << endl;cout <<"s2:" << s2 << endl;cout <<"s3:" << s3 << endl;Reminder(s1);Reminder(s2);Reminder(s3);}/* output:in const char * ctor1:"Mummy"in const char * ctor2:"Dracula"in const char * ctor3:""Remember to call contact...4:"Mummy"destructing object:4:"Mummy"Remember to call contact...5:"Dracula"destructing object:5:"Dracula"Remember to call contact...6:""destructing object:6:""after calls to reminders1:1:"Mummy"s2:2:"Dracula"s3:3:""after assignmentss1:2:"Dracula"s2:2:"Dracula"s3:2:"Dracula"Remember to call contact...7:"Dracula"destructing object:7:"Dracula"Remember to call contact...8:"Dracula"destructing object:8:"Dracula"Remember to call contact...9:"Dracula"destructing object:9:"Dracula"destructing object:2:"Dracula"destructing object:2:"XXXXXXX"destructing object:2:"XXXXXXX"*/c_cdas.cpp// c_cdas.cpp// this version contains a dtor, a copy ctor, and an assignment op#include <iostream>using namespace std;#include <cstring>class String {public:// dtor~String();// copy ctorString(const String&);// assignment operatorString& operator=(const String&);// class specific member functions// ctor from a const char *String(const char* = "");// length member functionunsigned int Length() const;// conversion operator to a const char *operator const char*() const;// idinline unsigned int Id() const{return m_uiId;}private:char *m_sz;static unsigned int m_uiNextId;unsigned int m_uiId;};// << operatortemplate <typename OS>OS& operator << (OS& os, const String& s){os << s.Id() << ':' << '"' << (const char *)s << '"';return os;}// dtorString::~String() {cout << "destructing object:" << *this << endl;// scribble on the datafor (int i = 0; i<Length(); i++)m_sz[i]='X';// free the repdelete [] m_sz;}// copy constructorString::String(const String& s) : m_sz(new char[s.Length()+1]),m_uiId(m_uiNextId++){strcpy(m_sz, s.m_sz);}// ctor from a const char *String::String(const char* sz): m_sz(new char[strlen(sz)+1]),m_uiId(m_uiNextId++){cout << "in const char * ctor" << endl;strcpy(m_sz, sz);cout << *this << endl;}// assignment operatorString& String::operator = (const String& s) {if (this!=&s) {delete [] m_sz;m_sz = new char[s.Length() + 1];strcpy(m_sz, s.m_sz);}return *this;}// length member functionunsigned int String::Length() const { return strlen(m_sz); }// conversion operator to a const char *String::operator const char*() const{ return m_sz; }unsigned int String::m_uiNextId = 1;void Reminder(String s){cout << "Remember to call contact..." << s << endl;}void main () {String s1("Mummy"),s2("Dracula"),s3;Reminder(s1);Reminder(s2);Reminder(s3);cout << "after calls to reminder" << endl;cout << "s1:" << s1 << endl;cout << "s2:" << s2 << endl;cout << "s3:" << s3 << endl;s1 = s2;s3 = s2;cout << "after assignments" << endl;cout <<"s1:" << s1 << endl;cout <<"s2:" << s2 << endl;cout <<"s3:" << s3 << endl;Reminder(s1);Reminder(s2);Reminder(s3);}/* output:in const char * ctor1:"Mummy"in const char * ctor2:"Dracula"in const char * ctor3:""Remember to call contact...4:"Mummy"destructing object:4:"Mummy"Remember to call contact...5:"Dracula"destructing object:5:"Dracula"Remember to call contact...6:""destructing object:6:""after calls to reminders1:1:"Mummy"s2:2:"Dracula"s3:3:""after assignmentss1:1:"Dracula"s2:2:"Dracula"s3:3:"Dracula"Remember to call contact...7:"Dracula"destructing object:7:"Dracula"Remember to call contact...8:"Dracula"destructing object:8:"Dracula"Remember to call contact...9:"Dracula"destructing object:9:"Dracula"destructing object:3:"Dracula"destructing object:2:"Dracula"destructing object:1:"Dracula"*/ InheritanceThis is how C++ provides the “IS-A” relationship. There are three types of inheritance: public, private, and protected. Public inheritance is truly an “IS-A” relationship and is the recommended form of use. It implies that all of the functions and data in the public interface to the base class are public in the derived class. The derived class then adds to this public interface and/or private data.Example:// si.cpp// simple inheritance#include <iostream>using namespace std;// definition of RoadVehicleclass RoadVehicle {int m_iNumberOfWheels;public:RoadVehicle(int iNumberOfWheels = 4) : m_iNumberOfWheels(iNumberOfWheels) {}inline int NumberOfWheels() {return m_iNumberOfWheels;}};// definition of Truckclass Truck : public RoadVehicle {int m_iCargo;public:Truck(int iCargo = 0, int iNumberOfWheels = 4) : RoadVehicle (iNumberOfWheels), m_iCargo(iCargo) {}inline int Cargo() {return m_iCargo;}};void main(){Truck t;cout << "Cargo:" << t.Cargo() << " "<< "Number of Wheels:" << t.NumberOfWheels() << endl;}/* output:Cargo:0 Number of Wheels:4*/Thus a Truck “IS-A” RoadVehicle and instances of class Truck can access both Cargo and NumberOfWheels.Private inheritance is used primarily to mean “is implemented in terms of”. That is, if a PhoneNumber class is defined as a private string, the string operations are not visible through the public interface to PhoneNumber.// pi.cpp// private inheritance#include <iostream>#include <string>using namespace std;// definition of PhoneNumberclass PhoneNumber : private string {public:PhoneNumber(string sPhoneNumber = "") :string(sPhoneNumber) {}void Output() { cout << *this << endl; }};void main(){PhoneNumber p("555-1212");p.Output();}/* output:555-1212*/A better way of accomplishing this is to have the PhoneNumber class contain a string rather than inherit from it.// pi1.cpp// better way to do pi.cpp#include <iostream>#include <string>using namespace std;// definition of PhoneNumberclass PhoneNumber {string m_sPhoneNumber;public:PhoneNumber(string sPhoneNumber = "") :m_sPhoneNumber(sPhoneNumber) {}void Output() { cout << m_sPhoneNumber << endl; }};void main(){PhoneNumber p("555-1212");p.Output();}/* output:555-1212*/Protected inheritance follows the same rules as protected data members. It means that the public interface of the base class is protected in the derived class and that the protected interface in the base class is private in the derived class. This should not be used.Virtual FunctionsVirtual functions provide run-time polymorphism. They allow a function defined in a base class to behave differently for the derived class even when it is being manipulated through the base class. See PolyOutput in the example below.// vi.cpp// illustration of inheritance and// virtual functions#include <iostream>using namespace std;// definition of baseclass Base {int m_iBase;public:Base(int i = 0);Base (const Base & bs);virtual ~Base();inline int BasePart() const {return m_iBase;}virtual void Output(const char * szMessage) const;};// ctor for baseBase::Base(int i) :m_iBase(i){Output("ctor for Base");}// copy ctor for baseBase::Base(const Base & bs) :m_iBase(bs.m_iBase){Output("copy ctor for Base");}// dtor for baseBase::~Base(){Output("dtor for Base");}// output for basevoid Base::Output(const char * szMessage) const{cout << "Output for Base" << ':'<< szMessage << ':' << m_iBase << endl;}// definition of Derivedclass Derived : public Base{int m_iDerived;public:Derived(int i = 0);Derived (const Derived & dv);virtual ~Derived();virtual void Output(const char * szMessage) const;};// ctor for DerivedDerived::Derived(int i) : Base(10+i),m_iDerived(i){Output("ctor for Derived");}// copy ctor for DerivedDerived::Derived(const Derived & dv) : Base(dv),m_iDerived(dv.m_iDerived){Output("copy ctor for Derived");}// dtor for DerivedDerived::~Derived(){Output("dtor for Derived");}// output for Derivedvoid Derived::Output(const char * szMessage) const{cout << "Output for Derived" << ':'<< szMessage << ':' << m_iDerived <<','<< BasePart() << endl;}// polymorphic output functionvoid PolyOutput(const char * szMessage, const Base & bs){cout << "calling virtual output: ";bs.Output(szMessage);}// a function that receives a Derivedvoid Func(const Derived dv){cout << "in Func" << endl;}int main(){Base bs(1);cout << "after constructing Base bs" << endl << endl;Derived dv(2);cout << "after constructing Derived dv" << endl << endl;PolyOutput("this is of type Base",bs);cout << "after PolyOutput of bs" << endl << endl;PolyOutput("this is of type Derived",dv);cout << "after PolyOutput of dv" << endl << endl;Func(dv);cout << "after Func(dv)" << endl << endl;return 0;}/* output:Output for Base:ctor for Base:1after constructing Base bsOutput for Base:ctor for Base:12Output for Derived:ctor for Derived:2,12after constructing Derived dvcalling virtual output: Output for Base:this is of type Base:1after PolyOutput of bscalling virtual output: Output for Derived:this is of type Derived:2,12after PolyOutput of dvOutput for Base:copy ctor for Base:12Output for Derived:copy ctor for Derived:2,12in FuncOutput for Derived:dtor for Derived:2,12Output for Base:dtor for Base:12after Func(dv)Output for Derived:dtor for Derived:2,12Output for Base:dtor for Base:12Output for Base:dtor for Base:1*/Virtual DestructorsDestructors work differently than other functions so it should be no surprise that virtual destructors work differently than other virtual functions. Since C++ objects are taken apart in the reverse order that they are put together, the sequence follows the reverse order of construction until the highest level object is destructed. If the object is being referenced through a pointer to the base class, destruction of the object may stop prematurely unless virtual destructors are used. Classes that are to be used as base classes should have virtual destructors. See example below.// vd.cpp// virtual dtor example#include <iostream>#include <string>using namespace std;// base class without a virtual dtorclass Mammal{public:Mammal(string sName="unnamed") : m_sName(sName){cout << m_sName << ": ctor for Mammal called" << endl;}~Mammal(){cout << m_sName << ": dtor for Mammal called" << endl << endl;}private:string m_sName;};// class derived from a base class without a virtual dtorclass Skunk : public Mammal{public:Skunk(string sName="unnamed") : Mammal("Skunk("+sName+")"), m_sName(sName){cout << m_sName << ": ctor for Skunk called" << endl;}~Skunk(){cout << m_sName << ": dtor for Skunk called" << endl;}private:string m_sName;};// base class with a virtual dtorclass Bird{public:Bird(string sName="unnamed") : m_sName(sName){cout << m_sName << ": ctor for Bird called" << endl;}virtual ~Bird(){cout << m_sName << ": dtor for Bird called" << endl << endl;}private:string m_sName;};// class derived from a base class with a virtual dtorclass Sparrow : public Bird{public:Sparrow(string sName="unnamed") :Bird("Sparrow("+sName+")"), m_sName(sName){cout << m_sName << ": ctor for Sparrow called" << endl;}virtual ~Sparrow(){cout << m_sName << ": dtor for Sparrow called" << endl;}private:string m_sName;};void main(){cout << "before Mammal ctors" << endl;Mammal * pmammalBugs = new Mammal("Bugs");Mammal * pmammalPeppyLaPu = new Skunk("Peppy La Pu");Mammal mammalPorky("Porky");cout << endl << "before Skunk ctors" << endl;Skunk * pskunkFlower = new Skunk("Flower");Skunk skunkTaz("Taz");cout << endl << "before Bird ctors" << endl;Bird * pbirdTweety = new Bird("Tweety");Bird * pbirdSandrine = new Sparrow("Sandrine");Bird birdPolly("Polly");cout << endl << "before Sparrow ctors" << endl;Sparrow * psparrowVivian = new Sparrow("Vivian");Sparrow sparrowCandy("Candy");cout << endl << "before deleting Mammals" << endl;delete pmammalBugs;delete pmammalPeppyLaPu;cout << endl << "before deleting Skunk" << endl;delete pskunkFlower;cout << endl;cout << endl << "before deleting Birds" << endl;delete pbirdTweety;delete pbirdSandrine;cout << endl << "before deleting Sparrow" << endl;delete psparrowVivian;cout << endl;cout << "end of main" << endl << endl;}/* output:before Mammal ctorsBugs: ctor for Mammal calledSkunk(Peppy La Pu): ctor for Mammal calledPeppy La Pu: ctor for Skunk calledPorky: ctor for Mammal calledbefore Skunk ctorsSkunk(Flower): ctor for Mammal calledFlower: ctor for Skunk calledSkunk(Taz): ctor for Mammal calledTaz: ctor for Skunk calledbefore Bird ctorsTweety: ctor for Bird calledSparrow(Sandrine): ctor for Bird calledSandrine: ctor for Sparrow calledPolly: ctor for Bird calledbefore Sparrow ctorsSparrow(Vivian): ctor for Bird calledVivian: ctor for Sparrow calledSparrow(Candy): ctor for Bird calledCandy: ctor for Sparrow calledbefore deleting MammalsBugs: dtor for Mammal calledSkunk(Peppy La Pu): dtor for Mammal calledbefore deleting SkunkFlower: dtor for Skunk calledSkunk(Flower): dtor for Mammal calledbefore deleting BirdsTweety: dtor for Bird calledSandrine: dtor for Sparrow calledSparrow(Sandrine): dtor for Bird calledbefore deleting SparrowVivian: dtor for Sparrow calledSparrow(Vivian): dtor for Bird calledend of mainCandy: dtor for Sparrow calledSparrow(Candy): dtor for Bird calledPolly: dtor for Bird calledTaz: dtor for Skunk calledSkunk(Taz): dtor for Mammal calledPorky: dtor for Mammal called*/Multiple InheritanceMultiple inheritance is where we would like an object to inherit the interfaces of more than one parent class. For the sake of this class, we will only use public inheritance (see previous). Simple multiple inheritance example// mis.cpp// simple multiple inheritance example// Multiple inheritance is where we would like an object to inherit the // interfaces of more than one parent class. For the sake of this class, // we will only use public inheritance. #include <iostream>using namespace std;// definition of SquareWindowclass SquareWindow {unsigned int m_uiDiagonal;public:SquareWindow(unsigned int uiDiagonal = 2) : m_uiDiagonal(uiDiagonal){cout<<"ctor of SquareWindow called"<<endl;}~SquareWindow(){cout<<"dtor of SquareWindow called"<<endl;}inline unsigned int Diagonal() {return m_uiDiagonal;}};// definition of Timerclass Timer {unsigned int m_uiTickInterval;public:Timer(unsigned int uiTickInterval = 10) : m_uiTickInterval(uiTickInterval){cout<<"ctor of Timer called"<<endl;}~Timer(){cout<<"dtor of Timer called"<<endl;}inline unsigned int TickInterval() {return m_uiTickInterval;}};// definition of Clockclass Clock : public SquareWindow, public Timer {public:Clock(unsigned int uiDiagonal = 4, unsigned int uiTickInterval = 1) : SquareWindow(uiDiagonal),Timer(uiTickInterval){cout<<"ctor of Clock called"<<endl;}~Clock(){cout<<"dtor of Clock called"<<endl;}};void main(){Clock clk;cout << "Diagonal:" << clk.Diagonal() << " "<< "TickInterval:" << clk.TickInterval()<< endl;}/* output:ctor of SquareWindow calledctor of Timer calledctor of Clock calledDiagonal:4 TickInterval:1dtor of Clock calleddtor of Timer calleddtor of SquareWindow called*/Multiple inheritance example with a common ancestor In the event that a object inherits from more than one parent, and those parents have a common ancestor, a problem can arise where there is more than one copy of that ancestor in the derived class. // mica.cpp// multiple inheritance example with a common ancestor// In the event that a object inherits from more than one parent, and those // parents have a common ancestor, a problem can arise where there is more // than one copy of that ancestor in the derived class. #include <iostream>#include <string>using namespace std;// definition of TagObjectclass TagObject {public:// default ctorTagObject() :m_sTag("untagged"),m_uiID(++m_uiNextID){m_uiID=++m_uiNextID;cout<<"default ctor of TagObject called:"<< "ID=" << m_uiID << ':' << "Tag=" << m_sTag <<endl;}// string ctorTagObject(string sTag) : m_sTag(sTag),m_uiID(++m_uiNextID){cout<<"string ctor of TagObject called:"<< "ID=" << m_uiID << ':' << "Tag=" << m_sTag <<endl;}// dtor~TagObject(){cout<<"dtor of TagObject called:"<< "ID=" << m_uiID << ':' << "Tag=" << m_sTag <<endl;}// accessorsinline string Tag() {return m_sTag;}inline unsigned int ID(){return m_uiID;}private:string m_sTag;static unsigned int m_uiNextID;unsigned int m_uiID;};unsigned int TagObject::m_uiNextID;// definition of SquareWindowclass SquareWindow : public TagObject {public:// ctorSquareWindow(unsigned int uiDiagonal = 5, string sTag = "SquareWindow") : TagObject(sTag),m_uiDiagonal(uiDiagonal){cout<<"ctor of SquareWindow called"<<endl;}// dtor~SquareWindow(){cout<<"dtor of SquareWindow called"<<endl;}// accessorinline unsigned int Diagonal() {return m_uiDiagonal;}private:unsigned int m_uiDiagonal;};// definition of Timerclass Timer : public TagObject {public:// ctorTimer(unsigned int uiTickInterval = 4, string sTag = "Timer") : TagObject(sTag),m_uiTickInterval(uiTickInterval){cout<<"ctor of Timer called"<<endl;}// dtor~Timer(){cout<<"dtor of Timer called"<<endl;}// accessorinline unsigned int TickInterval() {return m_uiTickInterval;}private:unsigned int m_uiTickInterval;};// definition of Clockclass Clock : public SquareWindow, public Timer {public:// ctorClock(unsigned int uiDiagonal = 3, unsigned int uiTickInterval = 6, string sTag = "Clock") : SquareWindow(uiDiagonal),Timer(uiTickInterval){cout<<"ctor of Clock called"<<endl;}// dtor~Clock(){cout<<"dtor of Clock called"<<endl;}};// test programvoid main(){Timer timer(2);cout << "TickInterval:" << timer.TickInterval() << " "<< "Tag:" << timer.Tag() << endl << endl;SquareWindow SquareWindow(9);cout << "Diagonal:" << SquareWindow.Diagonal() << " "<< "Tag:" << SquareWindow.Tag() << endl << endl;Clock clk(4,8);cout << "Diagonal:" << clk.Diagonal() << " "<< "TickInterval:" << clk.TickInterval() << " "// Tag must be disambiguated<< "Timer Tag:" << clk.Timer::Tag() << " " << "SquareWindow Tag:" << clk.SquareWindow::Tag() << endl << endl;cout << "end of main" << endl << endl;}/*output:string ctor of TagObject called:ID=1:Tag=Timerctor of Timer calledTickInterval:2 Tag:Timerstring ctor of TagObject called:ID=2:Tag=SquareWindowctor of SquareWindow calledDiagonal:9 Tag:SquareWindowstring ctor of TagObject called:ID=3:Tag=SquareWindowctor of SquareWindow calledstring ctor of TagObject called:ID=4:Tag=Timerctor of Timer calledctor of Clock calledDiagonal:4 TickInterval:8 Timer Tag:Timer SquareWindow Tag:SquareWindowend of maindtor of Clock calleddtor of Timer calleddtor of TagObject called:ID=4:Tag=Timerdtor of SquareWindow calleddtor of TagObject called:ID=3:Tag=SquareWindowdtor of SquareWindow calleddtor of TagObject called:ID=2:Tag=SquareWindowdtor of Timer calleddtor of TagObject called:ID=1:Tag=Timer*/Clock is a SquareWindow and a Timer. Both SquareWindow and Timer each have a TagObject part. Note that the TagObject ctor is called twice (once when constructing the SquareWindow part of Clock and once when constructing the Timer part of Clock). As a result, there two copies of TagObject's member data in Clock and the function Tag is ambiguous and must be clarified to the compiler by referring to it as either Timer::Tag() or SquareWindow::Tag(). We can solve this problem by using virtual inheritance.Multiple inheritance example using virtual inheritance// micav.cpp// multiple inheritance example with a common ancestor// using virtual inheritance#include <iostream>#include <string>using namespace std;// definition of TagObjectclass TagObject {public:// default ctorTagObject() :m_sTag("untagged"),m_uiID(++m_uiNextID){cout<<"default ctor of TagObject called:"<< "ID=" << m_uiID << ':' << "Tag=" << m_sTag <<endl;}// string ctorTagObject(string sTag) : m_sTag(sTag),m_uiID(++m_uiNextID){cout<<"string ctor of TagObject called:"<< "ID=" << m_uiID << ':' << "Tag=" << m_sTag <<endl;}// dtor~TagObject(){cout<<"dtor of TagObject called:"<< "ID=" << m_uiID << ':' << "Tag=" << m_sTag <<endl;}// accessorsinline string Tag() {return m_sTag;}inline unsigned int ID(){return m_uiID;}private:string m_sTag;static unsigned int m_uiNextID;unsigned int m_uiID;};unsigned int TagObject::m_uiNextID;// definition of SquareWindowclass SquareWindow : virtual public TagObject {public:// ctorSquareWindow(unsigned int uiDiagonal = 5, string sTag = "SquareWindow") : TagObject(sTag),m_uiDiagonal(uiDiagonal){cout<<"ctor of SquareWindow called"<<endl;}// dtor~SquareWindow(){cout<<"dtor of SquareWindow called"<<endl;}// accessorinline unsigned int Diagonal() {return m_uiDiagonal;}private:unsigned int m_uiDiagonal;};// definition of Timerclass Timer : virtual public TagObject {public:// ctorTimer(unsigned int uiTickInterval = 4, string sTag = "Timer") : TagObject(sTag),m_uiTickInterval(uiTickInterval){cout<<"ctor of Timer called"<<endl;}// dtor~Timer(){cout<<"dtor of Timer called"<<endl;}// accessorinline unsigned int TickInterval() {return m_uiTickInterval;}private:unsigned int m_uiTickInterval;};// definition of Clockclass Clock : public SquareWindow, public Timer {public:// ctorClock(unsigned int uiDiagonal = 3, unsigned int uiTickInterval = 6, string sTag = "Clock") : TagObject(sTag),SquareWindow(uiDiagonal),Timer(uiTickInterval){cout<<"ctor of Clock called"<<endl;}// dtor~Clock(){cout<<"dtor of Clock called"<<endl;}};// test programvoid main(){Timer timer(2);cout << "TickInterval:" << timer.TickInterval() << " "<< "Tag:" << timer.Tag() << endl << endl;SquareWindow SquareWindow(9);cout << "Diagonal:" << SquareWindow.Diagonal() << " "<< "Tag:" << SquareWindow.Tag() << endl << endl;Clock clk(4,8);cout << "Diagonal:" << clk.Diagonal() << " "<< "TickInterval:" << clk.TickInterval() << " "<< "Tag:" << clk.Tag() << endl << endl;cout << "end of main" << endl << endl;}/*output:string ctor of TagObject called:ID=1:Tag=Timerctor of Timer calledTickInterval:2 Tag:Timerstring ctor of TagObject called:ID=2:Tag=SquareWindowctor of SquareWindow calledDiagonal:9 Tag:SquareWindowstring ctor of TagObject called:ID=3:Tag=Clockctor of SquareWindow calledctor of Timer calledctor of Clock calledDiagonal:4 TickInterval:8 Tag:Clockend of maindtor of Clock calleddtor of Timer calleddtor of SquareWindow calleddtor of TagObject called:ID=3:Tag=Clockdtor of SquareWindow calleddtor of TagObject called:ID=2:Tag=SquareWindowdtor of Timer calleddtor of TagObject called:ID=1:Tag=Timer*/Cast operatorsC style castingusage:(target-type) (expr)This operator acts in the same way as it did in C. No checking of the appropriateness of the cast is performed either at run time or compile time. See “reinterpret_cast”. static_cast usage:static_cast <target-type> (expr)This operator allows conversion between related non-polymorphic types. No run time checking is performed. Failure to find an appropriate conversion will be reported at compile time. dynamic_castusage:dynamic_cast <target-type> (expr)This operator allows conversion between related polymorphic types based on RTTI (Run Time Type Information). NULL is returned if the cast fails. reinterpret_castusage:reinterpret_cast <target-type> (expr)This operator allows conversion between fundamentally different types. No checking of the appropriateness of the cast is performed either at run time or compile time. The advantage of this over a C style cast is that it makes explicit the desire to perform such a conversion. See “C style cast”. const_castusage:const_cast <target-type> (expr)This operator is used to explicitly cast away override const and/or volatile in a cast. The most common use of const_cast is to cast away const-ness. Handle/Body paradigmThis section deals with the Handle/Body paradigm (a way of separating the abstract interface of a class from it’s implementation; also called the “Cheshire Cat”). The program in the first subsection is a straight forward implementation of complex numbers. The program in the second subsection is a re-implementation of the first program in the Handle/Body paradigm. The program in the third section adds use counting to the Handle/Body plex - basic versionComplex Class Header// cx.h// this file contains the interface to the// simple complex number class#ifndef __CX_H__#define __CX_H__class Complex {public:friend const Complex operator+(const Complex &, const Complex&);friend const Complex operator-(const Complex &, const Complex&);friend const bool operator==(const Complex &, const Complex&);friend const bool operator!=(const Complex &, const Complex&);friend ostream& operator<<(ostream&, const Complex&);Complex(const double = 0, const double = 0);Complex(const Complex&);~Complex();Complex& operator=(const Complex&);Complex& operator+=(const Complex&);Complex& operator-=(const Complex&);const double Real() const {return m_dReal;}const double Imaginary() const {return m_dImaginary;}private:double m_dReal;double m_dImaginary;};#endifComplex Class Implementation// cx.cpp// this file contains the implementation of the // simple complex number class#include <iostream>using namespace std;#include "cx.h"// + operatorconst Complex operator+(const Complex& cx1,const Complex& cx2){return Complex(cx1.m_dReal+cx2.m_dReal, cx1.m_dImaginary+cx2.m_dImaginary);}// - operatorconst Complex operator-(const Complex& cx1,const Complex& cx2){return Complex(cx1.m_dReal-cx2.m_dReal, cx1.m_dImaginary-cx2.m_dImaginary);}// == operatorconst bool operator==(const Complex& cx1,const Complex& cx2){return ((cx1.m_dReal==cx2.m_dReal) &&(cx1.m_dImaginary==cx2.m_dImaginary));}// != operatorconst bool operator!=(const Complex& cx1,const Complex& cx2){return !(cx1==cx2);}// << operatorostream& operator<<(ostream& os, const Complex& cx){ os <<'('<<cx.m_dReal<<','<<cx.m_dImaginary<<')';return os; }// constructor from a pair of doublesComplex::Complex(const double dReal, const double dImaginary) : m_dReal(dReal), m_dImaginary(dImaginary){}// copy constructorComplex::Complex(const Complex& cx) :m_dReal(cx.m_dReal), m_dImaginary(cx.m_dImaginary){}// destructorComplex::~Complex(){// scribble on data to make desctruted members recognizablem_dReal=123456789;m_dImaginary=987654321;}// = operatorComplex& Complex::operator=(const Complex& cx){if (&cx!=this) {m_dReal=cx.m_dReal; m_dImaginary=cx.m_dImaginary;}return *this;}// += operatorComplex& Complex::operator+=(const Complex& cx){*this = *this + cx;return *this;}// -= operatorComplex& Complex::operator-=(const Complex& cx){*this = *this - cx;return *this;}Main// mains.cpp// this is the test procedure for the// simple complex number class#include <iostream>using namespace std;#include "cx.h"// output four complex vars and a messagevoid Dump(char * szMessage, const Complex& cx1, const Complex& cx2, const Complex& cx3, const Complex& cx4){cout << szMessage << ':' << endl;cout << "cx1=" << cx1 << endl;cout << "cx2=" << cx2 << endl;cout << "cx3=" << cx3 << endl;cout << "cx4=" << cx4 << endl;cout << endl;}// main test procedurevoid main() {Complex cx1(1,1);Complex cx2(1),cx3(5);Complex cx4;Dump("After constructors",cx1,cx2,cx3,cx4);cx3=cx4=cx1+cx2-cx3;Dump("After first assignment",cx1,cx2,cx3,cx4);cx3+=cx3;Dump("After +=",cx1,cx2,cx3,cx4);cx3-=cx4;Dump("After -=",cx1,cx2,cx3,cx4);}/*output:After constructors:cx1=(1,1)cx2=(1,0)cx3=(5,0)cx4=(0,0)After first assignment:cx1=(1,1)cx2=(1,0)cx3=(-3,1)cx4=(-3,1)After +=:cx1=(1,1)cx2=(1,0)cx3=(-6,2)cx4=(-3,1)After -=:cx1=(1,1)cx2=(1,0)cx3=(-3,1)cx4=(-3,1)*/Complex - handle/body versionThe handle/body idiom is where a class is used to encapsulate the interface to another class where the actual work is done. The class containing the interface is called the handle class; the class containing the implementation is called the body (or representation) plex Handle Class Header// cxh.h// this file contains the interface to the// handle class for complex numbers#ifndef __CXH_H__#define __CXH_H__class ComplexBody;class Complex {public:friend const Complex operator+(const Complex &, const Complex&);friend const Complex operator-(const Complex &, const Complex&);friend const bool operator==(const Complex &, const Complex&);friend const bool operator!=(const Complex &, const Complex&);friend ostream& operator<<(ostream&, const Complex&);Complex(const double = 0, const double = 0);Complex(const Complex&);~Complex();Complex& operator=(const Complex&);Complex& operator+=(const Complex&);Complex& operator-=(const Complex&);const double Real() const;const double Imaginary() const;private:ComplexBody *m_pcxb;};#endifComplex Handle Class Implementation// cxh.cpp// this file contains the implementation of the// handle class for complex numbers#include <iostream>using namespace std;#include "cxh.h"#include "cxb.h"// + operatorconst Complex operator+(const Complex& cx1, const Complex& cx2){ComplexBody cxbResult;cxbResult = *cx1.m_pcxb+*cx2.m_pcxb;return Complex(cxbResult.Real(),cxbResult.Imaginary());}// - operatorconst Complex operator-(const Complex& cx1, const Complex& cx2){ComplexBody cxbResult;cxbResult = *cx1.m_pcxb-*cx2.m_pcxb;return Complex(cxbResult.Real(),cxbResult.Imaginary());}// == operatorconst bool operator==(const Complex& cx1, const Complex& cx2){return *cx1.m_pcxb==*cx2.m_pcxb;}// != operatorconst bool operator!=(const Complex& cx1, const Complex& cx2){return *cx1.m_pcxb!=*cx2.m_pcxb;}// << operatorostream& operator<<(ostream& os, const Complex& cx) {os << *cx.m_pcxb;return os;}// constructor from a pair of doublesComplex::Complex(const double dReal, const double dImaginary) :m_pcxb(new ComplexBody(dReal, dImaginary)) {}// copy constructorComplex::Complex(const Complex& cx) : m_pcxb(new ComplexBody(*cx.m_pcxb)){}// destructorComplex::~Complex() {delete m_pcxb;}// = operatorComplex& Complex::operator=(const Complex& cx) {if (m_pcxb!=cx.m_pcxb) {delete m_pcxb;m_pcxb = new ComplexBody(*cx.m_pcxb);}return *this;}// += operatorComplex& Complex::operator+=(const Complex& cx) {*this = *this+cx;return *this;}// -= operatorComplex& Complex::operator-=(const Complex& cx) {*this = *this-cx;return *this;}// return real partconst double Complex:: Real() const{return m_pcxb->Real();}// return imaginary partconst double Complex:: Imaginary() const{return m_pcxb->Imaginary();}Complex Body Class Header// cxb.h// this file contains the interface to the// simple complex number class// now being used as the body for the complex handle class#ifndef __CXB_H__#define __CXB_H__class ComplexBody {public:friend const ComplexBody operator+(const ComplexBody &, const ComplexBody&);friend const ComplexBody operator-(const ComplexBody &, const ComplexBody&);friend const bool operator==(const ComplexBody &, const ComplexBody&);friend const bool operator!=(const ComplexBody &, const ComplexBody&);friend ostream& operator<<(ostream&, const ComplexBody&);ComplexBody(const double = 0, const double = 0);ComplexBody(const ComplexBody&);~ComplexBody();ComplexBody& operator=(const ComplexBody&);ComplexBody& operator+=(const ComplexBody&);ComplexBody& operator-=(const ComplexBody&);const double Real() const {return m_dReal;}const double Imaginary() const {return m_dImaginary;}private:double m_dReal;double m_dImaginary;};#endifComplex Body Class Implementation// cxb.cpp// this file contains the implementation of the // simple complex number class// now being used as the body for the complex handle class#include <iostream>using namespace std;#include "cxb.h"// + operatorconst ComplexBody operator+(const ComplexBody& cxb1,const ComplexBody& cxb2){return ComplexBody(cxb1.m_dReal+cxb2.m_dReal, cxb1.m_dImaginary+cxb2.m_dImaginary);}// - operatorconst ComplexBody operator-(const ComplexBody& cxb1,const ComplexBody& cxb2){return ComplexBody(cxb1.m_dReal-cxb2.m_dReal, cxb1.m_dImaginary-cxb2.m_dImaginary);}// == operatorconst bool operator==(const ComplexBody& cxb1,const ComplexBody& cxb2){return ((cxb1.m_dReal==cxb2.m_dReal) &&(cxb1.m_dImaginary==cxb2.m_dImaginary));}// != operatorconst bool operator!=(const ComplexBody& cxb1,const ComplexBody& cxb2){return !(cxb1==cxb2);}// << operatorostream& operator<<(ostream& os, const ComplexBody& cxb){ os <<'('<<cxb.m_dReal<<','<<cxb.m_dImaginary<<')';return os; }// constructor from a pair of doublesComplexBody::ComplexBody(const double dReal, const double dImaginary) : m_dReal(dReal), m_dImaginary(dImaginary){}// copy constructorComplexBody::ComplexBody(const ComplexBody& cxb) :m_dReal(cxb.m_dReal), m_dImaginary(cxb.m_dImaginary){}// destructorComplexBody::~ComplexBody(){// scribble on data to make desctruted members recognizablem_dReal=123456789;m_dImaginary=987654321;}// = operatorComplexBody& ComplexBody::operator=(const ComplexBody& cxb){if (&cxb!=this) {m_dReal=cxb.m_dReal; m_dImaginary=cxb.m_dImaginary;}return *this;}// += operatorComplexBody& ComplexBody::operator+=(const ComplexBody& cxb){*this = *this + cxb;return *this;}// -= operatorComplexBody& ComplexBody::operator-=(const ComplexBody& cxb){*this = *this - cxb;return *this;}Main// mainh.cpp// this is the test procedure for the// handle class for complex numbers#include <iostream>using namespace std;#include "cxh.h"// output four complex vars and a messagevoid Dump(char * szMessage, const Complex& cx1, const Complex& cx2, const Complex& cx3, const Complex& cx4){cout << szMessage << ':' << endl;cout << "cx1=" << cx1 << endl;cout << "cx2=" << cx2 << endl;cout << "cx3=" << cx3 << endl;cout << "cx4=" << cx4 << endl;cout << endl;}// main test procedurevoid main() {Complex cx1(1,1);Complex cx2(1),cx3(5);Complex cx4;Dump("After constructors",cx1,cx2,cx3,cx4);cx3=cx4=cx1+cx2-cx3;Dump("After first assignment",cx1,cx2,cx3,cx4);cx3+=cx3;Dump("After +=",cx1,cx2,cx3,cx4);cx3-=cx4;Dump("After -=",cx1,cx2,cx3,cx4);}/*output:After constructors:cx1=(1,1)cx2=(1,0)cx3=(5,0)cx4=(0,0)After first assignment:cx1=(1,1)cx2=(1,0)cx3=(-3,1)cx4=(-3,1)After +=:cx1=(1,1)cx2=(1,0)cx3=(-6,2)cx4=(-3,1)After -=:cx1=(1,1)cx2=(1,0)cx3=(-3,1)cx4=(-3,1)*/Complex - handle/body version with use countingThe handle/body paradigm also lends itself to use counting (also called reference counting). That’s where the same instance of a body (representation) may be shared by multiple instances of the handle class. This can save space as well as facilitate other functionality that wouldn’t be possible without the shared representation. All kernal objects in the Win32 API environment are use counted handle/body objects. They include file access objects, virtual memory objects, and semaphores. There are different ways of implementing use counting. The one shown here makes use of multiple inheritance (a topic explored further in another lecture). A representation object is defined as inheriting from the body object and from a use counting object.Use Counting Class Header// uc.h// this file contains the interface to the// UseCount class#ifndef __UC_H__#define __UC_H__class UseCount {public:UseCount();virtual ~UseCount();void Increment();void Decrement();unsigned int Count() const;private:unsigned int m_uiUseCount;};#endifUse Counting Class Implementation// uc.cpp// this file contains the implementation of the // UseCount class#include <iostream>using namespace std;#include "uc.h"// constructorUseCount::UseCount() : m_uiUseCount(0){}// destructorUseCount::~UseCount(){}// increment use countvoid UseCount::Increment() {m_uiUseCount++;}// decrement use countvoid UseCount::Decrement() {if (--m_uiUseCount <= 0)delete this;}// accessorunsigned int UseCount::Count() const{return m_uiUseCount;}Complex Handle Class Header// cxhu.h// this file contains the interface to the// handle class for complex numbers#ifndef __CXHU_H__#define __CXHU_H__class ComplexUCBody;class Complex {public:friend const Complex operator+(const Complex &, const Complex&);friend const Complex operator-(const Complex &, const Complex&);friend const bool operator==(const Complex &, const Complex&);friend const bool operator!=(const Complex &, const Complex&);friend ostream& operator<<(ostream&, const Complex&);Complex(const double = 0, const double = 0);Complex(const Complex&);~Complex();Complex& operator=(const Complex&);Complex& operator+=(const Complex&);Complex& operator-=(const Complex&);const double Real() const;const double Imaginary() const;private:ComplexUCBody *m_pcxub;};#endifComplex Handle Class Implementation// cxhu.cpp// this file contains the implementation of the// handle class for complex numbers// the rep here is used counted#include <iostream>using namespace std;#include "cxhu.h"#include "cxb.h"#include "uc.h"// use counted complex bodyclass ComplexUCBody: public ComplexBody, public UseCount{public:ComplexUCBody(){}ComplexUCBody(double dReal, double dImaginary) :ComplexBody(dReal, dImaginary){}ComplexUCBody(const ComplexBody& cxb) : ComplexBody(cxb){}};// << operatorostream& operator<<(ostream& os, const ComplexUCBody& cxub) {os << "Value="<< dynamic_cast<const ComplexBody&>(cxub)<< "; UseCount:"<< cxub.Count();return os;}// + operatorconst Complex operator+(const Complex& cx1, const Complex& cx2){ComplexUCBody cxubResult;cxubResult = *cx1.m_pcxub+*cx2.m_pcxub;return Complex(cxubResult.Real(),cxubResult.Imaginary());}// - operatorconst Complex operator-(const Complex& cx1, const Complex& cx2){ComplexUCBody cxubResult;cxubResult = *cx1.m_pcxub-*cx2.m_pcxub;return Complex(cxubResult.Real(),cxubResult.Imaginary());}// == operatorconst bool operator==(const Complex& cx1, const Complex& cx2){return *cx1.m_pcxub==*cx2.m_pcxub;}// != operatorconst bool operator!=(const Complex& cx1, const Complex& cx2){return *cx1.m_pcxub!=*cx2.m_pcxub;}// << operatorostream& operator<<(ostream& os, const Complex& cx) {os << *cx.m_pcxub;return os;}// constructor from a pair of doublesComplex::Complex(const double dReal, const double dImaginary) :m_pcxub(new ComplexUCBody(dReal, dImaginary)) {m_pcxub->Increment();}// copy constructorComplex::Complex(const Complex& cx) : m_pcxub(cx.m_pcxub) {m_pcxub->Increment();}// destructorComplex::~Complex() {m_pcxub->Decrement();}// = operatorComplex& Complex::operator=(const Complex& cx) {if (m_pcxub!=cx.m_pcxub) {m_pcxub->Decrement();m_pcxub = cx.m_pcxub;m_pcxub->Increment();}return *this;}// += operatorComplex& Complex::operator+=(const Complex& cx) {*this = *this+cx;return *this;}// -= operatorComplex& Complex::operator-=(const Complex& cx) {*this = *this-cx;return *this;}// return real partconst double Complex:: Real() const{return m_pcxub->Real();}// return imaginary partconst double Complex:: Imaginary() const{return m_pcxub->Imaginary();}Main// mainhu.cpp// this is the test procedure for the// handle class for complex numbers#include <iostream>using namespace std;#include "cxhu.h"// output four complex vars and a messagevoid Dump(char * szMessage, const Complex& cx1, const Complex& cx2, const Complex& cx3, const Complex& cx4){cout << szMessage << ':' << endl;cout << "cx1:" << cx1 << endl;cout << "cx2:" << cx2 << endl;cout << "cx3:" << cx3 << endl;cout << "cx4:" << cx4 << endl;cout << endl;}// main test procedurevoid main() {Complex cx1(1,1);Complex cx2(1),cx3(5);Complex cx4;Dump("After constructors",cx1,cx2,cx3,cx4);cx3=cx4=cx1+cx2-cx3;Dump("After first assignment",cx1,cx2,cx3,cx4);cx3+=cx3;Dump("After +=",cx1,cx2,cx3,cx4);cx3-=cx4;Dump("After -=",cx1,cx2,cx3,cx4);}/*output:After constructors:cx1:Value=(1,1); UseCount:1cx2:Value=(1,0); UseCount:1cx3:Value=(5,0); UseCount:1cx4:Value=(0,0); UseCount:1After first assignment:cx1:Value=(1,1); UseCount:1cx2:Value=(1,0); UseCount:1cx3:Value=(-3,1); UseCount:2cx4:Value=(-3,1); UseCount:2After +=:cx1:Value=(1,1); UseCount:1cx2:Value=(1,0); UseCount:1cx3:Value=(-6,2); UseCount:1cx4:Value=(-3,1); UseCount:1After -=:cx1:Value=(1,1); UseCount:1cx2:Value=(1,0); UseCount:1cx3:Value=(-3,1); UseCount:1cx4:Value=(-3,1); UseCount:1*/TemplatesThis section deals with templates. The program and headers that you find in this section find the extreme (greatest, least, et al) elements in a singly linked list (which is also implemented by these files). swap.h// swap.h// template for Swap#ifndef __SWAP_H__#define __SWAP_H__template <typename T>class Swap {public: void operator()(T * pt1, T * pt2) { T tTemp; tTemp=*pt1; *pt1=*pt2; *pt2=tTemp; }};#endif;findex.h// findex.h// template for FindExtreme#ifndef __FINDEXTREME_H__#define __FINDEXTREME_H__// finds the extreme element in a container // based on passed comparison functortemplate < typename ForwardIterator, typename ComparisonFunction, typename SwapFunction>ForwardIterator FindExtreme( ForwardIterator fiStart, ForwardIterator fiEnd, ComparisonFunction Compare, SwapFunction Swap){ ForwardIterator fiExtreme = fiStart; ForwardIterator fiCurrent; for(fiCurrent=fiStart; fiCurrent!=fiEnd; fiCurrent++) if(Compare(*fiCurrent,*fiExtreme)) Swap(&(*fiCurrent),&(*fiExtreme)); return fiExtreme;}#endiflist.h// list.h// template for singly linked lists#ifndef __LIST_H__#define __LIST_H__#ifndef NULL#define NULL 0L#endif// template for list node classtemplate <typename T>class ListNode {public:// constructor from link, but no dataListNode(ListNode<T>* pln) : m_plnNext(pln) {}// constructor from data and linkListNode(T t, ListNode<T>* pln) : m_tData(t), m_plnNext(pln) {}// return dataT& Data() {return m_tData;}// return next nodeListNode<T> * Next() {return m_plnNext;}// set next nodevoid SetNext(ListNode<T> *plnNext) {m_plnNext=plnNext;}private:// dataT m_tData;// pointer to next nodeListNode<T> * m_plnNext;};// template for list classtemplate <typename T>class List {public:class iterator;friend class iterator;// iterator for listsclass iterator {public:friend class List<T>;// default constructoriterator() : m_pln(NULL) {}// != operatorbool operator!=(const iterator& iter) const {return m_pln!=iter.m_pln;}// prefix incrementiterator& operator++() {m_pln=m_pln->Next(); return *this;}// postfix incrementiterator operator++(int) {iterator iterTemp=*this; m_pln=m_pln->Next(); return iterTemp;}// * operatorT& operator*() {return m_pln->Data();}private:// pointer to a node in the listListNode<T> * m_pln;// constructor from a list nodeiterator(ListNode <T>* pln) : m_pln(pln) {}};// add an element to the back of the listvoid PushBack(T t) {ListNode<T> * pln; pln=new ListNode<T>(t,m_plnHead); m_plnLast->SetNext(pln);m_plnLast = pln;}// return the start of the listiterator begin() const {return iterator(m_plnHead->Next());}// return the end of the listiterator end() const {return iterator(m_plnHead);}// default constructorList () {ListNode<T> * pln; pln=new ListNode<T>(NULL); pln->SetNext(pln);m_plnHead = pln;m_plnLast = pln;}// assignment operatorList& operator=(const List& lst){if (&lst!=this) {// clear old dataListNode<T> * pln = m_plnHead->Next();ListNode<T> * plnTemp;while(pln!=m_plnHead) {plnTemp = pln->Next();pln->SetNext(NULL);delete pln;pln = plnTemp;}m_plnHead->SetNext(m_plnHead);m_plnLast=m_plnHead; // insert new datapln = lst.m_plnHead->Next();while(pln!=lst.m_plnHead) {PushBack(pln->Data());pln=pln->Next();}}return *this;}// copy constructorList (const List& lst){ListNode<T> * pln;pln=new ListNode<T>(NULL); pln->SetNext(pln);m_plnHead = pln;m_plnLast = pln;pln = lst.m_plnHead->Next();while(pln!=lst.m_plnHead) {PushBack(pln->Data());pln=pln->Next();}}// destructor~List () {ListNode<T> * pln = m_plnHead->Next();ListNode<T> * plnTemp;while(pln!=m_plnHead) {plnTemp = pln->Next();pln->SetNext(NULL);delete pln;pln = plnTemp;}delete m_plnHead;}private:ListNode <T>* m_plnHead;// pointer to a node marking the endListNode <T>* m_plnLast;// pointer to the last node};#endiffet.cpp// fet.cpp// FindExtreme example// build line for MSVC: cl /GX fet.cpp#include <iostream>#include <functional>#include <string>#include <cstdlib>#include "list.h"#include "findex.h"#include "swap.h"using namespace std;// prints contents of a container which has a forward iterator// stored type must have an insertion operatortemplate < typename Container > void Print(Container container){ Container::iterator citer; for (citer=container.begin();citer!=container.end();citer++) cout<<(*citer)<<' '; }long main(){ char * szNames[]= { "Nick", "Mike", "Louise", "Steve", "Ronnie", "Mark", "Kathy" }; List<string> lsNames; List<int> liNumbers; int i; for(i=0;i<10;i++) liNumbers.PushBack(rand()%100-50); cout << "List of numbers:" << endl; Print(liNumbers); cout<<endl; cout << "Maximum value: " << *FindExtreme( liNumbers.begin(), liNumbers.end(), greater<int>(), Swap<int>() ) << endl; cout << "Minimum value: " << *FindExtreme( liNumbers.begin(), liNumbers.end(), less<int>(), Swap<int>() ) << endl; cout<<endl; for(i=0;i<sizeof(szNames)/sizeof(char *);i++) lsNames.PushBack(szNames[i]); cout << "List of strings:" << endl; Print(lsNames); cout<<endl; cout << "Maximum value: " << *FindExtreme( lsNames.begin(), lsNames.end(), greater<string>(), Swap<string>() ) << endl; cout << "Minimum value: " << *FindExtreme( lsNames.begin(), lsNames.end(), less<string>(), Swap<string>() ) << endl; cout<<endl; return 0;}/* output:List of numbers:-9 17 -16 -50 19 -26 28 8 12 14 Maximum value: 28Minimum value: -50List of strings:Nick Mike Louise Steve Ronnie Mark Kathy Maximum value: SteveMinimum value: Kathy*/STL OverviewThe STL (Standard Template Library) is can be thought of as consisting of five components:ContainersIteratorsAlgorithmsFunctorsAdaptorsContainersThese classes hold homogenous data and use value semantics. There are two basic types of containers:SequentialAssociativeSequential ContainersSequential containers hold data in whatever order the user inserts it. Examples of these types of containers are streams, vectors and strings.Associative ContainersAssociative containers hold keys and, possibly, data. The order is determined by the key. There are four associative containers:MapMultimapSetMultisetMapMaps hold keys and associated data. Keys must be unique.MultimapMultimaps hold keys and associated data. Keys need not be unique. There is no index operator for multimaps.SetSets only hold keys. Keys must be unique.MultisetMultisets only hold keys. Keys need not be unique.IteratorsThe iterator classes provide access to the data in containers. They may be thought of as generalized pointers. There are five types of iterators:Input IteratorsOutput IteratorsForward IteratorsBidrectional IteratorsRandom Access InteratorsInput IteratorsInput iterators may read data stored in a container and move forward. You may not modify data through an input iterator. The istream and ifstream iterators are input iterators.Output IteratorsOutput iterators may write data to a container and move forward. You may not read data through an output iterator. The ostream and ofstream iterators are output iterators.Forward IteratorsForward iterators merge the functionality of input iterators and output iterators. They may be stored and restored so they may be used to iterate over the same container multiple times. This is an abstraction that is used by the algorithms interface.Bidirectional IteratorsBidirectional iterators have all of the functionality of forward iterators and allow you to move back by one element in addition to moving forward by one element. Maps, sets, and lists contain bidirectional iterators.Random Access InteratorsRandom access iterators have all of the functionality of bidirectional iterators in addition to indexing. You may also perform arithmetic on them by subracting to iterators to determine their distance, adding an integer to an iterator to move forward that may positions, and subtracting an integer from one to move back that many positions. Vectors and deques contain random access iterators.AlgorithmsThe algorithms in the STL are manipulate the contents of containers. Some modify the contents (such as transform or sort) others find elements of the container that meet a particular criteria (such as find and count).FunctorsThese are function objects; they make it easier to write the other parts of the STL (sometimes called the “work horses” of the STL). They provide a way to forward calls to operators such as greater (‘>’) and minus (‘-‘).AdaptorsThese implement functionality in terms of other components of the STL. There are adaptors for containers, iterators, and algorithms. For example, stack is an adaptor. You can have a stack<string> and it will implement the stack in terms of a deque<string> by default. You could also specify that you would like a stack<string, vector <string> > and it will use a vector of strings as a representation instead.STL Container ExamplesThis section is about the STL and presents examples of uses of different containers.reunion.txtThis file is reunion.txt; it is used as input to listwrds.cpp in the next section.Reunionby Dan Leachfor VivianShe comes naked to the partyWith nothing to call her ownShe comes naked to the partySo beautiful and aloneAll that she has to giveIs a kind word and a smileAll that she has to give Is some warmth for a whileSomething that she would have givenEven if you’d just met herSomething that she would have givenLike the touch of a featherSo soft that its hardly thereBut enough so that you know itSo soft that its hardly thereBut like a dandelion, you blow itAnd she’s gone.-------------------------------------------------Published in Autumn/Winter, 1996 issue of CQlistwrds.cpp// listwrds.cpp// uses STL set to list words in text#pragma warning(disable:4786)#include <iostream>#include <fstream>#include <string>#include <set>#include <string>#include <iterator>using namespace std;void main(unsigned int unArgumentCount, char * szArguments[]){if (unArgumentCount!=2)cerr << "Usage: " << szArguments[0] << " file-name" << endl;else{set<string> ss;set<string>::iterator ssi;string s;ifstream ifInputFile(szArguments[1]);while(ifInputFile>>s)ss.insert(s);for (ssi=ss.begin();ssi!=ss.end();ssi++)cout<<*ssi<<endl;}}/*Program Output when applied to reunion.txt ("Reunion" by Dan Leach):-------------------------------------------------1996AllAndAutumn/Winter,ButCQDanEvenIsLeachLikePublishedReunionSheSoSomethingVivianWithaaloneandbeautifulblowbycallcomesdandelion,enoughfeatherforgivegivengone.hardlyhashaveherifinissueititsjustkindknowlikemetnakednothingofownpartysheshe'ssmilesosoftsomethatthetheretotouchwarmthwhilewordwouldyouyou'd*/answer.txtThis file is answer.txt; it is used as input to countw.cpp in the next section.In answer to a questionby Dan LeachFor KathyWhat do I do with letters from you?Funny you should ask...Since they come to the tuneOf one a blue moon,It's not much of a task.But usually, I boil them --Along with tannin leaves.This alone can raise the mummyThat I've buried beneath the eaves --Of course, he hasn't gotten Much exercise recently...-------------------------------------------------Published by The National Library of Poetry in Sea of Treasures, in December of 1995countw.cpp// countw.cpp// uses STL map to count words in text#pragma warning(disable:4786)#include <iostream>#include <fstream>#include <string>#include <map>#include <string>#include <iterator>using namespace std;void main(unsigned int uiArgumentCount, char * szArguments[]){map<string, int> msi;map<string, int>::iterator msii;string s;if (uiArgumentCount!=2) cerr << "Usage: " << szArguments[0] << " file-name" << endl;else{ifstream ifInputFile(szArguments[1]);while(ifInputFile>>s)msi[s]++;for (msii=msi.begin();msii!=msi.end();msii++)cout<<msii->first<<':'<<msii->second<<endl;}} /*Program Output when applied to answer.txt ("In Answer to a Question" by Dan Leach):--:2-------------------------------------------------:11995:1Along:1But:1Dan:1December:1For:1Funny:1I:2I've:1In:1It's:1Kathy:1Leach:1Library:1Much:1National:1Of:2Poetry:1Published:1Sea:1Since:1That:1The:1This:1Treasures,:1What:1a:3alone:1answer:1ask...:1beneath:1blue:1boil:1buried:1by:2can:1come:1course,:1do:2eaves:1exercise:1from:1gotten:1hasn't:1he:1in:2leaves.:1letters:1moon,:1much:1mummy:1not:1of:4one:1question:1raise:1recently...:1should:1tannin:1task.:1the:3them:1they:1to:2tune:1usually,:1with:2you:1you?:1*/mapex.cpp// mapex.cpp// example of use of an STL map#pragma warning(disable:4786)#include <iostream>#include <string>#include <map>#include <iterator>using namespace std;void main(){map<string, int> msi;map<string, int>::iterator msii;msi["Mark"]=100;msi["Bill"]=200;msi["Joan"]=150;msi["Pam"]=250;cout << "Mark:" << msi["Mark"] << endl;cout << "Bill:" << msi["Bill"] << endl;cout << "Joan:" << msi["Joan"] << endl;cout << "Pam:" << msi["Pam"] << endl;cout << endl;for (msii=msi.begin();msii!=msi.end();msii++)cout << msii->first << ':' << msii->second << endl;} /*Program Output is:Mark:100Bill:200Joan:150Pam:250Bill:200Joan:150Mark:100Pam:250*/mmex.cpp// mmex.cpp// this is an example of a multimap#include <map>#include <string>#include <algorithm>#include <iostream>using namespace std;// this is a functor for determining if this is the nth// occurrance of a keytemplate <typename Key, typename Data>class Predicate{public:bool operator()(pair<Key, Data> pkd){if (pkd.first == m_kFind)m_iSoFar++;return m_iSoFar>=m_iCount;}Predicate(Key k, int i=1) :m_kFind(k), m_iCount(i), m_iSoFar(0){}private:Key m_kFind;int m_iCount;int m_iSoFar;};void main(){// write a search for nth in a multimap...multimap<string,string> mm;mm.insert(mm.end(),pair<string,string>("dan","1st"));mm.insert(mm.end(),pair<string,string>("dan","2nd"));mm.insert(mm.end(),pair<string,string>("dan","3rd"));mm.insert(mm.end(),pair<string,string>("bob","first"));mm.insert(mm.end(),pair<string,string>("bob","second"));multimap<string,string>::iterator mmi;cout << "this is the multimap:\n";for(mmi=mm.begin();mmi!=mm.end();mmi++)cout << mmi->first << ':' << mmi->second << endl;cout << endl << "going to find the 1st occurance of \"bob\":\n";mmi = find_if(mm.begin(),mm.end(),Predicate<string,string>("bob",1));if(mmi!=mm.end())cout << mmi->first << ':' << mmi->second << endl;elsecout << "not found\n";cout << endl << "going to find the 2nd occurance of \"dan\":\n";mmi = find_if(mm.begin(),mm.end(),Predicate<string,string>("dan",2));if(mmi!=mm.end())cout << mmi->first << ':' << mmi->second << endl;elsecout << "not found\n";cout << endl << "going to find the 4th occurance of \"dan\":\n";mmi = find_if(mm.begin(),mm.end(),Predicate<string,string>("dan",4));if(mmi!=mm.end())cout << mmi->first << ':' << mmi->second << endl;elsecout << "not found\n";cout << endl << "going to find the 4th occurance of \"george\":\n";mmi = find_if(mm.begin(),mm.end(),Predicate<string,string>("george",4));if(mmi!=mm.end())cout << mmi->first << ':' << mmi->second << endl;elsecout << "not found\n";}/*output:this is the multimap:bob:firstbob:seconddan:1stdan:2nddan:3rdgoing to find the 1st occurance of "bob":bob:firstgoing to find the 2nd occurance of "dan":dan:2ndgoing to find the 4th occurance of "dan":not foundgoing to find the 4th occurance of "george":not found*/listex.cpp// listex.cpp// example of use of an STL list#pragma warning(disable:4786)#include <iostream>#include <string>#include <list>using namespace std;void main(){list<string> ls;ls.push_back("Dallas");ls.push_back("Fort Worth");ls.push_back("Boston");ls.push_back("Miami");ls.push_back("Tampa");list<string>::iterator lsi;for (lsi=ls.begin(); lsi!=ls.end(); lsi++)cout << *lsi << endl;}/* Program output:DallasFort WorthBostonMiamiTampa*/stackex.cpp// stackex.cpp// example of use of an STL stack#pragma warning(disable:4786)#include <iostream>#include <string>#include <stack>using namespace std;void main(){stack< string > stk;string s1("Dallas");string s2("Fort Worth");string s3("Boston");string s4("NYC");stk.push(s1);stk.push(s2);stk.push(s3);stk.push(s4);while (!stk.empty()) {cout << () << " ";stk.pop();}cout << endl;} /*Program Output is:NYC Boston Fort Worth Dallas */dequeex.cpp// dequeex.cpp// example of use of an STL deque#pragma warning(disable:4786)#include <iostream>#include <deque>using namespace std;void main(){deque<char *> dqsz;dqsz.push_front("Dallas");dqsz.push_front("Fort Worth");dqsz.push_front("Boston");dqsz.push_front("Miami");dqsz.push_front("Tampa");deque<char *>::iterator dqszi;for (dqszi=dqsz.begin(); dqszi!=dqsz.end(); dqszi++)cout << *dqszi << endl;}/* Program output:TampaMiamiBostonFort WorthDallas*/A Larger Example of Using Containers in the STLThis section contains definitions for a graph template, a shortest path template function, and a test program for the shortest path and graph templates.graph.h// graph.h// a template graph class#ifndef __GRAPH_H__#define __GRAPH_H__// don't report warning that names are too long#pragma warning(disable:4786)#pragma warning(disable:4503)#include <iostream>#include <map>#include <set>using namespace std;// template to return if t is a member of mtstemplate <typename T, typename S>bool PrFindFirst(map<T,S> mts, T t){map<T,S>::const_iterator mtsi;for (mtsi=mts.begin();(mtsi!=mts.end()) &&(mtsi->first!=t);mtsi++);return mtsi!=mts.end();}// template graph classtemplate <typename V, typename W>class Graph {public:// default ctorGraph(bool bUndirected = true) :m_bUndirected(bUndirected){}// ctor from a setGraph(set<V> sv, bool bUndirected = true) :m_bUndirected(bUndirected){set<V>::const_iterator svi;map<V,W> mvw;for (svi=sv.begin(); svi!=sv.end(); svi++)m_mGraph[*svi]=mvw;}// start vertexV StartVertex(){return m_mGraph.begin()->first;}// add a vertex to the graph if not already presentvoid AddVertex(V v){map< V, map<V,W> >::const_iterator mvmvwi;map<V,W> mvw;if (!PrFindFirst(m_mGraph,v))m_mGraph[v]=mvw;}// remove a vertex from the graph if presentvoid RemoveVertex(V v){if (PrFindFirst(m_mGraph,v)) {map<V,W>::const_iterator mvwi;map<V,W> mvw=m_mGraph[v];for (mvwi=mvw.begin();mvwi!=mvw.end();mvwi++) Break(v,mvwi->first);if (!m_bUndirected) {map< V, map<V,W> >::const_iterator mvmvwi;for (mvmvwi=m_mGraph.begin(); mvmvwi!=m_mGraph.end();mvmvwi++) Break(mvmvwi->first,v);}m_mGraph.erase(v);}}// join two vertexes using the indicated weight;// add each vertex to the graph if not already presentvoid Join(V v1,V v2,W w){AddVertex(v1);AddVertex(v2);(m_mGraph[v1])[v2]=w;if (m_bUndirected)(m_mGraph[v2])[v1]=w;}// remove an arc from two adjacent vertexesvoid Break(V v1,V v2){if (Adjacent(v1,v2)) {(m_mGraph[v1]).erase(v2);if (m_bUndirected)(m_mGraph[v2]).erase(v1);}}// print the graph to coutvoid Print(){map< V, map<V,W> >::const_iterator mvmvwi;bool bFirst=true;for (mvmvwi=m_mGraph.begin(); mvmvwi!=m_mGraph.end();mvmvwi++) {cout << mvmvwi->first;if (!(mvmvwi->second).empty()) {cout << ':';map<V,W>::const_iterator mvwi;for (mvwi=(mvmvwi->second).begin();mvwi!=(mvmvwi->second).end();mvwi++) {if (!bFirst)cout << ", ";bFirst=false;cout << '(' << mvmvwi->first;cout << ',' << mvwi->first;cout << ',' << mvwi->second;cout << ')';}bFirst=true;}cout << endl;}}// return true if two vertexes // (which must be present in the graph)// are joinedbool Adjacent(V v1,V v2){bool bAdjacent=false;if (PrFindFirst(m_mGraph,v1)) {if (PrFindFirst(m_mGraph[v1],v2))bAdjacent=true;}return bAdjacent;}// return the set of all vertexes that are joined to// the indicated vertexset<V> Adjacent(V v){set<V> sv;if (PrFindFirst(m_mGraph,v)) {map<V,W>::const_iterator mvwi;for (mvwi=m_mGraph[v].begin(); mvwi!=m_mGraph[v].end();mvwi++)sv.insert(mvwi->first);}return sv;}// return the map of all vertexes that are joined to// the indicated vertexmap<V,W> AdjacencyMap(V v){map<V,W> mvw;if (PrFindFirst(m_mGraph,v))mvw=m_mGraph[v];return mvw;}// return if the graph is emptybool Empty(){return m_mGraph.empty();}// return if the vertex is in the graphbool InGraph(V v){return PrFindFirst(m_mGraph,v);}// return iterator containing first vertexmap< V, map<V,W> >::const_iterator FirstVertex(){return m_mGraph.begin();}// return iterator containing end vertexmap< V, map<V,W> >::const_iterator EndVertex(){return m_mGraph.end();}// return the weight of the arc if two vertexes // (which must be present in the graph)// are joined; 0, otherwiseW Weight(V v1, V v2){W w=0;if (Adjacent(v1,v2))w=m_mGraph[v1][v2];return w;}inline bool Undirected(){return m_bUndirected;}inline unsigned int NumberOfVertexes(){return m_mGraph.size();}private:// graph representationmap < V, map <V,W> > m_mGraph;bool m_bUndirected;};#endifshortest.h// shortest.h// shortest path template#ifndef __SHORTEST_H__#define __SHORTEST_H__#include "graph.h"#include <list>using namespace std;// prints contents of a container which has a forward iterator// stored type must have an insertion operatortemplate < typename T > void Print(T t){T::const_iterator ti;bool bFirst = true;for (ti=t.begin();ti!=t.end();ti++) {if (!bFirst)cout << ", ";elsebFirst = false;cout<< *ti;}}template <typename V, typename W>Graph<V,W> ShortestPath(Graph<V,W> g, V vStart, V vEnd){Graph<V,W> gShortestPathFound(false);Graph<V,W> gFringe(false);Graph<V,W> gShortestPath(g.Undirected());W wDistance;V v;W w;map<V,W> mvw;map<V,W>::const_iterator mvwi;map< V, map<V,W> >::const_iterator mvmvwi;V vMin;W wMin;V vParent;V vMinParent;bool bMinSet=false;list<V> lvPath;if (!g.InGraph(vStart))// vStart not in greturn gShortestPath;if (!g.InGraph(vEnd))// vEnd not in greturn gShortestPath;gShortestPathFound.AddVertex(vStart);V vCurrent = vStart;wDistance=0;while (vCurrent != vEnd) {// rebuild fringemvw = g.AdjacencyMap(vCurrent);for (mvwi=mvw.begin();mvwi!=mvw.end();mvwi++){// v is vertex under considerationv=mvwi->first;if (!gShortestPathFound.InGraph(v)){// w is distance to v through vCurrentw=wDistance+g.Weight(vCurrent,v);if (gFringe.InGraph(v)){// already in fringe, replace parent?if (w<gFringe.Weight( v, ((gFringe.AdjacencyMap(v).begin()))->first)){gFringe.RemoveVertex(v);gFringe.Join(v,vCurrent,w);}}else// add to fringegFringe.Join(v,vCurrent,w);}}if (gFringe.Empty())// no path from vStart to vEndreturn gShortestPath;// find edge with minimum distancebMinSet=false;for ( mvmvwi=gFringe.FirstVertex(); mvmvwi!=gFringe.EndVertex(); mvmvwi++){if(!mvmvwi->second.empty()){v=(*mvmvwi).first;vParent=(mvmvwi->second.begin())->first;w=gFringe.Weight(v,vParent);if (!bMinSet){// no min yet; take this onevMin=v;vMinParent=vParent;wMin=w;bMinSet=true;}else{// replace min?if (w<wMin) {vMin=v;vMinParent=vParent;wMin=w;}}}}// remove vMin from fringegFringe.RemoveVertex(vMin);// join to shortest path foundgShortestPathFound.Join(vMin,vMinParent,wMin);// determine whether to remove vMinParent from fringebool bRemove=true;for ( mvmvwi=gFringe.FirstVertex(); bRemove && mvmvwi!=gFringe.EndVertex(); mvmvwi++){if(gFringe.Adjacent(mvmvwi->first,vMinParent))bRemove=false;}if (bRemove)gFringe.RemoveVertex(vMinParent);// set up for next timevCurrent=vMin;wDistance=wMin;}cout << "\nAll shortest paths found:\n";gShortestPathFound.Print();// build shortest pathgShortestPath.AddVertex(vEnd);V vNext;cout << "\nThe shortest path from "<< vStart << " to " << vEnd << " was: ";lvPath.push_front(vEnd);for (v=vEnd;v!=vStart;v=vNext){vNext=(gShortestPathFound.AdjacencyMap(v).begin())->first;gShortestPath.Join(vNext,v,g.Weight(vNext,v));lvPath.push_front(vNext);}Print(lvPath);cout << endl;cout << "Its length was: " << wMin << endl;return gShortestPath;}#endifshorttst.cpp// shorttst.cpp// test program for the shortest path in a graph#include <iostream>#include <set>#include <string>#include "graph.h"#include "shortest.h"using namespace std;// main test procedurevoid main(){ // build the set of nodes set<string> ss; ss.insert("A"); ss.insert("B"); ss.insert("C"); ss.insert("D"); ss.insert("E"); ss.insert("F"); ss.insert("G"); ss.insert("H"); ss.insert("I"); // build a graph from the set of nodes Graph<string,int> gsi(ss); // connect them gsi.Join("A","B",2); gsi.Join("A","G",5); gsi.Join("A","F",9); gsi.Join("B","G",6); gsi.Join("B","C",4); gsi.Join("C","H",5); gsi.Join("C","D",2); gsi.Join("D","H",1); gsi.Join("D","E",1); gsi.Join("E","I",3); gsi.Join("E","F",6); gsi.Join("F","I",1); gsi.Join("G","I",2); gsi.Join("G","H",5); gsi.Join("I","H",4); // print the graph cout << "This is the graph:\n"; gsi.Print(); // test shortest path Graph<string,int> gsisp = ShortestPath(gsi,string("A"),string("H")); cout << "\nThis is the computed graph:\n"; gsisp.Print();}/* output:This is the graph:A:(A,B,2), (A,F,9), (A,G,5)B:(B,A,2), (B,C,4), (B,G,6)C:(C,B,4), (C,D,2), (C,H,5)D:(D,C,2), (D,E,1), (D,H,1)E:(E,D,1), (E,F,6), (E,I,3)F:(F,A,9), (F,E,6), (F,I,1)G:(G,A,5), (G,B,6), (G,H,5), (G,I,2)H:(H,C,5), (H,D,1), (H,G,5), (H,I,4)I:(I,E,3), (I,F,1), (I,G,2), (I,H,4)All shortest paths found:AB:(B,A,2)C:(C,B,6)D:(D,C,8)E:(E,D,9)F:(F,I,8)G:(G,A,5)H:(H,D,9)I:(I,G,7)The shortest path from A to H was: A, B, C, D, HIts length was: 9This is the computed graph:A:(A,B,2)B:(B,A,2), (B,C,4)C:(C,B,4), (C,D,2)D:(D,C,2), (D,H,1)H:(H,D,1)*/Algorithms examplesThese examples are based on examples in chapter 5 from C++ Programming with the Standard Template Library, David R. Musser and Atul Saini, Addison Wesley, 1996, ISBN 0-201-63398-1.vs.h // this provides conversion functions // between vectors and strings#include <vector>#include <iostream>#include <string>using namespace std;template <typename T> void Print(T t){ T::iterator ti; for (ti=t.begin(); ti!=t.end(); ti++) cout << *ti; cout << endl;}vector<char> StringToVector(string s){ vector<char> vc(s.length()); vector<char>::iterator vci; string::iterator si; for ( si=s.begin(), vci=vc.begin(); ((si!=s.end()) && (vci!=vc.end())); si++,vci++ ) *vci=*si; return vc;}string VectorToString(vector<char> vc){ string s(""); vector<char>::iterator vci; for (vci=vc.begin(); vci!=vc.end(); vci++) s+=*vci; return s;}EX05-01.CPP // Using an in-place generic sort algorithm.#include <algorithm>#include <cassert>using namespace std;void main() { int iData[1000]; for (int i = 0; i < 1000; i++) iData[i] = 1000 - i - 1; sort(&iData[0], &iData[1000]); for (i = 0; i < 1000; i++) assert(iData[i] == i);}/* output: */EX05-02.CPP // Using reverse_copy, a copying version of the // generic reverse algorithm.#include <algorithm>#include <cassert>using namespace std;void main() { int iDataSrc[1000], iDataCpy[1000]; for (int i = 0; i < 1000; i++) iDataSrc[i] = i; reverse_copy(&iDataSrc[0], &iDataSrc[1000], &iDataCpy[0]); for (i = 0; i < 1000; i++) assert(iDataSrc[i] == i && iDataCpy[i] == 1000 - i - 1);}/* output: */EX05-03.CPP // Using the generic sort algorithm with a binary predicate.#include <algorithm>#include <functional> #include <cassert>using namespace std;void main() { int iData[1000]; for (int i = 0; i < 1000; i++) iData[i] = i; random_shuffle(&iData[0], &iData[1000]); // Sort into ascending order: sort(&iData[0], &iData[1000]); for (i = 0; i < 1000; i++) assert(iData[i] == i); random_shuffle(&iData[0], &iData[1000]); // Sort into descending order: sort(&iData[0], &iData[1000], greater<int>()); for (i = 0; i < 1000; i++) assert(iData[i] == 1000 - i - 1);}/* output: */EX05-04.CPP // Illustrating the generic find_if algorithm.#include <algorithm>#include <vector>#include <cassert>using namespace std;// Define a unary predicate object type: class GreaterThan50 { public: bool operator()(int i) const { return i > 50; }};void main(){ // Create a vector with values 0, 1, 4, 9, 16, ..., 144: vector<int> vi; for (int i = 0; i < 13; ++i) vi.push_back(i * i); vector<int>::iterator vii; vii = find_if(vi.begin(), vi.end(), GreaterThan50()); assert(*vii == 64);}/* output: */EX05-05.CPP // Illustrating the generic adjacent_find algorithm.#include <algorithm>#include <string>#include <deque>#include <functional>#include <cassert>using namespace std;void main(){ deque<string> ds(5, string()); deque<string>::iterator dsi; // Initialize the deque: ds[0] = "Pele"; ds[1] = "Platini"; ds[2] = "Maradona"; ds[3] = "Maradona"; ds[4] = "Rossi"; // Find the first pair of equal consecutive names: dsi = adjacent_find(ds.begin(), ds.end()); assert(*dsi == "Maradona" && *(dsi+1) == "Maradona"); // Find the first name that is lexicographically // greater than the following name: dsi = adjacent_find(ds.begin(), ds.end(), greater<string>()); assert(*dsi == "Platini" && *(dsi+1) == "Maradona");}/* output: */EX05-06.CPP // Illustrating the generic count algorithm.#include <functional>#include <algorithm>#include <cassert>using namespace std;void main(){ int iData[] = {0, 0, 0, 1, 1, 1, 2, 2, 2}; int iFinalCount; // Count the number of values in the array a // that are equal to 1: iFinalCount = count(&iData[0], &iData[9], 1); assert(iFinalCount == 3); // Determine the number of array elements that are not // equal to 1: iFinalCount = count_if(iData, iData + 9, bind2nd(not_equal_to<int>(), 1)); assert(iFinalCount == 6); // There are 6 elements not equal to 1.}/* output: */EX05-07.CPP // Illustrating the generic for_each algorithm.#include <algorithm>#include <string>#include <list>#include <iostream>using namespace std;void PrintList(string s){ cout << s << endl;}void main(){ list<string> ls; ls.insert(ls.end(), "Clark"); ls.insert(ls.end(), "Rindt"); ls.insert(ls.end(), "Senna"); // Print out each list element. for_each(ls.begin(), ls.end(), PrintList);}/* output: ClarkRindtSenna*/EX05-08.CPP // Illustrating the generic equal and mismatch algorithms.#include <algorithm>#include <string>#include <list>#include <deque>#include <cassert>#include <vector>#include <string>#include <iostream>using namespace std;void main(){ list<string> ls; vector<string> vs; deque<string> ds; ls.insert(ls.end(), "Clark"); ls.insert(ls.end(), "Rindt"); ls.insert(ls.end(), "Senna"); vs.insert(vs.end(), "Clark"); vs.insert(vs.end(), "Rindt"); vs.insert(vs.end(), "Senna"); vs.insert(vs.end(), "Berger"); ds.insert(ds.end(), "Clark"); ds.insert(ds.end(), "Berger"); // Show that ls and the first 3 elements of // vs are equal in all corresponding positions: assert(equal(ls.begin(), ls.end(), vs.begin())); // Show that ds and the first 2 elements of ls // are not equal in all corresponding positions: assert(!equal(ds.begin(), ds.end(), ls.begin())); // Find the corresponding positions in ds and ls // at which unequal elements first occur: pair<deque<string>::iterator, list<string>::iterator> pdsilsi = mismatch(ds.begin(), ds.end(), ls.begin()); if (pdsilsi.first != ds.end()) cout << "First disagreement in ds and ls:\n " << *(pdsilsi.first) << " and " << *(pdsilsi.second) << endl;}/* output: First disagreement in ds and ls: Berger and Rindt*/EX05-08A.CPP // Illustrating the generic equal and mismatch algorithms.// This is the modification of Example 5-8 discussed on p. 81, // in which the first call to equal is INCORRECT. It is // incorrect since the end of ls is reached // without finding a disagreement, causing dereferencing// beyond the end of the list.#include <algorithm>#include <string>#include <list>#include <deque>#include <cassert>#include <vector>#include <iostream>using namespace std;void main(){ list<string> ls; vector<string> vs; deque<string> ds; ls.insert(ls.end(), "Clark"); ls.insert(ls.end(), "Rindt"); ls.insert(ls.end(), "Senna"); vs.insert(vs.end(), "Clark"); vs.insert(vs.end(), "Rindt"); vs.insert(vs.end(), "Senna"); vs.insert(vs.end(), "Berger"); ds.insert(ds.end(), "Clark"); ds.insert(ds.end(), "Berger"); // Show that ls and the first 3 elements of // vs are equal in all corresponding positions: assert(equal(vs.begin(), vs.end(), ls.begin())); // INCORRECT // Show that ds and the first 2 elements of ls // are not equal in all corresponding positions: assert(!equal(ds.begin(), ds.end(), ls.begin())); // Find the corresponding positions in ds and ls // at which unequal elements first occur: pair<deque<string>::iterator, list<string>::iterator> pdsilsi = mismatch(ds.begin(), ds.end(), ls.begin()); if (pdsilsi.first != ds.end()) cout << "First disagreement in ds and ls:\n " << *(pdsilsi.first) << " and " << *(pdsilsi.second) << endl;}/* output: Assertion failed: equal(vs.begin(), vs.end(), ls.begin()), file EX05-08A.CPP, line 39abnormal program termination*/EX05-09.CPP // Illustrating the generic search algorithm.#include <algorithm>#include <vector>#include <deque>#include <cassert>using namespace std;void main(){ vector<int> vi(20); deque<int> di(5); // Initialize vector with 0, 1, ..., 19: for (int i = 0; i < 20; ++i) vi[i] = i; // Initialize deque di with 5, 6, 7, 8, 9: for (i = 0; i < 5; ++i) di[i] = i + 5; // Search for first occurrence of the deque contents // as a subsequence of the vector contents: vector<int>::iterator vii = search(vi.begin(), vi.end(), di.begin(), di.end()); for (i = 0; i < 5; ++i) assert(*(vii + i) == i + 5);}/* output: */EX05-10.CPP // Illustrating the generic copy and copy_backward algorithms.#include <vector>#include <algorithm>#include <iostream>#include <string>#include <cassert>#include "vs.h"using namespace std;void main(){ vector<char> vc1 = StringToVector("abcdefghihklmnopqrstuvwxyz"); vector<char> vc2(vc1.size()); // Copy vc1 to vc2: copy(vc1.begin(), vc1.end(), vc2.begin()); assert(vc1 == vc2); // Shift the contents of vc1 left by 4 positions: copy(vc1.begin() + 4, vc1.end(), vc1.begin()); assert(VectorToString(vc1) == string("efghihklmnopqrstuvwxyzwxyz")); // Shift it right by 2 positions: copy_backward(vc1.begin(), vc1.end() - 2, vc1.end()); assert(VectorToString(vc1) == string("efefghihklmnopqrstuvwxyzwx"));}/* output: */EX05-11.CPP // Illustrating the generic fill and fill_n algorithms.#include <algorithm>#include <vector>#include <string>#include <cassert>#include "vs.h"using namespace std;void main(){ vector<char> vc = StringToVector("Hello there"); // Fill first 5 positions of vc with X's: fill(vc.begin(), vc.begin() + 5, 'X'); assert(VectorToString(vc) == string("XXXXX there")); // Fill 3 more positions with Y's. fill_n(vc.begin() + 5, 3, 'Y'); assert(VectorToString(vc) == string("XXXXXYYYere"));}/* output: */EX05-12.CPP // Illustrating the generic generate algorithm.#include <algorithm>#include <vector>#include <cassert>using namespace std;class CalcSquare { int m_i; public: CalcSquare(): m_i(0) {} int operator()() { ++m_i; return m_i * m_i; }};void main(){ vector<int> vi(10); // Fill vi with 1, 4, 9, 16, ..., 100 generate(vi.begin(), vi.end(), CalcSquare()); for (int i = 0; i < 10; ++i) assert(vi[i] == (i+1)*(i+1));}/* output: */EX05-13.CPP // Illustrating the generic partition and stable_partition algorithms.#include <algorithm>#include <vector>#include <string>#include <iostream>using namespace std;bool Above40(int i) { return (i > 40); }void main(){ const int iSize = 7; int iData1[iSize] = {50, 30, 10, 70, 60, 40, 20}; int iData2[iSize]; copy(&iData1[0], &iData1[iSize], &iData2[0]); ostream_iterator<int> out(cout, " "); cout << "Original sequence: "; copy(&iData2[0], &iData2[iSize], out), cout << endl; // Partition iData2, putting numbers greater than 40 // first, followed by those less than or equal to 40: int* split = partition(&iData2[0], &iData2[iSize], Above40); cout << "Result of (unstable) partitioning: "; copy(&iData2[0], split, out), cout << "| "; copy(split, &iData2[iSize], out), cout << endl; // Restore iData2 to iData1 contents: copy(&iData1[0], &iData1[iSize], &iData2[0]); // Again partition iData2, putting numbers greater than 40 // first, followed by those less than or equal to 40, // preserving relative order in each group: split = stable_partition(&iData2[0], &iData2[iSize], Above40); cout << "Result of stable partitioning: "; copy(&iData2[0], split, out), cout << "| "; copy(split, &iData2[iSize], out), cout << endl;}/* output: Original sequence: 50 30 10 70 60 40 20 Result of (unstable) partitioning: 50 60 70 | 10 30 40 20 Result of stable partitioning: 50 70 60 | 30 10 40 20 */EX05-14.CPP // Illustrating the random_shuffle algorithm.#include <algorithm>#include <vector>#include <functional> #include <iostream>using namespace std;void main() { const int iSize = 20; vector<int> vi(iSize); int i; for (i = 0; i < iSize; ++i) vi[i] = i; for (i = 0; i < 3; ++i) { // Randomly shuffle the integers in vi: random_shuffle(vi.begin(), vi.end()); // Output the contents of vi: copy(vi.begin(), vi.end(), ostream_iterator<int>(cout, " ")); cout << endl; }}/* output: 4 19 0 17 10 12 8 11 18 1 6 16 7 14 9 3 13 2 5 15 17 9 10 15 8 2 11 16 6 18 19 7 4 13 0 14 12 5 1 3 6 19 3 18 4 12 8 1 0 11 17 5 9 2 10 15 7 16 14 13 */EX05-15.CPP // Illustrating the generic remove algorithm.#include <algorithm>#include <vector>#include <cassert>using namespace std;void main(){ const int iSize = 11; int iData[iSize] = {1, 2, 0, 3, 4, 0, 5, 6, 7, 0, 8}; vector<int> vi; for (int i = 0; i < iSize; ++i) vi.push_back(iData[i]); // Remove the zeros from vi: vector<int>::iterator viiNewEnd; viiNewEnd = remove(vi.begin(), vi.end(), 0); // The size of vi remains the same: assert(vi.size() == iSize); // The nonzero elements are left in // [vi.begin(), viiNewEnd). Erase the rest: vi.erase(viiNewEnd, vi.end()); // Show that 3 elements were removed and the // nonzero elements remain, in their original order: assert(vi.size() == iSize - 3); for (i = 0; i < vi.size(); ++i) assert(vi[i] == i+1);}/* output: */EX05-16.CPP // Illustrating the generic replace algorithm.#include <algorithm>#include <vector>#include <cassert>#include <string>using namespace std;void main(){ string s("FERRARI"); // Replace all occurrences of R by S: replace(s.begin(), s.end(), 'R', 'S'); assert(s == string("FESSASI"));}/* output: */EX05-17.CPP // Illustrating the generic rotate algorithm.#include <algorithm>#include <vector>#include <cassert>#include <string>#include "vs.h"using namespace std;void main(){ vector<char> vc = StringToVector("Software Engineering "); // Rotate the vector so that "Engineering " comes first: rotate(vc.begin(), vc.begin() + 9, vc.end()); assert(VectorToString(vc) == string("Engineering Software "));}/* output: */EX05-18.CPP // Illustrating the generic swap algorithm.#include <algorithm>#include <cassert>using namespace std;void main(){ int iHigh = 250, iLow = 0; swap(iHigh, iLow); assert(iHigh == 0 && iLow == 250);}/* output: */EX05-19.CPP // Illustrating the generic swap_ranges algorithm.#include <algorithm>#include <vector>#include <cassert>using namespace std;void main(){ vector<char> vc1, vc2; char cData1[5] = {'H', 'E', 'L', 'L', 'O'}; char cData2[5] = {'T', 'H', 'E', 'R', 'E'}; // Initialize vectors: for (int i = 0; i < 5; i++) { vc1.push_back(cData1[i]); vc2.push_back(cData2[i]); } // Save vc1 and vc2 contents, for checking: vector<char> vc3 = vc1, vc4 = vc2; // Swap the contents of vc1 and vc2: swap_ranges(vc1.begin(), vc1.end(), vc2.begin()); assert(vc1 == vc4 && vc2 == vc3);}/* output: */EX05-20.CPP // Illustrating the generic transform algorithm.#include <algorithm>#include <iostream>int Sum(int i1, int i2) { return i2 + i1; }using namespace std;void main(){ int iData1[5] = {0, 1, 2, 3, 4}; int iData2[5] = {6, 7, 8, 9, 10}; ostream_iterator<int> oii(cout, " "); // Put sums of corresponding iData1 and iData2 elements // into output stream transform(&iData1[0], &iData1[5], &iData2[0], oii, Sum); cout << endl;}/* output: 6 8 10 12 14 */EX05-21.CPP // Illustrating the generic unique algorithm.#include <algorithm>#include <vector>#include <cassert>#include <iostream>using namespace std;void main(){ const int iSize = 11; int iData[iSize] = {1, 2, 0, 3, 3, 0, 7, 7, 7, 0, 8}; vector<int> vi; for (int i = 0; i < iSize; ++i) vi.push_back(iData[i]); // Eliminate consecutive duplicates from vi: vector<int>::iterator viiNewEnd; viiNewEnd = unique(vi.begin(), vi.end()); // The size of vi remains the same; assert(vi.size() == iSize); // The nonconsecutive duplicate elements are left in // [vi.begin(), viiNewEnd). Erase the rest: vi.erase(viiNewEnd, vi.end()); // Put the resulting vi contents on the // standard output stream: copy(vi.begin(), vi.end(), ostream_iterator<int>(cout, " ")); cout << endl;}/* output: 1 2 0 3 0 7 0 8 */EX05-22.CPP // Illustrating the generic sort, stable_sort, and partial_sort algorithms.#include <vector>#include <algorithm>#include <iostream>class CompLast { public: bool operator()(int i1, int i2) // Compare i1 and i2 based on their last base-10 digits: { return i1 % 10 < i2 % 10; }};using namespace std;void main(){ const int iSize = 20; vector<int> vi1; for (int i = 0; i != iSize; ++i) vi1.push_back(i); vector<int> vi2 = vi1; ostream_iterator<int> out(cout, " "); cout << "Before sorting:\n"; copy(vi2.begin(), vi2.end(), out); cout << endl; sort(vi2.begin(), vi2.end(), CompLast()); cout << "After sorting by last digits with sort:\n"; copy(vi2.begin(), vi2.end(), out); cout << endl << endl; vi2 = vi1; cout << "Before sorting:\n"; copy(vi2.begin(), vi2.end(), out); cout << endl; stable_sort(vi2.begin(), vi2.end(), CompLast()); cout << "After sorting by last digits with stable_sort:\n"; copy(vi2.begin(), vi2.end(), out); cout << endl << endl; vi2 = vi1; reverse(vi2.begin(), vi2.end()); cout << "Before sorting:\n"; copy(vi2.begin(), vi2.end(), out); cout << endl << endl; partial_sort(vi2.begin(), vi2.begin() + 5, vi2.end(), CompLast()); cout << "After sorting with partial_sort to get\n" << "5 values with smallest last digits:\n"; copy(vi2.begin(), vi2.end(), out); cout << endl << endl;}/* output: Before sorting:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 After sorting by last digits with sort:10 0 11 1 12 2 13 3 4 14 5 15 6 16 7 17 8 18 9 19 Before sorting:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 After sorting by last digits with stable_sort:0 10 1 11 2 12 3 13 4 14 5 15 6 16 7 17 8 18 9 19 Before sorting:19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 After sorting with partial_sort to get5 values with smallest last digits:10 0 11 1 12 19 18 17 16 15 9 8 7 6 5 4 14 13 3 2 */EX05-23.CPP // Illustrating the generic nth_element algorithm.#include <vector>#include <algorithm>#include <cassert>using namespace std;void main(){ vector<int> vi(7); vi[0] = 25; vi[1] = 7; vi[2] = 9; vi[3] = 2; vi[4] = 0; vi[5] = 5; vi[6] = 21; const int iSize = 4; // Use nth_element to place the Nth smallest // element in vi in the Nth position, vi.begin() + iSize: nth_element(vi.begin(), vi.begin() + iSize, vi.end()); // Check that the element at vi.begin() + iSize, vi[iSize], is // greater than or equal to each of the preceding elements: for (int i = 0; i != iSize; ++i) assert(vi[iSize] >= vi[i]); // Check that the element at vi.begin() + iSize, vi[iSize], is // less than or equal to each of the following elements: for (i = iSize + 1; i != 7; ++i) assert(vi[iSize] <= vi[i]);}/* output: */EX05-24.CPP // Illustrating the generic binary search algorithms.#include <algorithm>#include <vector>#include <cassert>using namespace std;void main(){ vector<int> vi(5); bool bFound; // Initialize: for(int i = 0; i < 5; i++) vi[i] = i; // Search for each of the integers 0, 1, 2, 3, 4: for (i = 0; i < 5; i++) { bFound = binary_search(vi.begin(), vi.end(), i); assert(bFound == true); } // Try searching for a value that's not present: bFound = binary_search (vi.begin(), vi.end(), 9); assert(bFound == false); vi[1] = 7; vi[2] = 7; vi[3] = 7; vi[4] = 8; // Vector vi now contains: 0 7 7 7 8 vector<int>::iterator vii; // Apply upper_bound, lower_bound and equal_range on v: vii = lower_bound(vi.begin(), vi.end(), 7); assert(vii == vi.begin() + 1 && *vii == 7); vii = upper_bound(vi.begin(), vi.end(), 7); assert(vii == vi.end() - 1 && *vii == 8); pair<vector<int>::iterator, vector<int>::iterator> pvivi = equal_range(vi.begin(), vi.end(), 7); assert(pvivi.first == vi.begin() + 1); assert(pvivi.second == vi.end() - 1);}/* output: */EX05-25.CPP // Illustrating the generic merge algorithms.#include <vector>#include <algorithm>#include <cassert>using namespace std;void main(){ // Initialize vector of integers: vector<int> vi1(5); vector<int> vi2(5); vector<int> vi3(10); for (int i = 0; i < 5; i++) vi1[i] = 2 * i; for (i = 0; i < 5; i++) vi2[i] = 1 + 2 * i; // Merge contents of vi1 and vi2, // putting result in vi3: merge(vi1.begin(), vi1.end(), vi2.begin(), vi2.end(), vi3.begin()); for (i = 0; i < 10; i++) assert(vi3[i] == i); for (i = 0; i < 5; i++) vi3[i] = vi1[i]; for (i = 0; i<5; i++) vi3[i + 5] = vi2[i]; // Merge the two sorted halves of vi3 // in place to obtain a sorted vi3: inplace_merge(vi3.begin(), vi3.begin() + 5, vi3.end()); for (i = 0; i < 10; i++) assert(vi3[i] == i);}/* output: */EX05-26.CPP // Illustrating the generic set operations.#include <vector>#include <algorithm>#include <cassert>using namespace std;void main(){ bool result; // Initialize a vectors of characters: vector<char> vc1(5); vector<char> vc2(5); char cData1[5] = { 'a', 'b', 'c', 'd', 'e' }; char cData2[5] = { 'a', 'e', 'i', 'o', 'u' }; for(int i = 0; i < 5; i++) vc1[i] = cData1[i]; for(i = 0; i < 5; i++) vc2[i] = cData2[i]; // Illustrate includes: result = includes(vc1.begin(), vc1.end(), vc2.begin(), vc2.end()); assert(result == false); // Illustrate set_union(): vector<char> vcSetUnion(8); set_union(vc1.begin(), vc1.end(), vc2.begin(), vc2.end(), vcSetUnion.begin()); assert(vcSetUnion[0] == 'a'); assert(vcSetUnion[1] == 'b'); assert(vcSetUnion[2] == 'c'); assert(vcSetUnion[3] == 'd'); assert(vcSetUnion[4] == 'e'); assert(vcSetUnion[5] == 'i'); assert(vcSetUnion[6] == 'o'); assert(vcSetUnion[7] == 'u'); // Illustrate set_intersection: vector<char> setIntersection(2); set_intersection(vc1.begin(), vc1.end(), vc2.begin(), vc2.end(), setIntersection.begin()); assert(setIntersection[0] == 'a'); assert(setIntersection[1] == 'e'); // Illustrate set_symmetric_difference: vector<char> vcSetDiff(6); set_symmetric_difference(vc1.begin(), vc1.end(), vc2.begin(), vc2.end(), vcSetDiff.begin()); assert(vcSetDiff[0] == 'b'); assert(vcSetDiff[1] == 'c'); assert(vcSetDiff[2] == 'd'); assert(vcSetDiff[3] == 'i'); assert(vcSetDiff[4] == 'o'); assert(vcSetDiff[5] == 'u');}/* output: */ EX05-27.CPP // Illustrating the generic heap operations.#include <vector>#include <algorithm>#include <cassert>using namespace std;void main(){ // Initialize a vector of integers: vector<int> vi(5); for (int i = 0; i < 5; i++) vi[i] = i; random_shuffle(vi.begin(), vi.end()); // Sort the vector using push_heap and pop_heap: for (i = 2; i < 5; i++) push_heap(vi.begin(), vi.begin() + i); for (i = 5; i >= 2; i--) pop_heap(vi.begin(), vi.begin() + i); // Verify that the array is sorted: for (i = 0; i < 5; i++) assert(vi[i] == i); // Shuffle the elements again: random_shuffle(vi.begin(), vi.end()); // Sort the vector using make_heap and sort_heap: make_heap(vi.begin(), vi.end()); sort_heap(vi.begin(), vi.end()); // Verify that the array is sorted: for (i = 0; i < 5; i++) assert(vi[i] == i);}/* output: */EX05-28.CPP // Illustrating the generic min_element and max_element algorithms.#include <vector>#include <algorithm>#include <cassert>using namespace std;void main(){ // Initialize a vector of integers: vector<int> vi(5); for(int i = 0; i < 5; i++) vi[i] = i; random_shuffle(vi.begin(), vi.end()); // Find the max_element in the container: vector<int>::iterator vii; vii = max_element(vi.begin(), vi.end()); assert(*vii == 4); // Find the min_element in the container: vii = min_element(vi.begin(), vi.end()); assert(*vii == 0);}/* output: */EX05-29.CPP // Illustrating the generic lexicographical_compare algorithm.#include <vector>#include <algorithm>#include <cassert>using namespace std;void main(){ bool bResult; // Initialize vectors of characters: vector<char> vc1(5); char cData1[5] = {'h', 'e', 'l', 'i', 'o'}; for(int i = 0; i<5; i++) vc1[i] = cData1[i]; vector<char> vc2(5); char cData2[5] = {'h', 'e', 'l', 'l', 'o'}; for(i = 0; i<5; i++) vc2[i] = cData2[i]; // Show that vc1 is lexicographically less than // vc2: bResult = lexicographical_compare(vc1.begin(), vc1.end(), vc2.begin(), vc2.end()); assert(bResult == true);}/* output: */EX05-30.CPP // Illustrating the generic permutation algorithms.#include <vector>#include <algorithm>#include <cassert>using namespace std;void main(){ // Initialize a vector of integers: vector<int> vi(3); for(int i = 0; i < 3; i++) vi[i] = i; // In lexicographical order the permutations of 0 1 2 are // 0 1 2, 0 2 1, 1 0 2, 1 2 0, 2 0 1, 2 1 0. // Show that from 0 1 2 next_permutation produces 0 2 1: next_permutation(vi.begin(), vi.end()); assert(vi[0] == 0); assert(vi[1] == 2); assert(vi[2] == 1); // Show that from 0 2 1 prev_permutation() produces 0 1 2: prev_permutation(vi.begin(), vi.end()); assert(vi[0] == 0); assert(vi[1] == 1); assert(vi[2] == 2);}/* output: */EX05-31.CPP // Illustrating the generic accumulate algorithm.#include <numeric>#include <functional>#include <cassert>using namespace std;void main(){ int iResult; int iData[20]; for (int i = 0; i < 20; i++) iData[i] = i; // Show that 5 + 0 + 1 + 2 + ... + 19 == 195: iResult = accumulate(&iData[0], &iData[20], 5); assert(iResult == 195); // Show that 10 * 1 * 2 * 3 * 4 == 240: iResult = accumulate(&iData[1], &iData[5], 10, multiplies<int>()); assert(iResult == 240);}/* output: */EX05-32.CPP // Illustrating the generic partial_sum algorithm.#include <numeric>#include <iostream>using namespace std;void main(){ const int iSize = 20; int iData1[iSize], iData2[iSize]; for (int i = 0; i != iSize; ++i) iData1[i] = i; // Compute the partial sums of 0, 1, 2, 3, ..., iSize - 1, // putting the result in iData2: partial_sum(&iData1[0], &iData1[iSize], &iData2[0]); for (i = 0; i != iSize; ++i) cout << iData2[i] << " "; cout << endl;}/* output: 0 1 3 6 10 15 21 28 36 45 55 66 78 91 105 120 136 153 171 190 */EX05-33.CPP // Illustrating the generic adjacent_difference algorithm.#include <numeric>#include <cassert>using namespace std;void main(){ const int iSize = 20; int iData1[iSize], iData2[iSize]; for (int i = 0; i != iSize; ++i) iData1[i] = i; // Compute the partial sums of 0, 1, 2, 3, ..., iSize - 1, // putting the result in iData2: partial_sum(&iData1[0], &iData1[iSize], &iData2[0]); // Compute the adjacent differences of elements in iData2, // placing the result back in iData2: adjacent_difference(&iData2[0], &iData2[iSize], &iData2[0]); // The result is the original 0, 1, 2, 3, ..., iSize - 1: for (i = 0; i != iSize; i++) assert(iData2[i] == i);}/* output: */EX05-34.CPP // Illustrating the generic inner_product algorithm.#include <numeric>#include <iostream>#include <functional>using namespace std;void main(){ const int iSize = 5; int iData1[iSize], iData2[iSize]; for (int i = 0; i != iSize; ++i) { iData1[i] = i + 1; iData2[i] = i + 2; } // Compute inner product of 1, 2, ..., iSize and 2, 3, ..., iSize+1 int result = inner_product(&iData1[0], &iData1[iSize], &iData2[0], 0); cout << "Inner product as normally defined: " << result << endl; // Again compute "inner product," with roles of + and * // reversed: result = inner_product(&iData1[0], &iData1[iSize], &iData2[0], 1, multiplies<int>(), plus<int>()); cout << "Inner product with roles of + and * reversed: " << result << endl;}/* output: Inner product as normally defined: 70Inner product with roles of + and * reversed: 10395*/String stream examplesThese examples are based on examples in the Stroustrup text.iss.cpp 1:#include <iostream> 2:#include <sstream> 3:#include <string> 4:using namespace std; 5: 6:void WordPerLine(const string& sLine) 7:{ 8:istringstream iss(sLine); 9:string sWord; 10:while (iss>>sWord) 11:cout << sWord << endl; 12:} 13: 14:void main() 15:{ 16:WordPerLine("If you think that C++ is difficult, try English."); 17:} 18: 19:/* 20:output: 21: 22:If 23:you 24:think 25:that 26:C++ 27:is 28:difficult, 29:try 30:English. 31: 32:*/oss.cpp 1:#include <iostream> 2:#include <sstream> 3:#include <string> 4:using namespace std; 5: 6:string Compose(int iErrorNumber, const string& sComment) 7:{ 8:ostringstream oss; 9:oss 10:<< "error (" 11:<< iErrorNumber 12:<< "): " 13:<< sComment 14:<< endl; 15: 16:return oss.str(); 17:} 18: 19:void main() 20:{ 21:cout << Compose (12, "File not found"); 22:} 23: 24:/* 25:output: 26: 27:error (12): File not found 28:*/Exceptions -- OverviewAn exception is something outside of the normal processing of a program.There are 2 different models of exception handling:Termination modelContinuation modelThe termination model is intended for handling errors. You may not resume processing from the point of error without re-entering the code in some way. You should use this for errors which cannot be corrected by the code that detected it.The continuation model allows you to resume processing from the point of the exception. The implication is that the exception is an error which the program can fix or an exception which is not an error.The C++ model is portable across architectures as it is part of the language. The SEH is supported only on windows platforms, but it is available from all languages that Microsoft supports (C, C++, et al).The SEH (Structured Exception Handling) supports both models. C++ exceptions (using try, catch, and throw) only supports the termination model.There are 3 C++ keywords that support its exception handling mechanism:trythis defines a block to be associated with a catch blockcatch this defines a block to be associated with a try block which may be executed if an exception is thrown in or under the try block; there are catch blocks which catch a specific type (which may either be an integral type or a user defined type) as well as those which catch all exceptions not handled by an earlier catch block throw this throws (or re-throws) an exceptionThere are 4 keywords that support the SEH in C/C++:__trythis defines a block to be associated with either an __except block or an __finally block (this roughly corresponds to try in standard C++)__finally this defines a block to be associated with an __try block which will be executed after the __try block regardless of how it terminates__except this defines a block to be associated with an __try block which will be executed if an exception is raised in or under the try block; the filter (the part in ()’s before the ‘{‘) will always be executed if the exception perculates up to this level; the handler (the part in {}’s after the filter) will only be executed if the filter returns EXCEPTION_EXECUTE_HANDLER (this roughly corresponds to catch in standard C++)__leave this allows you to leave a __try block without resulting in a local unwindThere is also some APIs that may be used:GetExceptionCode this is used to get the exception code (NOTE: this is an intrinsic function)GetExceptionInformation this is used to get both the processor independent and processor dependent information (NOTE: this is an intrinsic function)RaiseException this is used to raise a user defined exception (this roughly corresponds to throw in standard C++)An exception filter associated with an __except block must return one of the following values:EXCEPTION_CONTINUE_SEARCHreturn this value if you don’t want to handle the exception; your handler will not be executed and the OS will continue to look for a handler that will handle the exceptionEXCEPTION_EXECTUTE_HANDLER return this value if you want to handle the exception; any __finally blocks whose execution has been deferred will be executed and then your handler will be executed; execution continues after the end of the handlerEXCEPTION_CONTINUE_EXECUTION return this value if you believe you have fixed the problem that caused the exception; execution will continue at the assembly language instruction (NOTE: NOT the source level statement) that caused the exception (it will be re-executed)Basic Try-Catch-Throw Examplestct1.cpp // tct1.cpp// basic try-catch-throw model// no throw#include <iostream>using namespace std;void main(){try {cout << "in try\n";}// catch all exceptionscatch (...){cout << "in catch all\n";}cout << "after catch\n";}/*output:in tryafter catch*/ tct2.cpp // tct2.cpp// basic try-catch-throw model// with throw#include <iostream>using namespace std;void main(){try {cout << "in try before throw\n";throw 1;cout << "in try after throw\n";}// catch all exceptionscatch (...){cout << "in catch all\n";}cout << "after catch\n";}/*output:in try before throwin catch allafter catch*/tct3.cpp // tct3.cpp// basic try-catch-throw model// with throw#include <iostream>using namespace std;void main(){try {cout << "in try before throw\n";throw 1;cout << "in try after throw\n";}// catch integerscatch (int i){cout << "in catch int; value thrown was: " << i<< endl;}// catch all exceptionscatch (...){cout << "in catch all\n";}cout << "after catch\n";}/*output:in try before throwin catch int; value thrown was: 1after catch*/tct4.cpp // tct4.cpp// basic try-catch-throw model// with throw of a class#include <iostream>#include <string>using namespace std;class MyException{public:// default and string ctorMyException(string sMessage="no error") :m_sMessage(sMessage){}// accessorinline string Message() const{return m_sMessage;}private:string m_sMessage;};// test programvoid main(){try {cout << "in try before throw\n";throw MyException("this is a test message");cout << "in try after throw\n";}// catch my execptionscatch (MyException me){cout << "in catch MyException; \n"<< "message of MyExecption thrown was: \"" << me.Message()<< "\""<< endl;}// catch integerscatch (int i){cout << "in catch int; value thrown was: " << i<< endl;}// catch all exceptionscatch (...){cout << "in catch all\n";}cout << "after catch\n";}/*output:in try before throwin catch MyException; message of MyExecption thrown was: "this is a test message"after catch*/tct5.cpp // tct5.cpp// basic try-catch-throw model// with throw of a class// this throws a derived class and catches it through the base class#include <iostream>#include <string>using namespace std;class MyException{public:// default and string ctorMyException(string sMessage="no error") :m_sMessage(sMessage){}// accessorinline string Message() const{return m_sMessage;}private:string m_sMessage;};class MyDerivedException : public MyException{public:MyDerivedException() : MyException(){}MyDerivedException(string sMessage) : MyException(sMessage){}};// test programvoid main(){try {cout << "in try before throw\n";throw MyDerivedException("this is a test message");cout << "in try after throw\n";}// catch my execptionscatch (MyException me){cout << "in catch MyException; \n"<< "message of MyExecption thrown was: \"" << me.Message()<< "\""<< endl;}// catch my derived execptionscatch (MyDerivedException mde){cout << "in catch MyDerivedException; \n"<< "message of MyDerivedExecption thrown was: \"" << mde.Message()<< "\""<< endl;}// catch integerscatch (int i){cout << "in catch int; value thrown was: " << i<< endl;}// catch all exceptionscatch (...){cout << "in catch all\n";}cout << "after catch\n";}/*output from VC 6.0:tct5.cpptct5.cpp(63) : warning C4286: 'class MyDerivedException' : is caught by base class ('class MyException') on line 52Microsoft (R) Incremental Linker Version 6.00.8447Copyright (C) Microsoft Corp 1992-1998. All rights reserved./out:tct5.exe tct5.obj program output:in try before throwin catch MyException; message of MyExecption thrown was: "this is a test message"after catch*/tct6.cpp // tct6.cpp// basic try-catch-throw model// with throw of a class#include <iostream>#include <string>using namespace std;class MyException{public:// default and string ctorMyException(string sMessage="no error") :m_sMessage(sMessage){}// accessorinline string Message() const{return m_sMessage;}private:string m_sMessage;};class MyDerivedException : public MyException{public:MyDerivedException() : MyException(){}MyDerivedException(string sMessage) : MyException(sMessage){}};// test programvoid main(){try {cout << "in try before throw\n";throw MyDerivedException("this is a test message");cout << "in try after throw\n";}// catch my derived execptionscatch (MyDerivedException mde){cout << "in catch MyDerivedException; \n"<< "message of MyDerivedExecption thrown was: \"" << mde.Message()<< "\""<< endl;}// catch my execptionscatch (MyException me){cout << "in catch MyException; \n"<< "message of MyExecption thrown was: \"" << me.Message()<< "\""<< endl;}// catch integerscatch (int i){cout << "in catch int; value thrown was: " << i<< endl;}// catch all exceptionscatch (...){cout << "in catch all\n";}cout << "after catch\n";}/*output:in try before throwin catch MyDerivedException; message of MyDerivedExecption thrown was: "this is a test message"after catch*/SEH Examplessehfin.cpp // sehfin.cpp// illustrates a control flow with a finally block#include <iostream>using namespace std;void main(){__try {cout << "in __try\n";}__finally {cout << "in __finally\n";}}/*output:in __tryin __finally*/sehfinzd.cpp // sehfinzd.cpp// causes a divide by zero to show exec path with a finally block#include <iostream>using namespace std;void main(){__try {cout << "in __try before div by 0\n";int iZero = 0;int i = 1/iZero;cout << "in __try after div by 0\n";}__finally {cout << "in __finally\n";}}/*output:in __try before div by 0in __finally*/sehfilt.cpp // sehfilt.cpp// contains an exception filter#include <iostream>using namespace std;#include <windows.h>ExceptionFilterContinueSearch(){cout << "in exception filter (returning continue search)\n";return EXCEPTION_CONTINUE_SEARCH;}ExceptionFilterExecuteHandler(){cout << "in exception filter (returning execute handler)\n";return EXCEPTION_EXECUTE_HANDLER;}ExceptionFilterContinueExecution(){cout << "in exception filter (returning continue execution)\n";return EXCEPTION_CONTINUE_EXECUTION;}void main(){__try {cout << "in __try (level 1)\n";__try {cout << "in __try (level 2)\n";__try {cout << "in __try (level 3)\n";RaiseException(0xE0000001,// my exection code0,0,NULL);cout << "after RaiseException in __try (level 3)\n";}__except(ExceptionFilterContinueSearch()){cout << "handling exception for __try (level 3)\n";}}__except(ExceptionFilterExecuteHandler()){cout << "handling exception for __try (level 2)\n";}__try {cout << "in __try (2nd level 2)\n";RaiseException(0xE0000001,// my exection code0,0,NULL);cout << "after RaiseException in __try (2nd level 2)\n";}__except(ExceptionFilterContinueExecution()){cout << "handling exception for __try (2nd level 2)\n";}}__finally {cout << "in __finally\n";}}/* output:in __try (level 1)in __try (level 2)in __try (level 3)in exception filter (returning continue search)in exception filter (returning execute handler)handling exception for __try (level 2)in __try (2nd level 2)in exception filter (returning continue execution)after RaiseException in __try (2nd level 2)in __finally*/sehtct.cpp // sehtct.cpp// illustrated merged seh/try-catch-throw#include <iostream>using namespace std;#include <windows.h>#include <eh.h>// converts structured exception to C++ exceptionclass StructuredExeceptionConversion {public:// call this function for each threadstatic void MapSEtoCE(){_set_se_translator(TranslateSEtoCE);}// unsigned int conversion opoperator unsigned int() const{return (m_er.ExceptionCode); }private:// ctor from PEXCEPTION_POINTERSStructuredExeceptionConversion(PEXCEPTION_POINTERS pep){m_er = *pep->ExceptionRecord;m_context = *pep->ContextRecord;}// callback registered by MapSEtoCE()static void _cdecl TranslateSEtoCE(UINT dwEC,PEXCEPTION_POINTERS pep){throw StructuredExeceptionConversion(pep);}EXCEPTION_RECORD m_er;CONTEXT m_context;};// print an error messagevoid ExecptionMessage(const StructuredExeceptionConversion& sec){switch(sec)// calls unsigned int() operator{case EXCEPTION_ACCESS_VIOLATION:cout << "error was access violation\n";break;case EXCEPTION_INT_DIVIDE_BY_ZERO:cout << "error was divide by zero\n";break;default:cout << "error was something else; rethrowing\n";throw;break;}}// test programvoid main(){// register callback for translation// should be called for each threadStructuredExeceptionConversion::MapSEtoCE();// test conversion of access violationtry{cout << "about to commit an access violation\n";// access violation*(int *) 0 = 0;cout << "after access violation\n";}catch(StructuredExeceptionConversion& sec){cout << "in catch after access violation\n";ExecptionMessage(sec);}// test conversion of divide by zerotry{cout << "about to commit divide by zero\n";// divide by zeroint i = 0;i = 5/i;cout << "after divide by zero\n";}catch(StructuredExeceptionConversion& sec){cout << "in catch after divide by zero\n";ExecptionMessage(sec);}cout << "end of main\n";}/*output:about to commit an access violationin catch after access violationerror was access violationabout to commit divide by zeroin catch after divide by zeroerror was divide by zeroend of main*/Larger Try-Catch-Throw ExampleThis is the basis for homework 8.queuet.h // queuet.h// this is a template queue class#ifndef __QUEUET_H__#define __QUEUET_H__#include <iostream>using namespace std;// queue errorsenum QueueError {QUEUE_NO_ERROR,QUEUE_UNDERFLOW,QUEUE_OUT_OF_MEMORY};// queue exceptionsclass QueueException {public:// ctorQueueException(QueueError qe=QUEUE_UNDERFLOW) {m_qe=qe;}// accessorQueueError GetQueueError() {return m_qe;}private:QueueError m_qe;};// queue nodestemplate <typename T>class QueueNode {public:// ctor from dataQueueNode(T t) : m_tData(t), m_pqnNext(NULL) {}// ctor from data and next ptrQueueNode(T t, QueueNode<T>* pqn) : m_tData(t), m_pqnNext(pqn) {}// accessorsT Data() {return m_tData;}QueueNode<T> * Next() {return m_pqnNext;}void SetNext(QueueNode<T> * pqn) {m_pqnNext=pqn;}private:T m_tData;QueueNode<T> * m_pqnNext;};// queuetemplate <typename T>class Queue {public:// remove and return front elementT Serve () {if (m_uiQueueSize==0)throw QueueException(QUEUE_UNDERFLOW);T t;QueueNode<T> * pqn=m_pqnHead; t=m_pqnHead->Data();m_pqnHead = m_pqnHead->Next();m_uiQueueSize--;if (m_uiQueueSize==0)m_pqnTail = NULL;delete pqn;return t;}// add element to endvoid Append (T t) {QueueNode<T> * pqn; pqn=new QueueNode<T>(t,NULL); if (pqn==NULL)throw QueueException(QUEUE_OUT_OF_MEMORY);if (m_pqnTail!=NULL)m_pqnTail->SetNext(pqn);m_pqnTail = pqn;if (m_pqnHead==NULL)m_pqnHead = pqn;m_uiQueueSize++;}// output queuevoid Print () { QueueNode<T> * pqn = m_pqnHead; cout << "*Head*"<<endl;while(pqn!=NULL) {cout << pqn->Data() << endl;pqn = pqn->Next();}cout << "*Tail*"<<endl;}// ctorQueue () : m_uiQueueSize(0), m_pqnHead(NULL), m_pqnTail(NULL) {}// copy ctorQueue (const Queue & q) : m_uiQueueSize(0), m_pqnHead(NULL), m_pqnTail(NULL){QueueNode<T> * pqnOld = q.m_pqnHead; QueueNode<T> * pqnLast = NULL;QueueNode<T> * pqnNew;T t;while(pqnOld!=NULL) {t=pqnOld->Data();pqnNew=new QueueNode<T>(t);if (pqnNew==NULL)throw QueueException(QUEUE_OUT_OF_MEMORY);if (m_pqnHead==NULL)m_pqnHead=pqnNew;if (pqnLast!=NULL)pqnLast->SetNext(pqnNew);pqnLast=pqnNew;m_pqnTail=pqnLast;m_uiQueueSize++;pqnOld = pqnOld->Next();}}// assignment opQueue& operator=(const Queue & q){QueueNode<T> * pqnOld = q.m_pqnHead; QueueNode<T> * pqnLast = NULL;QueueNode<T> * pqnNew;QueueNode<T> * pqn = m_pqnHead; QueueNode<T> * pqnTemp = NULL;T t;if (this!=&q) {// destroy old Queuewhile(pqn!=NULL) {pqnTemp = pqn->Next();delete pqn;pqn = pqnTemp;}m_uiQueueSize=0;while(pqnOld!=NULL) {t=pqnOld->Data();pqnNew=new QueueNode<T>(t);if (pqnNew==NULL)throw QueueException(QUEUE_OUT_OF_MEMORY);if (m_pqnHead==NULL)m_pqnHead=pqnNew;if (pqnLast!=NULL)pqnLast->SetNext(pqnNew);pqnLast=pqnNew;m_pqnTail=pqnLast;m_uiQueueSize++;pqnOld = pqnOld->Next();}}return *this;}// dtor~Queue () {QueueNode<T> * pqn = m_pqnHead; QueueNode<T> * pqnTemp = NULL;while(pqn!=NULL) {pqnTemp = pqn->Next();delete pqn;pqn = pqnTemp;}}// accessorint Size() const {return m_uiQueueSize;}private:unsigned int m_uiQueueSize;QueueNode <T>* m_pqnHead;QueueNode <T>* m_pqnTail;};// remove first two elements// add them and append to endtemplate <typename T>void Plus(Queue <T> * q){T tArg1;T tArg2;try {tArg1=q->Serve();tArg2=q->Serve();q->Append(tArg1+tArg2);}catch(QueueException & qe) {if (qe.GetQueueError()==QUEUE_UNDERFLOW)cout << "(in Plus) Queue UNDERFLOW!" << endl;else {cout << "(in Plus) Other Queue Error - Rethrowing" << endl;throw qe;}}}#endifqueuett.cpp// queuett.cpp// main test program for queue template// build line// cl /GX queuett.cpp#include <iostream>#include <string>using namespace std;#include "queuet.h"long main(){Queue<int> qi;Queue<int> qi2;Queue<string> qs;Queue<string> qs2;try {qi.Append(1);qi.Append(2);qi.Append(3);qi.Print();cout << "test of assignment operator" << endl;qi2 = qi;qi2.Print();cout << "Serve: " << qi.Serve() << endl;qi.Print();cout << "Serve: " << qi.Serve() << endl;qi.Print();cout << "Serve: " << qi.Serve() << endl;qi.Print();cout << "Serve: " << qi.Serve() << endl;qi.Print();}catch(QueueException & qe) {if (qe.GetQueueError()==QUEUE_UNDERFLOW)cout << "(in main) Queue UNDERFLOW!" << endl;else {cout << "(in main) Other Queue Error - Rethrowing" << endl;throw qe;}}cout << "this is qi2; should be unchanged" << endl;qi2.Print();Queue<int> qi3 = qi2;cout << "this is qi3; made from copy ctor" << endl;qi3.Print();try {qi.Append(1);qi.Append(2);qi.Append(3);qi.Print();Plus(&qi);qi.Print();Plus(&qi);qi.Print();Plus(&qi);qi.Print();}catch(QueueException & qe) {if (qe.GetQueueError()==QUEUE_UNDERFLOW)cout << "(in main) Queue UNDERFLOW!" << endl;else {cout << "(in main) Other Queue Error - Rethrowing" << endl;throw qe;}}try {qs.Append("one");qs.Append("two");qs.Append("three");qs.Print();cout << "test of assignment operator" << endl;qs2 = qs;qs2.Print();cout << "Serve: " << qs.Serve() << endl;qs.Print();cout << "Serve: " << qs.Serve() << endl;qs.Print();cout << "Serve: " << qs.Serve() << endl;qs.Print();cout << "Serve: " << qs.Serve() << endl;qs.Print();}catch(QueueException & qe) {if (qe.GetQueueError()==QUEUE_UNDERFLOW)cout << "(in main) Queue UNDERFLOW!" << endl;else {cout << "(in main) Other Queue Error - Rethrowing" << endl;throw qe;}}cout << "this is qs2; should be unchanged" << endl;qs2.Print();Queue<string> qs3 = qs2;cout << "this is qs3; made from copy ctor" << endl;qs3.Print();try {qs.Append("one");qs.Append("two");qs.Append("three");qs.Print();Plus(&qs);qs.Print();Plus(&qs);qs.Print();Plus(&qs);qs.Print();}catch(QueueException & qe) {if (qe.GetQueueError()==QUEUE_UNDERFLOW)cout << "(in main) Queue UNDERFLOW!" << endl;else {cout << "(in main) Other Queue Error - Rethrowing" << endl;throw qe;}}return 0;}/* output:*Head*123*Tail*test of assignment operator*Head*123*Tail*Serve: 1*Head*23*Tail*Serve: 2*Head*3*Tail*Serve: 3*Head**Tail*(in main) Queue UNDERFLOW!this is qi2; should be unchanged*Head*123*Tail*this is qi3; made from copy ctor*Head*123*Tail**Head*123*Tail**Head*33*Tail**Head*6*Tail*(in Plus) Queue UNDERFLOW!*Head**Tail**Head*onetwothree*Tail*test of assignment operator*Head*onetwothree*Tail*Serve: one*Head*twothree*Tail*Serve: two*Head*three*Tail*Serve: three*Head**Tail*(in main) Queue UNDERFLOW!this is qs2; should be unchanged*Head*onetwothree*Tail*this is qs3; made from copy ctor*Head*onetwothree*Tail**Head*onetwothree*Tail**Head*threeonetwo*Tail**Head*threeonetwo*Tail*(in Plus) Queue UNDERFLOW!*Head**Tail**/ Design TechniquesWaterfall ModelRequirements AnalysisPerformed by: Marketing or EngineeringEnd Product: Requirements SpecificationWhat it contains: What the product does viewed from the outsideFunctional AnalysisPerformed by: Engineering (team leader)End Product: Functional SpecificationWhat it contains: What the product does viewed from the insideDesignPerformed by: Engineering (team)End Product: Design SpecificationWhat it contains: How the pieces of the product fit together as viewed from the inside at a high levelLow Level DesignPerformed by: Engineering (individual engineers)End Product: Design SpecificationWhat it contains: How the pieces of the product fit together as viewed from the inside at a low level (including interface specifications)ImplementationPerformed by: Engineering (or outside contractor) (individual engineers)End Product: Source code; Implementation Specification; Maintenance ManualWhat it contains: the sourceimplementation specification (this includes where all the files are and comments as they relate to the low level design where appropriate)maintenance manual (this includes how to build product as well as bug reports and resolutions)Object Oriented DesignSpecify User Domain ObjectsTalk with the user (domain expert) and find out what the relevant nouns are. In a Dialer, one example would be a telephone number. In ProTesT (a system I helped build at Doble), the user domain objects included Relays, Nameplates, Test Plans, Tests, Test Results, Instruments, and Connection Tables. User domain objects usually drive the UI.Specify User Domain MethodsTalk with the user (domain expert) and find out what the relevant verbs are. In a Dialer, one example would be dialing a phone number. For ProTesT, an example user domain method was Execute for Tests. Specify Synthetic Methods on User Domain ObjectsThese are methods on user domain objects that don’t have to do with the user domain. Constructors, destructors, and an ability to save to a data base would be examples of synthetic methods.Specify Synthetic ObjectsThese are objects that don’t have to do with the user domain. A data base would be an example of a synthetic object. Others would include GUI objects, use-counted pointer classes, and trace objects.Specify Methods for Synthetic ObjectsThese are methods on objects that don’t have to do with the user domain.CRC cardsYou write down all of the names of the classes (user domain and synthetic) along with a brief description of each on a card. You then write down the methods and a brief description of each on the cards for that class. If they don’t fit on a card, the object is probably too big and should be layered.You may want to start this process at a meeting with domain experts (for user domain objects and methods) and then continue it at a later meeting with members of the software team (for synthetic objects and methods).PrototypingUI PrototypesIn a UI prototype, you dummy up the screens that a user would see for at least a representative part of the system. By this I mean that there would normally be no processing of information other than to connect the different pieces of the UI and show the flow of information, probably with a sample set of results. This may be implemented using a different set of tools than you plan to use in the actual system. Lots of people use VB or Delphi for this purpose even though their ultimate UI may be based on MFC or some other mechanism.One purpose of a UI Prototype is to show your domain experts and/or end users your understanding of their problem. This is usually done as part of the Functional Analysis stage in the Water Fall model and as part of the specification of User Domain Objects and Methods in OOD. You may have a number of meetings with such people as your prototype evolves through the design process until you achieve some consensus that you will have fulfilled their needs at the point at which this becomes real.Another use for the UI prototype once you are in the implementation step is as a tool for marketing and sales to show potential users what’s coming. You may get further feedback at this point which can be factored into your design.System Slice PrototypesA system slice prototype is a “proof of concept”. You chose a representative piece of system functionality and implement those parts of the system which are necessary to support this from the UI down. You might attach this to the UI prototype or you may implement those UI pieces in the real model that you expect to use in your real product. The important part of this is that the chosen slice be representative and that when you finish it, the functionality that you have implemented be real – not smoke and mirrors as in the UI prototype.This serves several purposes. One of which is to give you experience in the model sufficient to provide more realistic estimates for schedules. Another is that it validates your overall object model. You may need to adjust layering and class structure at this point. This may also be used by marketing and sales.Designing for ReuseAnticipate Base ClassesTry to anticipate which classes may be useful a base classes which are not currently base classes. These should have virtual destructors and specify functions as virtual that you envision might change in derived classes.Solve Problems in GeneralFor example, you may define a string class which better fulfills your current needs than those which are available to you. You know that today you only need constructors (one of which is based on a user defined class) and a concatenation operator. Don’t preclude implementing some of the other common string functions.Consider a handle body designThe advantage to this is that you have more flexibility in the implementation once an interface is agreed to.Reusing the DesignThere are those who say that the most reusable part of the software engineering process is the design itself. And the processes that led to successful completion of the project.Reusing the CodeThere are a number of steps in reusing code. The first of which is finding out about it (the “discovery process”). It may be easier to find out about a third party solution to a problem if you work for a large company rather than a library which was implemented as part of another project. If you implement a library that you believe may be generally useful (or, at least, useful to projects other than your current project), you should advertise it to those who might be interested since they may otherwise never know of your good works…The next is determining how close the problem that was previously solved by the code is to your problem and how well it worked in solving its intended problem (this is part of the “evaluation process”). You also need to determine who will be responsible for fixing problems that you find in previously un-exercised parts of it. If it’s an in-house class library, you may find yourself maintaining it, or you may come to some arrangement with the author. If it’s a third party solution, it may still come with source code (for example, Rogue Wave does this) that you can patch and rebuild while you’re waiting for the fix to be in an official release.You may have to specify an interface class that allows you to use the older code in the current model (the “adaptation process”). You should avoid redesigning the code if possible since changes to its interface will result in other changes to legacy code (or result in parallel maintenance if you clone the source).“Code isn’t reusable unless it’s been designed with reuse in mind.”--Anon.“Code isn’t reusable unless it’s been reused.”--MurrayCode InstrumentationCode instrumentation is the process of adding statements to your program for the sake of gathering information about the program itself rather than about the problems that it is used to solve. Sometimes this is done for the sake of debugging (both in engineering before releasing the product and in situ after the release of the product); other times for the sake of performance analysis; still other times it is done for the sake of determining testing coverage. There is also a distinction made between whether the instrumentation is done via white-box, gray-box, or black-box methods. When you use white-box methods, you are instrumenting code that you have source for and that you understand (generally as a result of having written it or worked with it extensively) by hand. When you use black-box methods, you are instrumenting code that you know little about (sometimes specifically for the sake of learning about it). Some black-box methods don’t even require that you have source. When you use gray-box methods, you are using a tool to instrument the source in an automatic (or semi-automatic) way.Some examples of these follow.Debugging in engineering before releasing the productOne example of code instrumentation is trace objects like the ones that were used in the examples presented in the first class. These are objects that contain information (and tracking statements either in the form of output to the console or to a file) about the creation and the deletion of objects of a particular type. You can either instrument the object directly or you can have special trace objects which you either descend from or compose with your usual object. This is a white-box method.A gray-box instrumentation technique used in this arena is a source level debugger.Debugging in situ after releasing the productThere are many ad hoc methods of gathering information after the release of a product, but they need to be planned for up front. The primary technique involves the embedding of a variety of trace statements (see above) that are activated conditionally based on some kind of “back door”. A “back door” is a way of telling the program that you would like it to behave differently than it normally does. They’ve gotten a bad name in the media as a result of malicious use by programmers attempting to steal things (money, passwords, et al) or as signals to activate viruses, but they do have legitimate purposes as well. The back doors are frequently activated by having the user enter what are otherwise unreasonable values in data entry fields or by introducing files in the system that shouldn’t otherwise be there. The back door to a product that I’m familiar with is activated as a result of entering “SAKAJAWAYA” as the name of the customer in the setup field. The product then presents the used with a new option on the normal screen – “trace”. If the option is activated, the user is prompted for a file name to write a communications log to. Tracing continues until it is turned off. This is a white-box technique.A different kind of back door is used in the product that I just released. If there is a file in the activation directory of the product with the name of one of the DLLs followed by the extension “LFN” (Log File Name), that file is assumed to contain the name of the file to write the log to. Logging continues to this file as long as the file exists (though the file is replaced at the beginning of each program activation). This produces a communication log similar to the one mentioned above, though with much more information about the various states leading up to each transmission. The communication log so generated may be used as a response file to play back the scenario. If a file named as above but with the extension RFN (“Response File Name”) exists in the activation directory, the real communication port is ignored and responses are drawn from the recording whose name is found in the RFN file. This is also a white-box technique.Other back doors may involve the use of command line parameters which specify both that tracing is desired and what file the trace is to be written to. They may also indicate a desired tracing level and/or the type of tracing desired. This is another white-box technique.Black (or gray) box techniques may involve the use of an assembly language level debugger at the customers site on release code. (Whether it’s black or gray depends largely on whether you have the source with you or not… Also, programmers (such as us), have been known to call into tech support of other companies when, having crashed the other company’s product, answered yes to the question about dropping into the debugger…).Performance analysisInstrumentation for the sake of performance analysis may be done in white-box, gray-box, or black-box form depending on the tools applied. One set of black-box techniques in this area involves measures of the program counter (sometimes statistical sampling is used rather than measuring every instruction executed). Histograms are then produced showing how much time is spent at each given address. Sometimes these are as simple as determining how much time is spent in the OS versus the application. Others, the idea is to determine graphically where the application is spending its time.A gray-box variation on the above involves instrumenting the source so that counters are introduced associated with each line of source code (these are done to each line of code automatically prior to compiling, hence they are “gray”). White-box techniques are usually applied to suspicious modules in what are believed to be the critical sections (perhaps having been selected by using either black or gray techniques first).Determining testing coverageThe four primary white-box and gray-box measures of coverage associated with testing are:statement level coveragefunction call coveragedecision to decision path coverageexecution path coverageThe fourth is significant only for small programs not involving loops which vary based on the size of the users input data and shall not be considered further.Statement level coverage can be made using techniques described previously for performance analysis. Now, though, we are only really concerned with 0 versus non-0 values for statement execution.Function call coverage is achieved by introducing counters at function entries rather than at every statement.Decision to decision paths are sequences of linear code segments that start at a branch (the result of a decision) and end at the beginning of the next test. Tools of this nature introduce counters at the beginning of each such path.Given that the code has been instrumented in the appropriate model, testing then proceeds as usual and the results are tallied based on exercising the UI. The programmer may have to be consulted for help in designing tests that reach portions of code that seem to be “dead”.A more limited white-box technique that could be applied here is to tag areas of interest only (perhaps those areas which have been until now unreachable (the famous “ERROR: UNKNOWN ERROR” from the MSVC compiler is an example of this)).Test driversA different form of instrumentation takes the form of a driver – either SW that can play user or SW that can simulate a run time situation. The RFN technique mentioned above is a white-box form of this technique. SW that plays user is usually done as a black-box form of this technique.Homeworks for Advanced C++Homework 1For this homework assignment, do the following exercises in the Stroustrup text:Chapter 6: 22Chapter 7: 4Chapter 9: 3Extra Credit 1 (10 points):In 9-3, add code that will make use of the INCLUDE environment variable in the way that the compiler does.Extra Credit 2 (10 points):In 9-3, add code to allow the user to specify additional include paths on the command line in the way that the compiler does. (search order if doing both 1 and 2 should be that user specified includes directories are searched before those in the INCLUDE path).Homework 2Write a class that supports the notion of a universal odometer. Make the use of the class flexibleby allowing to set upper and lower bounds for each “digit” independently.Extra credit (10 pts): have your program handle errors by throwing exceptionsInterface follows:// odometer.h// interface to universal odometer#ifndef __odometer_h__#define __odometer_h__#include <iostream>#include <stdexcept>using namespace std;class Odometer {public:Odometer(unsigned int uiNumberOfDigits = 4,int iMax = 10);Odometer(unsigned int uiNumberOfDigits, int iMax[]);Odometer(unsigned int uiNumberOfDigits, int iMin[],int iMax[]);~Odometer();Odometer(const Odometer&);Odometer& operator=(const Odometer&);unsigned int NumberOfDigits() const;int Max(unsigned int uiIndex) const;void SetMax(unsigned int uiIndex, int iValue);int Min(unsigned int uiIndex) const;void SetMin(unsigned int uiIndex, int iValue);int Digit(unsigned int uiIndex) const;void SetDigit(unsigned int uiIndex, int iValue);bool ValidRanges();bool Next();bool Prev();friend ostream& operator<<(ostream& os, const Odometer& od);private:unsigned int m_uiNumberOfDigits;int * m_piMax;int * m_piMin;int * m_piDigit;};#endifTest your program as follows:// hw2main.cpp// test program for universal odometer#include <iostream>using namespace std;#include "Odometer.h"const unsigned int uiNumberOfDigits=3;void main() {int uiMin[uiNumberOfDigits];int uiMax[uiNumberOfDigits];int i;// setup min and max valuesfor (i=0; i<uiNumberOfDigits; i++){uiMin[i]=i;uiMax[i]=i*2;}// count from min to maxOdometer od(uiNumberOfDigits, uiMin, uiMax);cout << "Counting up:\n";do cout << od << endl;while (od.Next());// set digits to maxfor (i=0; i<uiNumberOfDigits; i++)od.SetDigit(i,uiMax[i]);// count from max to mincout << "\nCounting down:\n";do cout << od << endl;while (od.Prev());}/*output:Counting up:210220310320410420Counting down:420410320310220210*/Homework 3This assignment is to demonstrate inheritance and class design. Start with an abstract base class Dessert which should contain common private data (baking time, calories, list of ingredients, list of instructions, name of dessert) and a virtual print function for the recipes (the cookie print function might include an indication of whether it was a drop or cut cookie; the cake print function might include whether it was a sheet cake or a layer cake). From Dessert, derive the following hierarchy (application specific member functions are in brackets). The Dessert class in on the course disk the same directory as the HW3MAIN.CPP file.Dessert/ \/ \CakeCookie\ /\ /BrownieSome members functions (Bake, Frost, Blend, Spread, Mix) should cause an instruction to be added to the list of instructions. “Frost” should also cause “Frosting” to be added to the list of ingredients.// dessert.h// definition of Dessert#ifndef __dessert_h__#define __dessert_h__#include <string>#include <list>using namespace std;class Dessert {public:Dessert();virtual ~Dessert() {}void Bake(unsigned int, unsigned int);void AddIngredient(const string&, unsigned int cal=0);void AddInstruction(const string&);virtual void Print() const = 0;void PrintIngredients() const;void PrintInstructions() const;inline void SetServings(unsigned int uiServings){m_uiServings = uiServings;}inline unsigned int GetServings() const{return m_uiServings;}inline void SetName(const string& sName){m_sName = sName;}inline const string GetName() const{return m_sName;}inline void SetFlavor(const string& sFlavor){m_sFlavor = sFlavor;}inline const string& GetFlavor() const{return m_sFlavor;}inline void SetShape(const string& sShape){m_sShape = sShape;}inline const string& GetShape() const{return m_sShape;}private:list<string> m_lsIngredients;list<string> m_lsInstructions;unsigned int m_uiBakingTime;unsigned int m_uiBakingTemp;unsigned int m_uiCalories;unsigned int m_uiServings;string m_sName;string m_sFlavor;string m_sShape;};#endif// dessert.cpp// implementation of Dessert#include "dessert.h"#include <iostream>using namespace std;// ctorDessert::Dessert() {m_uiBakingTime =0;m_uiBakingTemp = 0;m_uiCalories = 0;SetServings(8);SetFlavor("");SetShape("");}// bakevoid Dessert::Bake(unsigned int uiBakingTime, unsigned int uiBakingTemp){m_uiBakingTime = uiBakingTime;m_uiBakingTemp = uiBakingTemp;}// add an ingredientvoid Dessert::AddIngredient(const string& sIngredient, unsigned int uiCal){m_lsIngredients.push_back(sIngredient);m_uiCalories = m_uiCalories + uiCal;}// add an instructionvoid Dessert::AddInstruction(const string& sInstruction){m_lsInstructions.push_back(sInstruction);}// print the ingredientsvoid Dessert::PrintIngredients() const {list<string>::const_iterator iter;cout << "\tIngredients: " << endl;for (iter = m_lsIngredients.begin();iter!= m_lsIngredients.end();iter++)cout <<"\t\t"<<*iter<<endl;cout << "\tServings = " << m_uiServings << endl;cout << "\tCalories per serving= " << m_uiCalories/m_uiServings << endl;}// print the instructionsvoid Dessert::PrintInstructions() const {list<string>::const_iterator iter;cout << "\tInstructions: " << endl;for (iter = m_lsInstructions.begin();iter!= m_lsInstructions.end();iter++)cout <<"\t\t"<<*iter<<endl;cout <<"\tBake at "<< m_uiBakingTemp<<" for "<< m_uiBakingTime <<" minutes" << endl;}// hw3main.cpp// main test procedure for homework 3#include <iostream>using namespace std;#include "dessert.h"#include "cake.h"#include "cookie.h"#include "brownie.h"void main(){// test of CakeDessert *cakeGrandmas = new Cake;if (dynamic_cast<Cake*>(cakeGrandmas)) {cakeGrandmas->SetName("Grandma's Chocolate Cake");cakeGrandmas->SetFlavor("chocolate");cakeGrandmas->SetShape("layer");cakeGrandmas->SetServings(10);cakeGrandmas->AddIngredient("1.5 cups white sugar",(int)(770*1.5));cakeGrandmas->AddIngredient("1 cup flour",400);cakeGrandmas->AddIngredient(".75 cup baking cocoa",(int)(200*.75));cakeGrandmas->AddIngredient("2 tsp baking powder",0);cakeGrandmas->AddIngredient("1 tsp baking soda",0);cakeGrandmas->AddIngredient(".25 tsp salt",0);cakeGrandmas->AddIngredient("6 eggs",6*80);cakeGrandmas->AddIngredient(".75 cup vegetable oil",(int)(.75*1900));cakeGrandmas->AddIngredient(".5 cup water",0);cakeGrandmas->AddIngredient("1 tsp vanilla",10);dynamic_cast<Cake*>(cakeGrandmas)->Blend();dynamic_cast<Cake*>(cakeGrandmas)->Spread();cakeGrandmas->Bake(30, 350);dynamic_cast<Cake*>(cakeGrandmas)->Frost();cakeGrandmas->Print();cout << endl << endl;}// test of CookieDessert *cookieWorldsBest = new Cookie;if (dynamic_cast<Cookie*> (cookieWorldsBest)) {cookieWorldsBest->SetName("World's Best Chocolate Chip Cookies");cookieWorldsBest->SetFlavor("chocolate chip");cookieWorldsBest->SetServings(48);cookieWorldsBest->AddIngredient("2 sticks unsalted butter",2*800);cookieWorldsBest->AddIngredient(".75 cups white sugar",(int)(770*.75));cookieWorldsBest->AddIngredient("1.25 cups brown sugar",(int)(770*1.25));cookieWorldsBest->AddIngredient("2 eggs",2*80);cookieWorldsBest->AddIngredient(".75 tsp vanilla",8);cookieWorldsBest->AddIngredient("3.75 cups flour",(int)(400*3.75));cookieWorldsBest->AddIngredient("2 tsp baking soda",0);cookieWorldsBest->AddIngredient("1.25 tsp baking powder",0);cookieWorldsBest->AddIngredient(".5 tsp salt",0);cookieWorldsBest->AddIngredient("2 cups semi-sweet chocolate chips",825*2);dynamic_cast<Cookie*>(cookieWorldsBest)->Mix();cookieWorldsBest->Bake(12, 325);cookieWorldsBest->Print();cout << endl << endl;}// test of BrownieDessert *brownieSinful = new Brownie;if (dynamic_cast<Brownie*>(brownieSinful)) {brownieSinful->SetName("Sinfully Chocolate Brownies");brownieSinful->SetServings(16);brownieSinful->AddIngredient(".25 cup flour",(int)(400*.25));brownieSinful->AddIngredient(".25 tsp baking powder",0);brownieSinful->AddIngredient(".25 tsp salt",0);brownieSinful->AddIngredient("1 cup semi-sweet chocolate chips",825);brownieSinful->AddIngredient(".75 cup baking cocoa",(int)(200*.75));brownieSinful->AddIngredient("2 eggs",2*80);brownieSinful->AddIngredient("2 tsp vanilla",2*10);brownieSinful->AddIngredient("1 stick unsalted butter",800);brownieSinful->AddIngredient(".75 cups white sugar",(int)(770*.75));dynamic_cast<Brownie*>(brownieSinful)->Mix();dynamic_cast<Brownie*>(brownieSinful)->Blend();brownieSinful->Bake(55, 300);brownieSinful->Print();cout << endl << endl;}}/* output:CAKEGrandma's Chocolate CakeFlavor: chocolate Shape: layerIngredients: 1.5 cups white sugar1 cup flour.75 cup baking cocoa2 tsp baking powder1 tsp baking soda.25 tsp salt6 eggs.75 cup vegetable oil.5 cup water1 tsp vanillaone can of frostingServings = 10Calories per serving= 482Instructions: blend the ingredients together until smoothspread the mixture into a baking panafter the cake has baked and cooled, frost the cakeBake at 350 for 30 minutesCOOKIEWorld's Best Chocolate Chip CookiesFlavor: chocolate chip Shape: dropIngredients: 2 sticks unsalted butter.75 cups white sugar1.25 cups brown sugar2 eggs.75 tsp vanilla3.75 cups flour2 tsp baking soda1.25 tsp baking powder.5 tsp salt2 cups semi-sweet chocolate chipsServings = 48Calories per serving= 134Instructions: soften buttermix the batterBake at 325 for 12 minutesBROWNIESinfully Chocolate BrowniesFlavor: chocolate Shape: sheetIngredients: .25 cup flour.25 tsp baking powder.25 tsp salt1 cup semi-sweet chocolate chips.75 cup baking cocoa2 eggs2 tsp vanilla1 stick unsalted butter.75 cups white sugarServings = 16Calories per serving= 164Instructions: soften buttermix the batterblend the ingredients together until smoothBake at 300 for 55 minutes*/Homework 4This assignment is to illustrate the handle/body paradigm with use counting. Implement a use counted String class similar to the use counted complex class in the handouts. Your hw4s.h (the definition of the String class) must not #include hw4sb.h (the definition of the String Body class) or uc.h (the Use Count class). There can be no inline functions in this String class (this restriction does not apply to the Body). The String class should have the following features:assignment operators (both ‘=’ and ‘+=’)a copy constructora destructoran operator to convert to char *constructors to make a String from a char * (the char * constructor’s argument should be defaulted to the null string)a concatenation operator (overloaded ‘+’)an index operator that returns a char &NOTES: the representation should be private and const should be used wherever appropriate; binary operators should be friends where implicit conversion of the first argument is desirable or where the first argument logically is not of the same class as the containing class (i.e., inserters and extractors).Interface follows:// hw4s.h#ifndef __hw4s_h__#define __hw4s_h__#include <iostream>using namespace std;class StringUCBody;class String {public:friend String operator+(const String&, const String&);friend ostream& operator<<(ostream& os, const String& s);String& operator=(const String&);String& operator+=(const String&);String(const String&);~String();operator const char*() const;String(const char* = "");char& operator[] (int);unsigned int Length() const;private:StringUCBody *m_psub;};#endifTest your program as follows:// hw4main.cpp// this is the main test procedure for homework 4#include <iostream>#include <cctype>using namespace std;#include "hw4s.h"void main() {String s1("This is a test.");String s2("So is this.");String s3,s4,s5;String s6("hello world");String s7 = s2;s3=s4=s5=s1+ " " + s2;// s3, s4, & s5 should now have the same repcout << s3 << endl;// "This is a test. So is this.":3 cout << s4 << endl;// "This is a test. So is this.":3 cout << s5 << endl;// "This is a test. So is this.":3 s3+=s2;cout << s3 << endl;// "This is a test. So is this.So is this.":1s3=s3;cout << s3 << endl;// "This is a test. So is this.So is this.":1cout << s4 << endl;// "This is a test. So is this.":2 cout << s5 << endl;// "This is a test. So is this.":2 s6[0]=toupper(s6[0]);cout << s6 << endl;// "Hello world":1cout << s2 << endl;// "So is this.":2cout << s7 << endl;// "So is this.":2}/* output:"This is a test. So is this.":3"This is a test. So is this.":3"This is a test. So is this.":3"This is a test. So is this.So is this.":1"This is a test. So is this.So is this.":1"This is a test. So is this.":2"This is a test. So is this.":2"Hello world":1"So is this.":2"So is this.":2*/Homework 5This assignment is to illustrate the use of templates and container classes. 1) Implement an integral doubly linked list template class which contains at least a copy constructor, assignment operator, destructor, a no fail index operator (if the list is not currently long enough, it should be padded out to the appropriate length), Length, PushBack, PushFront, Erase. You should implement a bi-directional iterator (one which supports begin, end, ++, and --) template for your bi-directional template list class. (The test program expects this in "hw5list.h".)NOTE: You may start from the singly linked list template class on the course diskette or you may derive your template as a wrapper class to the template list class in the STL. All function names must exist as specified above.2) Implement a BubbleSort function as a template function. It should receive as arguments the stored type, a comparison operator, a swap function, and a forward iterator (containing at least begin, end, and ++). (The test program expects this in "hw5sort.h".)NOTE: a swap template class is on the course diskette// hw5main.cpp// main test program for list template exercise#include <iostream>#include <functional>#include <string>using namespace std;#include "hw5list.h"#include "hw5sort.h"#include "hw5swap.h"void main(){// sort testscout << endl;cout << "------- testing sort template function ------" << endl;cout << endl;char * szComics[]={"Pluggers","Dilbert","Garfield","Spiderman","Curtis","Zippy","Doonesbury","Adam","Thatch"};List<int> lstNumbers;int i;for(i=0;i<20;i++)lstNumbers.PushBack(rand()%100-50);cout << "Unsorted:" << endl;lstNumbers.Print();cout<<endl;Sort(lstNumbers.begin(), lstNumbers.end(),greater<int>(),Swap<int>());cout<<"Ascending Order:"<<endl;lstNumbers.Print();cout<<endl;Sort(lstNumbers.begin(), lstNumbers.end(),less<int>(),Swap<int>());cout<<"Descending Order:"<<endl;lstNumbers.Print();cout<<endl;cout<<endl;List<string> lstComicsStrings;for(i=0;i<sizeof(szComics)/sizeof(char *);i++)lstComicsStrings.PushBack(szComics[i]);cout << "Unsorted:" << endl;lstComicsStrings.Print();cout<<endl;Sort(lstComicsStrings.begin(), lstComicsStrings.end(),greater<string>(),Swap<string>());cout<<"Ascending Order:"<<endl;lstComicsStrings.Print();cout<<endl;Sort(lstComicsStrings.begin(), lstComicsStrings.end(),less<string>(),Swap<string>());cout<<"Descending Order:"<<endl;lstComicsStrings.Print();cout<<endl;cout<<endl;// test other functions of lists not tested by sort testsList<int> lstOtherNumbers;List<string> lstNumberStrings;cout << "-------------- testing push front ---------------" << endl;lstOtherNumbers.PushFront(1);lstOtherNumbers.PushFront(2);lstOtherNumbers.PushFront(3);cout << "List should contain: 3 2 1" << endl;lstOtherNumbers.Print();cout << endl;cout << "-------------- testing push back ---------------" << endl;lstNumberStrings.PushBack("one");lstNumberStrings.PushBack("two");lstNumberStrings.PushBack("three");cout << "List should contain: one two three" << endl;lstNumberStrings.Print();cout << endl;cout << "-------------- testing copy ctor ---------------" << endl;List<string> lstNumberStrings1 = lstNumberStrings;cout << "List should contain: one two three" << endl;lstNumberStrings1.Print();cout << endl;cout << "-------------- testing assignment operator -----" << endl;List<string> lstNumberStrings2;lstNumberStrings2 = lstNumberStrings;cout << "List should contain: one two three" << endl;lstNumberStrings2.Print();cout << endl;cout << "-------------- testing index operator -----" << endl;lstNumberStrings2[1] = "four";cout << "List should contain: one four three" << endl;lstNumberStrings2.Print();cout << endl;cout << "This list should contain: one two three" << endl;lstNumberStrings.Print();cout << endl;cout << "-------------- testing list's ability to grow -----" << endl;lstNumberStrings2[6] = "six";cout << "List should contain: one four three - - - six" << endl;lstNumberStrings2.Print();cout << endl;cout << "-------------- testing erase -----" << endl;List<string>::iterator lsi=lstNumberStrings2.begin();lstNumberStrings2.Erase(lsi);cout << "List should contain: four three - - - six" << endl;lstNumberStrings2.Print();cout << endl;cout << "-------------- print list backwards -----" << endl;for (lsi=lstNumberStrings2.last();lsi!=lstNumberStrings2.end();lsi--)cout << '"' << *lsi << '"' << ' ';cout << endl;cout << endl;}/* output:------- testing sort template function ------Unsorted:Length:20Data: "-9" "17" "-16" "-50" "19" "-26" "28" "8" "12" "14" "-45" "-5" "31" "-23" "11" "41" "45" "-8" "-23" "-14" Ascending Order:Length:20Data: "-50" "-45" "-26" "-23" "-23" "-16" "-14" "-9" "-8" "-5" "8" "11" "12" "14" "17" "19" "28" "31" "41" "45" Descending Order:Length:20Data: "45" "41" "31" "28" "19" "17" "14" "12" "11" "8" "-5" "-8" "-9" "-14" "-16" "-23" "-23" "-26" "-45" "-50" Unsorted:Length:9Data: "Pluggers" "Dilbert" "Garfield" "Spiderman" "Curtis" "Zippy" "Doonesbury" "Adam" "Thatch" Ascending Order:Length:9Data: "Adam" "Curtis" "Dilbert" "Doonesbury" "Garfield" "Pluggers" "Spiderman" "Thatch" "Zippy" Descending Order:Length:9Data: "Zippy" "Thatch" "Spiderman" "Pluggers" "Garfield" "Doonesbury" "Dilbert" "Curtis" "Adam" -------------- testing push front ---------------List should contain: 3 2 1Length:3Data: "3" "2" "1" -------------- testing push back ---------------List should contain: one two threeLength:3Data: "one" "two" "three" -------------- testing copy ctor ---------------List should contain: one two threeLength:3Data: "one" "two" "three" -------------- testing assignment operator -----List should contain: one two threeLength:3Data: "one" "two" "three" -------------- testing index operator -----List should contain: one four threeLength:3Data: "one" "four" "three" This list should contain: one two threeLength:3Data: "one" "two" "three" -------------- testing list's ability to grow -----List should contain: one four three - - - sixLength:7Data: "one" "four" "three" "" "" "" "six" -------------- testing erase -----List should contain: four three - - - sixLength:6Data: "four" "three" "" "" "" "six" -------------- print list backwards -----"six" "" "" "" "three" "four" */Homework 6For this homework assignment, do the following exercises with the STL in the Stroustrup text:Chapter 16: 1,2Chapter 17: 3Chapter 18: 14Chapter 19: 1Extra Credit (25 points):Chapter 20: 7Output from each exercise (except 20.7) follows:****************************16_1.outA B C D E F G H I J K L M N O P Q R S T U V W X Y Z Z Y X W V U T S R Q P O N M L K J I H G F E D C B A ****************************16_2.outgiven the following input:pearskiwisorangesapplesberriesthe output will be:apples berries kiwis oranges pears ****************************17_3a.outoutput when applied to "Beer and Pizza" (a poem by Dan Leach):"Hmmmmmm....."I"Must"What(To----"AAboutAfterwards,AndAnotherAsBeerByCleaningDanDriftEachForFreudianHisII'mIIIIIInIntoItK.LeachMovesMyNudgesOblivionOnePausingPizzaR.)ReplacingSitsTanglesTheThroughToUntilWeWereWhatYouaaboutacrylicagainagain!ageallamidandanswer,anythingarearmsasks.at?"averagebeachbeenbeforebeneathbluelycancandlechasingchest,chimeracolors,considerconsumesdreams...eachelse...fairfirefluorescentforgiggle--gildedgoldengoodnightgreatgrinhairhavehere,holdhugginginnocence...itselfjungleknowknowinglylargerlaylightlimplylivelookingmakememomentmovesmyneednowoblivionofonon...onceonlypalmpassionpizza,"polymerpositionprimalpurplelyremembersayscreamsilentlysimiansleepslowlyslysoftspectersstoptellthanthatthethentheythink..."thinkingtiredtotogethertonighttootreetryuponwaves.whatwishwithyouyours****************************17_3b.outoutput when applied to "Beer and Pizza" (a poem by Dan Leach):AAboutAfterwardsAndAnotherAsBeerByCleaningDanDriftEachForFreudianHisHmmmmmmIIIIIIInIntoItKLeachMovesMustMyNudgesOblivionOnePausingPizzaRReplacingSitsTanglesTheThroughToUntilWeWereWhatYouaaboutacrylicagainageallamidandansweranythingarearmsasksataveragebeachbeenbeforebeneathbluelycancandlechasingchestchimeracolorsconsiderconsumesdreamseachelsefairfirefluorescentforgigglegildedgoldengoodnightgreatgrinhairhavehereholdhugginginnocenceitselfjungleknowknowinglylargerlaylightlimplylivelookingmmakememomentmovesmyneednowoblivionofononceonlypalmpassionpizzapolymerpositionprimalpurplelyremembersayscreamsilentlysimiansleepslowlyslysoftspectersstoptellthanthatthethentheythinkthinkingtiredtotogethertonighttootreetryuponwaveswhatwishwithyouyours****************************18_14.outoutput of running "18_14 plus minus":Anagrams of "food":dfoodofodooffdoofodofoododfoodofofdoofodoodfoofdAnagrams of "plus":lpsulpuslspulsuplupsluspplsupluspslupsulpulspuslslpuslupspluspulsulpsuplulpsulspuplsupsluslpusplAnagrams of "minus":imnsuimnusimsnuimsunimunsimusninmsuinmusinsmuinsuminumsinusmismnuismunisnmuisnumisumnisunmiumnsiumsniunmsiunsmiusmniusnmminsuminusmisnumisunmiunsmiusnmnisumniusmnsiumnsuimnuismnusimsinumsiunmsniumsnuimsuinmsunimuinsmuisnmunismunsimusinmusninimsunimusnismunisumniumsniusmnmisunmiusnmsiunmsuinmuisnmusinsimunsiumnsmiunsmuinsuimnsuminuimsnuismnumisnumsinusimnusmisimnusimunsinmusinumsiumnsiunmsminusmiunsmniusmnuismuinsmunisnimusniumsnmiusnmuisnuimsnumisuimnsuinmsuminsumnisunimsunmiuimnsuimsnuinmsuinsmuismnuisnmuminsumisnumnisumnsiumsinumsniunimsunismunmisunmsiunsimunsmiusimnusinmusminusmniusnimusnmi****************************19_1.outinitial vector of strings: Kate Dee Louise Kim Midey reversed vector of strings: Midey Kim Louise Dee Kate initial string: "Madam, I'm Adam."reversed string: ".madA m'I ,madaM"Beer and PizzaBy Dan Leach (To K. R.) I I hold you bluely In my gilded arms And wish you purplely A fair goodnight -- I limply tell you I'm too tired tonight For anything else... And then Drift slowly Into a soft Oblivion -- II The acrylic simian Moves silently Through a polymer jungle of fluorescent colors, Pausing once In a great age To consider His position -- "Hmmmmmm..... About here, I think..." And then moves on... A larger than average golden chimera Sits beneath a palm tree on the beach -- Cleaning itself amid the waves. "What are you looking at?" It asks. And before I can answer, It consumes me with fire -- III A primal scream Nudges me with A Freudian innocence... "Must have been the pizza," I say "I know what you need --" You say knowingly with a sly grin and a giggle-- You light a candle and We lay together again -- My hair Tangles with yours -- One with Another And Another -- Each hugging each hugging each -- The oblivion of passion Replacing that of the dreams... You make me stop thinking -- We live now only for the moment -- Afterwards, As you sleep upon my chest, I try to remember What the chasing specters Were all about -- Until they are upon me again! ----------------------------------------------------------- Published in the Fall, 1995 issue of Illya’s Honey, in September, 1995. Homework 7Do the following exercises with the STL in the Stroustrup text:Chapter 21: 12, 13Chapter 22: 4Write a functor IntToString that returns its argument as a string; interface follows:class IntToString{public:string operator() (int iValue, unsigned int uiBase);};Test your class using the following:// hw71m.cpp#include <iostream>#include <string>using namespace std;#include "itos.h"void Test(int iValue, unsigned int uiBase){IntToString itos;cout << iValue << " base 10 is "<< itos(iValue,uiBase)<< " base "<< uiBase << endl;}void main(){Test(16,4);Test(15,2);Test(32,8);Test(255,16);Test(0x7FFFFFFF,16);Test(-16,4);Test(-15,2);Test(-32,8);Test(-255,16);Test(0x80000001,16);}/*output:16 base 10 is 100 base 415 base 10 is 1111 base 232 base 10 is 40 base 8255 base 10 is FF base 162147483647 base 10 is 7FFFFFFF base 16-16 base 10 is -100 base 4-15 base 10 is -1111 base 2-32 base 10 is -40 base 8-255 base 10 is -FF base 16-2147483647 base 10 is -7FFFFFFF base 16*/Homework 8Implement a linked stack as a template class containing the following: constructor, destructor, copy constructor, assignment operator, Push, Pop, Size. (NOTE: there is a queue class that follows these restrictions in the notes) It should be a homogeneous container with value semantics. In the event that an error occurs (e.g., stack underflow), throw an exception of type StackException:enum StackError {STACK_NO_ERROR,STACK_UNDERFLOW,STACK_OUT_OF_MEMORY};class StackException {StackError seErrorCode;public:StackException(StackError seError=STACK_UNDERFLOW) {seErrorCode=seError;}StackError GetErrorCode() {return seErrorCode;}};Test your program as follows:// hw8main.cpp// main test program for homework 8#include <iostream>#include <string>using namespace std;#include "hw8stk.h"using namespace std;void main(){Stack<int> stkInts;Stack<int> stkInts2;Stack<string> stkStrings;Stack<string> stkStrings2;try {stkInts.Push(1);stkInts.Push(2);stkInts.Push(3);stkInts.Print();cout << "test of assignment operator" << endl;stkInts2 = stkInts;stkInts2.Print();cout << "Pop: " << stkInts.Pop() << endl;stkInts.Print();cout << "Pop: " << stkInts.Pop() << endl;stkInts.Print();cout << "Pop: " << stkInts.Pop() << endl;stkInts.Print();cout << "Pop: " << stkInts.Pop() << endl;stkInts.Print();}catch(StackException & se) {if (se.GetErrorCode()==STACK_UNDERFLOW)cout << "(in main) STACK UNDERFLOW!" << endl;else {cout << "(in main) Other Stack Error - Rethrowing" << endl;throw se;}}cout << "this is stkInts2; should be unchanged" << endl;stkInts2.Print();Stack<int> stkInts3 = stkInts2;cout << "this is stkInts3; made from copy ctor" << endl;stkInts3.Print();try {stkInts.Push(1);stkInts.Push(2);stkInts.Push(3);stkInts.Print();Plus(&stkInts);stkInts.Print();Plus(&stkInts);stkInts.Print();Plus(&stkInts);stkInts.Print();}catch(StackException & se) {if (se.GetErrorCode()==STACK_UNDERFLOW)cout << "(in main) STACK UNDERFLOW!" << endl;else {cout << "(in main) Other Stack Error - Rethrowing" << endl;throw se;}}try {stkStrings.Push("one");stkStrings.Push("two");stkStrings.Push("three");stkStrings.Print();cout << "test of assignment operator" << endl;stkStrings2 = stkStrings;stkStrings2.Print();cout << "Pop: " << stkStrings.Pop() << endl;stkStrings.Print();cout << "Pop: " << stkStrings.Pop() << endl;stkStrings.Print();cout << "Pop: " << stkStrings.Pop() << endl;stkStrings.Print();cout << "Pop: " << stkStrings.Pop() << endl;stkStrings.Print();}catch(StackException & se) {if (se.GetErrorCode()==STACK_UNDERFLOW)cout << "(in main) STACK UNDERFLOW!" << endl;else {cout << "(in main) Other Stack Error - Rethrowing" << endl;throw se;}}cout << "this is stkStrings2; should be unchanged" << endl;stkStrings2.Print();Stack<string> stkStrings3 = stkStrings2;cout << "this is stkStrings3; made from copy ctor" << endl;stkStrings3.Print();try {stkStrings.Push("one");stkStrings.Push("two");stkStrings.Push("three");stkStrings.Print();Plus(&stkStrings);stkStrings.Print();Plus(&stkStrings);stkStrings.Print();Plus(&stkStrings);stkStrings.Print();}catch(StackException & se) {if (se.GetErrorCode()==STACK_UNDERFLOW)cout << "(in main) STACK UNDERFLOW!" << endl;else {cout << "(in main) Other Stack Error - Rethrowing" << endl;throw se;}}}/* output:*Top*321*Bottom*test of assignment operator*Top*321*Bottom*Pop: 3*Top*21*Bottom*Pop: 2*Top*1*Bottom*Pop: 1*Top**Bottom*(in main) STACK UNDERFLOW!this is stkInts2; should be unchanged*Top*321*Bottom*this is stkInts3; made from copy ctor*Top*321*Bottom**Top*321*Bottom**Top*51*Bottom**Top*6*Bottom*(in Plus) STACK UNDERFLOW!*Top**Bottom**Top*threetwoone*Bottom*test of assignment operator*Top*threetwoone*Bottom*Pop: three*Top*twoone*Bottom*Pop: two*Top*one*Bottom*Pop: one*Top**Bottom*(in main) STACK UNDERFLOW!this is stkStrings2; should be unchanged*Top*threetwoone*Bottom*this is stkStrings3; made from copy ctor*Top*threetwoone*Bottom**Top*threetwoone*Bottom**Top*threetwoone*Bottom**Top*threetwoone*Bottom*(in Plus) STACK UNDERFLOW!*Top**Bottom**/ ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download