One argument must be a user-defined type.
You can define Person
+ Person, Person + int, but not int + int.
| :: Scope Resolution | BankAccount::print(); | ||
| . Object member selection
-> Pointer member selection [] subscripting () function call type() construction typeid type identification ++ Post Increment -- Post Decrement dynamic_cast,static_cast,reinterpret_cast, const_cast |
account.getBalance();
p->getBalance(); v[i] = 5; a(i); Person("Lou"); typeid(x) index++; index--; const_cast<Person &> r; |
||
| sizeof
++ Pre increment -- Pre decrement ~ Bitwise NOT ! Logical NOT - Negation + Unary Plus sign & Address * dereference new, delete (type) Typecast |
sizeof(anObject); sizeof(aType);
++index; --index; ~expression !expression - expression + expression &anObject; *ptr; new Person; new Person[100]; (Person *) p; |
||
| .* pointer to
member
->* pointer to pointer member |
object.*method_ptr;
ptr->*method_ptr; |
||
| * Multiply
/ Divide % Modulus |
x*y;
x/y; x%y; |
||
| + Addition
- Subtraction |
x+y;
x-y; |
||
| << Left shift
>> Right shift |
expression << expression
expression >> expression |
||
| < Less Than
<= Less or Equal > Greater Than >= Greater or Equal |
x < y;
x <= y; x > y; x >= y; |
||
| == Equal
!= Not Equal |
x == y;
x != y; |
||
| & bitwise AND | expr & expr | ||
| ^ bitwise exclusive OR | expr ^ expr | ||
| | bitwise OR | expr | expr | ||
| && logical AND | expr && expr | ||
| || logical inclusive OR | expr || expr | ||
| = Assignment
+= op-assign (*=, /=, %=, +=, -=, <<= shift left assign and also >>= shift right assign &= AND assign, also |=, and ^= |
x = y;
x += y; //x = x + y x <<= y; x &= y; |
||
| ?: condidtional expression | flag ? expr1 : expr2
if (flag) expr1 else expr2; |
||
| Throw throw exception | throw expr | ||
| , sequencing operator | expr, expr |
*ptr[i]; means *(ptr[i]);
*ptr->foo(); means *(ptr->foo());
Person me, you;
me + you; // means
me.operator+(you);
me + him + her //means (me.operator+(him)).operator(her);
Option 1: //as member function
class Person{
Person & operator+(const
Person & p) {...; return *this;}
};
Option 2: //as global procedure
Person & operator+(Person &
p1, const Person & p2) {...; return p1}
Person me, you;
cout << me << you;
Option 1: //WRONG
class Person{
ostream &
operator<<(const
Person & p) {...}
};
This cannot work because cout
<< x means cout.operator<<(x) and not
x.operator<<(cout);
Option 2: //global procedure friend procedure
class Person{
friend ostream &
operator<<(ostream
&, const Person &);
...
private:
char * name;
int age;
};
ostream & operator<<(ostream &
o,
const Person & person) {
o << person.name
<<
person.age;
return o;
}
Option 3: //global procedure that invokes a public printOn method (Best Approach)
class Person{
public:
void printOn(ostream &
output) {
output
<<
name << age;
}
...
private:
char * name;
int age;
};
ostream & operator<<(ostream &
o,
const Person & person) {
person.printOn(o);
return o;
}
class Person {
public: char * getName() {...}
};
class PersonPointer {
Person * operator->(){...}
};
Person me("Lou");
PersonPointer p(me);
p->getName(); //means (p.operator->())->getName();
Notice the -> is in
effect applied
twice
x = y = z; //means x.operator(y.operator(z));
Customer& Customer::operator=(const
Customer&
custRef){
if (this != &custRef) { //do nothing
for x = x
delete [] name; //delete old memory
delete [] address;
name = new char[strlen(custRef.name) +
1]; //allocate new memory
strcpy(name, custRef.name);
address = new
char[strlen(custRef.address)
+ 1];
strcpy(address, custRef.address);
}
return *this; //to allow multiple
assignments
}
compare with copy
constructor
Customer::Customer(const Customer&
custRef){
name = new char[strlen(custRef.name) +
1];
strcpy(name, custRef.name);
address = new
char[strlen(custRef.address)
+ 1];
strcpy(address, custRef.address);
}
class Vector{
T & operator[](int i)
{return
buffer[i];}
T operator[](int i) const
{return
buffer[i];}
...
private:
T * buffer;
};
Vector v;
const Vector vc;
v[3] = vc[4];
will call non const version of operator for lhs and const version for rhs.
vc[5] = v[2]; //NOT ALLOWED
void foo(Vector & v1, const Vector &
v2)
{
v1[1]
= x;
v1[2]
= v2[3];
}
++x; //means x.operator++();
x++; //means x.operator++(int);
--x; //means x.operator--();
x--; //means x.operator--(int);
The (int) parameter is not used at all it is just there to distinquish the two operators that have the same name, or symbol.
T & operator++() {item++; //do whatever
++ means for the class
return
*this; }
T operator++(int) {T temp = *this;
item++;
return temp; }
A problem in C++ programming is deleting a pointer without deleting what it points at and leaving memory on the heap. One possible solution is to have a pointer that, in effect, owns the object it points to. If the pointer is deleted, the object it points to is also deleted. To create such a pointer we can make an object that behaves like a pointer. Such "owning" pointers are often called Auto-pointers.
class BankAccount{
public:
BankAccount(int acctNum, float amount = 0) :
accountNumber(acctNum), balance(amount){}
~BankAccount(void) {cout << "Destroying
Acct:" << accountNumber << "\n";}
void deposit(float amount){balance += amount;}
void withdraw(float amount){balance -= amount;}
void printOn(ostream & o) const {
o << "Acct:" <<
accountNumber << " $" << balance << "\n";
}
private:
const int accountNumber;
float balance;
};
ostream & operator<<(ostream & out, const BankAccount
& b){
b.printOn(out);
return out;
}
template <class T>
class Autopointer{
T * p;
Autopointer<T> & operator=(const
Autopointer<T> & p) {return *this;}
Autopointer(const Autopointer<T> & p) {}
public:
Autopointer(): p(NULL){}
Autopointer(T * ptr):p(ptr) {}
~Autopointer(void){if(p != NULL) delete p; }
Autopointer<T> & operator= (T * ptr)
{if (p != NULL) delete p;
p = ptr;
return *this;
}
T & operator*() {return *p;}
T * operator->(){return p;}
};
/*OUTPUT
Acct:1000 $100
Acct:1001 $50
Acct:1002 $1000
Destroying Acct:1001
Destroying Acct:1000
(Notice account #1002
was
not deleted -memory leak)
*/