Documente Academic
Documente Profesional
Documente Cultură
{ Operations: and, or, not, nand, etc. { Operations: create, dispose, push, pop,
is empty, is full, etc.
integer
queue
{ Values: Whole numbers between MIN and MAX
values { Values: Queue elements, i.e., queue of X :::
{ Operations: add, subtract, multiply, divide, { Operations: create, dispose, enqueue, dequeue,
etc. is empty, is full, etc.
3 4
Avoiding Over-Specication Over-Specication Examples
Goal: e.g.,
{ We want complete, precise, and unambigu- int buer[100], last = ,1;
ous descriptions and specications of software
components :::
buer[++last] = 13;
Problem: e.g.,
{ We do not want to be dependent on physical struct Node f
representation int item ;
Node *next ;
Too hard to port g *p, *rst = 0;
:::
Data Members
A class denition does not allocate stor-
age for any objects { Including both built-in types and user-dened
class objects
{ i.e., it is just a cookie cutter :::
15 16
Nested Classes et al.
Earlier releases of C++ (i.e., cfront ver-
sions pre,2.1) did not support nested se-
mantics of nested classes
C++ Class Components (cont'd) { i.e., nesting was only a syntactic convenience
17 18
Base/Member Initialization
Section (cont'd) Class Methods
e.g., Four types of methods
1. Manager functions (constructors, destructors,
class Vector f public: Vector (size t len); /* */ g;
::: and operator=)
class String f public: String (char *str); /* */ g;
{ Allow user-dened control over class creation,
:::
g;
class Vector Iterator f in the class's state
public:
Vector Iterator (const Vector &v): vr (v), i (0) fg 4. Implementor functions
// :::
private:
// accessor char *str ;
size t size (void) const; // :::
g;
// implementor void String::print (void) f
T &operator[] (size t i); puts (this->str ); // same as puts (str );
g
int main (void) f
private: String s, t;
// helper s.print (); // this == &s
bool in range (size t i) const; t.print (); // this == &t
g; g
25 26
if (islower (*cp)) g;
*cp = toupper (*cp);
return *this; Function product can now access private
g parts of both the Vector and Matrix, al-
int main (void) f
String s ("hello"); // this == &s
s.upper case ().print ();
lowing faster access, e.g.,
/* Could also be:
s.upper case (); Vector &product (const Vector &v, const Matrix &m) f
s.print (); int vector size = v.size ;
compare with: int matrix size = m.size ;
cout << s.upper case ();
*/ //
g g
:::
27 28
Friends (cont'd)
Note, a class may confer friendship on the
following: Friends (cont'd)
1. Entire classes
2. Selected methods in a particular class Using friends weakens information hiding
3. Ordinary stand-alone functions { In particular, it leads to tightly-coupled imple-
mentations that are overly reliant on certain
naming and implementation details
Friends allow for controlled violation of
information-hiding
{ e.g., ostream and istream functions: For this reason, friends are known as the
\goto of access protection mechanisms!"
#include <iostream.h>
class String f
friend ostream &operator << (ostream &, String &);
private: Note, C++ inline functions reduce the
char *str ;
// :::
need for friends
g; :::
delete [] this->buf ;
if (verbose logging)
log ("destructing Vector object"); However, exceptions have their own traps
g and pitfalls :::
33 34
{ Therefore
If a constructor or operator = is not dened Note, you can also dene compound as-
for the derived class, the compiler-generated
one will use the base class constructors and signment operators, such as operator +=,
operator ='s for each base class (whether which need have nothing to do with op-
user-dened or compiler-dened) erator =
In addition, a memberwise copy (e.g., using
operator =) is used for each of the derived
class members
41 42
g
43 44
Restricting Assignment and Restricting Assignment and
Initialization (cont'd) Initialization (cont'd)
Note, a similar trick can be used to pre- If you declare a class constructor protected
vent static or auto declaration of an ob- then only objects derived from the class
ject, i.e., only allows dynamic objects! can be created
class Foo f { Note, you can also use pure virtual functions
public: to achieve a similar eect, though it forces the
// use of virtual tables
void dispose (void);
::: :::
private:
//
~Foo (void); // Destructor is private
:::
g;
:::
e.g.,
Foo f; // error
Now the only way to declare a Foo object class Foo f protected: Foo (void); g;
is o the heap, using operator new class Bar : private Foo f public Bar (void); g;
Foo f; // Illegal
Bar b; // OK
Foo *f = new Foo;
Note, the delete operator is no longer accessible
Note, if Foo's constructor is declared in
delete f; // error! the private section then we can not de-
Therefore, a dispose function must be provided clare objects of class Bar either (unless
to delete this
class Bar is declared as a friend of Foo)
f->dispose ();
45 46
Overloading (cont'd)
Overloading (cont'd)
Bottom-line: do not use operator over-
There are two issues to consider when loading unless absolutely necessary!
composing overloaded operators in expres-
sions, e.g.,
{ Two issues to
Instead, many operations may be written
using functions with explicit arguments,
e.g.,
1. Memory Management
Matrix a, b, c, d;
Creation and destruction of temporary vari-
ables :::
Matrix t (b);
t.add (c);
Where is memory for return values allo- t.mult (d);
cated? a = t;
Note that the C++ compiler is responsi- The termination (rather than resumption)
ble for generating all the necessary code :::
model of exception handling is used
57 58
//
all forms of error-handling, e.g.,
:::
quired
Versus
{ If \error" case may occur frequently
Stack s;
e.g., reaching end of linked list int i;
try f s.push (10);
// :::
i = s.pop ();
Exception handling can be hard to pro- g
catch (Stack::UNDERFLOW &e) f /* */ g :::
59 60
Another C++ Exception Handling
Example Iterators
Note the sublte chances for errors :::
Iterators allow applications to loop through
class xxii f elements of some ADT without depend-
public: ing upon knowledge of its implementation
xxii (const String &r): reason (r) fg
String reason ; details
g;
int g (const String &s) f
String null ("");
if (s == null) throw xxii ("null string"); There are a number of dierent techniques
// destructors are automatically called! for implementing iterators
//
g
:::
delete [] s2;
return 1; { Providing a copy of each data item vs. provid-
g
catch (xxii &e) f ing a reference to each data item?
cerr << "g() failed, " << e.reason ;
return 22;
g { How to handle concurrency and insertion/deletion
catch ( ) f while iterator(s) are running
cerr << "unknown error occurred!";
:::
return ,1;
g
g
61 62
Iterators (cont'd)
Three primary methods of designing iter-
ators Pointer to Function Iterator
1. Pass a pointer to a function
{ Not very OO :::
e.g.,
{ Clumsy way to handle shared data #include <stream.h>
template <class T>
:::
References
Miscellaneous ADT Issues in
Parameters, return values, and variables
C++ can all be dened as \references"
{ This is primarily done for eciency
References
Call-by-reference can be used to avoid the
run-time impact of passing large arguments
const methods by value
{ Note, there is a trade-o between indirection
vs copying
static methods
struct Huge f int size ; int array [100000]; g;
int total (const Huge &h) f
int count = 0;
static data members for (int i = 0; i < h.size ; i++)
count += h.array [i];
return count;
g
mutable Type Qualier
Huge h;
g
67 68
References (cont'd)
The following behaves like Pascal's VAR
parameter passing mechanism (a.k.a. call-
by-reference): References (cont'd)
double square (double &x) f return x *= x; g
int bar (void) f A function can also return a reference to
double foo = 10.0; an object, i.e., an lvalue
square (foo);
cout << foo; // prints 100.0 { Avoids cost of returning by an object by value
g
In C this would be written using explicit { Allows the function call to be an lvalue
dereferencing: Employee &boss of (Employee &);
Employee smith, jones, vacant;
double square (double *x) f return *x *= *x; g if (boss of (smith) == jones)
int bar (void) f boss of (smith) = vacant;
double foo = 10.0;
square (&foo); { Note, this is often done with operator[], e.g.,
printf ("%f", foo); /* prints 100.0 */
g Vector<int> v (10);
v[3] = 100; // v.operator[] (3) = 100;
Note, reference variables may lead to sub- int i = v[3]; // int i = v.operator[] (3);
tle aliasing problems when combined with
side-eects:
cout << (square (foo) * foo);
// output result is not dened!
69 70
77 78
Arrays of objects
In order to create an array of objects that Anonymous Unions
have constructors, one constructor must
take no arguments A union is a structure who member ob-
{ Either directly or via default arguments for all jects all begin at oset zero and whose
formal parameters size is sucient to contain any of its mem-
ber objects
{ e.g.,
{ They are often used to save space
Vector<Vector<int>> vector vector1;
Vector<int> vector vector2[100];
Vector<int> *vector vector ptr = new Vector<int>[size];
A union of the form union f member-list
The constructor is called for each element g; is called an anonymous union; it denes
an unnamed object
{ Uses a library routine called vec new: : :
{ The union elds are used directly without the
{ Often not re-entrant :::
usual member access syntax, e.g.,
void f (void) f
union f int a ; char *p ; g;
If array created dynamically via new, then a = 1; p = "Hello World\n";
delete must use an empty [] // a and p have the same address!
{ This instructs the compiler to call the destruc- // i.e., &a == &p
tor the correct number of times, e.g., g
delete [] vector vector ptr;
79 80
Anonymous Unions (cont'd)
Anonymous Unions (cont'd) Some restrictions apply:
Here's an example that illustrates a typical { Unions in general
way of using unions, e.g.,
A union may not be used as a base class and
struct Types f can have no virtual functions
enum Type fINT, DOUBLE, CHARg type ;
union f int i ; double d ; char c ; g; An object of a class with a constructor or
g t; destructor or a user-dened assignment op-
if (t.type == Types::DOUBLE) t.d = 100.02; erator cannot be a member of a union
// Q: \what is the total size of STRUCT Types?" A union can have no static data members
// Q: \What if UNION were changed to STRUCT?"
{ Anonymous unions
Note that C++ provides other language Global anonymous unions must be declared
features that makes unions less necessary static
(compared to C)
An anonymous union may not have private
{ e.g., inheritance with dynamic binding or protected members
An anonymous union may not have methods
81 82
Summary
A major contribution of C++ is its sup-
port for dening abstract data types (ADTs),
e.g.,
{ Classes
{ Parameterized types
{ Exception handling
83