Chapter8 - McMaster CAS Dept.

Classes and Objects:
request for service
& possibly data
data
interface
methods
possibly data
Object and its encapsulation
Chapter 8, Slide 1
Inheritance is facilitated by subclasses (derived classes)
Polymorphism is characterized by overloading of names of
methods and operators.
In C “data containers” can be either in static memory, on
the heap, or on the stack. C++ objects can span all three:
Consider chapter8_1 program:
static memory
dynamic memory
(heap)
sample
h e
y '\0'
salutation
Chapter 8, Slide 2
Create some global objects:
Sample sample ("hey");
Sample sample1("good bye");
dynamic memory
(heap)
static memory
sample
h
e
y
o
o
d
'\0'
salutation
g
b
y
e
'\0'
sample1
salutation
Chapter 8, Slide 3
Analyze program chapter8_2 program:
activation frame
of doit()
dynamic memory
(heap)
sample
h e
y '\0'
salutation
Destructor is missing, memory is leaking!
Chapter 8, Slide 4
Constructors and destructors are not inherited from the base
class. The base constructor may be invoked implicitly or
explicitly. The base destructor will be invoked implicitly.
Analyze chapter8_3 program:
The program will display hey,Joe and then (the main
purpose of this illustration) ~CC() invoked followed by
~C() invoked. Notice the reverse order of destructors called.
All C allocators/deallocator can be used in C++. On top of it,
there are two new operators -- allocator new (and new[]) and
deallocator delete (and delete[]).
Chapter 8, Slide 5
When new fails, it either uses new_handler or throws an
exception of type bad_alloc.
The operator new is involved in object creation:
class X {
public:
X(..) { .... } // constructor
..
};//end class X
..
X* ptr;
..
ptr = new X(..);
Chapter 8, Slide 6
Placement syntax of the operator new:
#include <new>
..
class X {
public:
void* operator new(size_t s,int a1,int a2){
...
}
..
};//end class X
int main ()
{
X* ptr = new(1,2) X;
..
return 0;
}
Chapter 8, Slide 7
Even though destructors cannot be called explicitly, a placement
new should have a corresponding “placement” delete (used only
when construction fails midway):
#include <new>
..
class X {
public:
void* operator new(size_t s,int a1,int a2){
...
}
void operator delete(void* p,int a1,int a2){
...
}
..
};//end class X
Chapter 8, Slide 8
Arrays of objects must be created by new[] using default
constructors only!
Analyze chapter 8_4 program:
They have to be deallocated by delete[]
Analyze chapter8_5 program:
A few guidelines to make sure that the process memory manager
does not get corrupted:
• Never pass a pointer to free() that has not been returned
previously by malloc(), calloc(), or realloc().
• Deallocate segments allocated by malloc(), calloc(), and
realloc()}} using exclusively free().
Chapter 8, Slide 9
• Never pass a pointer to delete that has not been returned
previously by new.
• Deallocate segments allocated by new using exclusively delete.
• Never pass a pointer to delete[] that has not been returned
previously by new[].
• Deallocate segments allocated by new[] using exclusively
delete[].
• If your program uses placement-new, it should have a
corresponding placement-delete, even though it will be only called
implicitly by the compiler when an exception is thrown during the
construction of an object.
Chapter 8, Slide 10
Copy constructor:
Analyze chapter8_6 program:
The will work fine displaying hey Joe on the screen. The object
c created in main() using constructor C(char*) will be copied
to the activation frame of doit() using the copy constructor
C(const C&). When doit() terminates, the object d --- as
built in the activation frame of doit() --- is destructed using
~C().
Without the copy constructor (the memberwise copy constructor
would have been used), the program would have crashed, as no
“deep” copy of the salutation would have been provided, yet ~C()
would still try to deallocate it.
Chapter 8, Slide 11
Assignment operator --- operator=
This method specifies how to perform assignments of type o1=o2
between two objects (which is in a sense again a form of copying, from
o1 to o2). In the absence of an explicit assignment, the memberwise
assignment is performed. The same problems may ensue as discussed
for the missing copy constructor. However, a missing assignment is
even more dangerous as it can lead to memory leaks:
class C {
...
};//end class C
int doit()
{
C c1("hey Joe"), c2;
c1=c2;
return 0;
} //end doit
Chapter 8, Slide 12
c1 is created and c1.salutation points to a dynamically created
string "hey Joe". c2 is created using the default constructor and
hence the value of c2.salutation is set to NULL. When c1=c2
assignment is performed, due to the absence of an explicit assignment
method in the definition of the class C, the memberwise copy is
performed and thus c1.salutation is set to NULL. When c1 and
c2 are destructed, none of them is “linked” to the string "hey Joe"
and so the string is never deallocated and “leaks”.
The difference between copy and assignment results from the
fact that the copy is concerned with “forming the raw memory into an
object” while the assignment must deal with a “well-constructed
object’”, thus in essence the assignment must de-construct the object
before it can do the copying:
Analyze chapter8_7 program:
Chapter 8, Slide 13
End of slides for chapter 8
Chapter 8, Slide 14