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
Derived Class, 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 shapes (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;