C++
new
: Creating objects
delete
: Deallocating objects
---Slide 2---
Pointers in C
class
cell
cell *p;// p = pointer to an object of type cell class cell{ +------+--+ int info; | info |--+-----> next cell *next +------+--+ }
p -> info === (*p).info // The info field of the cell pointed to by p cell c, d; +----+--+ +----+--+ c.next = &d; | c | -+----->| d | | +----+--+ +----+--+
0
= Null pointer in C++
.
In the body of the object this
(a special name) denotes
a pointer to the object itself.
---Slide 3---
CONSTRUCTOR
class cell{ cell(int i){info = i; next = this;} cell(int i, cell *n){info = i; next = n;} int info; cell *next; }
cell d(1, 0); cell a(3);
new
dynamically constructs an
object.
``new
cell(1,0)
'' creates an anonymous object of
class cell
and initializes by passing (1,0)
to its
constructor.
cell *front; front = new cell(1,0); front = new cell(2, front);Creates a singly-linked list of length two pointed to by
front
.
---Slide 4---
Deallocation
Delete
explicitly deallocates a previously
allocated object.
cell *temp = front; front = front -> next; delete temp;
---Slide 5---
FRIENDS
class cell{ friend class circlist; cell(int i){info = i; next = this;} .... int info; cell *next; }
cell
are private (by
default).
class
circlist
.
---Slide 6---
circlist
cell
, a friend.
class circlist{ cell *rear; public: circlist() {rear = new cell(0);} // Access the constructor // (private member) in class cell boolean empty(){ return (boolean)(rear == rear -> next);} void push(int); int pop(); void enter(int); }
push(int)
Adds a cell to the front of the list.
enter(int)
Adds a cell to the rear of the list.
pop()
Deletes a cell from the front of the list and
returns its value.
---Slide 7---
Body of the class circlist
void circlist::push(int x){ rear->next = new cell(x, rear->next); } void circlist::enter(int x){ rear->info = x; rear = rear->next = new cell(0,rear->next); } int circlist::pop(){ if(empty()) return 0; cell *front = rear->next; rear->next = front->next; int x = front->info; delete front; return x; }
---Slide 8---
Nested Classes
C++
scope
rules it leads to confusion. Poor style.
char c; //c in external scope class X{ char c; //c in internal scope class Y{ char d; void foo(char e){c = e;} }; char baz(Y* q){return (q->d);} //Syntax error, d = private }
X
and
Y
are at the same lexical level.
c
in function foo
refers to
c
in external scope.
q->d
in function baz
is
attempting to access a private member of class Y
.
---Slide 9---
Derived Classes
B
D
D
derives its variables and operations, by suitably
modifying the properties of B
.
Declaration for D
needs to mention only the changes that
must be made to B
.
circlist
with members:
push pop enter emptyOne can easily obtain the derived classes
queue
and
stack
by suitably restricting the operations:
queue{ stack{ enter push pop pop empty empty } }
---Slide 10---
Access Control Mechanisms
---Slide 11---
Public & Private Bases Classes
class <derived>: public <base>{ <member-declarations> //visibility is kept }
class <derived>: private <base>{ <member-declarations> //visibility is lost }
class b{ class d: private b{ public: protected: int f; ==> int b::g; int g; public: } int b::f; }
---Slide 12---
Example
circlist
Revisited
class circlist{ public: //visible outside boolean empty(); protected: //visible to members of derived classes circlist(); void push(int); int pop(); void enter(int) private: cell *rear; };
---Slide 13---
Derived Class queue
queue
example
class queue: private circlist{ public: queue(){} void enter(int x){circlist::enter(x);} int exit(){return pop();} circlist::empty; }
enter
is overloaded. Full name has to be
used.
push
, pop
, enter
. Inherited variable rear
.
rear
is available only to the inherited function.
---Slide 14---
Derived Class stack
stack
example
class stack: private circlist{ public: stack(){} void push(int x){circlist::push(x);} int pop(){return circlist::pop();} circlist::empty; }
push
and pop
are overloaded. Full
names have to be used.
push
, pop
, enter
. Inherited variable rear
:
Available only to the inherited functions.
---Slide 15---
Usage Example
main(){ stack s; queue q; s.push(1); s.push(2); s.pop; q.enter(4); q.exit(); q.enter(5); . . . }
---Slide 16---
Virtual Functions
C++
\\ BASE CLASS \\ DERIVED CLASS virtual fn() ... fn() ... ... A(){ \\ inherits A, But A's fn; \\ body uses the fn, } \\ defined here.Suppose also that the virtual function
fn
is used in another
member F
of Base class.
Now a derived class that inherits F
, gets an inherited
instance of F
that normally uses the same instance of
fn
(i.e., the one in the BASE CLASS
) independent of whether
fn
is redefined in the Derived Class or not.
fn
is virtual, the rule is only to
``use the virtual function body only as a default.''
---Slide 17---
Example
class Base{ public: virtual char f(){return 'B';} char g(){return 'B';} void testF{cout << f() << "\n";} void testG{cout << g() << "\n";} } class Derive: public Base{ public: char f(){return 'D';} char g(){return 'D';} }
---Slide 18---
Example (contd)
Base b; Derive d; b.testF; //=> B b.testG; //=> B d.testF; //=> D d.testG; //=> B
d.testF
:testF
is inherited by d
.
When testF
calls
f
---Since f
is virtual in the Base
, the
body of f
in Derive
has to be used.
---Slide 19---
Usage: Virtual Functions
shape
circle
& square
class shape{ point center; ... public: void move(point to){center = to; draw();} virtual void draw(); virtual void rotate(); ... } class circle: public shape{ int radius; public: void draw(); void rotate(){}; ... } class square: public shape{ int side; public: void draw(); ... }
The draw
used by different shape
s (e.g., in move
)
is different.
---Slide 20---
Subtypes & Supertypes
S
= Subtype of T
(T
= Supertype of S
),S
-object (object of type S
) is at the same time a
T
-object (object of type T
).
Any operation that can be applied to a
T
-object can
also be applied to an S
-object.
Shapes => Polygons ==> Squares => Circles
class S: public T{ ... }
S
can appear wherever public base class T
is
expected.
---Slide 21---
Parametric Polymorphism: TEMPLATE
Template
in C++
allows the same code to be used with
respect to different types where the type is a
parameter of the code body.
template <class TYPE> class stack{ public: stack():max_len(1000), top(EMPTY) {s = new TYPE[1000];} stack(int size):max_len(size), top(EMPTY) {s = new TYPE[size];} ~stack(){delete []s;} void push(TYPE c){s[++top] = c;} TYPE pop(){return (s[top--]);} TYPE top_of() const{return (s[top]);} boolean empty() const{return boolean(top==EMPTY);} boolean full() const{return boolean(top==max_len-1);} private: enum {EMPTY = -1}; TYPE* s; int max_len; int top; }
---Slide 22---
Template Instantiation
reverse
stack<char> stk_ch; //1000 elements char stack stack<char*> stk_str(200); //200 element string stack //Reversing a sequence of strings void reverse(char * str[], int(n){ stack<char*> stk(n); for(int i=0; i<n; i++) stk.push(str[i]); for(i=0; i<n; i++) str[i] = stk.pop(); }
---Slide 23---
Function Templates
copy
template<class TYPE> void copy(TYPE a[], TYPE b[], int n){ for(int i = 0; i<n; i++) a[i] = b[i]; } double f1[50], f2[50]; copy(f1, f2, 50);
template <class T1, class T2> boolean coerce(T1& x, T2& y){ if(boolean b = (sizeof(x) >= sizeof(y))) x = (T1)y; return b; }
---Last Slide---
Inheritance
class safe_char_stack: public stack<char>{ public: void push(char c){assert(!full()); stack<char>::push(c);} char pop(){assert(!empty()); return(stack<char>::pop());} };
template<int n, class T> class declare_array{ public: T a[n]; }; declare_array<50,int> x, y, z;