c++ - Operator overloading -



c++ - Operator overloading -

what basic rules , idioms operator overloading in c++?

note: answers given in a specific order, since many users sort answers according votes, rather time given, here's index of answers in order in create sense:

the general syntax of operator overloading in c++ the 3 basic rules of operator overloading in c++ the decision between fellow member , non-member common operators overload assignment operator input , output operators function phone call operator comparison operators arithmetic operators array subscripting operators pointer-like types conversion operators overloading new , delete

(note: meant entry stack overflow's c++ faq. if want critique thought of providing faq in form, the posting on meta started this place that. answers question monitored in c++ chatroom, faq thought started out in first place, reply read came idea.)

common operators overload

most of work in overloading operators boiler-plate code. little wonder, since operators simply syntactic sugar, actual work done (and forwarded to) plain functions. of import boiler-plate code right. if fail, either operator’s code won’t compile or users’ code won’t compile or users’ code behave surprisingly.

assignment operator

there's lot said assignment. however, of has been said in gman's famous copy-and-swap faq, i'll skip of here, listing perfect assignment operator reference:

x& x::operator=(x rhs) { swap(rhs); homecoming *this; } bitshift operators (used stream i/o)

the bitshift operators << , >>, although still used in hardware interfacing bit-manipulation functions inherit c, have become more prevalent overloaded stream input , output operators in applications. guidance overloading bit-manipulation operators, see section below on binary arithmetic operators. implementing own custom format , parsing logic when object used iostreams, continue.

the stream operators, among commonly overloaded operators, binary infix operators syntax specifies no restriction on whether should members or non-members. since alter left argument (they alter stream’s state), should, according rules of thumb, implemented members of left operand’s type. however, left operands streams standard library, , while of stream output , input operators defined standard library indeed defined members of stream classes, when implement output , input operations own types, cannot alter standard library’s stream types. that’s why need implement these operators own types non-member functions. canonical forms of 2 these:

std::ostream& operator<<(std::ostream& os, const t& obj) { // write obj stream homecoming os; } std::istream& operator>>(std::istream& is, t& obj) { // read obj stream if( /* no valid object of t found in stream */ ) is.setstate(std::ios::failbit); homecoming is; }

when implementing operator>>, manually setting stream’s state necessary when reading succeeded, result not expected.

function phone call operator

the function phone call operator, used create function objects, known functors, must defined member function, has implicit this argument of fellow member functions. other can overloaded take number of additional arguments, including zero.

throughout c++ standard library, function objects copied. own function objects should hence inexpensive copy. if function object absolutely needs utilize info expensive copy, improve store info elsewhere , have function object refer it.

comparison operators

the binary infix comparing operators should, according rules of thumb, implemented non-member functions1. unary prefix negation ! should (according same rules) implemented fellow member function. (but not thought overload it.)

the standard library’s algorithms (e.g. std::sort()) , types (e.g. std::map) expect operator< present. however, users of type expect other operators present, too, if define operator<, sure follow 3rd fundamental rule of operator overloading , define other boolean comparing operators. canonical way implement them this:

inline bool operator==(const x& lhs, const x& rhs){ /* actual comparing */ } inline bool operator!=(const x& lhs, const x& rhs){return !operator==(lhs,rhs);} inline bool operator< (const x& lhs, const x& rhs){ /* actual comparing */ } inline bool operator> (const x& lhs, const x& rhs){return operator< (rhs,lhs);} inline bool operator<=(const x& lhs, const x& rhs){return !operator> (lhs,rhs);} inline bool operator>=(const x& lhs, const x& rhs){return !operator< (lhs,rhs);}

the of import thing note here 2 of these operators anything, others forwarding arguments either of these 2 actual work.

the syntax overloading remaining binary boolean operators (||, &&) follows rules of comparing operators. however, very unlikely find reasonable utilize case these2.

1 as rules of thumb, there might reasons break one, too. if so, not forget left-hand operand of binary comparing operators, fellow member functions *this, needs const, too. comparing operator implemented fellow member function have have signature:

bool operator<(const x& rhs) const { /* actual comparing *this */ }

(note const @ end.)

2 it should noted built-in version of || , && utilize shortcut semantics. while user defined ones (because syntactic sugar method calls) not utilize shortcut semantics. user expect these operators have shortcut semantics, , code may depend on it, hence highly advised never define them.

arithmetic operators unary arithmetic operators

the unary increment , decrement operators come in both prefix , postfix flavor. tell 1 other, postfix variants take additional dummy int argument. if overload increment or decrement, sure implement both prefix , postfix versions. here canonical implementation of increment, decrement follows same rules:

class x { x& operator++() { // actual increment homecoming *this; } x operator++(int) { x tmp(*this); operator++(); homecoming tmp; } };

note postfix variant implemented in terms of prefix. note postfix copy.2

overloading unary minus , plus not mutual , best avoided. if needed, should overloaded fellow member functions.

2 also note postfix variant more work , hence less efficient utilize prefix variant. reason prefer prefix increment on postfix increment. while compilers can optimize away additional work of postfix increment built-in types, might not able same user-defined types (which innocently looking list iterator). 1 time got used i++, becomes hard remember ++i instead when i not of built-in type (plus you'd have alter code when changing type), improve create habit of using prefix increment, unless postfix explicitly needed.

binary arithmetic operators

for binary arithmetic operators, not forget obey 3rd basic rule operator overloading: if provide +, provide +=, if provide -, not omit -=, etc. andrew koenig said have been first observe compound assignment operators can used base of operations non-compound counterparts. is, operator + implemented in terms of +=, - implemented in terms of -= etc.

according our rules of thumb, + , companions should non-members, while compound assignment counterparts (+= etc.), changing left argument, should member. here exemplary code += , +, other binary arithmetic operators should implemented in same way:

class x { x& operator+=(const x& rhs) { // actual add-on of rhs *this homecoming *this; } }; inline x operator+(x lhs, const x& rhs) { lhs += rhs; homecoming lhs; }

operator+= returns result per reference, while operator+ returns re-create of result. of course, returning reference more efficient returning copy, in case of operator+, there no way around copying. when write a + b, expect result new value, why operator+ has homecoming new value.3 note operator+ takes left operand by copy rather const reference. reason same reason giving operator= taking argument per copy.

the bit manipulation operators ~ & | ^ << >> should implemented in same way arithmetic operators. however, (except overloading << , >> output , input) there few reasonable utilize cases overloading these.

3 again, lesson taken a += b is, in general, more efficient a + b , should preferred if possible.

array subscripting

the array subscript operator binary operator must implemented class member. used container-like types allow access info elements key. canonical form of providing these this:

class x { value_type& operator[](index_type idx); const value_type& operator[](index_type idx) const; // ... };

unless not want users of class able alter info elements returned operator[] (in case can omit non-const variant), should provide both variants of operator.

if value_type known refer built-in type, const variant of operator should homecoming re-create instead of const reference.

operators pointer-like types

for defining own iterators or smart pointers, have overload unary prefix dereference operator * , binary infix pointer fellow member access operator ->:

class my_ptr { value_type& operator*(); const value_type& operator*() const; value_type* operator->(); const value_type* operator->() const; };

note these, too, need both const , non-const version. -> operator value_type must of class (or struct or union) type, otherwise implementation results in compile-time error.

the unary address-of operator should never overloaded.

for operator->*() see this question. it's used , ever overloaded. in fact, iterators not overload it.

continue conversion operators

c++ operators operator-overloading c++-faq

Comments

Popular posts from this blog

assembly - What is the addressing mode for ld, add, and rjmp instructions? -

vowpalwabbit - Interpreting Vowpal Wabbit results: Why are some lines appended by "h"? -

Is there a way to convert an HTML page styled with Bootstrap CSS into email-compatible html? -