Title: Operator Overloading
1Operator Overloading
- Fred Kuhns
- Computer Science and Engineering
- Washington University in St. Louis
2Intro
class complex double re, im public complex(d
ouble r) re(r) complex(double r, double
i) re(r), im(i) complex operator(complex)
complex operator(complex) complex w(1,0),
x(2,2) complex y w.operator(x) complex z w
x
- when overloading operators the usual precedence
rules apply - obj1.operator_at_(obj2) same as obj1 obj2
- you can not define new operator tokens
- what cant be defined for user types?
- scope resolution
- . member selection
- . member selection through pointer to function
3defining operators
- binary operators can be interpreted in either of
two ways (operator _at_) either way - a.operator_at_(b) nonstatic member functions
- operator_at_(a, b) nonmember function
- if both ar edefined then overload resolution
determines which to use - Unary operators, operator _at_
- prefix
- a.operator_at_() nonstatic member function
- operator_at_(a) nonmember function
- postfix
- a.operator_at_(int) nonstatic member function
- operator_at_(a, int) nonmember function
- overload resolution
- exact match
- promotions integral promotions
- standard conversions int to double, double to
int derived to base T to void, signed to
unsigned. - user-defined conversions
- ellipses
- If two matches at same level then ambiguous
- Note return types are not considered in overload
resolution
4predefined meanings of operators
- operators , , () and -gt must be nonstatic
member functions to ensure their first operands
are lvalues. - operators , and , have predefined meanings
- enumerations are user defined types so you can
define operators - Namespaces and operator resolution
- X x Y y x _at_ y // resolving operator _at_
- if X is a class and it or a base class defines _at_
then use it - find _at_ in immediate context
- if X defined in namespace N then look there
- if Y defined in namespace M then look there
5guidelines
- how do you choose which operators to make member
functions and which to make nonmember? - one approach is to just define a basic set of
simple operators that must alter object state
within the class. Then all other operators are
nonmember. - good candidates for member functions are
composite assignment operators , -, , /
etc.
complex complexoperator(complex(a)) re
a.re im a.im return this complex
operator(complex a, complex b) complex r
a return r b
class complex double re, im public comple
x operator(complex a)
6Implicit Type Conversion
Example 1 Date Date(int m) Date
operator(Date, Date) Date d1(02,19,06) int
i1 Date d2 d1 i1 // OK, implicit
- Constructor accepting a single argument defines
an implicit type conversion - In example 1 the integer i1 is implicitly
converted to a temporary object of type Date. - In example 2 the constructor is declared explicit
to prevent implicit conversions.
Example 2 Date explicit Date(int m)
Date operator(Date, Date) Date
d1(02,19,06) int i1 Date d2 d1 i1 //
Error Date d3 d1 Date(i1) // OK
7Copy Control
- Copy Constructor
- initialize one object from another
- copy an argument for a function call
- copy an object when returning from a function
call - initializing elements in a sequential container
- initialize array elements from an element
initializer listClass CX CX(CX) CX obj1
CX obj2 obj1 - If a copy constructor is not specified then the
compiler synthesizes one which uses memberwise
copy initialization. - Copy by assignment, the compiler will synthesize
an assignment operator if one is not specified.
Its semantics is also memberwise assignment.
8More on copy constructor
- Copy constructor is used for variable
initialization, argument passing, value return
and exception handling. - complexcomplex(complex a) re(a.re), im(a.im)
// error - complexcomplex(complex a) re(a.re),
im(a.im) // correct - controlling access to copy constructor
- complex
- private
- complexcomplex(const complex a)
- public
- explicit complexcomplex(double a)
-
-
- Complex c 0 // error, no implicit
complexcomplex(double) - Complex b Complex(0) // OK, explicit
- Complex x(b) // error, ComplexComplex(Complex
) is private - Complex y b // OK, memberwise copy is default
9Copy Objects
class Student char name public Student(c
har nnull) Student()
- Copy initialization
- XX(const X)
- Copy assignment
- X operator(const X)
- Example
- (0) void fn()
- (1) Student s1(Fred) // Value constructor
- (2) Student s2 s1 // copy initialization
- (3) Student s3 // default constructor
- (4) s3 s2 // copy assignment
- (5) // call destructors
- Do you see any problems here?
- memory leak
- delete called on same memory 3 times
10Fixing the problem
StudentStudent (char n) len_ calcLen(n)
name new charlen_ name \0
copyName(name, n) StudentStudent(const
Student s) len_ s.len_ name new
charlen_ copyName(name, s.name) Student
Studentoperator(Student s) if (this !
s) delete name name new
chars.len_ copyName(name, s.name)
return this StudentStudent() cout
ltlt Calling destructor\n if (name) delete
name
- Define
- Copy constructor.
- Copy assignment check for self-assignment,
delete old elements, initialize and copy new
elements.
class Student char name public
Student(char nNULL) Student(const
Student) Studentoperator(const
Student) Student()
11mixed mode, conversions and initializing
class complex double re, im public complex(d
ouble r, double i) re(r), im(i) // define
type conversions for complex complex(int a)
re(i), im(0) complex(double a) re(a),
im(0) complex x 4 // use
complex(int) complex y 5.0 // use complex
double complex z 6 y
- Note if type has a constructor then can not
initialize with list. - single argument constructor may be called
implicitly for type conversion.
12Conversion Operators
- Convert from type X to type T. A conversion
operator does not take arguments and does not
specify a return type. - Class type conversions may be followed by
standard conversion when finding the best match
of candidate functions. - Only one class type conversion is applied (can
not chain them together) - XoperatorT()
- class Number
- int val
- public
- Number() val(0)
- Number(int i) val(i)
- // define conversion from Number to int
- operator int() const return val
-
-
- int i Number(4)
- Number num(8)
- // num is converted to type int then compared to
10 - if (num gt 10)