Same Name Different Signatures: Add (Int, Long) Add (Long, Int) Add (Const Base &) Add (Const Derived &) Derived Base

You might also like

Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 7

Overview of C++ Overloading

• Overloading occurs when the same operator or


function name is used with different signatures

• Both operators and functions can be overloaded

• Different definitions must be distinguished by their


signatures (otherwise which to call is ambiguous)
– Reminder: signature is the operator/function name and the
ordered list of its argument types
– E.g., add(int,long) and add(long,int) have different
signatures
– E.g., add(const Base &) and add(const Derived &)
have different signatures, even if Derived is-a Base
– Most specific match is used to select which one to call

CSE 332: C++ Overloading


Overloading vs. Overriding
• Overriding a base class member function is
similar to overloading a function or operator
– But for overriding, definitions are distinguished by
their scopes rather than by their signatures

• C++ can distinguish method definitions


according to either static or dynamic type
– Depends on whether a method is virtual or not
– Depends on whether called via a reference or
pointer vs. directly on an object
– Depends on whether the call states the scope
explicitly (e.g., Foo::baz();)

CSE 332: C++ Overloading


Function Overloading
class A { • Calls to overloaded functions and
public:
int add(int i, int j);
operators are resolved by
– Finding all possible matches based
// not allowed, would be on passed arguments
// ambiguous with above: • May involve type promotion
// long add(int m, int n); • May involve instantiating templates
– Finding the “best match” among
// Ok, different signature those possible matches
long add(long m, long n);
};
• Signature does not include the
int return type
main (int argc, char **argv) {
int a = 7; – Which might not help even if it did,
int b = 8; i.e., calls may ignore result
int c = add(a, b); – So, overloading can’t be resolved by
return 0; return type alone
} – Compiler generates an error if the
call can’t be resolved

CSE 332: C++ Overloading


Operator Overloading
class A { • Similar to function
friend ostream &operator<<
(ostream &, const A &);
overloading
private: – Resolved by signature
int m_; – Best match is used
};

ostream &operator<< • But the list of operators and


(ostream &out, const A &a) { the “arity” of each is fixed
out << "A::m_ = " << a.m_;
return out; – Can’t invent operators (e.g.,
} like ** for exponentiation )
– Must use same number of
int main () { arguments as for built-in types
A a; (except for operator())
cout << a << endl; – Some operators are off limits
return 0;
}
:: (scope) ?: (conditional)
.* (member dereference)
. (member) sizeof
typeid (RTTI)

CSE 332: C++ Overloading


Operator Symmetry, Precedence
class Complex {
public:
• Make arithmetic
// Constructor operators symmetric
Complex (double r, double i); – As non-member friends
friend Complex operator* – Return result by value
(const Complex &, const Complex &); – Don’t mix base and
// but not friend Complex operator^ derived types in their
// (const Complex &, const Complex &); parameter lists
private:
• Operators for user-
int real_; defined types obey the
};
int imaginary_; same precedence rules
as for built-in types
// multiplication works just fine – Can lead to some
Complex operator* (const Complex &,
const Complex &);
unexpected mistakes
– E.g., if uncommented
// exponentiation operator unworkable exponentiation for
// Complex operator^ (const Complex &,
// const Complex &); a + b * c ^ 2
CSE 332: C++ Overloading
Member vs. Non-Member Overloading
// declarations in .h file • Remember a this pointer is passed
class A { to any non-static member function
public: – Object doesn’t appear in parameters
friend bool operator< – For non-member functions and
(const A &, const A &); operators all parameters are listed
A operator++(); // prefix • The rules about operator arity are
A operator++(int); // postfix obeyed in code on left
private: – Operator == is binary
int m_;
– Prefix/postfix ++ are unary, parameter
}; for postfix distinguishes its signature
bool operator==(const A &lhs,
const A &rhs);
• Must declare and define [] and ==
and -> and () as member operators
// definitions in .cpp file • Non-member operators are needed
bool operator==(const A &lhs, when working with classes you wrote
const A &rhs) and classes you didn’t write
{return lhs.m_ == rhs.m_;} – E.g., ostream << and istream >>
• Non-member operators are also useful
A A::operator++() // prefix to preserve symmetry
{++m_; return *this;} – E.g., for arithmetic/relational operators
– May help to avoid unexpected type
A A::operator++(int) // postfix conversions, especially with an
{A ret(*this); ++*this; return ret;} inheritance hierarchy

CSE 332: C++ Overloading


Summary: Tips on Overloading
• Use virtual overriding when you want to substitute
different subtypes polymorphically
– E.g., move() in derived and base classes

• Use overloading when you want to provide related


interfaces to similar abstractions
– E.g., migrate(Bird &) vs. migrate(Elephant &)
– Make[] -> () = *= ++ -- etc. members
– Make << >> + * - / == < etc. non-members

• Use different names when the abstractions differ


– E.g., fly() versus walk()

CSE 332: C++ Overloading

You might also like