irm chapter 6e 11

Upload: elvarg09

Post on 02-Jun-2018

220 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/10/2019 IRM Chapter 6e 11

    1/52

    1Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    Chapter 11

    Friends and Overloaded Operators

    1. Solutions to and Remarks on Selected Programming Problems

    1. Modify Money class.

    No solution is provided for this exercise.

    2. Implement constructors and overload >>,

  • 8/10/2019 IRM Chapter 6e 11

    2/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    2Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    int accessFirst();

    int accessSecond();

    // other members and friends

    friend Pair operator+(const Pair&, const Pair&);

    friend Pair operator*(const Pair&, int);

    friend istream& operator>> (istream&, Pair&);

    friend ostream& operator

  • 8/10/2019 IRM Chapter 6e 11

    3/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    3Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    x = y + z;

    cout second.f;

    ins >> ch; // discard comma ','

    ins >> second.s;

    ins >> ch; // discard final '('

    return ins;

    }

    ostream& operator

  • 8/10/2019 IRM Chapter 6e 11

    4/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    4Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    outs

  • 8/10/2019 IRM Chapter 6e 11

    5/52

  • 8/10/2019 IRM Chapter 6e 11

    6/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    6Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    {

    public:

    Rational(int numerator, int denominator);

    Rational(int numerator); // sets denominator to 1

    Rational(); // sets numerator to 0, denominator to 1

    friend Rational operator+(const Rational&,

    const Rational&);

    friend Rational operator-(const Rational&,

    const Rational&);

    friend Rational operator*(const Rational&,

    const Rational&);

    friend Rational operator/(const Rational&,const Rational&);

    friend bool operator=(const Rational&,

    const Rational&);

    friend bool operator ==(const Rational&,

    const Rational&);

    friend ostream& operator (istream&,

    Rational&);

    private:

    int n;int d;

    };

    void normalize(int &n, int &d);

    #endif

    //end file Rational.h

  • 8/10/2019 IRM Chapter 6e 11

    7/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    7Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    //file: ch11prb4cc

    //Implementations of the members of class Rational.

    //For Chapter 11 Problem 4

    #include

    #include

    #include "rational.h"

    using namespace std;

    //private members of class Rational

    // int n;

    // int d;

    Rational::Rational(int numer, int denom)

    {

    normalize(numer, denom);

    n = numer;

    d = denom;

    }

    //sets denominator to 1

    Rational::Rational(int numer): n(numer), d(1)

    // See the initializer appendix

    {

    //body deliberately empty

    }

    // sets numerator to 0, denominator to 1

    Rational::Rational():n(0), d(1)

    // see initializer appendix{

    //body deliberately empty

    }

    Rational operator +(const Rational& left,

    const Rational& right)

  • 8/10/2019 IRM Chapter 6e 11

    8/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    8Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    {

    int numer = left.n * right.d + left.d * right.n;

    int denom = left.d * right.d;

    normalize(numer, denom);

    Rational local(numer, denom);return local;

    }

    Rational operator -(const Rational& left,

    const Rational& right)

    {

    int numer = left.n * right.d - left.d * right.n;

    int denom = left.d * right.d;

    normalize(numer, denom);Rational local (numer, denom);

    return local;

    }

    Rational operator *(const Rational& left,

    const Rational& right)

    {

    Rational product;

    int numer = left.n * right.n;

    int denom = left.d * right.d;

    normalize(numer, denom);

    product = Rational(numer, denom);

    return product;

    }

    Rational operator/(const Rational& left,

    const Rational& right)

    {

    Rational quotient;int numer = left.n * right.d;

    int denom = left.d * right.n;

    normalize(numer, denom);

    quotient = Rational(numer, denom);

    return quotient;

    }

  • 8/10/2019 IRM Chapter 6e 11

    9/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    9Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    //precondition: all relational operators require d > 0

    bool operator =(const Rational& left,

    const Rational& right)

    {

    return left.n * right.d >= right.n * left.d;

    }

    bool operator==(const Rational& left,

    const Rational& right)

    {

    return left.n * right.d == right.n * left.d;}

    //NOTE:

    //Doing input changes the input stream state. This seems

    //obvious, but I have students who didn't realize this.

  • 8/10/2019 IRM Chapter 6e 11

    10/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    10Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    //This code, along with iostream library, goes into an

    //infinite loop if you make istream a const reference. There

    //are no error messages, only an infinite loop, involving

    //the single parameter constructor. This can be quite

    //disconcerting to the naive student.//

    //Bottom line: The first param MUST NOT be const. The

    //second one is written, so it cannot be const either.

    istream& operator >>(istream& in_str, Rational& right)

    {

    char ch;

    in_str >> right.n >> ch >> right.d;if (ch != '/') // properly done, we would set iostream

    //state

    {// to fail here in case of error.

    cout

  • 8/10/2019 IRM Chapter 6e 11

    11/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    11Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    char ch;

    out_str

  • 8/10/2019 IRM Chapter 6e 11

    12/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    12Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    // remove common factors:

    int g = gcd(n, d);

    n = n/g;

    d = d/g;

    //fix things so that if the fraction is 'negative'

    //it is n that carries the sign. If both n and d are

    //negative, each is made positive.

    if(n > 0 && d < 0 || n < 0 && d < 0)

    {

    n = -n;

    d = -d;

    }// assert: d > 0

    }

    //end file ch11prb4.cc

    //File: ch11prb4.tst.cc

    //File: test program for Rational class

    #include

    #include "rational.h"

    using namespace std;

    int main()

    {

    cout

  • 8/10/2019 IRM Chapter 6e 11

    13/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    13Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    cin >> x;

    cout

  • 8/10/2019 IRM Chapter 6e 11

    14/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    14Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    w = Rational(-21,9);

    z = Rational(3,5);

    cout

  • 8/10/2019 IRM Chapter 6e 11

    15/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    15Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    Rational a(1,1); a outputs as: 1/1

    -8/3 * 1/1 = -8/3

    Testing arithmetic and relational operator overloading

    25/9 * 3/5 = 5/3

    25/9 + 3/5 = 152/4525/9 - 3/5 = 98/45

    25/9 / 3/5 = 125/27

    25/9 < 3/5 = 0

    25/9 < 25/9 = 0

    25/9 25/9 = 025/9 >= 3/5 = 1

    25/9 >= 25/9 = 1

    -7/3 * 3/5 = -7/5

    -7/3 + 3/5 = -26/15

    -7/3 - 3/5 = -44/15

    -7/3 / 3/5 = -35/9

    -7/3 < 3/5 = 1

    -7/3 < -7/3 = 0

    -7/3 -7/3 = 0

    -7/3 >= 3/5 = 0

    -7/3 >= -7/3 = 1

    6. Complex Numbers

    Define an ADT for complex numbers. The problem specifies a form of a + i*b where a

    and b are of type double, and i is the complex unit, square root of -1. Implement

    operator overloading for ==, +, -< *, >>, and

  • 8/10/2019 IRM Chapter 6e 11

    16/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    16Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    understandable to the student. Even so, I acknowledge some overkill for the problem as

    specified in the text.

    I have used an external form different from this specification. The ISO/ANSI C++

    Standard says that the complex inserter and extractor should read and write a complex

    numbers of the form: re, (re), or (re, im), where re is the real part and im is the imaginary

    part. This is the external form that the C++ compilers will required by the ISO Standard

    for compliant compilers.

    I am only allowing the external form (re, im). I check only the input format, and I do not

    check for a good stream state at each read from the input stream. Robust software

    requires checking the stream state at each fetch.

    The student should not be expected to have a knowledge of the requirements of the ISO

    C++ Standard. Before assigning this exercise, the instructor should provide the student

    with information about the external form of a complex the C++ Standard expects.

    Not coincidentally, the ISO Standard requires a fully implemented type

    with overloaded operators, transcendental functions, a complex arrays including array

    slices, as part of the Numerics library.

    //file: complex.h

    // Chapter 11, problem 5: Define an ADT for complex numbers.

    #ifndef _COMPLEX_H

    #define _COMPLEX_H

    #include

    #include

    using namespace std;

    class complex{

    public:

    complex (double r = 0, double i = 0): re (r), im (i) { }

    double real () const { return re; }

  • 8/10/2019 IRM Chapter 6e 11

    17/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    17Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    double imag () const { return im; }

    private:

    double re, im;

    friend double real (const complex&) ;friend double imag (const complex&) ;

    friend complex operator + (const complex&, const

    complex&);

    friend complex operator - (const complex&,

    const complex&);

    friend complex operator * (const complex&,

    const complex&);

    friend complex operator / (const complex&,const complex&);

    friend bool operator == (const complex&,

    const complex&);

    friend bool operator != (const complex&,

    const complex&);

    friend complex polar (double, double);

    friend istream& operator>> (istream&, complex&);

    friend ostream& operator

  • 8/10/2019 IRM Chapter 6e 11

    18/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    18Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    o

  • 8/10/2019 IRM Chapter 6e 11

    19/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    19Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    //now get the imaginary part

    ins >> i;

    //and get the close parenthesis

    ins >> ch;

    if(')' != ch)//complex number must have a ')' last,

    //If not, complain and exit.

    {

    cout

  • 8/10/2019 IRM Chapter 6e 11

    20/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    20Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    return complex (real (x) - real (y), imag (x) - imag (y));

    }

    complex operator * (const complex& x, const complex& y)

    {return complex (real (x) * real (y) - imag (x) * imag (y),

    real (x) * imag (y) + imag (x) * real

    (y));

    }

    complex operator / (const complex& x, double y)

    {

    return complex (real (x) / y, imag (x) / y);}

    bool operator == (const complex& x, const complex& y)

    {

    return real (x) == real (y) && imag (x) == imag (y);

    }

    bool operator != (const complex& x, const complex& y)

    {

    return real (x) != real (y) || imag (x) != imag (y);

    }

    double abs (const complex& x)

    {

    return sqrt(norm(x));

    }

    complex conj (const complex& x)

    {

    return complex (real (x), -imag (x));

    }

    double norm (const complex& x)

  • 8/10/2019 IRM Chapter 6e 11

    21/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    21Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    {

    return real (x) * real (x) + imag (x) * imag (x);

    }

    //Divide overloading: There is a possible bug here.//The usual tool for complex division, num/den =

    //num*conj(den)*(1/(den * conj(den)), causes an infinite

    //recursion.

    //Exercise: How and why?

    complex operator / (const complex& num, const complex& den)

    {

    return(num * conj(den) * (1/norm(den)));}

    //file: tstcmplx.cpp

    //To test complex.h and complex.cpp class, members and

    //friends

    #include "complex.h"

    #include "cmath"

    using namespace std;

    //compile command: g++ testcomplex.cpp complex-io.cpp

    int main()

    {

    // test constructors

    complex x, y(3), z(-3.2, 2.1);

    cout

  • 8/10/2019 IRM Chapter 6e 11

    22/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    22Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

  • 8/10/2019 IRM Chapter 6e 11

    23/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    23Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    cout

  • 8/10/2019 IRM Chapter 6e 11

    24/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    24Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    (1,1)

    (2,3)

    Here is the output from our input routine when given bad data.

    x = (0, 0) y = (3, 0) z = (-3.2, 2.1)

    testing members and support functions as well as output

    operator:

    complex number x = (3, -4)

    real part: 3

    real part from friend real(x): 3

    imaginary part: -4

    imaginary part from friend imag(x) : -4

    norm: 25

    We test complex arithmetic and output routines.

    x = (3, -4) y = (1, -1) z = (-3.2, 2.1)

    z = x + y = (4, -5)

    z = x * y = (-1, -7)

    z = x - y = (2, -3)z = x / y = (3.5, -0.5)

    d: 2 x: (3, -4)

    x+d: (5, -4)

    x-d: (1, -4)

    x*d: (6, -8)

    x/d: (1.5, -2)

    d+x: (5, -4)d-x: (-1, 4)

    d*x: (6, -8)

    d/x: (0.24, 0.32)

    two/x: (0.24, 0.32)

    Getting data from standard input:

  • 8/10/2019 IRM Chapter 6e 11

    25/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    25Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    data read is: x = (1, 1) y = (2, 3)

    Messages from the input routine when given bad data.

    The content of the file, bad-data1, is:

    (1 2)The messages from the input routine with this file for data follow.

    [...snip...]

    Getting data from standard input:

    Bad complex form: found 2, need comma for complex input;

    A complex must be of the form (re, im)

    The content of the file, bad-data2, is:

    (1,2)

    (1,2_

    The messages from the input routine with this file for data follow.

    [...snip...]

    Getting data from standard input:

    Bad complex form: found _, need )for complex input;

    A complex must be of the form (re, im)

    7. No Solution Provided

    8. No Solution Provided

    9. No Solution Provided

    10. No Solution Provided

    11. No Solution Provided

    12.

    // ****************************************************************//// Ch11Proj12.cpp

  • 8/10/2019 IRM Chapter 6e 11

    26/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    26Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    //// This program defines a class for storing a set of STL strings.// The + operator unions two sets and the * operator intersects// two sets.//// ****************************************************************

    #include #include #include #include

    using namespace std;

    class StringSet{public:

    StringSet();StringSet(const string initialStrings[], int arraysize);bool add(const string s);bool remove(const string s);void clear();int size();void output();friend StringSet operator *(const StringSet &set1, const

    StringSet &set2);friend StringSet operator +(const StringSet &set1, const

    StringSet &set2);private:

    int search(const string s);vector data;

    };

    // ======================// StringSet::StringSet// Default Constructor// ======================StringSet::StringSet(){}

    // ======================// StringSet::StringSet// This constructor initializes the string set to those// strings in the input array.// ======================StringSet::StringSet(const string initialStrings[], int arraysize){

    int i;for (i=0; i < arraysize; i++){

    data.push_back(initialStrings[i]);}

    }

  • 8/10/2019 IRM Chapter 6e 11

    27/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    27Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    // ======================// StringSet::Output// This method simply outputs all strings to the console.// ======================void StringSet::output(){

    int i;for (i=0; i < data.size(); i++){

    cout

  • 8/10/2019 IRM Chapter 6e 11

    28/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    28Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    i = search(s);if (i>=0){

    return false; // s already in the set}

    data.push_back(s);return true;

    }

    // ======================// StringSet::remove// Removes an entry from the vector.// If the entry doesnt exist, then "false" is returned,// otherwise "true" is returned and the string is removed.// ======================bool StringSet::remove(const string s){

    int i;

    i = search(s);if (i>=0){

    // To remove the string from the vector, we make a new// copy of the vector without the string, then copy that// back to the original vector.// Chapter 18 describes a better technique using the

    "erase"// method and iterators.vector temp;for (int j=0; j

  • 8/10/2019 IRM Chapter 6e 11

    29/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    29Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    // ======================StringSet operator *(const StringSet &set1, const StringSet &set2){

    StringSet temp;int i,j;

    for (i=0; i

  • 8/10/2019 IRM Chapter 6e 11

    30/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    30Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    cout

  • 8/10/2019 IRM Chapter 6e 11

    31/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    31Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    using namespace std;

    // ******************************* Begin StringSet Class

    class StringSet{

    public:StringSet();StringSet(const string initialStrings[], int arraysize);bool add(const string s);bool remove(const string s);void clear();int size();void output();friend StringSet operator *(const StringSet &set1, const

    StringSet &set2);friend StringSet operator +(const StringSet &set1, const

    StringSet &set2);private:

    int search(const string s);vector data;

    };

    // ======================// StringSet::StringSet// Default Constructor// ======================StringSet::StringSet(){}

    // ======================

    // StringSet::StringSet// This constructor initializes the string set to those// strings in the input array.// ======================StringSet::StringSet(const string initialStrings[], int arraysize){

    int i;for (i=0; i < arraysize; i++){

    data.push_back(initialStrings[i]);}

    }

    // ======================// StringSet::Output// This method simply outputs all strings to the console.// ======================void StringSet::output(){

    int i;for (i=0; i < data.size(); i++){

    cout

  • 8/10/2019 IRM Chapter 6e 11

    32/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    32Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    }}

    // ======================// StringSet::clear// Erases all entries in the stringset.

    // ======================void StringSet::clear(){

    data.clear(); // Erases all elements from the vector}

    // ======================// StringSet::size// Number of entries in the stringset.// ======================int StringSet::size(){

    return data.size();}

    // ======================// StringSet::search// This private member function searches the vector for// the target string. If found, the index is returned,// otherwise -1 is returned.// ======================int StringSet::search(const string s){

    int i;for (i=0; i < data.size(); i++){

    if (data[i]==s) return i;

    }return -1;

    }

    // ======================// StringSet::add// Adds a new entry to the vector.// If the entry already exists, then "false" is returned,// otherwise "true" is returned.// ======================bool StringSet::add(const string s){

    int i;

    i = search(s);if (i>=0){

    return false; // s already in the set}data.push_back(s);return true;

    }

  • 8/10/2019 IRM Chapter 6e 11

    33/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    33Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    // ======================// StringSet::remove// Removes an entry from the vector.// If the entry doesnt exist, then "false" is returned,// otherwise "true" is returned and the string is removed.// ======================

    bool StringSet::remove(const string s){

    int i;

    i = search(s);if (i>=0){

    // To remove the string from the vector, we make a new// copy of the vector without the string, then copy that// back to the original vector.// Chapter 18 describes a better technique using the

    "erase"// method and iterators.vector temp;for (int j=0; j

  • 8/10/2019 IRM Chapter 6e 11

    34/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    34Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    if (set1.data[i]==set2.data[j]){

    temp.add(set1.data[i]);}

    }}

    return temp;}

    // ======================// StringSet::operator +// Unions the current StringSet and otherSet, and returns// a new StringSet that is the union of the two.// This code adds all the strings from the first set to temp,// then adds any words from the second set as well. The add// function will weed out any duplicates.// ======================StringSet operator +(const StringSet &set1, const StringSet &set2){

    StringSet temp;int i;

    // Add everything from set 1for (i=0; i

  • 8/10/2019 IRM Chapter 6e 11

    35/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    35Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    getline(cin,s);if (s != string("")){

    setKeywords.add(s);}

    } while (s != string(""));

    }

    // ************************// ReadFileKeywords:// Opens the specified file for reading and inputs its words// into the StringSet.// ************************void readFileKeywords(StringSet &setDocument, const char filename[]){

    ifstream in_stream;string s;

    // Open the filein_stream.open(filename);if (in_stream.fail()){

    cout s;

    setDocument.add(s);}in_stream.close();

    }

    // ======================// main function// ======================int main(){// Variable declarationsStringSet doc1;StringSet doc2;StringSet query;

    readFileKeywords(doc1, "Ch11Proj13Doc1.txt");readFileKeywords(doc2, "Ch11Proj13Doc2.txt");cout

  • 8/10/2019 IRM Chapter 6e 11

    36/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    36Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    StringSet intersect2 = doc2 * query;

    // Calculate similarity to eachdouble sim1 = intersect1.size() / (sqrt(doc1.size()) *sqrt(query.size()));cout

  • 8/10/2019 IRM Chapter 6e 11

    37/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    37Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    Here many of the tools necessary for defining abstract data types are presented. The

    notion of friend, the constkeyword, operator overloading, user-defined casts, and

    separate compilation are all important to the construction of Abstract Data types.

    Namespaces are treated, since the standard libraries require them.

    11.1 Friend Functions

    This section starts by revisiting the class DayOfYear. Recall that few of the operations

    (+, /, -, ==,

  • 8/10/2019 IRM Chapter 6e 11

    38/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    38Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    Consequently, the friend function is not called with member access operators, unless it is

    a member of some other class. The text does not discuss this.

    We emphasize the class grantsfriendship. A function cannot unilaterally seize friendship

    of a class. The declaration must be made in the class definition. It is pointed out in the

    text that friend status can result in increased efficiency by allowing bypassing access

    functions that are otherwise necessary.

    A function that is a friend of a class, unless it is a function member of another class, will

    be defined outside the scope of any class, making the function global, that is, accessible

    in any function definition.

    Like any programming effort, there is a balance to be struck between use of friend

    functions and use of accessor functions. If a function needs to writeto a private

    member of a class, one can have an accessor return a reference to the private

    member, but this makes the privatemember globally writeable. In this case, we

    might as well make the variable public. (This is where you needa friend :).2

    Example:

    //File: Friend.cc

    //To illustrate return by reference.

    #include using namespace std;

    class F

    {

    public:

    F();

    //various constructors

    int& rw_accessor_i();friend int& rw_friend_accessor_i(F& w);

    int read_accessor_i();

    private:

    2The symbol :)is called a smiley. This was originally inserted into email to represent intent tobe amusing. There are many, many of these. See Smileys, David Sanderson, OReilly, 1993.

  • 8/10/2019 IRM Chapter 6e 11

    39/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    39Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    int i;

    };

    F::F() { i = 10; } //we could have written F::F():i(10) {}

    int F::read_accessor_i(){ return i; }

    int& F::rw_accessor_i()

    {

    return i; // not &i, which is the address of i.

    }

    The argument in the following function mustbe pass-by-reference otherwise only the

    local variable xis changed when the variable that is returned is assigned, and the caller's

    argument is not changed. This is a classic error. There must be a chain of references from

    the returned value to the caller's argument.

    int& rw_friend_accessor_i(F& x)

    {

    return x.i; //

    }

    int main()

    {

    F x;

    cout

  • 8/10/2019 IRM Chapter 6e 11

    40/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    40Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

  • 8/10/2019 IRM Chapter 6e 11

    41/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    41Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    This suggests that the error is in the input or early in the output routines, since

    my_amountis set by constructor. The value reported formy_amountis wrong, as

    well as a ridiculous result for your_amount.

    Placing output statements in Money::input determined that this routine was working

    correctly. As soon as I looked at the output routine the lack of an= sign in the second

    line jumped out at me. The errors in output for my_amount and your_amountare

    caused by not setting positive_cents in that routine.

    The other error was leaving out the last two lines of Money::input(istream&).

    The program worked fine until tested with negative values, which were accepted, and

    recorded as positive entries. These seem like trivial errors, but my students make errors

    without having any idea about what the possibilities are, nor how to test to find the errors,

    let alone how to do efficient testing.

    A debugger can be a great help but it is not a panacea. Frequently it is faster to insert

    output statements at places in the code that are suggested by the errors produced. Under

    any circumstances, whether a debugger is used or output statements are added, planning

    is necessary.

    Again, I point out the need for the student to create her own exercises like those in

    Chapter 1 of the text that help students see what error messages are issued for particular

    questions about syntax.

    Many errors are more subtle. Fixing the typo fixed the routine, until I tried it for negative

    money amounts, as noted above.

    The const Parameter Modifier

    Remember these three things about usage of the constkeyword. One: Use of the

    keyword constis a promise to the compiler that you wont write code that changes

    something. Two: This use is a request that the compiler enforce these promises. Three:

    The use of constis difficult or impossible to retrofit. If you write code without const

    correctness, that code almost certainly will have to be rewritten from the ground up to get

    the code right.

    The declaration

  • 8/10/2019 IRM Chapter 6e 11

    42/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    42Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    const int x = 3;

    is a promise to the compiler that you wont write anything that has the potential to change

    x,such as using x on the left of an assignment statement or as an argument to a non-

    const reference parameter. A constmember function promises not to change any classdata using that function. A use of const in a class object declaration promises that you

    wont call any function with the potential to change that objects data members. As

    mentioned, the compiler tries to enforce these promises.

    The text points out that use of the constkeyword requires consistency. If you declare a

    constparameter for a function member declaration in a class, you mustuse the const

    keyword in your definition of that function member. If you use a non-constobject for

    an argument, and do not declare the function with a constparameter, you should get anerror or a warning from your compiler. If you fail to declare a member function to be

    const, then call this member on behalf of a constobject of this class, as below, you

    should get an error. The reason is in C++ the compilers encode all the information about

    a function: name of the function, the sequence of types in the argument list, including

    const qualifiers, and for member functions of a class, any const qualifiers that follow the

    declaration and uses this as the function name. If the constqualifier is in the definition

    but not in the class declaration, as far as the compiler is concerned, they are different

    functions, and you get an error.

    It is worth noting that in the following example, the Borland compiler is more forgiving

    of the const errors than the GNU compiler. The point is that each compiler has things it is

    fussy about. Know your compiler.

    //File: test.const.cc

    //to test attempt use of non-const arg for nonconst

    //reference parameter. and to apply a nonconst member

    //to a const object

    #include

    using namespace std;

    class C

    {

  • 8/10/2019 IRM Chapter 6e 11

    43/52

  • 8/10/2019 IRM Chapter 6e 11

    44/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    44Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    Compilation finished at Sun Dec 31 16:38:51

    g++ -c test.const.cpp

    In function 'int main()':

    29: passing 'const C' as 'this' argument of 'voidC::output()' discards qualifiers

    30: conversion from 'const int' to 'int &' discards

    qualifiers

    25: in passing argument 1 of 't(int &)'

    Compilation exited abnormally with code 1 at Sun Dec 31

    16:37:54

    Overloading Operators

    Suppose the compiler seesx andy in the context

    x op y

    where one of x ory is an object of class Some_Class. For the sake of definiteness,

    suppose it isx that is of classSome_Class. Further, suppose 'op' is one of the

    many C++ operators capable of being overloaded. The compiler then looks for a

    function:

    return_type operator op(Some_Class x, type_name y);

    or for a member function

    return_type Some_Class::operator op(type_name y);

    to which the compiler generates a call.

    For example, consider the infix expression

    x + y

    where for the variablesx andy have been defined to have the inttype. If the

    operatorop were overloaded as a standalone function, the infix expression is translated

    into the direct call to the operator function,

    operator+ (x, y);

  • 8/10/2019 IRM Chapter 6e 11

    45/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    45Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    If the operator op were overloaded as a standalone function, the infix expression is

    translated into this direct call to the operator function,

    x.operator+(y);

    The programmer can actually write direct calls to the operator functions, but there is no

    good reason to do so other than to verify that this is possible. Nevertheless, my students

    want to call the operator functions directly instead of the infix operators. I found it

    necessary to spend some time emphasizing that the compiler does that for them.

    Some Rules

    1. Precedence and arity (the number of arguments) of the operator cannot be changed by

    overloading. For example, a binary/ cannot be made to be a unary operator.

    2. Operator functions for=, ->, [] and () must be non-static members of the

    class to which they apply. (Overloading of the operators =, [] and-> is discussed

    later in the text.)

    The student must know and understand the rules listed on page 471 of the text.

    Friends Vs Member overloading (for the instructor)

    Please note that the text does not discuss overloading operators as members until Chapter

    11.

    There is a compelling argument in favor of overloading operators using friends rather

    than overloading as members. Professor Savitch pointed out to me that he did not put

    both in the text at this point because presumably the students only know about the friend

    overloading method. It is worth pointing out to the instructor that if both operands are

    arguments, then C++ will do automatic type conversion of either argument to the class

    type from simple types such as int (provided you have supplied an appropriate

    constructor). This allows you to use 2 as a Rational or an amount of money in an

    expression such as

    object + 2

    or

    2 + object

  • 8/10/2019 IRM Chapter 6e 11

    46/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    46Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    which are converted to

    operator+(object, 2);

    or

    operator+(2, object);

    where the non class type arguments will be converted to an object using the constructor

    having anintargument. However, if operator+is a member, then the first argument

    must always be an object,

    as in:

    object + 2

    and expressions such as

    2 + object

    are always illegal. This is the reason for presenting the friend rather than member

    operator overloading first.

    More detail on operator overloading (for the instructor)

    The decision on whether to write an overloading operator function as a stand-alone

    function (most likely a friend of the class) or to write the operator function as a memberdepends on several things. Is the operator expected to behave symmetrically between the

    arguments? If so, the operator should be a standalone function (and probably a friend of

    the class). If the asymmetry is desired or is no problem, then a member operator function

    may be used.

    Here is an example, stripped of all details except the minimum to illustrate the language

    behavior. This code illustrates the essential asymmetry of operators overloaded as

    members.

    //File: overload1.cc

    //to test behavior of member operator overloading.

    //What conversions and when the conversions are made.

    #include

  • 8/10/2019 IRM Chapter 6e 11

    47/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    47Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    using namespace std;

    class F

    {

    public:F(){};

    void operator +(Fx);

    F(int);

    operator int ();

    };

    F::F(){} //does nothing

    F::F(int)

    {

    cout

  • 8/10/2019 IRM Chapter 6e 11

    48/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    48Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    F x;

    int i = 2;

    cout

  • 8/10/2019 IRM Chapter 6e 11

    49/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    49Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    using namespace std;

    class F

    {

    public:friend F operator +(F u, F v);

    F(int q);

    operator int ();

    private:

    int p;

    };

    F::F(int q){

    p = q;

    cout

  • 8/10/2019 IRM Chapter 6e 11

    50/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    50Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    int i = 2;

    cout

  • 8/10/2019 IRM Chapter 6e 11

    51/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    51Copyright 2007 Pearson Education, Inc. Publishing as Pearson Addison-Wesley

    If we are the class author, we can add a member overloading

    operator

  • 8/10/2019 IRM Chapter 6e 11

    52/52

    Savitch Instructors Resource GuideProblem Solving w/ C++, 6e Chapter 11

    The difference in coding amounts to replacing the return type with void, and removing

    the returnstatement from the function. The sole advantage is not having to return the

    stream.

    // returns istream&:istream& operator >> (istream& ins, Money& amount)

    {

    //all the necessary code to fetch the amount

    //from the istream and do some format checking

    //are in Display 11.8 in the text.

    return ins;

    }

    void operator >> (istream& ins, Money& amount)

    {

    //all the necessary code to fetch the amount

    //from the istream and do some format checking

    //are in Display 11.8 in the text.

    //no return statement

    }

    Similar arrangements work for overloading operator