class CInt Ptr int mp Int public CInt

  • Slides: 15
Download presentation

class CInt. Ptr { int* m_p. Int; public: CInt. Ptr(); CInt. Ptr(int); CInt. Ptr(const

class CInt. Ptr { int* m_p. Int; public: CInt. Ptr(); CInt. Ptr(int); CInt. Ptr(const CInt. Ptr& r); virtual ~CInt. Ptr(); //operadores unários const CInt. Ptr operator+ () const CInt. Ptr operator- () int& operator* () const; CInt. Ptr* operator& (); const CInt. Ptr operator~ () const CInt. Ptr operator! () const; //operadores binários friend const CInt. Ptr operator+ (const CInt. Ptr& l, const CInt. Ptr& r); friend const CInt. Ptr operator- (const CInt. Ptr& l, const CInt. Ptr& r); friend const CInt. Ptr operator* (const CInt. Ptr& l, const CInt. Ptr& r); friend const CInt. Ptr operator/ (const CInt. Ptr& l, const CInt. Ptr& r); friend const CInt. Ptr operator% (const CInt. Ptr& l, const CInt. Ptr& r); friend const CInt. Ptr operator^ (const CInt. Ptr& l, const CInt. Ptr& r); friend const CInt. Ptr operator& (const CInt. Ptr& l, const CInt. Ptr& r); friend const CInt. Ptr operator| (const CInt. Ptr& l, const CInt. Ptr& r); friend const CInt. Ptr operator<< (const CInt. Ptr& l, const CInt. Ptr& r); friend const CInt. Ptr operator>> (const CInt. Ptr& l, const CInt. Ptr& r); . . .

… //operadores de atribuição CInt. Ptr& operator= (const CInt. Ptr& r); CInt. Ptr& operator+=

… //operadores de atribuição CInt. Ptr& operator= (const CInt. Ptr& r); CInt. Ptr& operator+= (const CInt. Ptr& r); CInt. Ptr& operator-= (const CInt. Ptr& r); CInt. Ptr& operator*= (const CInt. Ptr& r); CInt. Ptr& operator/= (const CInt. Ptr& r); CInt. Ptr& operator%= (const CInt. Ptr& r); CInt. Ptr& operator^= (const CInt. Ptr& r); CInt. Ptr& operator&= (const CInt. Ptr& r); CInt. Ptr& operator|= (const CInt. Ptr& r); CInt. Ptr& operator>>= (const CInt. Ptr& r); CInt. Ptr& operator<<= (const CInt. Ptr& r); //operadores de comparação friend bool operator == (const CInt. Ptr& l, const CInt. Ptr& r); friend bool operator != (const CInt. Ptr& l, const CInt. Ptr& r); friend bool operator <= (const CInt. Ptr& l, const CInt. Ptr& r); friend bool operator >= (const CInt. Ptr& l, const CInt. Ptr& r); friend bool operator < (const CInt. Ptr& l, const CInt. Ptr& r); friend bool operator > (const CInt. Ptr& l, const CInt. Ptr& r); friend bool operator&& (const CInt. Ptr& l, const CInt. Ptr& r); friend bool operator|| (const CInt. Ptr& l, const CInt. Ptr& r); // ++ //-> }; -[] ->* () , new[] delete[]

CInt. Ptr: : CInt. Ptr() { m_p. Int = new int; *m_p. Int =

CInt. Ptr: : CInt. Ptr() { m_p. Int = new int; *m_p. Int = 0; } CInt. Ptr: : CInt. Ptr(int i) { m_p. Int = new int; *m_p. Int = i; } CInt. Ptr: : CInt. Ptr(const CInt. Ptr& r) { m_p. Int = new int; *m_p. Int = *r. m_p. Int; } CInt. Ptr: : ~CInt. Ptr() { delete m_p. Int; } //operadores unários const CInt. Ptr: : operator+ () const { return *this; } int main () { CInt. Ptr p 1, p 2(7); p 1 = +p 2; // 7 p 1 = -p 2; // -7 *p 1 = 5; // 5 const CInt. Ptr: : operator- () const { return CInt. Ptr(-*m_p. Int); } int& CInt. Ptr: : operator* () const { return *m_p. Int; } CInt. Ptr* p = &p 1; CInt. Ptr* CInt. Ptr: : operator& () { return this; } p 1 = ~p 2; // -8 p 1 = !p 2; // 0 const CInt. Ptr: : operator~ () const { return CInt. Ptr(~*m_p. Int); } const CInt. Ptr: : operator! () const { return CInt. Ptr(!*m_p. Int); } return 0; }

Operadores binários const CInt. Ptr operator+ (const CInt. Ptr& l, const CInt. Ptr& r)

Operadores binários const CInt. Ptr operator+ (const CInt. Ptr& l, const CInt. Ptr& r) { return CInt. Ptr(*l. m_p. Int + *r. m_p. Int); } const CInt. Ptr operator- (const CInt. Ptr& l, const CInt. Ptr& r) { return CInt. Ptr(*l. m_p. Int - *r. m_p. Int); } const CInt. Ptr operator* (const CInt. Ptr& l, const CInt. Ptr& r) { return CInt. Ptr(*l. m_p. Int * *r. m_p. Int); } const CInt. Ptr operator/ (const CInt. Ptr& l, const CInt. Ptr& r) { return CInt. Ptr(*l. m_p. Int / *r. m_p. Int); } const CInt. Ptr operator% (const CInt. Ptr& l, const CInt. Ptr& r) { return CInt. Ptr(*l. m_p. Int % *r. m_p. Int); } const CInt. Ptr operator^ (const CInt. Ptr& l, const CInt. Ptr& r) { return CInt. Ptr(*l. m_p. Int ^ *r. m_p. Int); } const CInt. Ptr operator& (const CInt. Ptr& l, const CInt. Ptr& r) { return CInt. Ptr(*l. m_p. Int & *r. m_p. Int); } const CInt. Ptr operator| (const CInt. Ptr& l, const CInt. Ptr& r) { return CInt. Ptr(*l. m_p. Int | *r. m_p. Int); }

const CInt. Ptr operator<< (const CInt. Ptr& l, const CInt. Ptr& r) { return

const CInt. Ptr operator<< (const CInt. Ptr& l, const CInt. Ptr& r) { return CInt. Ptr(*l. m_p. Int << *r. m_p. Int); } const CInt. Ptr operator>> (const CInt. Ptr& l, const CInt. Ptr& r) { return CInt. Ptr(*l. m_p. Int >> *r. m_p. Int); } int main () { CInt. Ptr p 1(10), p 2(3); CInt. Ptr p 3 = p 1 + p 2; p 3 = p 1 - p 2; p 3 = p 1 * p 2; p 3 = p 1 / p 2; p 3 = p 1 % p 2; p 3 = p 1 ^ p 2; p 3 = p 1 & p 2; p 3 = p 1 | p 2; p 3 = p 1 << p 2; p 3 = p 1 >> p 2; return 0; } //13 // 7 // 30 // 3 // 1 // 9 // 2 // 11 // 80 // 1

Operadores de comparação bool operator == (const CInt. Ptr& l, const CInt. Ptr& r)

Operadores de comparação bool operator == (const CInt. Ptr& l, const CInt. Ptr& r) { return *l. m_p. Int == *r. m_p. Int; } bool operator != (const CInt. Ptr& l, const CInt. Ptr& r) int main () { return *l. m_p. Int != *r. m_p. Int; } { CInt. Ptr p 1(10), p 2(3); bool operator >= (const CInt. Ptr& l, const CInt. Ptr& r) bool f = p 1 == p 2; { return *l. m_p. Int >= *r. m_p. Int; } assert(p 1 != p 2); f = p 1 <= p 2; bool operator <= (const CInt. Ptr& l, const CInt. Ptr& r) assert (p 1 >= p 2); { return *l. m_p. Int <= *r. m_p. Int; } f = p 1 < p 2; assert (p 1 > p 2); bool operator > (const CInt. Ptr& l, const CInt. Ptr& r) assert (p 1 && p 2); { return *l. m_p. Int > *r. m_p. Int; } assert (p 1 || p 2); bool operator < (const CInt. Ptr& l, const CInt. Ptr& r) { return *l. m_p. Int < *r. m_p. Int; } bool operator&& (const CInt. Ptr& l, const CInt. Ptr& r) { return *l. m_p. Int && *r. m_p. Int; } bool operator|| (const CInt. Ptr& l, const CInt. Ptr& r) { return *l. m_p. Int || *r. m_p. Int; } return 0; }

Operadores de atribuição CInt. Ptr& CInt. Ptr: : operator= (const CInt. Ptr& r) {

Operadores de atribuição CInt. Ptr& CInt. Ptr: : operator= (const CInt. Ptr& r) { if (this != &r) *m_p. Int = *r. m_p. Int; return *this; } CInt. Ptr& CInt. Ptr: : operator+= (const CInt. Ptr& r) { *m_p. Int += *r. m_p. Int; return *this; } CInt. Ptr& CInt. Ptr: : operator-= (const CInt. Ptr& r) { *m_p. Int -= *r. m_p. Int; return *this; } CInt. Ptr& CInt. Ptr: : operator*= (const CInt. Ptr& r) { *m_p. Int *= *r. m_p. Int; return *this; } ………… int main () { CInt. Ptr p 1(10), p 2(3); p 1 = p 2; //3 p 1 += p 2; //6 p 1 -= p 2; //3 p 1 *= p 2; //9 p 1 /= p 2; //3 p 1 %= p 2; //0 p 1 ^= p 2; //3 p 1 &= p 2; //3 p 1 |= p 2; //3 p 1 >>= p 2; //0 p 1 <<= p 2; //0 return 0; }

Operadores de atribuição class CVector { unsigned m_n. Elements; int* m_ar. Elements; public: int&

Operadores de atribuição class CVector { unsigned m_n. Elements; int* m_ar. Elements; public: int& operator[](unsigned pos); CVector& operator=(const CVector& rv); CVector(unsigned el = 0); CVector(const CVector& v); virtual ~CVector(); int main () { CVector v 1 (5); v 1[3]= 3; v 1 = v 1; return 0; } }; CVector& CVector: : operator=(const CVector& rv) { if (this != &rv) { É sempre necessário verificar esta condição!!! delete [] m_ar. Elements; m_n. Elements = rv. m_n. Elements; m_ar. Elements = new int[m_n. Elements]; for (unsigned i = 0; i < m_n. Elements; i++) m_ar. Elements[i] = rv. m_ar. Elements[i]; } return *this; }

Operador de atribuição vs. construtor de cópia CVector: : CVector(const CVector& rv) { m_n.

Operador de atribuição vs. construtor de cópia CVector: : CVector(const CVector& rv) { m_n. Elements = rv. m_n. Elements; m_ar. Elements = new int [m_n. Elements]; for (unsigned i = 0; i < m_n. Elements; i++) m_ar. Elements[i] = rv. m_ar. Elements[i]; } CVector& CVector: : operator=(const CVector& rv) { if (this != &rv) { delete [] m_ar. Elements; m_n. Elements = rv. m_n. Elements; m_ar. Elements = new int [m_n. Elements]; for (unsigned i = 0; i < m_n. Elements; i++) m_ar. Elements[i] = rv. m_ar. Elements[i]; } return *this; } construtor de cópia CVector v 1(3); CVector v 2 = v 1; CVector v 3; v 3 = v 1; operador =

class conjunto { //… public: conjunto& operator+= (const conjunto& rv); const conjunto operator+ (const

class conjunto { //… public: conjunto& operator+= (const conjunto& rv); const conjunto operator+ (const conjunto& rv) const; conjunto& operator= (const conjunto& right); //… }; conjunto function (conjunto& my_set) { conjunto my_set 1=my_set; conjunto my_set 2 = my_set 1; my_set 1 = my_set; my_set 2 += my_set; my_set 2 = my_set + my_set 1; return my_set 2; } //1 //2 //3 //4 //5 //6 //7

O operador = , quando redefinido, precisa de ser membro da classe! É impossível

O operador = , quando redefinido, precisa de ser membro da classe! É impossível definir um operador = global! Na redefinição do operador = é quase sempre necessário verificar o caso do self-assignment. No caso geral, antes de começar a reservar a memória para os membros do objecto é necessário apagar toda a memória reservada previamente! Caso não redefina o operador = é o próprio compilador que vai sintetizar um operador = para si! O operador = sintetizado pelo compilador vai efectuar uma cópia bit. O operador = sintetizado pelo compilador não serve para objectos complexos (que contêm ponteiros, reservam memória dinamicamente, etc. ). O operador = não é herdado pelas classes derivadas. Por essas razões qualquer classe relativamente complexa deve sempre definir o operador =, bem como o construtor de cópia e o destrutor.

Operador = em classes bases e derivadas class base { char* nome; void copy(char*

Operador = em classes bases e derivadas class base { char* nome; void copy(char* str); public: base(char* str = 0); base (const base& r); virtual ~base(); base& operator= (const base& r); }; class derivada : public base { int indice; public: derivada(char* s = 0, int i = 0); derivada (const derivada& r); ~derivada(); derivada& operator= (const derivada& r); };

base: : base(char* str /*= 0*/) { copy (str); } base: : base(const base&

base: : base(char* str /*= 0*/) { copy (str); } base: : base(const base& r) { copy (r. nome); } base: : ~base() { delete [] nome; } void base: : copy(char* str) { if (str) { nome = new char[strlen(str) + 1]; strcpy (nome, str); } else nome = 0; } base& base: : operator= (const base& r) { if (&r != this) { delete [] nome; copy (r. nome); } return *this; } derivada: : derivada (char* s /*= 0*/, int i /*= 0*/ ) : base (s), indice(i) { } derivada: : derivada (const derivada& r) : base(r), indice(r. indice) { } derivada: : ~derivada() { } derivada& derivada: : operator = (const derivada& r) { if (&r != this) { base: : operator =(r); indice = r. indice; } return *this; }

Se não redefinir explicitamente o operador = na classe derivada, o compilador vai sintetizar

Se não redefinir explicitamente o operador = na classe derivada, o compilador vai sintetizar um operador = que primeiro vai chamar o operador = da classe base e depois vai efectuar a uma cópia bit dos membros da classe derivada. Exactamente o mesmo acontece com os construtores de cópia quando não definidos em classes derivadas. int main () { derivada d 1("aaa", 15); derivada d 2("bbb", 21); derivada d 3, d 4 = d 2; d 3 = d 1; d 1 = d 1; return 0; }