revisions:
Oct 6, 2008 reformatted example code at the
end of this section
Oct 1, 2007 Changed the sample code to compile with Visual C++ 2005 Express
Edition and also use the strcpy_s rather than strcpy from the string.h library
The memory of an object are the variables described in its class and those inherited from superclasses (base classes)
The memory is initialized when the memory is allocated and constructors are run
Super class constructors need to run to initialize memory specified in the super classes
Class variables can be value, reference or pointer variables
Variables can be const qualified
Class data is initialized with default construction, but this can be overridden
Base member initializer list syntax is required for certain initializations (const, reference, user-defined types and base class construction)
class Person {
public:
Person( ...) :
initializer_list {... }
};
Destructors provide an opportunity to release
memory
that is not part the classes explicit variables
//date.h
class Date {
// ========
public:
//Notice there is no default constructor
Date(int d, int m, int y) {day = d; month = m; year = y;}
private:
int day, month, year;
};
//person.h
#include <string.h>
/* this code uses the more secure strcpy_s procedure from
string.h rather than the more traditional strcpy.
strcpy_s require an additional parameter which represents
the length of the destination string. The routine then checks
that there is enough room in the destination string to hold the
source string. The older strcpy did not check if there was
enough room in the destination string and would happly over-run
the destination memory if the source string was longer.
*/
class Person {
// ========
public:
Person(char * their_name, Date & bday, char * email = "unknown"):
name(0), email_address(0), birthday(bday), pid(pid_counter++) {
char * temp = new char[strlen(their_name) + 1];
strcpy_s(temp, strlen(their_name) + 1, their_name);
name = temp;
email_address = new char[strlen(email) + 1];
strcpy_s(email_address, strlen(email) + 1, email);
}
Person(const Person & p):
name(0), email_address(0), birthday(p.birthday), pid(pid_counter++) {
char * temp = new char[strlen(p.name) + 1];
strcpy_s(temp, strlen(p.name) + 1, p.name);
name = temp;
email_address = new char[strlen(p.email_address) + 1];
strcpy_s(email_address, strlen(p.name) + 1, 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_s(email_address, strlen(address) + 1,
address);
}
}
Person & operator=(const Person & p){ //assignment operator
if(this != &p) {
delete [] (char *) name;
delete [] email_address;
char * temp = new char[strlen(p.name) + 1];
strcpy_s(temp, strlen(p.name) + 1, p.name);
name = temp;
email_address = new char[strlen(p.email_address)
+ 1];
strcpy_s(email_address, strlen(p.email_address) +
1, p.email_address);
birthday = p.birthday;
}
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;
Date birthday;
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;
}
//employee.h
class Employee : public Person {
// ========
public:
Employee(char * their_name, Date & bday, Person & supervisor, char * email =
"unknown"):
Person(their_name, bday, email), manager(supervisor),
employeeNumber(empNumberCounter++)
{ }
private:
Person & manager;
const int employeeNumber;
static int empNumberCounter;
};
int Employee::empNumberCounter = 0;
//main.cpp
#include <iostream>
using namespace std;
#include "date.h"
#include "person.h"
#include "employee.h"
void main() {
Person lou("Lou", Date(29,7,1963), "lou@chat");
Person sue("Sue", Date(21,7,1945) );
Employee john("John", Date(4,8,1973), sue, "john@chat");
cout << lou <<"\n" << sue <<"\n" << john << "\n";
}










2) Default constructors are used to initialize memory unless other are specified in the base member initializer list
3) Base class default constructors are called unless alternatives are specified in the base member initializer list
4) const and references cannot be given an initial value with an assignment operator so they require the use of the base member initializer list (remember the difference between T x = y; and T x; x=y;
5) Assignment operators and copy constructors are likely needed for any class with pointer or reference variables, especially classes the use heap space.
6) Destructors are called automatically when an
objects
memory is being reclaimed, and provide an opportunity for to clean up
other
memory (or other resources).
#include
<iostream>class
A {class
B {
A a;
public:
B(){cout <<
"B()\n";}
B(int
i){
a = i; cout <<
"B(int)\n";
}
const B & operator=(const
B & b){
a = b.a; cout <<
"B::operator=()\n";
return *this;
}
};
int
main() {
1) When a variable is declared in a program, the memory is
allocated
immediately for the variable?
2) If a class does not define a default constructor, the compiler
will always provide a default constructor?
3) If a class does not define a copy constructor, the compiler
will
always provide a copy constructor?
4) A constructor can be used as a type conversion function only
if
it has exactly one parameter?
5) Only operators provided by C++ can be overloaded.
Operator
overloading cannot create new operators?
6) Two functions may have the same name if they must be called
with
different parameter lists, or they have different return types?
7) You may assign a pointer of type const int * to a pointer of
type
int * ?
8) You may assign a variable of type const int to a variable of
type
int
?
9) Whenever a class has a pointer member, a destructor must be
defined
in the class?
10) If a class has a constructor that initializes its data
members,
but has no default constructor defined, then you cannot define an array
of objects without initialization?
Each of the following program segments has a problem that can occur during the creation, use, or destruction of the objects. In each case circle the place in the program where the problem appears to be and write a brief explanation of the problem.
1A)
#include <iostream.h>
class Foo {
int i;
public:
Foo(int x) : i(x) {}
void set(int x) {i=x;}
void print() {cout << i;}
};
int main() {
Foo a;
a.set(3);
a.print();
return 0;
}
1B)
#include <iostream.h>
#include <string.h>
class ArrayClass {
char * info;
int size;
public:
ArrayClass(char *a = NULL) : info(new char[strlen(a)+1])
{strcpy(info, a);}
~ArrayClass() {delete [] info;}
void print() const {cout << info << endl;}
};
int main() {
ArrayClass a("a_string"), b(a);
a.print();
b.print();
return 0;
}
1C)
#include <iostream.h>
#include <string.h>
class Whatever {
int * p;
public:
Whatever() :p(NULL) {}
Whatever(int * q) :p(q) {}
~Whatever() {delete p;}
void print() const {cout << *p;}
};
int main() {
int i=3, *q = &i;
Whatever a(q);
a.print();
return 0;
}
#include
<iostream>