Beruflich Dokumente
Kultur Dokumente
6
l The operator :: of scope (called scope of resolution) included in
the definition of set_values(). It is used to declare a member of a
class outside it. Notice that we have defined the behavior of
function area() within the definition of the CRectangle class
given its extreme simplicity. Whereas set_values() has only its
prototype declared within the class but its body definition is
outside. In this outside declaration we must use the operator of
scope ::
void calculate_total( );
public:
student()
{ strcpy(name,"AHMAD");
ID=900901123;
First=second=final=0; }
void main()
{student st;
cout<<st.get_total();
st.print();
st.print();
}
10
The call to rect.area( ) does not give the same result as the call to rectb.area( ), each object of class
CRectangle has its own variables x and y, and its own functions set_value() and area(). functions are
properties of the object, instead of the usual view of objects as function parameters in structured
programming. In this concrete case, the class (type of object) is CRectangle, of which there are two
instances, or objects: rect and rectb, each one with its own member variables and member functions.11
Quiz
l Design a class named Triangle, that has Base
and the Height
l Build a method named Area
l Build a method named Set_Dim, that takes
Base,Height.
l Build A constructer that sets the Base and the
Height to zero.
l Build the main ()
l to create an object T
l Set the values to 10 ,5
l Print the area 12
Quiz
l Design a class named Student that has a name, ID,
first,second, final and Total marks.
l This class has a calculate_total method which is has a
private permission
l The class has set_Name_ID( char[ ],int) method that
stores the name of the student
l The class has set_marks(int,int,int) method
l The class has print( ) method that calls the
calculate_total and then prints the student name ,
student ID and student total mark.
l The main function looks like this:
void main( ){
Student St;
St.set_Name_ID(“Ahmad”,1000901123);
St.set_marks(19,21,41);
13
St.print(); }
void calculate_total( );
public:
void Set_Name_ID(char n[ ],int id)
{ strcpy(name,n);
ID=id;}
void Set_marks(int ,int ,int );
void print(void)
{ calculate_total( );
cout<<name<<"\t"<<ID<<"\t"<<total<<endl;}
}; // end of class definition
14
void Student::calculate_total( )
{total=first+second+final;}
void main( ){
Student St;
St.Set_Name_ID("Ahmad",1000901123);
St.Set_marks(19,21,41);
St.print( ); } 15
18
class Student {
char name[20]; Example on
int first,second,final,total,ID;
Constructors
void calculate_total( );
public:
Student( )
{ cout<<"An object has been constructed\n";}
void print(void)
{ calculate_total( );
cout<<name<<"\t"<<ID<<"\t"<<total<<endl;}
}; // end of class definition
19
void Student::calculate_total( )
{total=first+second+final;}
void main( ){
Student St;
St.Set_Name_ID("Ahmad",1000901123);
St.Set_marks(19,21,41);
St.print( ); }
20
Default Constructors
Commonly, a default constructor is declared without any parameters,
but it is also possible for a constructor with parameters to be a default
constructor if all of those parameters are given default values.
Student( )
{strcpy(name,”No name”) ;
ID=0;
first=second=final=0;}
21
Note:
In order to create an array of objects of a class type, the class must have an accessible default
constructor; C++ has no syntax to specify constructor arguments for array elements
In the main
Student St2("Ali");
St2.print(); 22
Empty Constructor
l If we didn’t define a constructor then there is an
empty constructor as default
l Also there is a default copy_constructor that allow
copying one constructor to another.
void main( ){
Student St1;
St1.print();
St1.Set_Name_ID("Ahmad",1000901123);
St1.Set_marks(19,21,41);
St1.print( );
Student St2;
St2=St1;
St2.print();
}
23
l With no constructors, the compiler automatically assumes that it has empty constructor:
l Empty constructor: It is a constructor with no parameters defined as empty block of
instructions. It does nothing. The empty construction exists only if no other constructor
is explicitly declared. In case that any constructor with any number of parameters is
declared, the default constructor is not called.
l CExample::CExample () { };
l To copy one instance of class to another, Copy constructor is needed: when ever one
object assigned to another we are making a copy of it. There are two types of copy
constructor.
l Perform simple variable by variable assignment: copy of all the components of
one object to another.
l Passing an object to a function. It is a constructor with one parameter of same type
that assigns to every non-static class member variable of the object a copy of the
passed object.
CExample::CExample (const CExample& rv)
create a new object of
class CExample (rv) {a=rv.a; b=rv.b; c=rv.c;}
l In the example above, a new object of class CExample is created
and which is a copy of the passed object, then in the
implementation part will initialize the data members of the current
object with the rv data members.
25
Overloading Constructors
l A constructor can also be overloaded with several functions that have the
same name but different types or numbers of parameters.
l In the cases where a class is declared and no constructor is specified, the
compiler automatically assumes two overloaded constructors ("default
constructor" and "copy constructor"). For example, for the class:
class CExample { public:
int a,b,c;
void multiply (int n, int m) { a=n; b=m; c=a*b; } };
26
واﺋﻞ ﻗﺼﺎص 27
28
Summary
l Constructors can be
l Empty Constructor
l Constructors that take parameters
l Copy Constructor
29
Destructor
l The Destructor is automatically called when an object is
released from the memory in two cases:
1. Its scope of existence has finished (i.e, if it was defined as a
local object within a function and the function ends)
2. Object dynamically assigned and it is released using delete
operator.
l The destructor must have the same name as the class with a
tilde (~) as prefix.
l Destructor receives no parameter and returns no value.
l A class may have only one destructor.
l The use of destructors is specially suitable when an object
assigns dynamic memory.
l Build a Destructor that prints a messege denoting
when an object is being destructed
~Student()
{
cout<<name<<"\nAn object has been destructed\n";
}
31
Example on destruction
void F(Student S)
{Student S1;
S1=S;
S.Set_marks(25,25,50);
S.print();
S1.print();}
void main( ){
Student St1,St2;
St1.Set_Name_ID("Ahmad",1000901123);
St2.Set_Name_ID("Ali",1000902321);
F(St1);
cout<<"back from function\n";
}
32
new , delete keywords
l The new keyword allocate memory
dynamically at run time , so that the records
are allocated while execution
l There is a direct relationship between new
and pointer.
33
#include <iostream.h>
void main()
{ int *p1, *p2;
p1=new int;
*p1=10;
cout<<&p1<<endl; // location of the pointer
cout<<"Memory location "<<p1<<" contains " <<*p1<<endl;
p2=new int;
*p2=10;
cout<<&p2<<endl; // location of the pointer
cout<<"Memory location "<<p2<<" contains "<<*p2<<endl;
delete p1;
delete p2;
34
}
Output
0x0012FF7C
Memory location 0x00901F80 contains 10
0x0012FF78
Memory location 0x00901D20 contains 10
Press any key to continue
35
#include <iostream.h>
void main()
{ int *p1, *p2;
p1=new int;
*p1=10;
cout<<&p1<<endl; // location of the pointer
cout<<"Memory location "<<p1<<" contains "
; <<*p1<<endl
moving ; delete p1
delete P1 ;p2=new int
to here *p2=10;
cout<<&p2<<endl; // location of the pointer
cout<<"Memory location "<<p2<<" contains
"<<*p2<<endl;
delete p2;
} 36
l 0x0012FF7C
l Memory location 0x00901F80 contains 10
l 0x0012FF78
l Memory location 0x00901F80 contains 10
l Press any key to continue
37
void main ( ) {
CRectangle rect (3,4), rectb (5,6);
cout << "rect area: " << rect.area() << endl;
واﺋﻞ ﻗﺼﺎص
cout << "rectb area: " << rectb.area() << endl;
} 38
Inline functions
39
40
class c1 {
int i; l If you compile this version of the program,
public: save its object code, and then compile it again
intexample
get_i(); with the inline specifier removed, you will see
void put_i(int j);}; the inline version is several bytes smaller.
inline int c1::get_i() l Inline is a request not a command, that the
{ return i;} compiler generate inline code.
inline void c1::put_i(int j)
{ i=j;}
l Some compilers will not generate inline code if
a function contains a loop, a switch, or a goto.
void main() l no inline recursive functions.
{ c1 s;
s.put_i(10); l Inline functions that contain static variables
cout<<s.get_i();} are disallowed.
output
10
return 0;}
42
Enumeration in C++
l The keyword enum creates a user-defined type
l Examples:
enum semesters {first, second, summer};
enum months{jan=1,feb,mar,apr,may,jun,jul,aug,sept, oct,nov,dec};
#include <iostream.h>
void main(){
enum mark {pass, fail};
mark m;
int score;
cout<<"Enter your mark ";
cin>>score;
if (score>=50)
m=pass;
else
m=fail;
if( m==pass)
cout<<" you passed the exam\n";
else
cout<<"you failed in the exam\n";
} 44
3.3 Array of object and Pointers to Objects
Array of objects can be created in the same way that you create arrays of
any other data types.
45
It is perfectly valid to
create pointers
pointing to classes, in
order to do that,
simply consider that
once declared, the
class becomes a valid
type, so use the class
name as the type for
the pointer.
47
l (*p).show_num(); and
p->show_num(); are the same
l *p can be read: pointed by p
l &x can be read: address of x
l x.y can be read: member y of object x
l (*p).y can be read: member y of object pointed by p
l p->y can be read: member y of object pointed by
p (equivalent to the previous one)
l x[0] can be read: first object pointed by x
l x[1] can be read: second object pointed by x
l x[n] can be read: (n+1)th object pointed by x
48
If there is array of objects are to be defined, and there exist a constructor, then the
declaration will be:
class_name obj[n]={values of initialization}
#include <iostream.h> 10
class p_example { 20
int num;
public:
p_example(int a){num=a;}
void set_num(int val) {num=val;}
void show_num( );};
void p_example::show_num()
{cout<<num<<“\n”;}
void main()
{ p_example ob[2]={10,20};
ob[0]. show_num();
ob[1]. show_num();
49
}
class Student {
char name[20];
int first,second,final,total,ID; Another
public:
Student( ) //constructor example on
{strcpy(name,"No name") ;
ID=0; array
first=second=final=0;
}
void print(void)
{cout<<name<<"\t"<<ID<<"\t"<<total<<endl;}
}; // end of class definition
50
void main( )
{
Student S1("Ali",123),S2("Ahmad",456);
Student St[3]={S1,S2};
for (int i=0;i<3;i++)
St[i].print();
}
51
Student St[3]={S1,S2};
SP=St;
for (int i=0;i<3;i++)
(SP+i)->print();
}
52
Rewrite the main in the prev.
example with pointers
void main( )
{
Student S1("Ali",123),S2("Ahmad",456), *SP;
Student St[3]={S1,S2};
SP=St;
for (int i=0;i<3;i++)
SP++->print();
}
53
v Each object has its own copy of all data members of the class.
54
Example on class -
<#include< iostream.h
<include <cstring#
;class Student { static int count ;
char name[20];
int first,second,final,total,ID;
public:
Student( ) //constructor
{strcpy(name,"No name") ;
ID=0;
first=second=final=0;
count++;
cout<<"Numbers of students constructed :"<<count<<endl;}
}; // end of class
int Student::count=0;
void main( )
{ cout<<"\nConstruct 2 objects\n";
Student S1,S2;
cout<<"\nConstruct 3 objects\n";
Student St[3]; } // end of main
55
Construct 2 objects
Numbers of students constructed : 1
Numbers of students constructed : 2
Construct 3 objects
Numbers of students constructed : 3
Numbers of students constructed : 4
Numbers of students constructed : 5
Press any key to continue
56
Example:
#include <iostream.h>
class st_example {
static int count;
public:
st_example (){count++;}
int get_count(){return count;}}; count is1
count is2
int st_example::count=0; count is2
count is3
void main()
{ st_example ob1;
cout<<”\n count is”<<ob1.get_count();
st_example ob2;
cout<<”\n count is”<<ob1.get_count();
cout<<”\n count is”<<ob2.get_count();
st_example ob3;
cout<<”\n count is”<<ob3.get_count(); }
57
58
class Student { static int count;
char name[20];
int first,second,final,total,ID;
public:
static void print_count(){cout<<“Students constructed: “ <<count<<endl;}
Student( ) //constructor
{strcpy(name,"No name") ;
ID=0;
first=second=final=0;
count++;
print_count(); }
}; // end of class
int Student::count=0;
void main( )
{ Student::print_count();
cout<<"\nConstruct 2 objects\n";
Student S1,S2;
cout<<"\nConstruct 3 objects\n";
Student St[3];}
59
Construct 2 objects
Numbers of students constructed : 1
Numbers of students constructed : 2
Construct 3 objects
Numbers of students constructed : 3
Numbers of students constructed : 4
Numbers of students constructed : 5
Press any key to continue
60
Example:
#include <iostream.h>
class st_example {
static int count;
public:
st_example (){count++;} count is1
static int get_count(){return count;}}; count is2
int st_example::count=0; count is2
count is3
void main()
{ st_example ob1;
cout<<”\n count is”<<ob1.get_count();
st_example ob2;
cout<<”\n count is”<< st_example ::get_count();
cout<<”\n count is”<<ob2.get_count();
st_example ob3;
cout<<”\n count is”<<ob3.get_count(); }
61
62
#include <iostream.h>
class time {
private:
int h,m,s;
public:
void print() const; //constant function
time(int i, int j, int k){h=i; m=j; s=k;}};
void main()
{ const time noon(12,0,0); //constant object
:
}
Notes:
* It is not allowed for any member_function calls for const
object unless the member functions also constant.
#include <iostream.h>
class time {
private:
int h,m,s;
public: 12:0:0
void print() const {cout<<h<<”:”<<m<<”:”<<s; }
time(int i, int j, int k) {h=i; m=j; s=k;}
int get_h() {return h;}};
void main()
{ const time noon(12,0,0);
noon.print();
// cout<<noon.get_h(); //error since get_h not const
}
65
Example:
class myclass {
int a, b;
public:
myclass(int i, int j) {a=i;b=j;}
friend int sum(myclass x); };
// note: sum() is not a member function of any class
int sum(myclass x) {
//sum() is a friend of myclass, it can access a and b through object x
return x.a+x.b;}
int main()
{ myclass n(3,4);
cout<<sum(n);
return 0;}
68
#include <iostream.h>
class CRectangle {
int width, height; 24
public:
void set_values (int, int);
int area (void) {return (width * height);}
friend CRectangle duplicate (CRectangle); }; // End of Class def.
void main () {
CRectangle rect, rectb;
rect.set_values (2,3);
rectb = duplicate (rect);
cout << rectb.area(); }
69
72
#include <iostream.h>
class CSquare;
class CRectangle {
int width, height;
public:
int area (void) {return (width * height);}
void convert (CSquare a); };
16
class CSquare {
private:
int side;
public:
void set_side (int a) {side=a;}
friend class CRectangle; };
void main () {
CSquare sqr;
CRectangle rect;
sqr.set_side(4);
rect.convert(sqr);
cout << rect.area(); }
73
74
Topic covered up to now
l Functions
l Function Overloading
:l Struct
:l Classes
,l Public, private
l scope operator )::(
l Empty constructor , Copy constructor
l Constructor Destructor
l New delete keywords and its relation with Constructor and destructor
l Inline function
l Enum
l Arrays of objects and relation with pointers
l Static object
l Static function
l Const Object
.l Const member function
l Friend function
l Friend Class 75
Dynamic initialization
l In c++, both local and global variables can initialized at run
time. This process is sometimes referred to as Dynamic
initialization.
l Most initializations have used constants.
l Under Dynamic initialization, a variable can be initialized at
run time using any c++ expression valid at the time the
variable is declared.
l You can initialize a variable using other variables.
The following are all perfectly valid variables initializations in
c++:
int n = strlen(str);
double arc = sin(theta);
float d= 1.02 * count / deltax;
76
#include <iostream.h>
class myclass { Applying Dynamic Initialization to
int a, b;
public:
Constructors
void setab(int i, int j) {a=i; b=j;}
void showab(); };
void myclass::showab() {
cout << "a is " <<a << "\n"; obj1 befor assignment:
cout<< "b is " << b << "\n";} a is 10
b is 20
main() ob2 before assignment:
{myclass obj1, obj2; a is 0
obj1.setab(10, 20);
obj2.setab(0,0);
b is 0
cout<<"obj1 before assignment:\n"; ob1 after assignment:
obj1.showab(); a is 10
cout<< "obj2 before assignment: \n"; b is 20
obj2.showab(); Ob2 after assignment:
cout<< "\n";
a is 10
obj2=obj1;// assign ob1 to obj2
cout<<"obj1 after assignment: \n"; b is 20
obj1.showab();
cout<<"obj2 after assignment: \n";
obj2.showab();} 77
78
#include <iostream.h>
class C1{ int x,y;
public:
C1(){}
C1(int a,int b)
{x=a;y=b;}}; //End of Class C1
class C2{ int x,y;
public:
C2(){}
C2(int a,int b)
{x=a,y=b;} }; //End of Class C2
void main()
{ C1 L,M(10,20);
C2 N,P;
L=M;
N=P;
N=M; //Error no acceptable conversion } //End of main
79
80
#include <iostream.h>
class OBJ { int i; Executing function f
public: 10
void set_i(int x) { i = x;} 100
void out_i() {cout << i <<"\n";}};
Returning from function to main
void f(OBJ x) {
10
cout<<" Executing function f\n";
x.out_i(); // outputs 10
Press any key to continue
x.set_i(100); // this affects only local copy
x.out_i(); // outputs 100
cout<<" Returning from function to main\n";}
void main()
{ OBJ o;
o.set_i(10);
f(o);
o.out_i(); // still outputs 10, value of I unchanged
}
void main()
{ myclass a(10);
display (a);}
l As you can see, there is one call to the constructor function
(as expected), but there are two calls to the destructor.
Why?
83
l When the copy is destroyed (usually by going out of scope when the
function returns), the destructor function is called.
A potential problem when passing objects
85
#include <iostream.h>
#include <stdlib.h>
class myclass {
int *p; Abort screen
public: myclass(int i);
~myclass();
int getval(){return *p;}};
myclass::myclass(int i) {
cout<<"allocating p\n";
p= new int;
*p=i;}
myclass::~myclass() {
cout<<"Freeing p\n";
delete p;} //This will cause a problem .
void display(myclass ob) { // try to use &ob what will happen??
cout<<ob.getval()<<"\n"; }
void main()
{ myclass a(10);
display(a); }
86
this
l Each time a member function is invoked, it is automatically
passed a pointer, called this, to the object that has invoked. The
"this" pointer is an implicit parameter to all member functions.
Therefore, inside a member function, this may be used to refer to
the invoking object. For the following example:
class c1 {int i;
void load_i(int val){i=val;};
87
#include <iostream.h>
class c1 {
int i;
public:
void load_i(int val) {this->i=val;} // same as i=val 100
int get_i() {return this->i;} // same as return i
};
int main()
{ c1 o;
o.load_i(100);
cout<<o.get_i();
return 0;}
88
l As I see, one of the uses of this pointer is to
provide us a way to reach to the variables of
the object that has the same name with
variables in the function. We discussed such
a problem before.
l Next example clarifies the idea.
89
#include <iostream.h>
class Student {
int id;
public:
void set_id(int id)
{id=id;} // it should be { this->id=id;}
void print_id()
{cout<<"ID is "<<id<<endl;} }; //end of class
void main(){
Student St;
St.set_id(10);
St.print_id();
}
90
Operator Overloading
l C++ incorporates the option to use language standard
operators between classes and between fundamental
types. For example:
int a, b, c;
a = b + c;
l is valid, since the different variables of the addition are all
fundamental types. While, the following operation is
incorrect.
91
#include <iostream.h>
class CVector { int x,y;
public:
CVector ( ) { };
CVector (int a, int b) { x = a; y = b;}
CVector operator + (CVector);
void print( ){cout<<x<<','<<y<<endl;}}; // End of class
void main ( ) {
CVector a (3,1), b (1,2), c ;
c = a + b; // c = a.operator + (b);
c.print( );}
94
The function operator+ of class CVector is the one that is in charge
of overloading the arithmetic operator +. This one can be called
by any of these two ways:
c = a + b;
c = a.operator+ (b);
97
The x refers to this->x, which is the x associated with the object that
invokes the operator function. In all cases it is the object on the
left side of an operation that causes the call to the operator
function. The object on the right side is passed to the function.
103
void C1::show() {
cout<<x<<", "<<y<<", "<<z<<"\n";}
void main()
{ C1 a(1,2,3),b;
++a;
a.show();
b=++a;
b.show();
b=a++; // warning : no postfix form of 'operator ++' found for type 'C1', using prefix
form
b.show(); 107
}
class three_d {
three_d three_d::operator++()
int x, y, z;
public: { ++x; ++y; ++z;
three_d() {x=y=z=0;} return *this;}
three_d(int i, int j, int k){x=i; y=j; z=k;} three_d three_d::operator++(int notused)
three_d operator+(three_d op2); { three_d temp=*this;
three_d operator=(three_d op2); x++; y++; z++;
three_d operator++();
three_d operator++(int notused); // postfix
return temp;}
void show(); }; void three_d::show() {
cout<<x<<", ";
three_d three_d::operator+(three_d op2) cout<<y<<", ";
{ three_d temp; cout<<z<<"\n ";}
temp.x=x+op2.x; void main()
temp.y=y+op2.y;
temp.z=z+op2.z;
{ three_d a(1,2,3), b(10,10,10), c;
return temp; } a.show(); b.show(); c=a+b; c.show();
c=a+b+c; c.show(); c=b=a; c.show();
three_d three_d::operator=(three_d op2) b.show();
{ x=op2.x; ++c;
y=op2.y;
c.show();
z=op2.z;
return *this;} c++;
c.show(); a=++c; a.show(); c.show();
a=c++; a.show(); c.show(); }
Output of prev. Example
1, 2, 3
10, 10, 10
11, 12, 13
22, 24, 26
1, 2, 3
1, 2, 3
2, 3, 4
3, 4, 5
4, 5, 6
4, 5, 6
4, 5, 6
5, 6, 7
109
class C {
int x, y, z;
public: Unary minus b= -a
C() {x=y=z=0;}
C(int i, int j, int k){x=i; y=j; z=k;}
C operator-()
{ C t;
t.x=-x;
t.y=-y;
t.z=-z;
return t;}
void print(){cout<<x<<','<<y<<','<<z<<endl;} };
void main(){
C a(10,10,10), b;
b=-a; //b = a.operator- ( ) ;
b.print();
a.print(); 110
}
Overloading a relational operator
class RelationalOver {
int x, y, z;
public:
RelationalOver() {x=y=z=0;}
RelationalOver(int i, int j, int k){x=i; y=j; z=k;}
int operator==(RelationalOver op2); };
int RelationalOver::operator==(RelationalOver t) {
if ((x==t.x) && (y==t.y) && (z==t.z))
return 1;
else
return 0;}
void main(){
RelationalOver a(10,10,10), b(10,10,10);
if (a==b) //if ( a.operator==(b) )
cout<<"The two objects are equal";
else
cout<<"The two objects are not equal";
}
Friend Operator Functions
Solution:
l The problem of having a built-in type on the left side of an operation can be
eliminated if the + is overloaded using two friend functions. In this case, the
operator function is explicitly passed both arguments, and it is invoked like
any other overloaded function, based upon the types of its argument.
class C{
int x,y;
public:
C(){x=0;y=0;}
C(int i,int j)
{ x=i;y=j;}
C operator+(int i)
{C T;
T.x=x+i; T.y=y+i;
return T;}
void main()
{C a(10,20),b,c;
b=a+10; // b= a.operator+ (10);
b.print();
c=10+b; // this will call the friend function c= operator+(10,b) 116
c.print(); }
class CL {
//this handles int + ob.
public:
int count; CL operator+(int i, CL ob){
CL operator=(CL obj); CL temp;
friend CL operator+(CL ob, int i); temp.count=ob.count+i;
friend CL operator+(int i, CL ob); return temp;
}; }
CL CL::operator=(CL obj) { main() {
count = obj.count; CL o;
return *this; o.count=10;
} cout<<o.count<<“ “;//outputs 10
//this handles ob + int.
o=10+ o;// adds object to integer.
CL operator+(CL ob, int i){
cout<<o.count<<“ “;//outputs 20
CL temp;
o=o+12;// adds integer to object.
temp.count=ob.count+i;
return temp; cout<<o.count; // outputs 32
} return o;
}
117
//This will not work This function will not work because only a
three_d operator++(three_d op1) copy of the object that activated the call to
{ operator++() is passed to the function in
parameter op1. Thus, the changes inside
op1.x++;
will not effect the calling object
op1.y++; 118
op1.z++;
return op1;
l Using a friend function when overloading a unary ++ or --
requires that the object be passed to the function as a
reference parameter.
parameter In this way the function can modify the
object.
l When a friend is used for overloading the increment or
decrement operators, the prefix form takes one parameter.
The postfix form takes two parameters. The second is an
integer, which is not used.
119
class C {
int x, y, z;
public:
C() {x=y=z=0;}
C(int i, int j, int k){x=i; y=j; z=k;}
void print(){cout<<x<<','<<y<<','<<z<<endl;}
friend C operator++(C);
};
120
class three_d {
int x, y, z;
public:
three_d() {x=y=z=0;}
three_d(int i, int j, int k){x=i; y=j; z=k;}
friend three_d operator+(three_d op1, three_d op2);
three_d operator=(three_d op2);
friend three_d operator++(three_d &op1); // prefix
friend three_d operator++(three_d &op1 , int notused);
void show();
};
return temp; }
Overloading [ ]
l The last operator we will overload is the [] array subscripting
operator. In C++, the [] is considered a binary operator when
it is overloaded.
l The [] can only be overloaded relative to a class, and only by
a member function. Therefore, the general form of a member
operator[ ]() function is:
O[3]
125
#include <iostream>
using namespace std;
const int SIZE=3;
class atype {
int a[SIZE];
public:
atype() {
register int i;
for(i=0; i<SIZE;i++) a[i] = i;
}
int operator[](int i) {return a[i];}
};
int main()
{
atype ob;
cout<<ob[2]; // ob.operator[](2)
return 0;
}
128
#include <iostream.h> main()
#include <stdlib.h> {
const int SIZE=3; atype ob;
class atype { cout<<ob[2]; // display 2
int a[SIZE];
cout<<“ “;
public:
ob[2]=25; // [ ] on left of =
atype() {
cout<<ob[2]; // display 25
register int i;
for(i=0; i<SIZE;i++) a[i] = i; ob[3] = 44; // generates
//runtime error, 3
}
//out=of-range
int &operator[ ](int i);
return 0;
};
// provide range checking for atype }
int &atype::operator[ ](int i) { In this program, when the
if(i<0 || i>SIZE-1) { statement ob[3]=44;
executes, the boundary
cout<<“\nindex value of “;
error is intercepted by
cout<<i<<“ is out-of-range.\n”;
operator[ ](), and the
exit(1); program is terminated befor
} any damage can be done.
return a[i]; 129
Inheritance
#include <iostream.h>
class CPolygon {
protected:
base class int width, height;
public:
void set_values (int a, int b){ width=a; height=b;} };
void main () {
CRectangle rect;
CTriangle trgl;
rect.set_values (4,5);
trgl.set_values (4,5);
cout << rect.area() << endl; 132
cout << trgl.area() << endl; }
l Objects of classes CRectangle and CTriangle each contain
members of CPolygon, that are: width, height and set_values().
The protected specifier is similar to private, its only difference
occurs when deriving classes. When we derive a class, protected
members of the base class can be used by other members of the
derived class. Nevertheless, private member cannot. Since we
wanted width and height to have the ability to be manipulated by
members of the derived classes CRectangle and CTriangle and
not only by members of CPolygon, we have used protected
access instead of private.
133
members of the
yes yes yes
same class
members of
yes yes no
derived classes
not-members yes no no
134
l where "not-members" represent any reference from outside the
class, such as from main(), from another class or from any
function, either global or local. In above example, the members
inherited by CRectangle and CTriangle follow with the same
access permission as in the base class CPolygon:
CPolygon::width // protected access
CRectangle::width // protected access
CPolygon::set_values() // public access
CRectangle::set_values() // public access
This is because we have derived a class from the other as public,
remember:
l class CRectangle: public CPolygon;
class A{
int i;
protected:
int j;
public :
int k;
};
class B :public A{
int x;
public:
int y;
int get_i(){
return i;} //cannot access private member declared in class 'A'
int get_j(){
return j;}
};
void main(){
B OP;
OP.i=5; // cannot access private member declared in class 'A'
OP.j=6; // cannot access protected member declared in class 'A'
OP.k=7;
138
OP.x=8; //cannot access private member declared in class 'B'
{ ;OP.y=9
class A{
int i;
protected:
int j;
public :
int k;
};
class B : A { // class B: private A {
int x;
public:
int y;
int get_j(){
return j;}
};
void main(){
B OP;
OP.k=7; // cannot access public member declared in class 'A'
OP.y=9; 139
}
Granting Access:
l When a base class is inherited as private, all members of
that class (public or protected) become private members of
the derived class.
l However, in certain circumstances, you may want to restore
one or more inherited members to their original access
specification. For example, you might want to grant certain
public members of the base class public status in the derived
class even though the base class is inherited as private.
l To do this, you must use an access declaration within the
derived class. An access declaration takes this general form:
base-class::member;
140
class base {
public:
int j; // public in base};
class base {
int i; // private to base
void main()
public: {
int j, k; derived ob;
void seti(int x) {i=x;} //ob.i=10; illegal because
int geti() {return i;}}; ob.j=20; /* legal j is made public*/
//ob.k=30;/*illegal k is private */
class derived: private base { ob.a=40;/* legal a is public*/
/* The next three statements override ob.seti(10);
base’s inheritance as private and cout<<ob.geti()<<“ “;
restore j, seti( ) and geti( ) to public cout<<ob.j<<“ “<<ob.a;
access. */ }
public:
base::j; // make j public again
base::seti; // make seti( ) public
base::geti; // make geti( ) public
// base::i; //illegal, you cannot elevate
access
int a; }; // public 142
What is inherited from the base class?
l In principle every member of a base class is inherited by a derived
class except:
void main () {
daughter cynthia (1); son daniel(1);}
144
l Observe the difference between which mother's
constructor is called when a new daughter object
is created and which when it is a son object. The
difference is because the constructor declaration
of daughter and son:
Multiple inheritance
l In C++ it is perfectly possible that a class inherits fields and
methods from more than one class simply by separating the
different base classes with commas in the declaration of the
derived class. For example, if we had a specific class to
print on screen (COutput) and we wanted that our classes
CRectangle and CTriangle also inherit its members in
addition to those of CPolygon we could write:
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b) { width=a; height=b;}};
void main () {
CRectangle rect;
class COutput {
CTriangle trgl;
public:
rect.set_values (4,5);
void output (int i); };
trgl.set_values (4,5);
rect.output (rect.area());
void COutput::output (int i){ cout << i << endl; }
Trgl.output (trgl.area());}
class CRectangle: public CPolygon, public COutput {
public:
int area (void) { return (width * height); } };
20
class CTriangle: public CPolygon, public COutput { 10
public:
int area (void) { return (width * height / 2); }};
147
void print(){
print_name();
print_id();} };
void main()
{student ST("Ahmad",1000901123);
ST.print();
}
149
Exercise 1
l 1- Develop a class named person which can perform the following
functions, individually:
l can set name, nationality and date of birth
l can print name, nationality and date of birth
l Now inherit a class named student and teacher from the class person,
that can perform the above listed task and in addition, the new class
should also perform the following functions, individually.
l For student:
l Can set his semester and CGPA
l Can display his semester and GPA
l For teacher:
l Can set subject he is teaching
l Can display subject he is teaching
l Write a main program to test above classes. For example, create student
object and display his name, nationality, date of birth, semester and
CGPA. Similarly, create object for teacher.
150
Exercise 2
l 2- Create a class Shape and its subclasses having different
kinds/types of shape under it. Shape should have data members’
width and height and a constructor that accepts two parameters
width and height. Also create a display() method that will display
the width and height of the shape.
l Shape class should have a subclass Rectangle that should have
a constructor that accepts width and height of Rectangle and a
function that can calculate the area() of rectangle.
l Rectangle should have a subclass Square that should have a
constructor that accepts width and height of Square (use
overriding here) and function that can calculate area() (use the
concept of overriding here) of Square.
l Write a main program and create objects in it.
151
Polymorphism
l For a suitable understanding of this section you
should clearly know how to use pointers and
inheritance between classes.
l Polymorphism in the context of object-oriented
programming, is the ability of one type, A, to
appear as and be used like another type, B. Type
A somehow derives from type B, or type C
implements an interface that represents type B.
152
Pointers to base class
153
Virtual members
156
#include <iostream.h> void main () {
class CPolygon { CRectangle rect;
protected: CTriangle trgl;
int width, height; CPolygon poly;
public: CPolygon * p1, *p2, *p3;
void set_values (int a, int b) p1= ▭
{ width=a; height=b; }
p2=&trgl;
virtual int area (void) {
p3 = &poly;
return (0); } };
p1->set_values(4,5);
class CRectangle: public CPolygon { p2->set_values(4,5);
public: p3->set_values (4,5);
int area (void){ cout << p1->area() << endl;
return (width * height); } }; cout << p2->area() << endl;
cout << p3->area() << endl;}
class CTriangle: public CPolygon { 20
public: 10
int area (void){ 0
return (width * height / 2); }
157
};
public:
void set_values(int a, int b){width=a; height=b;}
virtual int area (void) =0; };
162
class Polygon {
protected: int width, height;
public:
void set_values (int a, int b){ width=a; height=b; }
virtual int area (void) =0;
void printarea (void){ cout << this->area( ) << endl; }
};
void main ( ) {
Rectangle rect;
Triangle trgl;
Polygon * p1 = ▭
Polygon * p2 = &trgl;
p1->set_values (4,5);
p2->set_values (4,5);
p1->printarea( );
p2->printarea( );
}
164
l Remember that this represents a pointer to the object whose
code is being executed.
165
168
Function templates
l Templates allow creating generic functions that accept any data
type as parameters and return a value without having to overload
the function with all the possible data types. Its prototype is any
of the two following ones:
int x=5,y=7,z;
z=GetMax <int> (x,y);
k=GetMax<int>(i,j);
n=GetMax<long>(l,m);
173
l Because our template function includes only one data type (class
T) and both arguments it admits are both of that same type, we
cannot call our template function with two objects of different
types as parameters:
int i;
long l;
k = GetMax (i,l);
int i,j;
long l;
j=6;
l=7;
i = GetMin<int,long> (j,l);
or simply
i = GetMin (j,l);
#include <iostream.h>
class C{ int i,j;
public :
C (){}
C(int a,int b){ i=a; j=b;}
bool operator>(C W)
{ if (i>W.i && j>W.j)return true;
else return false;} };
void main () {
C x(4,5), y(4,6) ,z;
int t=5, u= 7, v;
z=GetMax(x,y); 176
v=GetMax(t,u); }
Class templates
l In class templates, so that a class can have members based on
generic types that do not need to be defined at the moment of
creating the class or whose members use these generic types. For
example:
178
#include <iostream.h>
template <class T> class pair {
T value1, value2;
public:
pair (T first, T second)
{value1=first; value2=second;}
T getmax ( ){
T temp;
if (value1>value2) temp = value1 ;
else temp = value2;
return temp; }
}; Output
100
void main () {
pair <int> myobject (100, 75);
cout << myobject.getmax();
} 179
#include <iostream.h>
template <class T> class pair {
T value1, value2;
public:
pair (T first, T second)
{value1=first; value2=second;}
T getmax (); };
void main () {
pair <int> myobject (100, 75);
cout << myobject.getmax();} 180
l notice how the definition of member function
getmax begins:
181
Template specialization
int module( )
{ return ( value1%value2); }
};
183
#include <iostream.h>
template <class T>
class pair { 25
T value1, value2; 0
public:
pair (T first, T second)
{value1=first; value2=second;}
int main () {
T module () {return 0;}};
pair <int> myints (100,75);
pair <float> myfloats (100.0,75.0);
template < > class pair <int> { cout << myints.module() << '\n';
int value1, value2; cout << myfloats.module() << '\n';
public: return 0;}
pair (int first, int second)
{value1=first; value2=second;}
int module ();};
186
Parameter Values for Templates
187
#include <iostream.h>
template <class T, int N> class array {
T memblock [N];
public:
void setmember (int x, T value);
T getmember (int x); };
void main () {
array <int,5> myints;
array <float,5> myfloats;
myints.setmember (0,100);
myfloats.setmember (3,3.1416);
cout << myints.getmember(0) << '\n';
واﺋﻞ ﻗﺼﺎص 188
189
Exception handling
- The code within the try block is executed normally. In case that
an exception takes place, this code must use the throw keyword
and a parameter to throw an exception. The type of the parameter
details the exception and can be of any valid type.
Example 1
#include <iostream.h>
void main () {
try {
int answer;
cout<<"5+7 =";
cin >> answer;
if (answer!=12) throw "Error, Wrong answer\n";
192
Example 2: with compile error
#include <iostream.h>
void main () {
try {
int answer;
cout<<"5+7 =";
cin >> answer;
if (answer!=12) throw "Error, Wrong answer\n";
#include <iostream.h>
void main () {
char myarray[10];
try
Example 3
{ int L;
cout<<"Enter last value ";
cin>>L;
for (int n=0; n<=L; n++)
{
if (n>9)
throw "Out of range";
myarray[n]='z';
cout<<n<<" "; 0 1 2 3 4 5 6 7 8 9 Exception: Out of range
} } Finish
cout<<"\nfinish\n";
} 194
l In this example, if within the n loop, n gets to be more than 9 an
exception is thrown, since myarray[n] would in that case point to
a non-trustworthy memory address.
l When throw is executed, the try block finalizes right away and
every object created within the try block is destroyed.
l After that, the control is passed to the corresponding catch block
(that is only executed in these cases).
l Finally the program continues right after the catch block, in this
case: cout<<"\nfinish"; return 0;
l The parameter that catch accepts can be of any valid type.
l Even more, catch can be overloaded so that it can accept
different types as parameters. In that case the catch block
executed is the one that matches the type of the exception sent
(the parameter of throw):
#include <iostream.h>
void main () {
try {
int A[10]={2,3,4,1,3,5,6,8,9};
int index;
cout<<"Enter Index: ";
cin >> index;
if (index<0) throw "Error, Negative index\n";
if (index>=10) throw index;
catch (int i) {
cout << "Exception: "; cout << "index " << i << " is out of range"
<< endl; }
198
Standard exceptions
l Some functions of the standard C++
language library send exceptions that can be
captured if we include them within a try block.
These exceptions are sent with a class
derived from std::exception as type. This
class (std::exception) is defined in the C++
standard header file <exception> and serves
as a pattern for the standard hierarchy of
exceptions:
199
myfile.close(); 202
}
Read files
// read file , letter by letter
#include <iostream>
#include <fstream>
using namespace std;
void main () {
char letter;
ifstream infile("c:/example.txt", ios::binary);
while(!infile.eof() )
{
letter=infile.get();
cout<< letter <<endl;
}
}
203
Read files
// read file , line by line
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void main () {
string line;
ifstream infile("c:/example.txt", ios::binary);
while(!infile.eof() )
{
getline(infile,line);
cout<< line <<endl;
} 204
}
// read file , word by word
#include <iostream>
#include <fstream>
while(!infile.eof() )
{ getline(infile, line);
cout<< line <<endl;}
}
206
Read numbers from file
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void main () {
ifstream myfile;
char fname[20];
cout<<"Enter file name ";
cin.getline(fname,20);
myfile.open (fname, ios::binary);
char number[10];
int Sum=0;
for (int i=1;i<=10;i++)
{ myfile.getline(number,10);
Sum=Sum+atoi(number);}
cout<<Sum; 207
Built in functions
l 1- write( (char *) (&ObjName), sizeof(class_name) );
l Takes the first argument a char pointer for the data to be
stored and the second argument as size of the memory
to be stored in file.
l 2- read( (char *) (&ObjName), sizeof(data type) );
l Takes the first argument a char pointer for the variable /
object in which retrieved data (from file) is to be stored
and the second argument as size of the memory to be
read.
208
#include <iostream.h>
#include <string>
class C{
char Fname[10],Lname[10];
public:
C(char * F, char * L)
{strcpy(Fname,F);
strcpy(Lname,L);
}};
void main()
{
C OB1("Ahmad","Ali");
cout.write((char *)(&OB1),20 );
}
209
Opening a file
l The first operation generally performed on an object of one of
these classes is to associate it to a real file. This procedure is
known as to open a file. An open file is represented within a
program by a stream object (an instantiation of one of these
classes, in the previous example this was myfile) and any
input or output operation performed on this stream object will
be applied to the physical file associated to it.
l In order to open a file with a stream object we use its member
function open():
l open (filename, mode);
l Where filename is a null-terminated character sequence of
type const char * (the same type that string literals have)
representing the name of the file to be opened, and mode is
an optional parameter with a combination of the following
flags:
212
l Mode Meaning
l ios::in Open for input operations.
l ios::out Open for output operations.
l ios::binary Open in binary mode.
l ios::ate Set the initial position at the end of the file.
If this flag is not set to any value, the initial position is the
beginning of the file.
l ios::app All output operations are performed at the
end of the file, appending the content to the current
content of the file. This flag can only be used in streams
open for output-only operations.
213