Object Oriented Programming
Object Oriented Programming
MINISTRY OF EDUCATION
DIPLOMA IN
INFORMATION COMMUNICATION
TECHNOLOGY
Contents
CHAPTER 1: INTRODUCTION TO OBJECT ORIENTED PROGRAMMING................ 4
Define Object Oriented Programming....................................................................................
4 Evolution of Object Oriented Programming..........................................................................
4 Programming paradigms
......................................................................................................... 4 Merits and demerits of
OOP.................................................................................................... 5 Examples of object
oriented languages................................................................................... 5 Object Oriented
Databases (OODBs) ..................................................................................... 5
CHAPTER 2: OBJECT ORIENTED PROGRAMMING CONCEPTS ................................. 7
Concepts associated with OOP ................................................................................................ 7
Objects and Classes............................................................................................................... 7
Abstraction and Encapsulation......................................................................................... 10
Inheritance and polymorphism......................................................................................... 11
Comparison between structured and OOP.......................................................................... 11
Keywords and identifiers ...................................................................................................
11 Comments and Punctuators...............................................................................................
12
Reasons for embracing OOP.................................................................................................. 13
CHAPTER 3: LANGUAGE STRUCTURES OF OOP ..........................................................
14 Basic Structure of C++ Program...........................................................................................
14 Features of the Object Oriented programming ...................................................................
17 Header and Source Files and extensions...............................................................................
17 Data Types in OOP.................................................................................................................
21 Built-in/Simple Data Types....................................................................................................
21 Derive Data Types............................................................................................................... 23
User Defined Data Types.................................................................................................... 23
Variable and variable declaration......................................................................................... 25
Declaration and Initialization............................................................................................ 25
Scope of Variables............................................................................................................... 26
Type Conversion and Type Casting...................................................................................... 28
Implicit Type Conversions:............................................................................................... 28
Explicit Type Conversion:................................................................................................. 29
Type Compatibility ............................................................................................................. 30
CHAPTER4 : ESSENCE OF OBJECTS AND CLASSES .....................................................
32 Objects and classes in OOP....................................................................................................
32 Importance of objects and classes in OOP ...........................................................................
32 Implementation of objects and classes..................................................................................
32 CHAPTER 5: INHERITANCE.................................................................................................
44 Introduction and Rules in inheritance .............................................................................
44 Types of inheritance.............................................................................................................
45 Importance of Inheritance ..................................................................................................
45 Inheritance Advantages and Disadvantages ...................................................................
45 Implementation of Inheritance..........................................................................................
46 Base & Derived Classes:..................................................................................................... 46
Access Control and Inheritance: .......................................................................................
47 Concepts in inheritance
...................................................................................................... 48 Inheritance and
friends...................................................................................................... 50 Pointers to
objects............................................................................................................... 52
Inheritance and constructors............................................................................................. 54
Base class conversions.........................................................................................................
56 Overloading with Inheritance............................................................................................
60 Inheritance relationship
..................................................................................................... 60
CHAPTER 6: POLYMORPHISM............................................................................................ 61
Introduction to Polymorphism ............................................................................................
61 Advantages/importance of Polymorphism
............................................................................ 61 Encapsulation / Information hiding
...................................................................................... 64 Encapsulation / Information
hiding subject properties ...................................................... 66
Virtual Function: ................................................................................................................ 66
Pure Virtual Functions:...................................................................................................... 66
Data Abstraction ................................................................................................................. 67
Data Encapsulation............................................................................................................. 69
Interfaces (Abstract Classes) ................................................................................................. 71
CHAPTER 7: CONSTRUCTORS AND DESTRUCTORS.................................................... 74
Definition of Constructors...................................................................................................... 74
Types of Constructors............................................................................................................. 74
Constructor Overloading ....................................................................................................... 76
Destructors............................................................................................................................... 77
Implementation of constructors and Destructors................................................................78
CHAPTER 8: OPERATOR OVERLOADING .......................................................................
79
Meaning and importance of operator overloading.............................................................. 79
Implementing Operator Overloading................................................................................... 79
Overloading I/O operator....................................................................................................... 81
CHAPTER 9: FILE ORGANISATION....................................................................................87
Introduction to File organization........................................................................................87
Description of File Stream......................................................................................................87
Files and Streams properties..................................................................................................87
CHAPTER 10: EMERGING TRENDS IN OOP.....................................................................
92
Programming paradigms
A programming paradigm is a fundamental style of computer programming, a way of
building the structure and elements of computer programs.
The following are considered the main programming paradigms. There is inevitably some
overlap in these paradigms but the main features or identifiable differences are summarized
below:
✔ Imperative programming – defines computation as statements that change a program state
✔ Procedural programming, structured programming – specifies the steps the program must
Terms:
A hybrid database - is usually an object-oriented framework created to act as an interface
between an "impure" object-oriented language like C++ and a relational database manager. The
hybrid manager allows the language to access the database as though it were truly object-
oriented, while leaving the database itself unchanged. The hybrid design allows the object-
oriented programmer to use nearly any OOP feature that they want (much like an OODBMS),
while keeping the database itself relational which allows the use of commercially available and
supported products, allowing the "best of both worlds" at the cost of the run-time overhead to
support the hybrid framework.
Persistent object oriented databases - data manipulated by the application is transient and data in the
database is persisted (Stored on a permanent storage device). In object databases, the application can
manipulate both transient and persisted data. Persistence is often defined as objects (and their classes in
the case of OODBs) that outlive the programs that create them.
Pure object oriented databases is based solely on the object-oriented data model
Objects
When class is defined, only specification for the object is defined. Object has same
relationship to class as variable has with the data type. Objects can be defined
in similarly way as structure is defined.
class is known as member function. These two technical terms are frequently used in
explaining OOP. In the above class temp, data1 and data2 are data members and
func1() and func2() are member functions. Accessing Data Members and Member functions
Data members and member functions can be accessed in similar way the member of
structure is accessed using member operator(.). For the class and object defined above,
func1() for object obj2 can be called using code:
obj2.func1();
Similary, the data member can be accessed as:
object_name.data_memeber;
Note: You cannot access the data member of the above class temp because both data
members are private so it cannot be accessed outside that class.
Identifiers
Keywords in C++ Language
auto double
int
char extern
return
continue signed
for
do if static
In C++ programming, identifiers are names given to C++ entities, such as variables,
functions, structures etc. Identifier are created to give unique name to C++ entities to
identify it during the execution of program. For example:
int money;
int mango_tree;
Here, money is a identifier which denotes a variable of type integer. Similarly,
mango_tree is another identifier, which denotes another variable of type integer.
A literal is some data that's presented directly in the code, rather than indirectly
through a variable or function call.
Comments are portions of the code ignored by the compiler which allow the user to
make simple notes in the relevant areas of the source code. Comments come either in
block form or as single lines.
∙ Single-line comments (informally, C++ style), start with // and continue until the
end of the line. If the last character in a comment line is a \ the comment will
continue in the next line.
∙ Multi-line comments (informally, C style), start with /* and end with */.
Punctuators: Punctuators are used to group or separate the part of code. These helps to
demarcate the program structure
In the above code, {, } and ; are the punctuators.
∙ Braces are used to group the multiple statements into a separate block.
∙ Semicolon is used to terminate the statement.
Operators: It combines the expressions or transforms them.
Ex: a + b.
'+' is called as an operator which combines a and b and performs
addition. In the above example code, ., (), + and = are the operators.
There are several kinds of operators are there in C++ which does different operations
based on the operands(literals). Reasons for embracing OOP
∙ Code Reuse and Recycling: Objects created for Object Oriented Programs can easily
be reused in other programs.
∙ Encapsulation (part 1): Once an Object is created, knowledge of its implementation
is not necessary for its use.
CHAPTER 3: LANGUAGE STRUCTURES OF
OOP
Basic Structure of C++ Program
As C++ is a programming language so it follows a predefined structure. The program
is divided into many sections, it is important to know the need of every section. The
easiest way to understand the basic structure of c++ program is by writing a program.
The basic C++ program is as follows:
//simple c++ program
{
cout<<"simple c++ program \n"; // c++ statement
cout<<"hello world";
cout<<a<<b;
The basic structure of c++ program mentioned above can be divided into following
sections:
∙ Documentation Section : This section comprises of comments. As the name
suggests, this section is used to improve the readability and understanding of the
program.// (Double Slash) represents comments in C++ program. Comments can
be of single line or multiple lines. Double Slash comments are used to represent
single line comments. For multiple line comment, you can begin with /* and end
with */. For example :
One more example which explains the basic structure of c++ program is as follows :
1
/* basic example
which
explains
3
the structure of c++ program */ 9
4
int a=10,b=34;
#include <iostream> // header file 10
/* basic example
which
explains
the structure of c++ program */ .
∙ float f=10.2, j=4.5; are global variables which are declared outside the main()
function.
The statements written in the above mentioned programs can be written in a single line
for example :
int main(){int a=10,b=34; cout<<"simple c++ program
\n"; cout<<"hello world"; cout<<a<<b; return 0;}
Headers usually have the .h extension and contain declarations that we will use in our
source files. Let‘s take as an example the iostream header file that we include when
working with input-output in our program. We could have never used cout to print to
the screen without including the iostream header file because we have never declared
and defined that identifier anywhere in our program. That is why we are telling the
compiler to include the iostream header file, which actually means that, the compiler
will locate and read all the declarations from that header file when it reaches the
preprocessor directive, #include.
Usually header files only contain declarations and do not provide the actual definitions.
When we only declare a function and do not provide the definition for it, when we are
calling that function in our program, the linker will complain about ―Unresolved
Symbols―. So, how does the compiler know where to get the definition for cout then?
Well, the cout is actually defined in the standard runtime library which is
automatically linked in the link process.
mathPrimer.h
// mathPrimer.h
// ChapterII.HeaderSourceFiles
//
// Created by Vlad Isan on 20/04/2013.
// Copyright (c) 2013 INNERBYTE SOLUTIONS LTD. All rights
reserved.
//
#ifndef mathPrimer_h
#define mathPrimer_h
#endif
First, let‘s take a look a little at the preprocessor directives in this file. You already
know what #define is, as we have covered it a little when talking about variables and
constants. Let‘s talk a little about the conditional compilation, #ifdef, #ifndef and
#endif.
The conditional compilation preprocessor directives, tell your compiler what should
be compiled or not and under what conditions.
The #ifdef preprocessor directive basically checks if something was previously defined
using the #define preprocessor directive. If this condition is met, then the code between
the #ifdef and the corresponding #endif is compiled, otherwise it is ignored by the
compiler.
The same goes for #ifndef, and, as you can already imagine, it is the complete opposite
of #ifdef, and it allows the compiler to check whether a name has not been defined
with #define.
So, why are we using these preprocessor directives in our header file? These
preprocessor directives in the header files are called header guards, and helps us to
avoid including the same declaration in multiple times.
This works by skipping the entire contents of the header file if it was already included
in some other place. In our example, when you first include our header file,
mathPrimer.h, the #ifndef condition is met, because we haven‘t defined the name
mathPrime_h by using the #define preprocessor directive until now. So, the
condition is met and everything inside the header file will be compiled, and most
importantly, the mathPrimer_h will be defined as well, by using the #define
mathPrimer_h right after the #ifndef. Now, when you include the header file a
second time, the #ifndef mathPrimer_h condition will not be met, because we have
already defined that name when we included the header file in some other place. By
using these header guards we are avoiding the complaint we could get from the
compiler when declaring the header contents twice, or even multiple times. OK, now
let‘s look at what is declared inside our mathPrimer.h header file. We have two
function declarations, add and subtract, both having two integer parameters and an
integer return type.
We have to also define our functions. Let‘s create another file called mathPrimer.cpp.
This file will contain the function definitions:
mathPrimer.cpp
//
// mathPrimer.cpp
// ChapterII.HeaderSourceFiles
//
// Created by Vlad Isan on 20/04/2013.
// Copyright (c) 2013 INNERBYTE SOLUTIONS LTD. All rights
reserved.
#include "mathPrimer.h"
#include <iostream>
#include "mathPrimer.h" /* including our header file
int main()
{
return 0;
}
As you can see we are including our header file in here as well, so we can use the
functions declared in it, add and subtract. If you were to remove the #include
“mathPrimer.h” from here, you will see that you cannot compile the code, because the
compiler would not know anything about those functions, and it will complain about
―Undeclared identifiers―.
An important thing to note about header files is to never include variables in them, unless they
are constants. Header files should only be used for declarations. Also, you should never include
the definition for a function in the header file because it will change the whole scope of having a
header file, and it will make it hard to read.
Also, you should always split the parts of your code into separate header and source
files grouped by a certain criteria or functionality, because when only needing a part of
it, you do not need to include all of the declarations that reside in your program. As in
our example, we have called our header file mathPrime.h, as it will only contain basic
math functions. If we want to make some other helper functions, for example, for
printing to the screen and retrieving user input, we should make another pair of
header/source files, that we should only include when needed.
o A void pointer can be assigned a pointer value of any basic data type.
2147483648 unsigned: 0 to
4294967295
float Floating point number. 4 bytes +/- 3.4e +/-38 (~7 digits)
double Double precision floating 8 bytes +/- 1.7e +/-308 (~15 digits)
point number.
long double Long double precision 8 bytes +/- 1.7e +/-308 (~15 digits)
floating point number
software development. There are four user defined data types. These are:
∙Structure
∙Union
∙Class, and
∙Enumerator
A structure allows for the storage, in contiguous areas of memory, of associated data
items. A structure is a template for a new data type whose format is defined by the
programmer. A structure is one of a group of language constructs that allow the
programmer to compose his/her own data types.
struct [tag]
{
[variable];
members;
}
Example
struct Person
{
char ssn[12]
,last_name[20]
,first_name[16]
,street[20] float height
,city[20] ,state[3] ,weight
,zip_code[11] ; ;
int age; double salary; };
Where tag is optional and only needs to be present if no variable is present. The
members are variables declared as any C supported data type or composed data type. A
structure is a set of values that can be referenced collectively through a variable name.
The components of a structure are referred to as members of a structure. A structure
differs from an array in that members can be of different data types. A structure is
defined by creating a template. A structure template does not occupy any memory space
and does not have an address, it is simply a description of a new data type. The name of
the structure is the tag. The tag is optional when a variable is present and the variable
is optional when the tag is present. Each member-declaration has the form
A Class specified by the keyword class, is a user defined type that contains both data
members and member functions...
A union is a user-defined data or class type that, at any given time, contains only one
object from its list of members (although that object can be an array or a class type).
Program Example
Let's look at an example of how to declare an integer variable in the C++ language
and use it.
a) Below is an example C++ program where we declare an integer variable and
assign value in it:
#include <iostream>
int main()
{
String name;
int age;
cout<<"Enter your name plz:\n";
cin>>name;
cout<<"Enter your age plz:\n";
cin>>age;
This C program would print "Your Name is KIM and your age is 10 yrs".
Scope of Variables
All the variables have their area of functioning, and out of that boundary they don't hold
their value, this boundary is called scope of the variable. For most of the cases its
between the curly braces,in which variable is declared that a variable exists, not outside
it. We will study the storage classes later, but as of now, we can broadly divide
variables into two main types,
∙ Global Variables
∙ Local variables
Global variables
Global variables are those, which ar once declared and can be used throughout the
lifetime of the program by any class or any function. They must be declared outside the
main() function. If only declared, they can be assigned different values at different
time in program lifetime. But even if they are declared and initialized at the same time
outside the main() function, then also they can be assigned any value at any point in the
program.
Example : Only declared, not initialized
include <iostream> using namespace std;
Both Type conversion and Type casting in C++ are used to convert one predefined type
to another type.
Type Conversion is the process of converting one predefined type into another type.
and type Casting is the converting one predefined type into another type forcefully.
Need of Type Conversion and Type Casting in C++
An Expression is composed of one or more operations and operands. Operands consists
of constants and variables. Constants and expressions of different types are mixed
together in an expression. so they are converted to same type or says that a conversion
is necessary to convert different types into same type.
6 long int ant (i) long int (provided long int can represent Step 7
the other is all values of unsigned int)
unsigned int
(ii) unsigned long int(if all values of Step 7
unsigned int can‘t be represented by long
int)
Step 1: If either operand is of type long double, the other is converted to long double. Step2 :
Otherwise, if either is of type double, the other is converted to double.
After applying above arithmetic conversions, each pair f operands is of same type and
the result of each operation is the same as the type of both operands.
Example of Implicit Type Conversion :
Type Compatibility
In an assignment statement, the types of right types and left side of an assignment
should be compatible, so that conversion can take place. For example,
So, the information i.e. the value stores at address 1001, will be lost after assigning an
integer variable value to a character variable
variables.
For value types, like int the compiler will give them a valid value if you do not do
so explicitly. int's initialize to zero by default, DateTime's initialize to
DateTime.MinValue by default.
Reference type variables initialize to the object you give it. The compiler will
not assign an object (i.e. a valid value) if you don't. In this case the value is
null - nothing. So we say that the reference is initialized to null.
✔ Free store
Static Storage vs Heap vs Stack
1. Static vs Dynamic
Static: Storage can be made by compiler looking only at the text of the program. One
reason for statically allocating as many data objects as possible is that the addresses of
these objects can be compiled into target code.
Dynamic: Storage can be made by looking at what the program does when the program
is running.
2. Static
Global constants and other data generated by the compiler (e.g. info to support garbage
collection) are allocated static storage. Static variables are bound to memory cells
before execution begins and remains bound to the same memory cell throughout
execution. E.g., C static variables.
Advantage: efficiency (direct addressing), history-sensitive subprogram support
Disadvantage: lack of flexibility, no recursion if this is the *only* kind of variable, as
was the case in FORTRAN
3. Heap/free-store
Data that may outlive the call to the procedure that created it is usually allocated on a
heap. E.g. new to create objects that may be passed from procedure to procedure. The
size of heap cannot be determined at compile time. Referenced only through pointers
or references, e.g., dynamic objects in C++, all objects in Java
Advantage: provides for dynamic storage management
Disadvantage: inefficient and unreliable
4. Stack
Names local to a procedure are allocated space on a stack. The size of stack can not be
determined at compile time.
Advantages: allows recursion conserves storage
Disadvantages: Overhead of allocation and deallocation Subprograms cannot be history
sensitive
Inefficient references (indirect addressing)
✔ Static objects
Static Objects: Global objects, static data members, file scope objects and local
variables declared static are variables with static storage duration. A strategy for
initialization of objects with static storage duration is needed to avoid the risk of
accessing uninitialized objects.
Objects with static storage duration should only be declared within the scope of a
Static objects make it possible to access an object inside a function without having to
pass along a pointer or reference to it. Many objects can use the same object without
each object storing a pointer to the object, which can save space and sometimes make
the code less complex.
In most languages, the word coercion is used to denote an implicit conversion, either
during compilation or during run time. A typical example would be an expression
mixing integer and floating point numbers (like 5 + 0.1), where the integers are
normally converted into the latter. Explicit type conversions can either be performed
via built-in routines (or a special syntax) or via separately defined conversion routines
such as an overloaded object constructor.
A pointer is a programming language object, whose value refers directly to (or "points
to") another value stored elsewhere in the computer memory using its address. implicit
conversion help result of data pointed to by a pointer be converted to respective type of
type of the pointer
Example, in C++
int *money;
char *bags;
money would be an integer pointer and bags would be a char pointer. The
following would yield a compiler warning of "assignment from incompatible
pointer type"
bags = money;
Because money and bags were declared with different types. To suppress the compiler
warning, it must be made implicit that you do indeed wish to make the assignment by
typecasting it
bags = (*char) money; //implicit conversion
bags = (char*) money; // implicit conversion
In many languages, pointers have the additional restriction that the object they point to
has a specific type. For example, a pointer may be declared to point to an integer; the
language will then attempt to prevent the programmer from pointing it to objects which
are not integers, such as floating-point numbers, eliminating some errors.
✔ In-line function
Inline Functions
An inline function is a function whose statements are embedded in the caller as a
substitute for the function call. This avoids the overhead a context switch which must
be performed whenever a function is called and whenever a function returns to the
caller. The only purpose for inlining is to increase the execution speed of a program.
Inline functions should be small and simple. Since a function may be called from many
different places in a program, inlining large functions can result in an undesirable
increase in the size of a program. Inline functions should not contain any function calls
or I/O statements. As a general rule, if a function has more than five statements it
should not be inlined.
When you specify that a function is an inline function, it is merely a request of the
compiler. The compiler may or may not actually inline the function.
Inlining Global Functions
To inline a global function:
∙ Put the keyword inline before the return type in the function header.
∙ Make sure that the function definition (not just the prototype) appears before
any calls to the function.
Example:
inline void swap(int &a, int &b)
{
int c = a;
a = b;
b = c;
}
int main()
{
int x = 5;
int y = 10;
swap(x,y);
cout << x << " " y << endl;
}
Inlining Member Functions
There are two ways to inline a member function: implicit and
explicit. Implicit
In implicit inlining, the inline member function is defined within the class definition.
The keyword inline is not used.
Example:
class Date
{
public:
Date(int mm,int dd,int yy) {month = mm; day = dd; year =
yy;}
void setdate(int mm,int dd,int yy)
{month = mm; day = dd; year = yy;} void showdate(); //
not inlined
private: year; };
int month; int Explicit
day; int
In explicit inlining, the prototype in the class definition is preceded by the keyword
inline. The member function defintion is defined outside the class definition, and is also
preceded by the keyword inline.
Example:
class Date
{
public:
inline Date(int,int,int);
inline void setdate(int,int,int);
void showdate(); // not inlined
private:
int month;
int day;
int year;
};
private:
int i;
};
class A {
public:
A(B b) {
b.i = 0; // legal access due to friendship }
};
Features
∙ Friendships are not symmetric – If class A is a friend of class B, class B is not
automatically a friend of class A.
∙ Friendships are not inherited – A friend of class Base is not automatically a friend
of class Derived and vice versa; equally if Base is a friend of another class,
Derived is not automatically a friend and vice versa.
class c { int i;
i and j are instance variables and m and n are class variables. Every object of class c
will have its own private i and j, which can have different values for different
objects; however, all objects will access the same m and n, which will, of course, have
the same values for all objects.
Static variables are like non-inline member functions in that they are declared in a class
declaration and defined in the corresponding source file. To define static variables m
and n, the source file for class c must contain the following declarations (which are
also definitions):
int c::m;
int c::n;
These definitions can also be used to assign initial values to the static member
variables. For example, the following definitions give m the initial value 5 and n the
initial value 6:
int c::m = 5; int c::n = 6;
The accessibility rules for class variables are the same as for instance variables.
Thus private and protected class variables can be accessed by member and friend
functions, but not by functions that are not associated with the class. Likewise, a
derived class with a public base class inherits access to the protected and public class
variables of the base class.
In addition, we can define static member functions that can manipulate only static
member variables – they cannot access the instance variables of class objects. Like
static member variables, static member functions are associated with a class rather than
with any class object. A static member function is invoked via the name of the class
rather than via the name of a class object.
The preceding example defines an ordinary member function zap() and a static
member function clear(). To invoke the ordinary member function zap(), we
must declare a class object cc and apply zap() to it with the dot operator:
c cc; // declare cc as c object
cc.zap(); // apply zap() to class object cc
From the definition of zap(), we note that it can manipulate the instance variables i and
j of cc as well as the class variables m and n.
In contrast, the static member function clear() is invoked using the name of the class
and the :: operator:
c::clear();
We can call clear() even if no class objects have been created. From the definition of
clear(), we note that it manipulates only the class variables m and n; clear() does not
have access to the instance variables i and j of any class object.
An enumerated type (also called enum ) is a data type consisting of a set of named
values called elements, members or enumerators of the type.
Example:
1) enum Color {Red, Green, Blue};
typedef keyword allows the programmer to create new names for types such as int or it
literally stands for "type definition". Typedefs can be used both to provide more clarity
to your code and to make it easier to make changes to the underlying data types that
you use.
Note:
∙ Typedef is a keyword that is used to give a new symbolic name for the existing name
in a C program. This is same like defining alias for the commands.
∙ When we use “typedef” keyword before struct <tag_name> like above, after that we
can simply use type definition “status” in the C program to declare structure
variable.
∙ This is equal to “struct student record”. Type definition for “struct student” is
status. i.e. status = “struct student”
An alternative way for structure declaration using typedef in C:
typedef struct student char name [10];
{ float average;
int mark [2]; } status;
∙To declare structure variable, we can use the status record2; /* record 2 is structure variable */
below statements.
status record1; /* record 1 is structure variable */ ✔ Enumerated constant
✔ Pointer to members
Pointer-to-Member Operators: .* and ->*
Syntax
expression .* expression
expression –>* expression
Simple Example
We can define pointer of class type which can be used to point to class objects
Here you see that we have declared a ppointer of class type which points to class‘s
object. We can access data members and member fucntions using pointer name with
arrow ->symbol.
✔ nested classes
Nested class is a class defined inside a class, that can be used within the scope of the class in
which it is defined.
Example:
class Nest
{
public:
class Display
{
private:
int s;
public:
void sum( int a, int b)
{ s =a+b; }
void show( )
{ cout << "\nSum of a and b is:: " << s;}
};
};
void main()
{
Nest::Display x;
x.sum(12, 10);
x.show();
}
Result:
Sum of a and b is::22
The container manages the storage space for its elements and provides member
functions to access them, either directly or through iterators (reference objects with
similar properties to pointers).
xample
The following C++ code establishes an explicit inheritance relationship between classes
B and A, where B is both a subclass and a subtype of A, and can be used as an A
wherever a B is specified (via a reference, a pointer or the object itself).
class A
{ public:
void DoSomethingALike() const {}
};
class B : public A
{ public:
void DoSomethingBLike() const {}
};
void SomeFunc()
{
B b;
UseAnA(b); // b can be substituted for an A.
}
Types of inheritance
There are various types of inheritance, depending on paradigm and specific language.
∙ Single Inheritance : In the single inheritance, subclasses inherits the features of a
single super class. A class acquire the property of another class.
∙ Multiple Inheritance : Multiple Inheritance allows a class to have more than
one super class and to inherit features from all parent class.
∙ Multilevel Inheritance : In multilevel inheritance a subclass is inherited from
another subclass.
Importance of Inheritance
Inheritance is a good choice when:-
∙ Your inheritance hierarchy represents an "is-a" relationship and not a "has-a"
relationship.
∙ You want to make global changes to derived classes by changing a base class.
1. One of the key benefits of inheritance is to minimize the amount of duplicate code in an
application by sharing common code amongst several subclasses. Where equivalent
code exists in two related classes, the hierarchy can usually be refactored to move the
common code up to a mutual superclass. This also tends to result in a better
organization of code and smaller, simpler compilation units.
2. Inheritance can also make application code more flexible to change because classes
that inherit from a common superclass can be used interchangeably. If the return type
of a method is superclass
3. Reusability -- facility to use public methods of base class without rewriting the same 4.
Extensibility -- extending the base class logic as per business logic of the derived class
5. Data hiding -- base class can decide to keep some data private so that it cannot be
altered by the derived class
6. Overriding--With inheritance, we will be able to override the methods of the base class
so that meaningful implementation of the base class method can be designed in the
derived class.
Disadvantages:-
2. Main disadvantage of using inheritance is that the two classes (base and inherited
class) get tightly coupled.
This means one cannot be used independent of each other.
3. Also with time, during maintenance adding new features both base as well as derived
classes are required to be changed. If a method signature is changed then we will be
affected in both cases (inheritance & composition)
4. If a method is deleted in the "super class" or aggregate, then we will have to re-factor in
case of using that method. Here things can get a bit complicated in case of inheritance
because our programs will still compile, but the methods of the subclass will no longer
be overriding superclass methods. These methods will become independent methods
in their own right.
Implementation of Inheritance
// Base class
class Shape
{
public:
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h; };
}
protected: int main(void)
int width; {
int height; Rectangle Rect;
};
Rect.setWidth(5);
// Derived class Rect.setHeight(7);
class Rectangle: public Shape
{ // Print the area of the object.
public:
cout << "Total area: " << Rect.getArea() <<
int getArea()
endl;
{
return (width * height);
return 0;
}
}
When the above code is compiled and executed, it produces the following result:
Total area: 35
Outside classes no no
yes
A derived class inherits all base class methods with the following exceptions:
∙ Constructors, destructors and copy constructors of the base class.
∙ Overloaded operators of the base class. ∙ The friend functions of the base class.
When deriving a class from a base class, the base class may be inherited through
public, protected or private inheritance. The type of inheritance is specified by the
access-specifier as explained above.
We hardly use protected or private inheritance, but public inheritance is commonly
used. While using different type of inheritance, following rules are applied:
∙ Public Inheritance: When deriving a class from a public base class, public
members of the base class become public members of the derived class and
protected members of the base class become protected members of the derived
class. A base class's private members are never accessible directly from a
derived class, but can be accessed through calls to the public and protected
members of the base class.
∙ Protected Inheritance: When deriving from a protected base class, public and
protected members of the base class become protected members of the derived
class.
∙ Private Inheritance: When deriving from a private base class, public and
protected members of the base class become private members of the derived
class.
Concepts in inheritance
Single Inheritance is method in which a derived class has only one base class.
Example:
#include <iostream.h> class Value
{
protected:
int val;
public: {
void set_values (int a) Cube cub;
{ val=a;} cub.set_values (5);
}; class Cube: public Value cout << "The Cube of 5 is::" << cub.cube() << endl;
{ return 0;
public: }
int cube()
{ return (val*val*val); }
Result:
The Cube of 5 is:: 125
}; int main ()
Multiple inheritance is achieved whenever more than one class acts as base classes for other
classes. This makes the members of the base classes accessible in the derived class, resulting
in better integration and broader re-usability.
example:
#include <iostream>
using namespace std;
class Cpolygon
{
protected:
int width, height;
public:
void input_values (int one, int two)
{
width=one;
height=two;
}
};
class Cprint
{
public:
void printing (int output);
};
int main ()
{
Crectangle rectangle;
Ctriangle triangle;
rectangle.input_values (2,2);
triangle.input_values (2,2);
rectangle.printing (rectangle.area());
triangle.printing (triangle.area());
return 0;
}
In principle, private and protected members of a class cannot be accessed from outside the
same class in which they are declared. However, this rule does not apply to "friends".
A non-member function can access the private and protected members of a class if it is
declared a friend of that class. That is done by including a declaration of this external function
within the class, and preceding it with the keyword friend:
// friend functions
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
Rectangle() {}
Rectangle (int x, int y) : width(x), height(y) {} int
area() {return width * height;}
friend Rectangle duplicate (const Rectangle&);
};
int main () {
Rectangle foo;
Rectangle bar (2,3);
foo = duplicate (bar);
cout << foo.area() << '\n';
return 0;
}
Friend classes
Similar to friend functions, a friend class is a class whose members have access to the private
or protected members of another class:
// friend class
#include <iostream>
using namespace std;
class Square;
class Rectangle {
int width, height;
public:
int area ()
{return (width * height);}
void convert (Square a);
};
class Square {
friend class Rectangle;
private:
int side;
public:
Square (int a) : side(a) {}
};
int main () {
Rectangle rect;
Square sqr (4);
rect.convert(sqr);
cout << rect.area();
return 0;
}
In this example, class Rectangle is a friend of class Square allowing Rectangle's member
functions to access private and protected members of Square. More concretely, Rectangle
accesses the member variable Square::side, which describes the side of the square.
Pointers to objects
A variable that holds an address value is called a pointer variable or simply pointer. Pointer can point
to objects as well as to simple data types and arrays. sometimes we don’t know, at the time that we
write the program , how many objects we want to creat. when this is the case we can use new to
create objects while the program is running. new returns a pointer to an unnamed objects. Let’s see
the example of student that will clear your idea about this topic
int main()
{
Simple obj;
Simple* ptr; // Pointer of class type
ptr = &obj;
Object.*pointerToMember
ObjectPointer->*pointerToMember
Let‘s take an example, to understand the complete void print() { cout << "a is="<<
concept. a; } };
d.*ptr=10;
d.print();
dp->*ptr=20;
dp->print();
}
The syntax is very tough, hence they are only used under special circumstances.
class Data
{ public:
int f (float) { return 1; }
};
int main(0
{
fp2 = &Data::f; // Assignment Some Points to remember
inside main() }
1. You can change the value and behaviour of these pointers on runtime. That
means, you can point it to other member function or member variable.
2. To have pointer to data member and member functions you need to make them
public.
Derived classes do not inherit constructors or destructors from their base classes, but
they do call the constructor and destructor of base classes. Destructors can be declared
with the keyword virtual.
Constructors are also called when local or temporary class objects are created, and
destructors are called when local or temporary objects go out of scope.
Constructor and Destructor invoking sequence with
inheritance Example Program
class Base
{
public:
Base ( ) void main( )
{ {
cout << "Inside Base constructor" << endl; Derived x;
} }
~Base ( ) So, here is what the output of the code above would
{ look like:
cout << "Inside Base destructor" <<
endl; }
};
public:
Derived ( )
{
cout << "Inside Derived constructor" <<
endl; }
~Derived ( )
{
cout << "Inside Derived destructor" <<
endl; }
};
Base class constructors and derived class destructors are called first
In the code above, when the object "x" is created, first the Base class constructor is
called, and after that the Derived class constructor is called. Because the Derived class
inherits from the Base class, both the Base class and Derived class constructors will be
called when a Derived class object is created.
When the main function is finished running, the object x's destructor will get called
first, and after that the Base class destructor will be called.
Base class conversions
Upcasting is converting a derived-class reference or pointer to a base-class. In other
words, upcasting allows us to treat a derived type as though it were its base type. It is
always allowed for public inheritance, without an explicit type cast. This is a result of
the is-a relationship between the base and derived classes.
Here is the code dealing with shapes. We created Shape class, and derived Circle,
Square, and Triangle classes from the Shape class. Then, we made a member function
that talks to the base class:
void play(Shape& s)
{
s.draw();
s.move();
s.shrink();
....
}
The function speaks to any Shape, so it is independent of the specific type of object
that it's drawing, moving, and shrinking. If in some other part of the program we use
the play( ) function like below:
Circle c;
Triangle t;
Square sq;
play(c);
play(t);
play(sq);
Let's check what's happening here. A Triangle is being passed into a function that is
expecting a Shape. Since a Triangle is a Shape, it can be treated as one by play(). That
is, any message that play() can send to a Shape a Triangle can accept.
Upcasting allows us to treat a derived type as though it were its base type. That's how
we decouple ourselves from knowing about the exact type we are dealing with.
Note that it doesn't say "If you're a Triangle, do this, if you're a Circle, do that, and so
on." If we write that kind of code, which checks for all the possible types of a Shape, it
will soon become a messy code, and we need to change it every time we add a new
kind of Shape. Here, however, we just say "You're a Shape, I know you can move(),
draw(), and shrink( ) yourself, do it, and take care of the details correctly."
The compiler and runtime linker handle the details. If a member function is virtual, then
when we send a message to an object, the object will do the right thing, even when
upcasting is involved.
Note that the most important aspect of inheritance is not that it provides member
functions for the new class, however. It's the relationship expressed between the new
class and the base class. This relationship can be summarized by saying, "The new
class is a type of the existing class."
class Parent {
public:
void sleep() {}
}; // upcast - implicit type cast allowed
Parent *pParent = &child;
class Child: public Parent {
public: // downcast - explicit type case required
void gotoSchool(){} Child *pChild = (Child *) &parent;
};
pParent -> sleep();
int main( ) pChild -> gotoSchool();
{
Parent parent; return 0;
Child child; }
A Child object is a Parent object in that it inherits all the data members and member
functions of a Parent object. So, anything that we can do to a Parent object, we can do
to a Child object. Therefore, a function designed to handle a Parent pointer (reference)
can perform the same acts on a Child object without any problems. The same idea
applies if we pass a pointer to an object as a function argument. Upcasting is transitive:
if we derive a Child class from Parent, then Parent pointer (reference) can refer to a
Parent or a Child object.
Upcasting can cause object slicing when a derived class object is passed by value as a
base class object, as in foo(Base derived_obj).
Downcasting
The opposite process, converting a base-class pointer (reference) to a derived-class
pointer (reference) is called downcasting. Downcasting is not allowed without an
explicit type cast. The reason for this restriction is that the is-a relationship is not, in
most of the cases, symmetric. A derived class could add new data members, and the
class member functions that used these data members wouldn't apply to the base class.
As in the example, we derived Child class from a Parent class, adding a member
function, gotoSchool(). It wouldn't make sense to apply the gotoSchool() method to a
Parent object. However, if implicit downcasting were allowed, we could accidentally
assign the address of a Parent object to a pointer-to-Child
Child *pChild = &parent; // actually this won't compile //
error: cannot convert from 'Parent *' to 'Child *'
and use the pointer to invoke the gotoSchool() method as in the following
line. pChild -> gotoSchool();
Because a Parent isn't a Child (a Parent need not have a gotoSchool() method), the
downcasting in the above line can lead to an unsafe operation.
C++ provides a special explicit cast called dynamic_cast that performs this conversion.
Downcasting is the opposite of the basic object-oriented rule, which states objects of a
derived class, can always be assigned to variables of a base class.
Dynamic Casting
The dynamic_cast operator answers the question of whether we can safely assign the
address of an object to a pointer of a particular type.
class Parent {
public:
void sleep() {
}
};
int main( )
{
Parent *pParent = new Parent;
Parent *pChild = new Child;
Type cast #1 is not safe because it assigns the address of a base-class object (Parent) to
a derived class (Child) pointer. So, the code would expect the base-class object to have
derived class properties such as gotoSchool() method, and that is false. Also, Child
object, for example, has a member classes that a Parent object is lacking.
Type case #2, however, is safe because it assigns the address of a derived-class object
to a base-class pointer. In other words, public derivation promises that a Child object is
also a Parent object.
The question of whether a type conversion is safe is more useful than the question of
what kind of object is pointed to. The usual reason for wanting to know the type is so
that we can know if it's safe to invoke a particular method.
∙ It returns 0, otherwise.
Notes
∙ downcast - A downcast is a cast from a base class to a class derived from that base
class.
∙ cross-cast - A cross-cast is a cast between unrelated types (user-defined conversion)
The fact that the scope of a derived class nests inside the scope of its base classes can
be surprising. After all, the base and derived classes are defined in separate parts of our
program‘s text. However, it is this hierarchical nesting of class scopes that allows the
members ...
Overloading with Inheritance
Overloading doesn‘t work for derived class in C++ programming language. There is no overload
resolution between Base and Derived. The compiler looks into the scope of Derived, finds the
single function ―double f(double)‖ and calls it. It never disturbs with
the (enclosing) scope of Base. In C++, there is no overloading across scopes – derived
class scopes are not an exception to this general rule.
Inheritance relationship
Subclasses and superclasses can be understood in terms of the is a relationship. A subclass is a
more specific instance of a superclass. For example, an orange is a citrus fruit, which is a fruit.
A shepherd is a dog, which is an animal.
If the is a relationship does not exist between a subclass and superclass, you should not use
inheritance.
Note: inheritance only reuses implementation and establishes a syntactic relationship, not
necessarily a semantic relationship (inheritance does not ensure behavioral subtyping). To
distinguish these concepts, subtyping is also known as interface inheritance, while inheritance
as defined here is known as implementation inheritance.
CHAPTER 6: POLYMORPHISM
Introduction to Polymorphism
Polymorphism is an object-oriented programming concept that refers to the ability of a
variable, function or object to take on multiple forms. A language that features
polymorphism allows developers to program in the general rather than program in the
specific.
In a programming language that exhibits polymorphism, objects of classes belonging to the
same hierarchical tree (i.e. inherited from a common base class) may possess functions
bearing the same name, but each having different behaviors.
As an example, let us assume there is a base class named Animals from which the subclasses
Horse, Fish and Bird are derived. Let us also assume that the Animals class has a function named
Move, which is inherited by all subclasses mentioned. With
polymorphism, each subclass may have its own way of implementing the function. So,
for example, when the Move function is called in an object of the Horse class, the
function might respond by displaying trotting on the screen. On the other hand, when
the same function is called in an object of the Fish class, swimming might be displayed
on the screen. In the case of a Bird object, it may be flying.
In effect, polymorphism trims down the work of the developer because he can now
create a sort of general class with all the attributes and behaviors that he envisions for
it. When the time comes for the developer to create more specific subclasses with
certain unique attributes and behaviors, the developer can simply alter code in the
specific portions where the behaviors will differ. All other portions of the code can be
left as is.
Advantages/importance of Polymorphism
When an object has a reference to another, it can invoke methods on that object reference
without knowing, or caring, what the implementation is.
Why Polymorphism?
Note
•Substitutability means, the type of the variable does not have to match with the type of the
value assigned to that variable.
•Substitutability cannot be achieved in conventional languages in C, but can be achieved in
Object Oriented languages like Java.
•We have already seen the concept of “Assigning a subclass object to superclass variable or
reference”. This is called substitutability. Here I am substituting the superclass object with the
object of subclass.
Exten
Discussion
The word polymorphism means having many forms. Typically, polymorphism occurs
when there is a hierarchy of classes and they are related by inheritance.
C++ polymorphism means that a call to a member function will cause a different
function to be executed depending on the type of object that invokes the function.
Consider the following example where a base class has been derived by other two
classes:
#include <iostream>
using namespace std;
class Shape {
protected:
int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// Main function for the program
int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
return 0;
}
When the above code is compiled and executed, it produces the following result:
Parent class area
Parent class area
The reason for the incorrect output is that the call of the function area() is being set
once by the compiler as the version defined in the base class. This is called static
resolution of the function call, or static linkage - the function call is fixed before the
program is executed. This is also sometimes called early binding because the area()
function is set during the compilation of the program.
But now, let's make a slight modification in our program and precede the declaration of
area() in the Shape class with the keyword virtual so that it looks like this:
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
After this slight modification, when the previous example code is compiled and
executed, it produces the following result:
This time, the compiler looks at the contents of the pointer instead of it's type. Hence,
since addresses of objects of tri and rec classes are stored in *shape the respective
area() function is called.
As you can see, each of the child classes has a separate implementation for the function
area(). This is how polymorphism is generally used. You have different classes with a
function of the same name, and even the same parameters, but with different
implementations.
By Information Hiding we mean ―Showing only those details to the outside world
which are necessary for the outside world and hiding all other details from the outside
world.”
Encapsulation means “we have enclosed all the characteristics of an object in the
object itself”.
Encapsulation and information hiding are much related concepts (information hiding is
achieved using Encapsulation). We have seen in previous lecture that object
characteristics include data members and behavior of the object in the form of
functions. So we can say that Data and Behavior are tightly coupled inside an object
and both the information structure and implementation details of its operations are
hidden from the outer world.
Examples of Encapsulation
Consider the same example of object Ali of previous lecture we described it as follows.
Ali
Characteristics (attributes)
· Name
· Age
Behavior (operations)
· Walks
· Eats
You can see that Ali stores his personal information in itself and its behavior is also
implemented in it. Now it is up to object Ali whether he wants to share that information
with outside world or not. Same thing stands for its behavior if some other object in real
life wants to use his behavior of walking it can not use it without the permission of Ali.
So we say that attributes and behavior of Ali are encapsulated in it. Any other object
don‘t know about these things unless Ali share this information with that object through
an interface. Same concept also applies to phone which has some data and behavior of
showing that data to user we can only access the information stored in the phone if
phone interface allow us to do so. Advantages of Encapsulation
The following are the main advantages of
Encapsulation, 1. Simplicity and clarity
As all data and functions are stored in the objects so there is no data or function around
in program that is not part of any object and is this way it becomes very easy to
understand the purpose of each data member and function in an object.
2. Low complexity
As data members and functions are hidden in objects and each object has a specific
behavior so there is less complexity in code there will be no such situations that a
functions is using some other function and that functions is using some other function.
3. Better understanding
Everyone will be able to understand whole scenario by simple looking into object
diagrams without any issue as each object has specific role and specific relation with
other objects.
be based on the kind of object for which it is called. This sort of operation is referred to
as dynamic linkage, or late binding.
The = 0 tells the compiler that the function has no body and above virtual function will
be called pure virtual function. Data Abstraction
Data abstraction refers to, providing only essential information to the outside world and
hiding their background details, i.e., to represent the needed information in program
without presenting the details.
Data abstraction is a programming (and design) technique that relies on the separation
of interface and implementation.
Let's take one real life example of a TV, which you can turn on and off, change the
channel, adjust the volume, and add external components such as speakers, VCRs, and
DVD players, BUT you do not know its internal details, that is, you do not know how it
receives signals over the air or through a cable, how it translates them, and finally
displays them on the screen.
Thus, we can say a television clearly separates its internal implementation from its
external interface and you can play with its interfaces like the power button, channel
changer, and volume control without having zero knowledge of its internals.
Now, if we talk in terms of C++ Programming, C++ classes provides great level of data
abstraction. They provide sufficient public methods to the outside world to play with
the functionality of the object and to manipulate object data, i.e., state without actually
knowing how class has been implemented internally.
For example, your program can make a call to the sort() function without knowing
what algorithm the function actually uses to sort the given values. In fact, the
int main( )
.{
cout << "Hello C++" <<endl;
return 0;
}
Here, you don't need to understand how cout displays the text on the user's screen. You
need to only know the public interface and the underlying implementation of cout is
free to change.
∙ Members defined with a private label are not accessible to code that uses the
class. The private sections hide the implementation from code that uses the type.
There are no restrictions on how often an access label may appear. Each access label
specifies the access level of the succeeding member definitions. The specified access
level remains in effect until the next access label is encountered or the closing right
brace of the class body is seen.
#include <iostream>
using namespace std;
class Adder{
public:
// constructor
Adder(int i = 0)
{
total = i;
}
// interface to outside world
void addNum(int number)
{
total += number;
}
// interface to outside world
int getTotal()
{
return total;
};
private:
// hidden data from outside world
int total;
};
int main( )
{
Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
When the above code is compiled and executed, it produces the following result:
Total 60
Above class adds numbers together, and returns the sum. The public members addNum
and getTotalare the interfaces to the outside world and a user needs to know them to
use the class. The private member total is something that the user doesn't need to know
about, but is needed for the class to operate properly.
Designing Strategy:
Abstraction separates code into interface and implementation. So while designing your
component, you must keep interface independent of the implementation so that if you
change underlying implementation then interface would remain intact.
In this case whatever programs are using these interfaces, they would not be impacted
and would just need a recompilation with the latest implementation.
Data Encapsulation
All C++ programs are composed of the following two fundamental elements: ∙
Program statements (code): This is the part of a program that performs actions and
they are called functions.
∙ Program data: The data is the information of the program which affected by the
program functions.
Encapsulation is an Object Oriented Programming concept that binds together the data
and functions that manipulate the data, and that keeps both safe from outside
interference and misuse. Data encapsulation led to the important OOP concept of data
hiding.
Data encapsulation is a mechanism of bundling the data, and the functions that use
them and data abstraction is a mechanism of exposing only the interfaces and hiding
the implementation details from the user.
C++ supports the properties of encapsulation and data hiding through the creation of
user-defined types, called classes. We already have studied that a class can contain
private, protected and publicmembers. By default, all items defined in a class are
private. For example:
class Box
{
public:
double getVolume(void)
{
return length * breadth * height;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
The variables length, breadth, and height are private. This means that they can be
accessed only by other members of the Box class, and not by any other part of your
program. This is one way encapsulation is achieved.
To make parts of a class public (i.e., accessible to other parts of your program), you
must declare them after the public keyword. All variables or functions defined after the
public specifier are accessible by all other functions in your program.
Making one class a friend of another exposes the implementation details and reduces
encapsulation. The ideal is to keep as many of the details of each class hidden from all
other classes as possible.
#include <iostream>
using namespace std;
class Adder{
public:
// constructor
Adder(int i = 0)
{
total = i;
}
// interface to outside world
void addNum(int number)
{
total += number;
}
// interface to outside world
int getTotal()
{
return total;
};
private:
// hidden data from outside world
int total;
};
int main( )
{
Adder a;
a.addNum(10);
a.addNum(20);
a.addNum(30);
When the above code is compiled and executed, it produces the following result:
Total 60
Above class adds numbers together, and returns the sum. The public members addNum
and getTotalare the interfaces to the outside world and a user needs to know them to
use the class. The private member total is something that is hidden from the outside
world, but is needed for the class to operate properly.
Designing Strategy:
Most of us have learned through bitter experience to make class members private by
default unless we really need to expose them. That's just good encapsulation.
This wisdom is applied most frequently to data members, but it applies equally to all
Classes that can be used to instantiate objects are called concrete classes.
#include <iostream>
// Base class
class Shape
{
public:
// Derived classes
class Rectangle: public Shape
{
public:
int getArea()
{
return (width * height);
}
};
class Triangle: public Shape
{
public:
int getArea()
{
return (width * height)/2;
}
};
int main(void)
{
Rectangle Rect;
Triangle Tri;
Rect.setWidth(5);
Rect.setHeight(7);
// Print the area of the object.
cout << "Total Rectangle area: " << Rect.getArea() << endl;
Tri.setWidth(5);
Tri.setHeight(7);
// Print the area of the object.
cout << "Total Triangle area: " << Tri.getArea() << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Total Rectangle area: 35
Total Triangle area: 17
You can see how an abstract class defined an interface in terms of getArea() and two
other classes implemented same function but with different algorithm to calculate the
area specific to the shape.
Designing Strategy:
An object-oriented system might use an abstract base class to provide a common and
standardized interface appropriate for all the external applications. Then, through
inheritance from that abstract base class, derived classes are formed that all operate
similarly.
The capabilities (i.e., the public functions) offered by the external applications are
provided as pure virtual functions in the abstract base class. The implementations of
these pure virtual functions are provided in the derived classes that correspond to the
specific types of the application.
This architecture also allows new applications to be added to a system easily, even after
the system has been defined.
CHAPTER 7: CONSTRUCTORS AND
DESTRUCTORS
Definition of Constructors
Constructors are special class functions which performs initialization of every object.
The Compiler calls the Constructor whenever an object is created. Constructors iitialize
values to object members after storage is allocated to the object
class A
{
int x;
public:
A(); //Constructor
};
While defining a contructor you must remeber that the name of constructor will be
same as the name of the class, and contructors neverhave return type.
Constructors can be defined either inside the class definition or outside class definition
using class name and scope resolution‖::‖ operator.
class A
{
int i;
public:
A(); //Constructor declared
};
A::A() // Constructor definition
{
i=1;
}
Types of Constructors
Constructors are of three types :
1. Default Constructor
2. Parametrized Constructor
3. Copy Constructor
Default Constructor
Default constructor is the constructor which doesn't take any argument. It has no
parameter.
Syntax :
class_name ()
{ Constructor Definition }
Example : }
class Cube };
{ int main()
int side; {
public: Cube c;
Cube() cout << c.side;
{ }
side=10;
Output : 10
In this case, as soon as the object is created the constructor is called which initializes its
data members.
class Cube
{
int side;
};
int main()
{
Cube c;
cout << c.side;
Output : 0
In this case, default constructor provided by the compiler will be called which will
initialize the object data members to default value, that will be 0 in this case.
Parameterized Constructor
These are the constructors with parameter. Using this Constructor you can provide
different values to data members of different objects, by passing the appropriate values
as argument.
Example : int main()
{
class Cube Cube c1(10);
{ Cube c2(20);
int side; Cube c3(30);
public: cout << c1.side;
Cube(int x) cout << c2.side;
{ cout << c3.side;
side=x; }
}
}; OUTPUT : 10 20 30
By using parameterized construcor in above case, we have initialized 3 objects with
user defined values. We can have any number of parameters in a constructor.
Copy Constructor
These are special type of Constructors which takes an object as argument, and is used
to copy values of data members of one object into other object. We will study copy
constructors in detail later.
Constructor Overloading
Just like other member functions, constructors can also be overloaded. Infact when you
have both default and parameterized constructors defined in your class you are having
Overloaded Constructors, one with no parameter and other with parameter.
You can have any number of Constructors in a class that differ in parameter list
class Student
{
int rollno;
string name;
public:
Student(int x)
{
rollno=x;
name="None";
}
Student(int x, string str)
{
rollno=x ;
name=str ;
}
};
int main()
{
Student A(10);
Student B(11,"Ram");
}
In above case we have defined two constructors with different parameters, hence
overloading the constructors.
One more important thing, if you define any constructor explicitly, then the compiler
will not provide default constructor and you will have to define it yourself.
In the above case if we write Student S; in main(), it will lead to a compile time error,
because we haven't defined default constructor, and compiler will not provide its
default constructor because we have defined other parameterized constructors.
Destructors
Destructor is a special class function which destroys the object as soon as the scope of
object ends. The destructor is called automatically by the compiler when the object
goes out of scope.
The syntax for destructor is same as that for the constructor, the class name is used for
the name of destructor, with a tilde ~ sign as prefix to it.
class A
{
public:
~A();
};
class A
{
A()
{
cout << "Constructor called"; {
} cout << "Destructor called";
~A() }
class Dual
{
int a;
public:
Dual(int x=0)
{
a=x;
}
};
int main()
{
Dual obj1;
Dual obj2(10);
}
Here, in this program, a single Constructor definition will take care for both these
object initializations. We don't need separate default and parameterized constructors.
CHAPTER 8: OPERATOR OVERLOADING
Meaning and importance of operator overloading
Operator overloading is an important concept in C++. It is a type of polymorphism in
which an operator is overloaded to give user defined meaning to it. Overloaded
operator is used to perform operation on user-defined data type. For example '+'
operator can be overloaded to perform addition on various data types, like for Integer,
String(concatenation) etc.
Almost any operator can be overloaded in C++. However there are few operator which
can not be overloaded. Operator that are not overloaded are follows 1. scope
operator - ::
2. sizeof
3. member selector - .
4. member pointer selector - *
5. ternary operator - ?:
#include< iostream.h>
#include< conio.h>
class time
{
int h,m,s;
public:
time()
{
h=0, m=0; s=0;
}
void getTime();
void show()
{
cout<< h<< ":"<< m<< ":"<< s;
}
time operator+(time); //overloading '+' operator
};
time time::operator+(time t1) //operator function
{
time t;
int a,b;
a=s+t1.s;