The following classes show many a apsect of object life-cycle management, including the single argument constructor, copy constructor, default constructor, expclit constructor, destructor and the non-static member and static member, and how to define/impl those classes
We might use the definition on this chapter later for other illustration.
/**
* file
* acct.h
* description:
* the class definition of the Account class
*
*/
class Account {
public:
/* =================
* ctor and dtors
========================*/
Account();
// since a constructor that takes only a single parameter can serves as a conversion operator
// we don't want tripwire people into the trap of
// Account acct = "new user";
// to help curb/reign this kind of unwantted/unwelcome compiler aid, the explicit keyword is introduced
//
explicit
Account(const char *, double = 0.0);
for the purpose of demo the use of the array initalizer, we decide to use the implicit constructor approach
//Account(const char *, double = 0.0);
// the copy constructor
// the most important thing about the copy constructor is to decide whether or not to provide the copy constructor
// the how as to implements the copy constructor comes seconds
Account(const Account & );
~Account();
const char * name();
private:
char * _name;
unsigned int _acct_nmbr;
double _balance;
static unsigned int _unique_acct_nmbr;
static unsigned int get_unique_acct_nmbr();
static void return_acct_nmbr(unsigned int acct_nmbr);
protected:
};
and below is the definition/implementatio of the classes..
/**
* file
* acct.cpp
* description:
* the implementation source file of the acct.h
*/
#include "stdafx.h"
#include "acct.h"
#include <iostream>
#include <typeinfo>
#include <exception>
#include <fstream>
#include <functional>
#include <algorithm>
#include <vector>
#include <list>
#include <array>
#include <iterator>
#include <cstring>
#include <memory>
using std::cout;
using std::endl;
using std::end;
using std::cerr;
using std::fstream;
using std::vector;
using std::list;
using std::strcpy;
using std::strcat;
using std::strlen;
using std::auto_ptr;
/*=================================
* ctor(s) and dtor(s)
==================================*/
// for non-class members, it does not matter if you initialize the non-class member in the initializer list of you initialize the
// the non-class member inside the constructor's body
// the convention is to initialize the non-class members inside the ctor's body, while initialize the class members in the initializer's initializer list
Account::Account() {
_balance = 0.0;
_name = 0;
_acct_nmbr = 0;
_acct_nmbr = get_unique_acct_nmbr();
cout << "Account::Account" << endl;
}
// As said before,you can initialize the non-class member in the initliazer list.
//Account::Account() :
// _balance (0.0), _name(0), _acct_nmber(0)
//{
//}
// though the declaration of the Account is as such
// Account(const char * naem_, double balance_ = 0.0);
// but in our discussion, we can NOT redefine the default value of the balance_
Account::Account(const char * name_, double balance_) {
cout << "Account::Account(const char * name_, double balance_)" << endl;
if (name_ != NULL) {
// thereis no need to call the delete operator because
// in the intializer, the name_ is guaranteed to be filled with som randome bitness
// while the static members will be filled with zero or its default values (normally it is zeros)
//delete name_;
_name = new char[strlen(name_) + 1];
strcpy(_name, name_);
}
_balance = balance_;
_acct_nmbr = get_unique_acct_nmbr();
}
Account::Account(const Account& rhs)
: _balance(rhs._balance)
{
cout << "Account::Account(const Account & rhs)" << endl;
_name = new char[strlen(rhs._name) + 1];
strcpy(_name, rhs._name);
// must copy rhs._acct_nmbr
_acct_nmbr = get_unique_acct_nmbr();
}
unsigned int
Account::_unique_acct_nmbr;
unsigned int
Account::get_unique_acct_nmbr() {
return ++_unique_acct_nmbr;
}
void
Account::return_acct_nmbr(unsigned int acct_nmbr) {
}
inline
const char *
Account::name() {
return _name;
}
// Destructor server primarily to relinquish resources acquired either within the constructor or urnig the lifetime
// thelifetime of the class object, again such as freeing a mutal exclsion lock or deleting memory allocated through operator new.
Account::~Account()
{
delete _name;
return_acct_nmbr(_acct_nmbr);
// there is no need to do the check
// because the compiler will ensure that.
//if (_name != NULL ) delete _name;
// and since the object is destructed, there is no need to rest to some uninitialized value.
//_name = 0;
//_balance = 0;
//_acct_nmbr = 0;
}
Account global;
void destructor_life_cycle_test()
{
Account local("Anna live Plurablle", 1000);
Account &loc_ref = global;
auto_ptr<Account> pact(new Account("stephen Dedalus"));
{
Account local_too("Stephen Hero");
// the local_too will destroy before exit the current local space.
}
// the auto_ptr will destruct here
}