View
227
Download
2
Embed Size (px)
Citation preview
this, friend this, friend and operatorsand operators
thisthis
exists in every exists in every non-staticnon-static method method a pointer to the oblect, for which the method a pointer to the oblect, for which the method
was calledwas called used for returning reference or pointer to the used for returning reference or pointer to the
object for which the method was calledobject for which the method was called does not occupy memorydoes not occupy memory does not need to be declareddoes not need to be declared
thisthis
person & person::timeTravel(int years)person & person::timeTravel(int years){{ age += years; age += years; return *this; return *this; }}
person Boss(„John”, „Kovalsky”, 40);person Boss(„John”, „Kovalsky”, 40);( Boss.timeTravel(+20) ).timeTravel(-30)( Boss.timeTravel(+20) ).timeTravel(-30)
friendfriend
by declaring a „friendly” code we allow by declaring a „friendly” code we allow accessing protected and private members of accessing protected and private members of the classthe class
friendfriend
class class AA{{ friend C::friend C::theMethodNoArgtheMethodNoArg(); (); // specific method (if overloaded, then with specific args)// specific method (if overloaded, then with specific args) friend class B; friend class B; // concerns whole declaration of B// concerns whole declaration of B // declarations inside B also can access // declarations inside B also can access // non-public A members// non-public A members friend fun(); friend fun(); // specific function (if overloaded, then with specific args)// specific function (if overloaded, then with specific args)}}
friendfriend
friendship is not inheritivefriendship is not inheritive
friendship is not transtivefriendship is not transtive
friendship is declared in any section of a class friendship is declared in any section of a class (even private)(even private)
friendfriendclass M {
friend void f() { ……}
};
is equivalent tois equivalent to
class M {friend void f();
};
void f() { … }
OperatorsOperators
What is an operator?What is an operator?
a = b.val >> 4 + c * d[ e++ ]a = b.val >> 4 + c * d[ e++ ]
OperatorsOperators
operator operator defines operations performed on its defines operations performed on its arguments and the type of the resulting arguments and the type of the resulting expression expression – – similarly to functionssimilarly to functions..
inin C C++++ we may define operators to be used we may define operators to be used with objectswith objects ( (at least one argument of the at least one argument of the operator should be an objectoperator should be an object).).
OperatorsOperators
Most operators are overloadableMost operators are overloadable
Overloading may improve performance – Overloading may improve performance – similarly to functionssimilarly to functions
There is no obligation, and usually no need There is no obligation, and usually no need either, to define a lot of operators. Instead of either, to define a lot of operators. Instead of operator that is used rarely it is advised to operator that is used rarely it is advised to declare a method or a functiondeclare a method or a function
Overloadable operatorsOverloadable operators
() [] ->() [] ->+ - ++ -- ! ~ * & new delete (typ)+ - ++ -- ! ~ * & new delete (typ) // unary// unary->*->** / %* / %+ -+ -<< >><< >>< <= > >=< <= > >=== !=== !=&&^̂||&&&&||||= += -= *= /= %= &= ^= |= <<= >>= = += -= *= /= %= &= ^= |= <<= >>= // assignment// assignment
OperatorsOperators Not overloadable operators:Not overloadable operators:
.. .* .* :::: ?:?: sizeofsizeof
operators to be declared exclusively as a class members:operators to be declared exclusively as a class members:
()() [][] ->-> newnew deletedelete (typ)(typ) ==
predefined operarors (redefinable):predefined operarors (redefinable):
== &&
AssociativityAssociativity
assignment and unary operatorsassignment and unary operators are of right are of right associativityassociativity
a=b=c a=b=c is equivalent to is equivalent to a=(b=c)a=(b=c)
remaining onesremaining ones are of right associativityare of right associativity
a+b+ca+b+c is equivalent to is equivalent to (a+b)+c(a+b)+c
Order of evaluationOrder of evaluation
order of evaluation is undefined, except for:order of evaluation is undefined, except for:
,, |||| && &&
„ „ , , ”, „ || ”, „ && ” evaluated in the left to right order”, „ || ”, „ && ” evaluated in the left to right order
right arguments of operators „ || ”, „ && ” are right arguments of operators „ || ”, „ && ” are evaluated only if necessary.evaluated only if necessary.
Operators vs. methodsOperators vs. methods
different syntax for declaring, defining an callindifferent syntax for declaring, defining an callin
no default arguments allowed (exception: function no default arguments allowed (exception: function call operator)call operator)
there is a fixed number of arguments for specific there is a fixed number of arguments for specific operator (exception: function call operator)operator (exception: function call operator)
there is a traditional semantics (meaning) of operatorsthere is a traditional semantics (meaning) of operators
OperatorsOperators If You need += then define it, If You need += then define it,
defining + and = does not sufficedefining + and = does not suffice
If You need ++ then define it,If You need ++ then define it,defining + and = does not sufficedefining + and = does not suffice
Mind the traditional meaning of operatorsMind the traditional meaning of operators let the unarylet the unary & & return the addressreturn the address
Be cosistentBe cosistent ++i; ++i; i++; i++; i+=1; i+=1; i=i+1; i=i+1; // should result in the same change of i// should result in the same change of i
Operators as methodsOperators as methods object of the class is the first argument of the operatorobject of the class is the first argument of the operator we declare all arguments, but the first onewe declare all arguments, but the first one
declaringdeclaring
int point::operator<=(point);int point::operator<=(point);
callingcalling
point point1, point2;point point1, point2;int i=int i= point1point1 <=<= point2;point2;int int jj== point1.operator<=(point2);point1.operator<=(point2);
Operators as functionsOperators as functions at least one argument of the operator should be an objectat least one argument of the operator should be an object all the arguments are operator function parametersall the arguments are operator function parameters there is no thisthere is no this
declaringdeclaring
int operator<=(pointint operator<=(point, point, point););
callingcalling
point point1, point2;point point1, point2;int iint i == point1point1 <=<= point2;point2;int int jj== operator<=(operator<=(point1, point1, point2);point2);
Convention for Convention for ++ ++ andand -- --
operator++() operator++() andand operator operator----()() are prefix ones are prefix ones
++i++i --i --i
postfix operators should be drfined using one postfix operators should be drfined using one additional unnamed int argumentadditional unnamed int argument: :
operator++(int)operator++(int);; operatoroperator----(int);(int);
i++i++ i--i--
Convention for Convention for ++ ++ andand -- --
class X {public:
X& operator++(); // prefix ++aX operator++(int); // postfix a++
};
class Y {public:};
Y& operator++(Y&); // prefix ++bY operator++(Y&, int); // postfix b++
Convention for Convention for ++ ++ andand -- --
void f(X a, Y b){
++a; // a.operator++();a++; // a.operator++(0);++b; // operator++(b);b++; // operator++(b, 0);a.operator++(); // explicit call: like ++a;a.operator++(0); // explicit call: like a++;operator++(b); // explicit call: like ++b;operator++(b, 0); // explicit call: like b++;
}
OperatorsOperatorsclass X class X // members with this pointer avaliable// members with this pointer avaliable{{
X* operator&();X* operator&(); // prefix, unary, &// prefix, unary, &X operator&(X);X operator&(X); // two args// two argsX operator++(int);X operator++(int); // suffix// suffix
//// X operator&(X, X);X operator&(X, X);// error! 3 args// error! 3 args//// X operator/();X operator/(); // error! unary / ???// error! unary / ???};};
// standalone functions, no this, often friends of some class// standalone functions, no this, often friends of some classX operator-(X);X operator-(X); // prefix, unary, -// prefix, unary, -X operator-(X, X);X operator-(X, X); // two args// two argsX operator--(X&, int);X operator--(X&, int); // suffix (post// suffix (post--decrementation)decrementation)// X operator-(X, X, X);// X operator-(X, X, X); // error! 3 args// error! 3 args// X operator/();// X operator/(); // error! // error! 0-argument operator! ;)0-argument operator! ;)
Assignment operatorAssignment operator
Define it as a nonstatic class memberDefine it as a nonstatic class member
T& T::operator=(const T &)T& T::operator=(const T &)
No initialization list, it’s not a constructor !!!No initialization list, it’s not a constructor !!!
Assignment operatorAssignment operator
person& person::operator=(const person &o)person& person::operator=(const person &o){{ if (this == &o) if (this == &o) // // Tom Tom == Tom Tom;; return return *this*this;; delete delete [] [] name;name; name=new char[strlen(o.name) + 1];name=new char[strlen(o.name) + 1]; strcpy(name, o.name);strcpy(name, o.name); delete delete [] [] lastName;lastName; lastName=new char[strlen(o.lastName) + 1];lastName=new char[strlen(o.lastName) + 1]; strcpy(lastName, o.lastName);strcpy(lastName, o.lastName); age=o.age;age=o.age; return *this;return *this; //// returning an object (as a returning an object (as a referencereference))}}
Assignment operatorAssignment operator why it returns a reference?why it returns a reference?
we’d like to do:we’d like to do: o1=o2=o3; o1=o2=o3;
person& operator=(const person&);person& operator=(const person&);1.1. assignment to: assignment to: oo2 from: 2 from: oo332.2. assignment to: assignment to: oo1 from: 1 from: oo22
person operator=(const person&);person operator=(const person&);1.1. assignment to: assignment to: oo2 2 fromfrom: : oo332.2. copy constructor (temporary object t1 created)copy constructor (temporary object t1 created)3.3. assignment to: assignment to: oo1 from: t11 from: t14.4. copy constructor (temporary object t2 created)copy constructor (temporary object t2 created)5.5. destructor t2destructor t26.6. destructor t1destructor t1
Assignment operatorAssignment operator
why it returns a reference?why it returns a reference? we’d like to do:we’d like to do: o1=o2=o3; o1=o2=o3;
void operator=(const person&);void operator=(const person&); we may do:we may do: o2=o3; o2=o3; we cannot do:we cannot do: o1=o2=o3; o1=o2=o3;
Default (compiler generated) Default (compiler generated) assignment operatorassignment operator
if we do not define an assignment operator, if we do not define an assignment operator, then compiler generates one, that copies then compiler generates one, that copies objects field by field.objects field by field. it does not work for const fields it does not work for const fields it does not work for reference fields it does not work for reference fields it simply copies the pointer fieldsit simply copies the pointer fields
Stream operatorsStream operators
InputInput
friend friend istream & operator >>(istream &, istream & operator >>(istream &, T T &)&);;
OutputOutput
friend friend ostream &operator <<(ostream &, const ostream &operator <<(ostream &, const TT &) &);;
Stream operatorsStream operators
class pointclass point{{ int x, y;int x, y;public:public:
…… friend friend istream &operator >>(istream & s, istream &operator >>(istream & s, point point & & pp));; friend friend ostream &operator <<(ostream & s, const ostream &operator <<(ostream & s, const pointpoint &) &);;}}
point p, p2;point p, p2;cin>>p;cin>>p;cin>>p>>p2;cin>>p>>p2;cout<<p2<<p;cout<<p2<<p;
Stream operatorsStream operators
istream & operator >>(istream & s, istream & operator >>(istream & s, point point & & pp)){{ s >> s >> p.xp.x >> >> p.yp.y;;
return s;return s;}}
ostream &operator <<(ostream & s, const ostream &operator <<(ostream & s, const pointpoint & & pp)){{ s << s << p.xp.x << << p.yp.y;;
return s;return s;}}
Member access operator ->Member access operator ->
T* operator->();T* operator->();
T t;T t; t->m is interpreted as:t->m is interpreted as:
( t.operator-> )->m( t.operator-> )->m
we may use object as if it was pointerwe may use object as if it was pointer if operator-> returns no pointer, then if operator-> returns no pointer, then
we still may use it: a=we still may use it: a=t.t.operator->(); operator->(); we cannot do: a=t->; it’s a syntax errorwe cannot do: a=t->; it’s a syntax error
Function call operatorFunction call operator
result T::operator()(args);result T::operator()(args);
Any number of arguments, overloadableAny number of arguments, overloadable Exception: function call operator may have default argumentsException: function call operator may have default arguments We may use object as if it was a functionWe may use object as if it was a function
T ob; T ob; ob();ob();
we use it we use it when there is no appropriate operator, that we needwhen there is no appropriate operator, that we neededed there is a dominant method for the class (it now has nthere is a dominant method for the class (it now has noo name, but is name, but is
easier to call – for exaple class counter and method of incrementing)easier to call – for exaple class counter and method of incrementing)
InIndedex operatorx operator
resultresult T::operator[] T::operator[](index);(index);
Any type of result and index allowed, common Any type of result and index allowed, common sense implies integer indexsense implies integer index
We may use object as if it was We may use object as if it was an arrayan array
Conversion operatorConversion operator
a.k.a. confersion function / method, a.k.a. confersion function / method, it converts object of its own class to other classit converts object of its own class to other class
TT::operator ::operator XX();();
Conversion operator of class T to the X typeConversion operator of class T to the X type:: no retrn value specifiedno retrn value specified, , no argument(s) specifiedno argument(s) specified, , declared as a class methoddeclared as a class method
Conversion operatorConversion operator for example.: for example.:
person::operator int();person::operator int();
conversion does not have to be explicit:conversion does not have to be explicit:person o; person o; int i=o+5; int i=o+5;
In expressionIn expressionss for the specific object conversion is performed only if it is necessary, for the specific object conversion is performed only if it is necessary, no more than one conversion per no more than one conversion per singlesingle argument argument no ambiguity allowedno ambiguity allowed
Conversion operatorConversion operator for example for classes A, B and C, conversion operators for example for classes A, B and C, conversion operators
B::operator A() and C::operator B(); are definedB::operator A() and C::operator B(); are defined
int f(A a);int f(A a);A a; B b; C c;A a; B b; C c;
f(a); f(a); // ok..// ok..f(b); f(b); // f(A(b)) // f(A(b)) // f(c); // f(c); // there is no operator C::operator A() // there is no operator C::operator A()
// compiler cannot interpret this as f(A(B(c))) // compiler cannot interpret this as f(A(B(c))) // (2 conversions of single argument)// (2 conversions of single argument)
Conversion operatorConversion operator
For converting objects of one type into other For converting objects of one type into other type we could use a constructor, however:type we could use a constructor, however: this way we could not convert to fundamental type this way we could not convert to fundamental type
(like: int, it’s not a class), (like: int, it’s not a class), this way we could not convert to already defined this way we could not convert to already defined
class without redefining it.class without redefining it.
ExampleExample
class counterclass counter{{ int cnt;int cnt; public:public: counter(int counter(int ii=0)=0):cnt(i){}:cnt(i){}; ; int operator()(int =1); int operator()(int =1); // increment by arg. or by 1// increment by arg. or by 1 operator int(); operator int(); // // convert toconvert to int int operator double(); operator double(); // // convert toconvert to doubledouble counter &operator+=(int); counter &operator+=(int); friend counter operator+(int, counter); friend counter operator+(int, counter); // int+counter// int+counter, friend, friend counter operator+(int); counter operator+(int); // counter+int// counter+int int operator++();int operator++(); // ++counter// ++counter int operator++(int);int operator++(int); // counter++// counter++};};
ExampleExample
inline int counter::operator ()(int i)inline int counter::operator ()(int i){{ return cnt+=i;return cnt+=i;}}
inline counter::operator int()inline counter::operator int(){{ return cnt;return cnt;}}
inline counter::operator double()inline counter::operator double(){{ return double(cnt);return double(cnt);}}
ExampleExample
counter & counter::operator +=(int i)counter & counter::operator +=(int i){{ cnt+=i; cnt+=i; // operator// operator()()((ii)); (*this)(i); (*this)(i)
return *this;return *this;}}
counter operator+(int i, counter l)counter operator+(int i, counter l){{ l+=i; l+=i; // // friend was not necessaryfriend was not necessary
return l;return l;}}
ExampleExample
counter counter::operator +(int i)counter counter::operator +(int i){{ counter l=*this; counter l=*this; l+=i;l+=i; return l;return l;}}
int counter::operator ++()int counter::operator ++(){{ cnt+=1;cnt+=1; return cnt;return cnt;}}
int counter::operator ++(int)int counter::operator ++(int){{ int ret=cnt;int ret=cnt; cnt+=1;cnt+=1; return ret;return ret;}}
ExampleExample
class complexclass complex{{ double re, im;double re, im;public:public: complex(double re, double im):re(re), im(im) {};complex(double re, double im):re(re), im(im) {}; complex & operator = (const complex &c)complex & operator = (const complex &c);; complex & operator += (const complex &c)complex & operator += (const complex &c);; complex operator + (const complex &);complex operator + (const complex &); friend complex & operator -= (complex &, const complex &);friend complex & operator -= (complex &, const complex &); friend complex operator - (const complex &, const complex &);friend complex operator - (const complex &, const complex &); friend istream & operator >>(istream &, complex &); friend istream & operator >>(istream &, complex &); friend ostream & operator <<(ostream &, const complex &);friend ostream & operator <<(ostream &, const complex &);};};
ExampleExample
complex & complex::operator = (const complex &c)complex & complex::operator = (const complex &c) {{ re=c.re;re=c.re; im=c.im;im=c.im;
return *this;return *this; }}
ExampleExample
complex & complex::operator += (const complex &c)complex & complex::operator += (const complex &c) {{ re+=c.re;re+=c.re; im+=c.im;im+=c.im;
return *this;return *this; }}
inline complex complex::operator + (const complex & c)inline complex complex::operator + (const complex & c){{ return complex(re+c.re, im+c.im); return complex(re+c.re, im+c.im); // // complex(double, double)complex(double, double)}}
ExampleExampleinline complex & operator-=(complex & c1, const complex & c2)inline complex & operator-=(complex & c1, const complex & c2) //friend//friend{{ c1.re-=c2.re;c1.re-=c2.re; c1.im-=c2.im;c1.im-=c2.im;
return c1;return c1;}}
complex operator-(const complex & c1, const complex & c2) complex operator-(const complex & c1, const complex & c2) //friend//friend{{ complex c=c1; complex c=c1; c-=c2;c-=c2;
return c;return c;}}
ExampleExample
istream & operator >>(istream & s, complex & c)istream & operator >>(istream & s, complex & c){{ s >> c.re >> c.im;s >> c.re >> c.im;
return s;return s;}}
ostream &operator <<(ostream & s, const complex & c)ostream &operator <<(ostream & s, const complex & c){{ s << c.re << c.im;s << c.re << c.im;
return s;return s;}}