Topical Information

The purpose of this quiz is to give you a chance to focus your knowledge of overloading operators in C++.

Quiz Information

Questions

  1. Name three operators which cannot be overloaded at all.

    
        operators that cannot be overloaded include ., .*, sizeof, and :: in both
        unary and binary forms.
    
    

  2. How does one go about deciding whether an operator should be a member function or a non-member? (Hint: There is a three rule process to the decision.)

    
        1) Does it have to be a member operator?  (I.E. =, [], and ().)
        2) Is its left-hand operand of the type being overloaded for?  Then it must
           not be a member!
        3) Otherwise, it is up to the programmer's discretion.
    
    

  3.  
    TRUE   FALSE   The meaning of an operator can be changed when overloading it.
    TRUE   FALSE   When overloading an operator, we can easily change the arity of the operator.
    TRUE   FALSE   One can change the precedence of an operator when overloading it.
    TRUE   FALSE   The associativity of an overloaded operator, however, cannot be changed.
  4. When overloading the ____ operator, it is important to consider if the programmer will want to/should be allowed to use this operator as an Lvalue (value usable on the left side of an assignment). If so, the operator should return a ____ the data in question. If not, the operator should return a copy of the data and the operator function should be made ____. Often, we do both (so that the operation can work on both regular and constant objects).

    1. =, pointer to, const NO
    2. +, reference to, a friend NO
    3. &, address of, a member NO
    4. -, copy of, unary NO
    5. [], reference to, const YES

  5. operators which can be, but are seldom, overloaded include new (which is used to allocate memory on the heap for single objects), delete[] (used to deallocate heap memory for whole arrays), and , (which normally returns the result of its right-hand operand unchanged).

  6. Show the code for an overloaded + operator for a Rational class. (Make sure you've accounted for reasonable compatibility with the built-in types.)

    
        Either just:
    
            Rational operator+(const Rational & left, const Rational & right)
            {
                return Rational{left.numer*right.denom + left.denom*right.numer,
                                left.denom*right.denom};
            }
    
        or we could do three overloads assuming an explicit constructor that makes
        Rational objects from lone integers.
    
    

  7. What is the ~ operator normally used for? What sort of clever use might you put it to on a Rational class? Is this a good idea?

    
        ~ is normally used to change 0s to 1s in an integer memory location and
        vice versa.  We often say it is flipping the bits.
    
        We might use it for either reciprocal because of its flipping heritage or
        for decimal approximation because it resembles "approximately equal to" from
        math.
    
        Since there are two perfectly reasonable uses for this operator in a
        Rational class, we should probably refrain from overloading it at all to
        avoid confusion.
    
    

  8. When overloading either ++ or --, how does the programmer tell the compiler that you desire to change the pre- or post- version of the operator? (i.e. How can you distinguish between x++ and ++x during overloading?)

    
        The postfix version of these operators takes a plain int argument that is
        unnamed and unused inside the function definition.  Its entire purpose is
        to make the signatures of the two function forms different so the compiler
        can tell them apart.
    
        That is:
    
            Rational operator++(int) const;   // post-increment
            Rational & operator++(void) const;  // pre-increment
    
    

  9. Recalling that the statement:

        y = 2 + x;
    

    is translated by the compiler into:

        y.operator=(operator+(2,x));
    

    Show the operator function call syntax for each of the following statements. (Whenever possible, assume the operator is a class member and the variable an object. If an operator is NOT overloadable, don't use the function call syntax!)

    1.     y = 4*x+z/7;
      
      
          y.operator=(operator*(4,x).operator+(z.operator/(7)));
      
      
    2.     x << 5 << "Hi";
      
      
          x.operator<<(5).operator<<("Hi");
      
      
    3.     y = x++;
      
      
          y.operator=(x.operator(0));
      
      
    4.     (7 == x) ? (&u) : (-::p);
      
      
          operator==(7,x) ? u.operator&() : ::p.operator-();
      
      
    5.     q += 7 & t;
      
      
          q.operator+=(operator&(7,t));
      
      
    6.     7 >> h > 2;
      
      
          operator>>(7,h).operator>(2);
      
      
    7.     y(12 + 7 - *u - !a + z[u^t] | j++) = 10 % +w < (z , m);
      
      
          y.operator()(operator-(12+7,u.operator*()).operator-(a.operator!())
                                 .operator+(z.operator[](u.operator^(t)))
                                 .operator|(j.operator++(0))).operator=(
                                 operator<(10 % w.operator+(),z.operator,(m)));
      
      

  10. Name three operators which must be member functions when overloaded.

    
        These would be assignment (=), function call (()), subscript ([]), and
        arrow (->).
    
    
  11.  
    TRUE   FALSE   When overloading operators, we can also create our own new operators.
  12. Why can't we overload the ~ operator in an assignment form just like * (*=), + (+=), and - (-=)? (i.e. Why isn't there a ~= operator?)

    
        ~ is only a unary operator.  The other mentioned operators are both
        unary and binary depending on context.  It is their binary versions that
        have "with assignment" variants -- not their unary versions!  Thus there
        can be no unary "with assignment" variants.