class Person {
// ========
public:
Person(char *
their_name = "unknown", char * email = "unknown"):
name(0),
email_address(0), pid(pid_counter++) {
char
*
temp = new char[strlen(their_name) + 1];
strcpy(temp, their_name);
name = temp;
email_address = new char[strlen(email) +
1];
strcpy(email_address, email);
}
Person(const Person
& p):
name(0),
email_address(0), pid(pid_counter++) {
char
*
temp = new char[strlen(p.name) + 1];
strcpy(temp, p.name);
name = temp;
email_address = new
char[strlen(p.email_address) + 1];
strcpy(email_address, p.email_address);
}
~Person(void) {
delete [] (char *) name;
delete [] email_address; }
const char *
getName() const {return name;}
int getPID() { return
pid;
}
const char *
getEmailAddress() {return email_address;}
void setEmailAddress( const char *
address )
{
if(address) {
delete [] email_address;
email_address = new
char[strlen(address) + 1];
strcpy(email_address,
address);
}
}
Person & operator=(const Person
& p){
if(this != &p) {
delete [] (char *)
name;
delete [] email_address;
char * temp = new char[strlen(p.name) + 1];
strcpy(temp, p.name);
name = temp;
email_address = new
char[strlen(p.email_address) + 1];
strcpy(email_address,
p.email_address);
}
return *this;
}
static int
getCurrentPIDCount() {return pid_counter;}
void printOn(ostream
&
o) const {
o << name << " #"
<< pid << " email:" << email_address;
}
private:
const char * name;
char * email_address;
int pid;
static int
pid_counter;
};
int Person::pid_counter = 1000; //pid's start at 1000 and get larger
ostream & operator<<(ostream &
ostr, const Person & p) {
p.printOn(ostr);
return ostr;
}
class BankAccount {
// ===========
static int nextAccountNumber;
Person & owner; //Note because
owner is
a person reference
//There is no default constructor
//Even if we write one, we would not be able to initialize
//Therefore we could not have an BankAccount accounts[100];
int accountNumber;
float balance_;
public:
BankAccount(Person & customer, float
amount
= 0.0):
owner(customer), balance_(amount),
accountNumber(nextAccountNumber++)
{}
BankAccount(const BankAccount & b):
owner(b.owner),
balance_(b.balance_), accountNumber(nextAccountNumber++) {}
~BankAccount(void) { cout <<
"deleting account #" << accountNumber << "\n"; }
void printOn(ostream & out) const {
out << "acct#"
<<accountNumber <<
" " << owner.getName() << " $" <<
balance_;
}
BankAccount & deposit(float amount) {balance_ += amount; return *this;}
BankAccount & withdraw(float amount) {balance_ -= amount; return *this;}
float balance() const {return balance_;}
const Person & getOwner() const {
return owner; }
};
ostream & operator<< (ostream &
out, const BankAccount & b) {
b.printOn(out);
return out;
}
int BankAccount::nextAccountNumber = 1000;
template <class T>
class OrderedIterator; //forward
declaration
template <class T>
class OrderedCollection {
// =================
friend class OrderedIterator<T>;
const int capacity_;
int size_; //number of elements
T **buffer;
public:
OrderedCollection(int size = 100) :
capacity_(size),
buffer(new T*[size]), size_(0){}
OrderedCollection(const
OrderedCollection<T> & c):
capacity_(c.capacity_),
size_(c.size_),
buffer(new T*[c.capacity_])
{
for(int i = 0; i < capacity_; i
++)
buffer[i] = c.buffer[i];
}
~OrderedCollection() {delete []
buffer; }
typedef OrderedIterator<T> iterator;
int size() {return size_;}; //answer
number of elements
OrderedCollection<T> & add( T
& element);
OrderedCollection<T> & addLast(
T
& element);
OrderedCollection<T> &
addFirst( T
& element);
T & removeLast();
T & removeFirst();
int remove(const T & element);
iterator begin(void) {
//answer an iterator pointing to
first
element
return
OrderedIterator<T>(*this);
}
iterator end(void) {
//answer an iterator pointer "one
past"
last element
return
OrderedIterator<T>(*this, size());
}
void printOn(ostream & out) {
for (int i = 0; i < size_; i++)
cout << *buffer[i]
<< "\n";
}
};
template <class T>
OrderedCollection<T> &
OrderedCollection<T>::add( T & element){
if(size_ < capacity_)
buffer[size_++] =
&element;
return *this;
}
template <class T>
OrderedCollection<T> &
OrderedCollection<T>::addLast( T & element){
return add(&element);
}
template <class T>
OrderedCollection<T> &
OrderedCollection<T>::addFirst( T & element){
if(size_ < capacity_){
for (int i = size_; i>0;
i--)
buffer[i] = buffer[i-1];
buffer[0] = &element;
size_++;
}
return *this;
}
template <class T>
T & OrderedCollection<T>::removeLast(){
return * (buffer[--size_]);
}
template <class T>
T &
OrderedCollection<T>::removeFirst(){
T* temp = buffer[0];
for(int i = 0; i<size_ - 1; i++)
buffer[i] = buffer[i + 1];
size_--;
return * temp;
}
template <class T>
int OrderedCollection<T>::remove(const T
& item){
//remove first occurence of element == item
//return 1 if element was found and
removed and
0 otherwise
int found = 0;
for(int i = 0; i<size_; i++) {
if((*buffer[i] == item) &&
!found)
found = 1;
buffer[i] = buffer[i + found];
}
size_ -= found;
return found;
}
template <class T>
ostream & operator<<(ostream &
out, OrderedCollection<T>
& collection) {
collection.printOn(out);
return out;
}
//=============THE ITERATOR======================
template <class T>
class OrderedIterator {
// ===============
int index;
OrderedCollection<T> & s;
public:
OrderedIterator(OrderedCollection<T>
&
set, int position = 0) :
s(set), index(position){}
OrderedIterator(OrderedIterator<T> & iter) :
s(iter.s), index(iter.index){}
T & operator*() {return
*(s.buffer[index]);}
T * operator->() {return
s.buffer[index];}
OrderedIterator<T>
operator++(int) {
OrderedIterator<T> temp(*this);
index++;
return temp;
}
bool
operator==(OrderedIterator<T>
& iter)
{return (&(this->s) ==
&(iter.s))&&(this->index == iter.index);}
bool
operator!=(OrderedIterator<T>
& iter) {return !(*this == iter);}
};
int main() {
Person lou("Lou", "lou@chat");
Person sue("Sue", "sue@chat");
Person john("John", "john@chat");
BankAccount acc1(lou);
BankAccount acc2(sue);
cout << acc1.getOwner()
<< "address: " << & (acc1.getOwner()) <<
"\n";
cout << acc2.getOwner()
<< "address: " << & acc2.getOwner() << "\n";
// acc3 = acc1; would not be
allowed since we have no operator=()
// BankAccount accs[100]; not
allowed because no BankAccount() constructor
// accs[1] = acc1; not allowed
because no operator=()
OrderedCollection<Person>
people;
OrderedCollection<BankAccount> accounts;
people.add(lou).add(sue).add(john);
accounts.add(*(new
BankAccount(lou)))
.add(*(new BankAccount(sue)))
.add(*(new
BankAccount(john)))
.add(*(new
BankAccount(lou)));
cout << "THE PEOPLE\n";
cout << people;
//Print the accounts using the
OrderedCollection Iterator
//Notice how we don't need to know
the
actual class of the
//iterator, we ask
OrderedCollection<BankAccount> for its
//iterator type
cout << "THE ACCOUNTS\n";
for(OrderedCollection<BankAccount>::iterator iter =
accounts.begin(); iter != accounts.end(); iter++) {
iter->deposit(100).withdraw(50).deposit(30);
cout << *iter <<
"\n";
}
//Remove the heap storage
accounts
//Here we would not use the
iterator. It is dangerous
//To modify a container while
iterating over it
//The following code would not
work properly
// for (int i = 0;
i<accounts.size(); i++)
// delete &
accounts.removeFirst();
int numberOfAccounts =
accounts.size();
for (int i = 0;
i<numberOfAccounts; i++)
delete &
accounts.removeFirst();
return 0;
}
/* Program output
Lou #1000
email:lou@chataddress: 0x0066FDE0
Sue #1001
email:sue@chataddress: 0x0066FDD4
THE PEOPLE
Lou #1000 email:lou@chat
Sue #1001 email:sue@chat
John #1002 email:john@chat
THE ACCOUNTS
acct#1005 Lou
$80
acct#1004 Sue
$80
acct#1003 John
$80
acct#1002 Lou
$80
deleting account #1005
deleting account #1004
deleting account #1003
deleting account #1002
deleting account #1001
deleting account #1000
*/