C Program Full
C Program Full
C Program Full
Meaning
ios::app
ios::ate
ios::binary
ios::in
ios::out
ios::nocreate
ios::noreplace
ios::trunc
All these flags can be combined using the bitwise operator OR (|). For example, if we want to
open the file example.bin in binary mode to add data we could do it by the following call to
member function open():
fstream file;
file.open ("example.bin", ios::out | ios::app | ios::binary);
Closing File
outFile.close();
inFile.close();
INPUT AND OUTPUT OPERATION
put() and get() function
the function put() writes a single character to the associated stream. Similarly, the function get()
reads a single character form the associated stream.
example :
file.get(ch);
file.put(ch);
write() and read() function
write() and read() functions write and read blocks of binary data.
example:
file.read((char *)&obj, sizeof(obj));
file.write((char *)&obj, sizeof(obj));
ERROR HANDLING FUNCTION
FUNCTION
eof()
fail()
bad()
good()
ofstream, like ostream, has a pointer known as the put pointer that points to the location where
the next element has to be written.
Finally, fstream, inherits both, the get and the put pointers, from iostream (which is itself derived
from both istream and ostream).
These internal stream pointers that point to the reading or writing locations within a stream can
be manipulated using the following member functions:
seekg()
seekp()
tellg()
tellp()
char data[100];
// open a file in write mode.
ofstream outfile;
outfile.open("afile.dat");
cout << "Writing to the file" << endl;
cout << "Enter your name: ";
cin.getline(data, 100);
// write inputted data into the file.
outfile << data << endl;
cout << "Enter your age: ";
cin >> data;
cin.ignore();
// again write inputted data into the file.
outfile << data << endl;
// close the opened file.
outfile.close();
// open a file in read mode.
ifstream infile;
infile.open("afile.dat");
cout << "Reading from the file" << endl;
infile >> data;
// write the data at the screen.
cout << data << endl;
// again read the data from the file and display it.
infile >> data;
cout << data << endl;
// close the opened file.
infile.close();
return 0;
}
When the above code is compiled and executed, it produces the following sample input and
output:
$./a.out
An exception is a problem that arises during the execution of a program. A C++ exception is a
response to an exceptional circumstance that arises while a program is running, such as an
attempt to divide by zero.
Exceptions provide a way to transfer control from one part of a program to another. C++
exception handling is built upon three keywords: try, catch, and throw.
throw: A program throws an exception when a problem shows up. This is done using
a throwkeyword.
catch: A program catches an exception with an exception handler at the place in a
program where you want to handle the problem. The catch keyword indicates the catching of an
exception.
try: A try block identifies a block of code for which particular exceptions will be
activated. It's followed by one or more catch blocks.
Assuming a block will raise an exception, a method catches an exception using a combination of
thetry and catch keywords. A try/catch block is placed around the code that might generate an
exception. Code within a try/catch block is referred to as protected code, and the syntax for using
try/catch looks like the following:
try
{
// protected code
}catch( ExceptionName e1 )
{
// catch block
}catch( ExceptionName e2 )
{
// catch block
}catch( ExceptionName eN )
{
// catch block
}
You can list down multiple catch statements to catch different type of exceptions in case
your try block raises more than one exception in different situations.
Throwing Exceptions:
Exceptions can be thrown anywhere within a code block using throw statements. The operand of
the throw statements determines a type for the exception and can be any expression and the type
of the result of the expression determines the type of exception thrown.
Following is an example of throwing an exception when dividing by zero condition occurs:
int main ()
{
int x = 50;
int y = 0;
double z = 0;
try {
z = division(x, y);
cout << z << endl;
}catch (const char* msg) {
cerr << msg << endl;
}
return 0;
}
Because we are raising an exception of type const char*, so while catching this exception, we
have to use const char* in catch block. If we compile and run above code, this would produce the
following result:
Division by zero condition!
C++ Standard Exceptions:
C++ provides a list of standard exceptions defined in <exception> which we can use in our
programs. These are arranged in a parent-child class hierarchy shown below:
Here is the small description of each exception mentioned in the above hierarchy:
Exception
Description
std::exception
std::bad_alloc
std::bad_cast
std::bad_exception
std::bad_typeid
std::logic_error
std::domain_error
std::out_of_range
std::runtime_error
std::overflow_error
std::range_error
std::underflow_error
MyException caught
C++ Exception
Here, what() is a public method provided by exception class and it has been overridden by all the
child exception classes. This returns the cause of an exception.
Wap to demonstrate overloading of operator + to add 2 complex number using friend
function?
Some of the most commonly used operators in C++ are the arithmetic operators that is, the
plus operator (+), minus operator (-), multiplication operator (*), and division operator (/). Note
that all of the arithmetic operators are binary operators meaning they take two operands
one on each side of the operator. All four of these operators are overloaded in the exact same
way.
Overloading operators using friend functions
When the operator does not modify its operands, the best way to overload the operator is via
friend function. None of the arithmetic operators modify their operands (they just produce and
return a result), so we will utilize the friend function overloaded operator method here.
The following example shows how to overload operator plus (+) in order to add two Cents
objects together:
Operators can be overloaded in c++ with friend functions also. The procedure is same as we
discussed earlier. Here I will demonstrate operator overloading with "+" operator which is a
binary operator. I will be using a complex number class (called complex). The class will have 2
data types, real and imaginary.
Operator overloading will not be a part of class complex, but we will declare that this function is
a friend of class complex.
Note that since overloaded function is not part of class , so will require 2 args (overloading with
member function require 1 arg for binary operator, as the first arg is the object itself.)
Use:
Most student wonder why we need to use operator overloading in such manner? The answer is
simple, this will allow you to manipulate operator for predefined objects that you mat not have
access. (Like cout or cin)
Code:
#include<iostream>
using namespace std;
// complex class with real and imaginary part
class complex
{
public:
int real;
int img;
//default constructor
complex()
{
real=img=0;
}
//overloaded constructor with 2 args
complex(int x,int y)
{
real=x;
img=y;
}
//show function to display complex number
void show()
{
cout<<"\n"<<real<<"+"<<img<<"i";
}
//declaring that "opeartor+" is friend of class complex
friend complex operator+(complex c,complex d);
};
//operator+ is not part of complex class so have 2 args for + operator overload.
complex operator+(complex c, complex f)
{
complex ans;
ans.real=c.real+f.real;
ans.img=c.img+f.img;
return(ans);
}
int main()
{
complex x(1,2), y(0,7);
complex c=x+y;//overloaded + is called here
//note that compiler will convert this to
// c=operator+(x,y)
c.show();
}
Overloading
Example
Overriding
public class MyBaseClass
{
public virtual void MyMethod()
{
Console.Write("My BaseClass Method");
}
}
public class MyDerivedClass : MyBaseClass
{
public override void MyMethod()
{
Console.Write("My DerivedClass Method");
}
}
Overloading
int add(int a, int b)
int add(float a , float b)
In this tutorial you will learn about Objects, Classes, Inheritance, Data Abstraction, Data
Encapsulation, Polymorphism, Overloading, and Reusability.
Before starting to learn C++ it is essential to have a basic knowledge of the concepts of Object
oriented programming. Some of the important object oriented features are namely:
Objects
Classes
Inheritance
Data Abstraction
Data Encapsulation
Polymorphism
Overloading
Reusability
In order to understand the basic concepts in C++, a programmer must have a good knowledge of
the basic terminology in object-oriented programming. Below is a brief outline of the concepts of
object-oriented programming languages :
Objects:
Object is the basic unit of object-oriented programming. Objects are identified by its unique
name. An object represents a particular instance of a class. There can be more than one instance
of a class. Each instance of a class can hold its own relevant data.
An Object is a collection of data members and associated member functions also known as
methods.
Classes:
Classes are data types based on which objects are created. Objects with similar properties and
methods are grouped together to form a Class. Thus a Class represents a set of individual objects.
Characteristics of an object are represented in a class as Properties. The actions that can be
performed by objects become functions of the class and are referred to as Methods.
For example consider we have a Class of Cars under which Santro Xing, Alto and WaganR
represents individual Objects. In this context each Car Object will have its own, Model, Year of
Manufacture, Color, Top Speed, Engine Power etc., which form Properties of the Car class and
the associated actions i.e., object functions like Start, Move, and Stop form the Methods of Car
Class.
No memory is allocated when a class is created. Memory is allocated only when an object is
created, i.e., when an instance of a class is created.
Inheritance:
Inheritance is the process of forming a new class from an existing class or base class. The base
class is also known as parent class or super class. The new class that is formed is called derived
class. Derived class is also known as a child class or sub class. Inheritance helps in reducing the
overall code size of the program, which is an important concept in object-oriented programming.
Data Abstraction:
Data Abstraction increases the power of programming language by creating user defined data
types. Data Abstraction also represents the needed information in the program without presenting
the details.
Data Encapsulation:
Data Encapsulation combines data and functions into a single unit called Class. When using Data
Encapsulation, data is not accessed directly; it is only accessible through the functions present
inside the class. Data Encapsulation enables the important concept of data hiding possible.
Polymorphism:
Polymorphism allows routines to use variables of different types at different times. An operator
or function can be given different meanings or functions. Polymorphism refers to a single
function or multi-functioning operator performing in different ways.
Overloading:
Overloading is one type of Polymorphism. It allows an object to have different meanings,
depending on its context. When an existing operator or function begins to operate on new data
type, or class, it is understood to be overloaded.
Reusability:
This term refers to the ability for multiple programmers to use the same written and debugged
existing class of data. This is a time saving device and adds code efficiency to the language.
Additionally, the programmer can incorporate new features to the existing class, further
developing the application and allowing users to achieve increased performance. This time
saving feature optimizes code, helps in gaining secured applications and facilitates easier
maintenance on the application.
The implementation of each of the above object-oriented programming features for C++ will be
highlighted in later sections.
A sample program to understand the basic structure of C++
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
void getvalue()
{
cout<<"INPUT Employee Name:";
cin>>empname;
//
waiting input from the Keyboard for the name
17.
cout<<"INPUT Employee Number:";
18.
cin>>empno;
// waiting
input from the Keyboard for the number
19.
}
20.
void displayvalue(){
21.
cout<<"Employee Name:"<< empname << endl; // displays the
employee name
22.
cout<<"Employee Number:"<< empno << endl; // displays the
emloyee number
23.
24.
25.
26.
27.
28.
29.
};
void main()
{
employee e1;
// Creation of Object
e1.getvalue();
// the getvalue method is
being called
30.
e1.displayvalue(); // the displayvalue method is being called
31.
}
32.
33.
///// code ends here //////////////
Output:
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 userdefined 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.
Data Encapsulation Example:
Any C++ program where you implement a class with public and private members is an example
of data encapsulation and data abstraction. Consider the following example:
#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);
cout << "Total " << a.getTotal() <<endl;
return 0;
}
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 members,
including virtual functions.
When you define a class, you define a blueprint for a data type. This doesn't actually define any
data, but it does define what the class name means, that is, what an object of the class will consist
of and what operations can be performed on such an object.
A class definition starts with the keyword class followed by the class name; and the class body,
enclosed by a pair of curly braces. A class definition must be followed either by a semicolon or a
list of declarations. For example, we defined the Box data type using the keyword class as
follows:
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
The keyword public determines the access attributes of the members of the class that follow it. A
public member can be accessed from outside the class anywhere within the scope of the class
object. You can also specify the members of a class as private or protected which we will
discuss in a sub-section.
Define C++ Objects:
A class provides the blueprints for objects, so basically an object is created from a class. We
declare objects of a class with exactly the same sort of declaration that we declare variables of
basic types. Following statements declare two objects of class Box:
Box Box1;
Box Box2;
Both of the objects Box1 and Box2 will have their own copy of data members.
Accessing the Data Members:
The public data members of objects of a class can be accessed using the direct member access
operator (.). Let us try the following example to make the things clear:
#include <iostream>
using namespace std;
class Box
{
public:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
int main( )
{
Box Box1;
// Declare Box1 of type Box
Box Box2;
// Declare Box2 of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
// box 2 specification
Box2.height = 10.0;
Box2.length = 12.0;
Box2.breadth = 13.0;
// volume of box 1
volume = Box1.height * Box1.length * Box1.breadth;
cout << "Volume of Box1 : " << volume <<endl;
// volume of box 2
volume = Box2.height * Box2.length * Box2.breadth;
cout << "Volume of Box2 : " << volume <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Volume of Box1 : 210
Volume of Box2 : 1560
It is important to note that private and protected members can not be accessed directly using
direct member access operator (.). We will learn how private and protected members can be
accessed.
Classes & Objects in Detail:
So far, you have got very basic idea about C++ Classes and Objects. There are further interesting
concepts related to C++ Classes and Objects which we will discuss in various sub-sections listed
below:
Concept
Description
Inheritance
One of the most important concepts in object-oriented programming is that of inheritance.
Inheritance allows us to define a class in terms of another class, which makes it easier to create
and maintain an application. This also provides an opportunity to reuse the code functionality
and fast implementation time.
When creating a class, instead of writing completely new data members and member functions,
the programmer can designate that the new class should inherit the members of an existing class.
This existing class is called the base class, and the new class is referred to as the derived class.
The idea of inheritance implements the is a relationship. For example, mammal IS-A animal, dog
IS-A mammal hence dog IS-A animal as well and so on.
Base & Derived Classes:
A class can be derived from more than one classes, which means it can inherit data and functions
from multiple base classes. To define a derived class, we use a class derivation list to specify the
base class(es). A class derivation list names one or more base classes and has the form:
class derived-class: access-specifier base-class
Where access-specifier is one of public, protected, or private, and base-class is the name of a
previously defined class. If the access-specifier is not used, then it is private by default.
Consider a base class Shape and its derived class Rectangle as follows:
#include <iostream>
using namespace std;
// Base class
class Shape
{
public:
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
// Derived class
class Rectangle: public Shape
{
public:
int getArea()
{
return (width * height);
}
};
int main(void)
{
Rectangle Rect;
Rect.setWidth(5);
Rect.setHeight(7);
// Print the area of the object.
cout << "Total area: " << Rect.getArea() << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Total area: 35
Access Control and Inheritance:
A derived class can access all the non-private members of its base class. Thus base-class
members that should not be accessible to the member functions of derived classes should be
declared private in the base class.
We can summarize the different access types according to who can access them in the following
way:
Access
public
protected
private
Same class
yes
yes
yes
Derived classes
yes
yes
no
Outside classes
yes
no
no
A derived class inherits all base class methods with the following exceptions:
When deriving a class from a base class, the base class may be inherited through public,
protected orprivate 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 publicand protected members of the base class.
Protected
Inheritance: When
deriving
from
a protected base
class, public and protectedmembers 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.
Multiple Inheritances:
A C++ class can inherit members from more than one class and here is the extended syntax:
class derived-class: access baseA, access baseB....
Where access is one of public, protected, or private and would be given for every base class
and they will be separated by comma as shown above. Let us try the following example:
#include <iostream>
using namespace std;
// Base class Shape
class Shape
{
public:
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
// Base class PaintCost
class PaintCost
{
public:
int getCost(int area)
{
return area * 70;
}
};
// Derived class
class Rectangle: public Shape, public PaintCost
{
public:
int getArea()
{
return (width * height);
}
};
int main(void)
{
Rectangle Rect;
int area;
Rect.setWidth(5);
Rect.setHeight(7);
area = Rect.getArea();
// Print the area of the object.
cout << "Total area: " << Rect.getArea() << endl;
// Print the total cost of painting
cout << "Total paint cost: $" << Rect.getCost(area) << endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Total area: 35
Total paint cost: $2450
// volume of box 2
volume = Box2.getVolume();
cout << "Volume of Box2 : " << volume <<endl;
// Add two object as follows:
Box3 = Box1 + Box2;
// volume of box 3
volume = Box3.getVolume();
cout << "Volume of Box3 : " << volume <<endl;
return 0;
}
When the above code is compiled and executed, it produces the following result:
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400
Overloadable/Non-overloadableOperators:
Following is the list of operators which can be overloaded:
+
&
<
>
<=
>=
++
--
<<
>>
==
!=
&&
||
+=
-=
/=
%=
^=
&=
|=
*=
<<=
>>=
[]
()
->
->*
new
new []
delete
delete []
.*
?:
PolyMorphism
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 width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0):Shape(a, b) { }
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);
// store the address of Rectangle
shape = &rec;
// call rectangle area.
shape->area();
// store the address of Triangle
shape = &tri;
// call triangle area.
shape->area();
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, orstatic linkage - the function call is fixed before the program is executed. This is also
sometimes calledearly 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:
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 underlying
implementation of the sorting functionality could change between releases of the library, and as
long as the interface stays the same, your function call will still work.
In C++, we use classes to define our own abstract data types (ADT). You can use the cout object
of class ostream to stream data to standard output like this:
#include <iostream>
using namespace std;
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.
Access Labels Enforce Abstraction:
In C++, we use access labels to define the abstract interface to the class. A class may contain
zero or more access labels:
Members defined with a public label are accessible to all parts of the program. The dataabstraction view of a type is defined by its public members.
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.
Benefits of Data Abstraction:
Data abstraction provides two important advantages:
Class internals are protected from inadvertent user-level errors, which might corrupt the
state of the object.
The class implementation may evolve over time in response to changing requirements or
bug reports without requiring change in user-level code.
By defining data members only in the private section of the class, the class author is free to make
changes in the data. If the implementation changes, only the class code needs to be examined to
see what affect the change may have. If data are public, then any function that directly accesses
the data members of the old representation might be broken.
Data Abstraction Example:
Any C++ program where you implement a class with public and private members is an example
of data abstraction. Consider the following example:
#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);
cout << "Total " << a.getTotal() <<endl;
return 0;
}
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.
InterFace
public:
// pure virtual function
virtual double getVolume() = 0;
private:
double length;
// Length of a box
double breadth; // Breadth of a box
double height;
// Height of a box
};
The purpose of an abstract class (often referred to as an ABC) is to provide an appropriate base
class from which other classes can inherit. Abstract classes cannot be used to instantiate objects
and serves only as an interface. Attempting to instantiate an object of an abstract class causes a
compilation error.
Thus, if a subclass of an ABC needs to be instantiated, it has to implement each of the virtual
functions, which means that it supports the interface declared by the ABC. Failure to override a
pure virtual function in a derived class, then attempting to instantiate objects of that class, is a
compilation error.
Classes that can be used to instantiate objects are called concrete classes.
Abstract Class Example:
Consider the following example where parent class provides an interface to the base class to
implement a function called getArea():
#include <iostream>
using namespace std;
// Base class
class Shape
{
public:
// pure virtual function providing interface framework.
virtual int getArea() = 0;
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
// 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.
The stack: All variables declared inside the function will take up memory from the stack.
The heap: This is unused memory of the program and can be used to allocate the
memory dynamically when program runs.
Many times, you are not aware in advance how much memory you will need to store particular
information in a defined variable and the size of required memory can be determined at run time.
You can allocate memory at run time within the heap for the variable of a given type using a
special operator in C++ which returns the address of the space allocated. This operator is
called new operator.
If you are not in need of dynamically allocated memory anymore, you can use delete operator,
which de-allocates memory previously allocated by new operator.
The new and delete operators:
There is following generic syntax to use new operator to allocate memory dynamically for any
data-type.
new data-type;
Here, data-type could be any built-in data type including an array or any user defined data types
include class or structure. Let us start with built-in data types. For example we can define a
pointer to type double and then request that the memory be allocated at execution time. We can
do this using the newoperator with the following statements:
double* pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable
The memory may not have been allocated successfully, if the free store had been used up. So it is
good practice to check if new operator is returning NULL pointer and take appropriate action as
below:
Let us put above concepts and form the following example to show how new and delete work:
#include <iostream>
using namespace std;
int main ()
{
double* pvalue = NULL; // Pointer initialized with null
pvalue = new double; // Request memory for the variable
*pvalue = 29494.99; // Store value at allocated address
cout << "Value of pvalue : " << *pvalue << endl;
delete pvalue;
return 0;
}
If we compile and run above code, this would produce the following result:
Value of pvalue : 29495
Dynamic Memory Allocation for Arrays:
Consider you want to allocate memory for an array of characters, i.e., string of 20 characters.
Using the same syntax what we have used above we can allocate memory dynamically as shown
below.
char* pvalue = NULL; // Pointer initialized with null
Following the similar generic syntax of new operator, you can allocat for a multi-dimensional
array as follows:
double** pvalue = NULL; // Pointer initialized with null
pvalue = new double [3][4]; // Allocate memory for a 3x4 array
However, the syntax to release the memory for multi-dimensional array will still remain same as
above:
delete [] pvalue;
If you were to allocate an array of four Box objects, the Simple constructor would be called four
times and similarly while deleting these objects, destructor will also be called same number of
times.
If we compile and run above code, this would produce the following result:
Constructor called!
Constructor called!
Constructor called!
Constructor called!
Destructor called!
Destructor called!
Destructor called!
Destructor called!
Wap to read 2 integer from keyboard and to perform simple airthematic operation using
the pointer technique?The memory space for the operator is allocated by the new
operator?
Wap a program to define a class vector that operates on vector. write the member function
to compute the vector product, scalar product ,sum of the element of the vector, average of
elements, and sum of the square of elements?
class/sub class). In this example scenario, class A will inherit all public and protected attributes
and methods of the super class (B). The subclass can optionally override (provide new or
extended functionality to methods) the behavior inherited from the parent class. Inheritance
represents an is-a relationship in OOP. This essentially means that A is also a B. In other
words, B can be the class with a general description of a certain real world entity but A specifies
a certain specialization. In a real world programming problem, the Person class could be
extended to create the Employee class. This is called specialization. But you could also first
create the Employee class and then generalize it to a Person class as well (i.e. generalization). In
this example, the Employee will have all the properties and behavior of the Person (i.e.
Employee is also a Person) and may contain some additional functionality (so, Person is not an
Employee) as well.
What is Containership?
Containership is the ability of a class to contain objects of different classes as member data. For
example, class A could contain an object of class B as a member. Here, all the public methods
(or functions) defined in B can be executed within the class A. Class A becomes the container,
while class B becomes the contained class. Containership is also referred to as Composition. In
this example, it can be said that class A is composed of class B. In OOP, Containership
represents a has-a relationship. It is important to note that, even though the container has
access to execute all the public methods of the contained class, it is not able to alter or provide
additional functionality. When it comes to a real world programming problem, an object of class
TextBox may be contained in the class Form, and thus can be said that a Form contains a
TextBox (or alternatively, a Form is composed of a TextBox).
Difference between Inheritance and Containership
Although Inheritance and Containership are two OOP concepts, they are quite different in what
they allow the programmer to achieve. Inheritance is the ability for a class to inherit properties
and behavior from a parent class by extending it, while Containership is the ability of a class to
contain objects of different classes as member data. If a class is extended, it inherits all the public
and protected properties/behavior and those behaviors may be overridden by the subclass. But if
a class is contained in another, the container does not get the ability to change or add behavior to
the contained. Inheritance represents an is-a relationship in OOP, while Containership
represents a has-a relationship.
Objects and classes are used in object oriented programming languages. All object oriented
programming languages such as C++, Java, .NET and others, employs objects and classes.
Objects
An object is defined as any entity that can be utilized by using commands in a programming
language. Object can be a variable, value, data structure or a function. In object oriented
environment, object is referred to as instance of a class. Objects and classes are closely related to
each other. In real world, the objects are your TV, bicycle, desk and other entities. Methods are
used to access the objects of a class. All the interaction is done through the objects methods.
This is known as data encapsulation. The objects are also used for data or code hiding.
A number of benefits are provided by the objects when they are used in the code:
Ease of debugging The object can be easily removed from the code if there is some problem
due to it. A different object can be plugged in as a replacement of the former one.
Information hiding The code or internal implementation is hidden from the users when
interaction is done through objects methods.
Reuse of code if an object or code is written by some other programmer then you can also use
that object in your program. In this way, objects are highly reusable. This allows experts to
debug, implement task specific and complex objects that can be used in your own code.
Modularity You can write as well as maintain the source codes of objects in an independent
manner. This provides modular approach to programming.
Classes
A class is a concept used in object oriented programming languages such as C++, PHP, and
JAVA etc. Apart from holding data, a class is also used to hold functions. An object is an instant
of a class. In case of variables, the type is the class whereas the variable is the object. The
keyword class is used to declare a class and it has the following format:
class CLASS_NAME
{
AccessSpecifier1:
Member-1;
AccessSpecifier2:
Member-2;
} OBJECT_NAMES;
Here, the valid identifier is CLASS_NAME and the names for objects are represented by
OBJECT_NAMES. The benefit of objects include information hiding, modularity, ease in
debugging and reuse of the code. The body contains the members that can be functions or data
declarations. The keywords for access specifiers are public, protected or private.
Inheritance: Inheritance is the phenomenon of deriving a new class from an old one.
Inheritance supports code reusability. Additional features can be added to a class by deriving a
class from it and then by adding new features to it. Class once written or tested need not be
rewritten or redefined. Inheritance is also referred to as specialization or derivation, as one class
is inherited or derived from the other. It is also termed as is-a relationship because every
object of the class being defined is also an object of the inherited class.
Wap to using polymorphism that will accept a geometrical figure and displays its shaped and
calculates its area?
an integer expression. The switch selection structure is a multiple selection structure, it selects
the action to perform from many different action states.
C++ provides three types of repetition structures also called looping structures or loops,
namely while, do/while, and for. A repetition structure allows the programmer to specify that a
program should repeat an action while some condition remains true.
posted by Carlos @ 1:30 PM
If Selection Structure
Programs use selection structures to choose among alternative courses of action. For example,
suppose the passing grade on exam is 60. The pseudo code statement
If students grade is greater than or equal to 60
Print Passed
Determines whether the condition "students" grade is greater than or equal to 60 is true or false.
If the condition is true, then "Passed" If the condition is false the print statement is ignored.
Example as follows
If single selection structure activity diagram
while structure containing an empty statement. Thus, the do/while with one statement is often
written as follows to avoid confusion;
do {
statement
} while (condition);
Example as follows
do/while repetition structure activity diagram
Every object in C++ has access to its own address through an important pointer
called this pointer. Thethis pointer is an implicit parameter to all member functions. Therefore,
inside a member function, this may be used to refer to the invoking object.
Friend functions do not have a this pointer, because friends are not members of a class. Only
member functions have a this pointer.
Let us try the following example to understand the concept of this pointer:
#include <iostream>
using namespace std;
class Box
{
public:
// Constructor definition
Box(double l=2.0, double b=2.0, double h=2.0)
{
cout <<"Constructor called." << endl;
length = l;
breadth = b;
height = h;
}
double Volume()
{
return length * breadth * height;
}
int compare(Box box)
{
return this->Volume() > box.Volume();
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
int main(void)
{
Box Box1(3.3, 1.2, 1.5);
Box Box2(8.5, 6.0, 2.0);
// Declare box1
// Declare box2
if(Box1.compare(Box2))
{
cout << "Box2 is smaller than Box1" <<endl;
}
else
{
cout << "Box2 is equal to or larger than Box1" <<endl;
}
return 0;
}
When the above code is compiled and executed, it produces the following result:
Constructor called.
Constructor called.
Box2 is equal to or larger than Box1
Call by Value
Argument is passed by a value
A compiler gets a copy of the variable, and
therefore any modification in sub-function,
won't affect the main function.
When an argument passed by value, the data
item copied to function.
This method is used in common
Call by Reference
Argument is passed by a reference
Here the compiler works on the actual copy
and therefore any modification in subfunction has an impact on the main function.
When an argument passed by reference then
address of that data item passed to the
function
This method is also used when we require
multiple values to be returned by the calling
function
1) Call by Value:-when we call a Function and if a function can accept the Arguments from the
Called Function, Then we must have to Supply some Arguments to the Function. So that the
Arguments those are passed to that function just contains the values from the variables but not an
Actual Address of the variable.
So that generally when we call a Function then we will just pass the variables or the Arguments
and we doesnt Pass the Address of Variables , So that the function will never effects on the
Values or on the variables. So Call by value is just the Concept in which you must have to
Remember that the values those are Passed to the Functions will never effect the Actual Values
those are Stored into the variables.
2) Call By Reference :-When a function is called by the reference then the values those are
passed in the calling functions are affected when they are passed by Reference Means they
change their value when they passed by the References. In the Call by Reference we pass the
Address of the variables whose Arguments are also Send. So that when we use the Reference
then, we pass the Address the Variables.
When we pass the Address of variables to the Arguments then a Function may effect on the
Variables. Means When a Function will Change the Values then the values of Variables gets
Automatically Changed. And When a Function performs Some Operation on the Passed values,
then this will also effect on the Actual Values.
Multiple Inheritances?
Multiple Inheritance in C++
Multiple Inheritance is a feature of C++ where a class can inherit from more than one classes.
The constructors of inherited classes are called in the same order in which they are inherited. For
example, in the following program, Bs constructor is called before As constructor.
#include<iostream>
using namespace std;
class A
{
public:
A() { cout << "A's constructor called" << endl; }
};
class B
{
public:
B() { cout << "B's constructor called" << endl; }
};
class C: public B, public A // Note the order
{
public:
C() { cout << "C's constructor called" << endl; }
};
int main()
{
C c;
return 0;
}
Output:
B's constructor called
A's constructor called
C's constructor called
The destructors are called in reverse order of constructors.
The diamond problem
The diamond problem occurs when two superclasses of a class have a common base class. For
example, in the following diagram, the TA class gets two copies of all attributes of Person class,
this causes ambiguities.
};
class TA : public Faculty, public Student {
public:
TA(int x):Student(x), Faculty(x) {
cout<<"TA::TA(int ) called"<< endl;
}
};
int main() {
TA ta1(30);
}
Output:
Person::Person() called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called
In the above program, constructor of Person is called once. One important thing to note in the
above output is, the default constructor of Person is called. When we use virtual keyword, the
default constructor of grandparent class is called by default even if the parent classes explicitly
call parameterized constructor.
How to call the parameterized constructor of the Person class? The constructor has to be
called in TA class. For example, see the following program.
#include<iostream>
using namespace std;
class Person {
public:
Person(int x) { cout << "Person::Person(int ) called" << endl; }
Person() { cout << "Person::Person() called" << endl; }
};
class Faculty : virtual public Person {
public:
Faculty(int x):Person(x) {
cout<<"Faculty::Faculty(int ) called"<< endl;
}
};
class Student : virtual public Person {
public:
Student(int x):Person(x) {
cout<<"Student::Student(int ) called"<< endl;
}
};
class TA : public Faculty, public Student {
public:
TA(int x):Student(x), Faculty(x), Person(x) {
cout<<"TA::TA(int ) called"<< endl;
}
};
int main() {
TA ta1(30);
}
Output:
Person::Person(int ) called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called
In general, it is not allowed to call the grandparents constructor directly, it has to be called
through parent class. It is allowed only when virtual keyword is used.
As an exercise, predict the output of following programs.
Question 1
#include<iostream>
using namespace std;
class A
{
int x;
public:
void setX(int i) {x = i;}
void print() { cout << x; }
};
class B: public A
{
public:
B() { setX(10); }
};
class C: public A
{
public:
C() { setX(20); }
};
class D: public B, public C {
};
int main()
{
D d;
d.print();
return 0;
}
Question 2
#include<iostream>
using namespace std;
class A
{
int x;
public:
A(int i) { x = i; }
void print() { cout << x; }
};
class B: virtual public A
{
public:
B():A(10) { }
};
class C: virtual public A
{
public:
C():A(10) { }
};
The major disadvantage of friend functions is that they require an extra line of code when you
want dynamic binding. To get the effect of a virtual friend, the friend function should call a
hidden (usually protected) virtual member function. This is called the Virtual Friend Function
Idiom. For example:
class Base {
public:
friend void f(Base& b);
...
protected:
virtual void do_f();
...
};
inline void f(Base& b)
{
b.do_f();
}
class Derived : public Base {
public:
...
protected:
virtual void do_f(); // "Override" the behavior of f(Base& b)
...
};
void userCode(Base& b)
{
f(b);
}
The statement f(b) in userCode(Base&) will invoke b.do_f(), which is virtual. This means
that Derived::do_f() will get control if b is actually a object of class Derived. Note
that Derivedoverrides the behavior of the protected virtual member function do_f(); it
does not have its own variation of the friend function, f(Base&).
In C++ all functions must be declared before they are used. This is accomplished using function
prototype. Prototypes enable complier to provide stronger type checking. When prototype is
used, the compiler can find and report any illegal type conversions between the type of
arguments used to call a function and the type definition of its parameters. It can also find the
difference between the no of arguments used to call a function and the number of parameters in
the function. Thus function prototypes help us trap bugs before they occur. In addition, they help
verify that your program is working correctly by not allowing functions to be called with
mismatched arguments.
A general function prototype looks like following:
return_type func_name(type param_name1, type param_name2, ,type param_nameN);
The type indicates data type. parameter names are optional in prototype.
Following program illustrates the value of function parameters:
void sqr_it(int *i);
int main()
{
int num;
num = 10;
sqr_it(num);
return 0;
}
//type mismatch
code of functions is same except data type, C++ provides a solution to this problem we can
create a single function for different data types which reduces code size which is via templates.
C++ programming code for function overloading
#include <iostream>
using namespace std;
/* Number of arguments are different */
void display(char []); // print the string passed as argument
void display(char [], char []);
int main()
{
char first[] = "C programming";
char second[] = "C++ programming";
display(first);
display(first, second);
return 0;
}
void display(char s[])
{
cout << s << endl;
}
void display(char s[], char t[])
{
cout << s << endl << t << endl;
}
Output of program:
C programming
C programming
C++ programming
What is the difference between opening a file with constructor function & opening a file with
open () function? When is one method preferred over other?
To show: How to use the write(), seekp(), tellp(), open() and close() member functions in
C++ programming
// using the seekp() and tellp() member functions
#include <iostream>
#include <fstream>
using namespace std;
void main(void)
{
// provide a full path if needed
char filename[ ] = "C:\\testfileio4.txt";
ofstream outputfile;
int locate;
// creating, opening and writing data to a file
outputfile.open(filename, ios::out);
// simple error handling for file creating/opening test if fail to open
if(outputfile.fail())
{
cout<<"Creating and opening "<<filename<<" file for writing\n";
cout<<"----------------------------------------------------\n";
cout<<"The "<<filename<<" file could not be created/opened!\n";
cout<<"Possible errors:\n";
cout<<"1. The file does not exist.\n";
cout<<"2. The path was not found.\n";
exit(1); // just exit
// 0-normal, non zero - some error
}
// if successful creating/opening the file
else
{
cout<<"The "<<filename<<" file was created and opened successfully!\n";
cout<<"\nDo some file writing....\n\n";
outputfile.write("Testing: Just simple example.", 29);
// tell the pointer position
locate = outputfile.tellp();
// seek the pointer position with offset
outputfile.seekp(locate-16);
// write for 7 length
outputfile.write(" rumble", 7);
// close the output file
outputfile.close();
// simple error handling for output files closing test if fail to close the file, do...
if(outputfile.fail())
{
cout<<"The "<<filename<<" file could not be closed!\n";
exit(1);
}
// if successful to close the file
else
cout<<"\nThe "<<filename<<" file was closed successfully!\n";
}
}
Output example:
The C:\testfileio4.txt file was created and opened successfully!
Do some file writing....
The C:\testfileio4.txt file was closed successfully!
Press any key to continue . . .
The testfileio4.txt file content is shown below.
Hope you already understand the concept of C++ Template which we already have discussed in
one of the chapters. The C++ STL (Standard Template Library) is a powerful set of C++
template classes to provides general-purpose templatized classes and functions that implement
many popular and commonly used algorithms and data structures like vectors, lists, queues, and
stacks.
At the core of the C++ Standard Template Library are following three well-structured
components:
Component
Description
Containers
Algorithms
Iterators
We will discuss about all the three C++ STL components in next chapter while discussing C++
Standard Library. For now, keep in mind that all the three components have a rich set of predefined functions which help us in doing complicated tasks in very easy fashion.
Let us take the following program demonstrates the vector container (a C++ Standard Template)
which is similar to an array with an exception that it automatically handles its own storage
requirements in case it grows:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
// create a vector to store int
vector<int> vec;
int i;
// display the original size of vec
cout << "vector size = " << vec.size() << endl;
// push 5 values into the vector
for(i = 0; i < 5; i++){
vec.push_back(i);
}
// display extended size of vec
cout << "extended vector size = " << vec.size() << endl;
// access 5 values from the vector
for(i = 0; i < 5; i++){
cout << "value of vec [" << i << "] = " << vec[i] << endl;
}
// use iterator to access the values
vector<int>::iterator v = vec.begin();
while( v != vec.end()) {
cout << "value of v = " << *v << endl;
v++;
}
return 0;
}
When the above code is compiled and executed, it produces the following result:
vector size = 0
extended vector size = 5
value of vec [0] = 0
value of vec [1] = 1
value of vec [2] = 2
value of vec [3] = 3
value of vec [4] = 4
value of v = 0
value of v = 1
value of v = 2
value of v = 3
value of v = 4
Here are following points to be noted related to various functions we used in the above example:
The push_back( ) member function inserts value at the end of the vector, expanding its
size as needed.
Function Template
Templates are the foundation of generic programming, which involves writing code in a way that
is independent of any particular type.
A template is a blueprint or formula for creating a generic class or a function. The library
containers like iterators and algorithms are examples of generic programming and have been
developed using template concept.
There is a single definition of each container, such as vector, but we can define many different
kinds of vectors for example, vector <int> or vector <string>.
You can use templates to define functions as well as classes, let us see how do they work:
Function Template:
The general form of a template function definition is shown here:
template <class type> ret-type func-name(parameter list)
{
// body of function
}
Here, type is a placeholder name for a data type used by the function. This name can be used
within the function definition.
The following is the example of a function template that returns the maximum of two values:
#include <iostream>
#include <string>
using namespace std;
template <typename T>
inline T const& Max (T const& a, T const& b)
{
return a < b ? b:a;
}
int main ()
{
int i = 39;
int j = 20;
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "Hello";
string s2 = "World";
cout << "Max(s1, s2): " << Max(s1, s2) << endl;
return 0;
}
If we compile and run above code, this would produce the following result:
Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World
Class Template:
Just as we can define function templates, we can also define class templates. The general form of
a generic class declaration is shown here:
template <class type> class class-name {
.
.
.
}
Here, type is the placeholder type name, which will be specified when a class is instantiated.
You can define more than one generic data type by using a comma-separated list.
Following is the example to define class Stack<> and implement generic methods to push and
pop the elements from the stack:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
using namespace std;
template <class T>
class Stack {
private:
vector<T> elems;
// elements
public:
void push(T const&); // push element
void pop();
// pop element
T top() const;
// return top element
bool empty() const{
// return true if empty.
return elems.empty();
}
};
template <class T>
void Stack<T>::push (T const& elem)
{
// append copy of passed element
elems.push_back(elem);
}
template <class T>
void Stack<T>::pop ()
{
if (elems.empty()) {
throw out_of_range("Stack<>::pop(): empty stack");
}
// remove last element
elems.pop_back();
}
template <class T>
T Stack<T>::top () const
{
if (elems.empty()) {
throw out_of_range("Stack<>::top(): empty stack");
}
// return copy of last element
return elems.back();
}
int main()
{
try {
Stack<int>
intStack; // stack of ints
Stack<string> stringStack; // stack of strings
// manipulate int stack
intStack.push(7);
cout << intStack.top() <<endl;
// manipulate string stack
stringStack.push("hello");
cout << stringStack.top() << std::endl;
stringStack.pop();
stringStack.pop();
}
catch (exception const& ex) {
cerr << "Exception: " << ex.what() <<endl;
return -1;
}
}
If we compile and run above code, this would produce the following result:
7
hello
Exception: Stack<>::pop(): empty stack
File Pointers and fopen
requested file, and it's important to check for this case before going off and using fopen's return
value as a file pointer. Every call to fopen will typically be followed with a test, like this:
ifp = fopen("input.dat", "r");
if(ifp == NULL)
{
printf("can't open file\n");
exit or return
}
If fopen returns a null pointer, and you store it in your file pointer variable and go off and try to
do I/O with it, your program will typically crash.
It's common to collapse the call to fopen and the assignment in with the test:
if((ifp = fopen("input.dat", "r")) == NULL)
{
printf("can't open file\n");
exit or return
}
You don't have to write these ``collapsed'' tests if you're not comfortable with them, but you'll
see them in other people's code, so you should be able to read them
When a class is derived form another derived class is called multilevel inheritance. In the
following figure the class A serves as a base class for the derived class B, which in turn serves as
a base class for the derived class C/ the class B is known as intermediate base class since it
provides a link for the inheritance between A and C. the chain ABC is known as inheritance
path.
class A{};
class B: public A{};
class C: public B{};
//Base Class
// B derived from A
// C derived from B
Example:
#include<iostream.h>
#include<conio.h>
class Student //Base Class
{
protected:
int rno;
public:
void get_number(int);
void put_number(void);
};
void Student::get_number(int a)
{ rno = a; }
void Student::put_number(void)
{
cout<<"Roll Number :"<<rno<<endl;
}
class Test: public Student //Intermediate Base Class
{
protected:
int sub1;
int sub2;
public:
void get_marks(int , int );
void put_marks(void);
};
void Test::get_marks(int x, int y)
{
sub1 = x;
sub2 = y;
}
void Test::put_marks(void)
{
cout<<"Subject-1 : "<<sub1<<endl;
cout<<"Subject-2 :"<<sub2<<endl;
}
class Result: public Test //Derived Class
{
int total;
public:
void display(void);
};
void Result::display(void)
{
total = sub1 + sub2;
put_number();
put_marks();
cout<<"Total : "<<total<<endl;
}
void main()
{
clrscr();
Result stud;
stud.get_number(111);
stud.get_marks(56,78);
stud.display();
getch();
}
example, in the following diagram, the TA class gets two copies of all attributes of Person class,
this causes ambiguities.
};
class TA : public Faculty, public Student {
public:
TA(int x):Student(x), Faculty(x) {
cout<<"TA::TA(int ) called"<< endl;
}
};
int main() {
TA ta1(30);
}
Person::Person(int ) called
Faculty::Faculty(int ) called
Person::Person(int ) called
Student::Student(int ) called
TA::TA(int ) called
In the above program, constructor of Person is called two times. Destructor of Person will
also be called two times when object ta1 is destructed. So object ta1 has two copies of all
members of Person, this causes ambiguities. The solution to this problem is virtual keyword.
We make the classes Faculty and Student as virtual base classes to avoid two copies of
Person in TA class. For example, consider the following program.
#include<iostream>
using namespace std;
class Person {
public:
Person(int x) { cout << "Person::Person(int ) called" << endl; }
Person() { cout << "Person::Person() called" << endl; }
};
class Faculty : virtual public Person {
public:
Faculty(int x):Person(x) {
cout<<"Faculty::Faculty(int ) called"<< endl;
}
};
class Student : virtual public Person {
public:
Student(int x):Person(x) {
cout<<"Student::Student(int ) called"<< endl;
}
};
class TA : public Faculty, public Student {
public:
TA(int x):Student(x), Faculty(x) {
cout<<"TA::TA(int ) called"<< endl;
}
};
int main() {
TA ta1(30);
}
Output:
Person::Person() called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called
In the above program, constructor of Person is called once. One important thing to note in the
above output is, the default constructor of Person is called. When we use virtual keyword, the
default constructor of grandparent class is called by default even if the parent classes explicitly
call parameterized constructor.
How to call the parameterized constructor of the Person class? The constructor has to be
called in TA class. For example, see the following program.
#include<iostream>
using namespace std;
class Person {
public:
Person(int x) { cout << "Person::Person(int ) called" << endl; }
Person() { cout << "Person::Person() called" << endl; }
};
class Faculty : virtual public Person {
public:
Faculty(int x):Person(x) {
cout<<"Faculty::Faculty(int ) called"<< endl;
}
};
class Student : virtual public Person {
public:
Student(int x):Person(x) {
cout<<"Student::Student(int ) called"<< endl;
}
};
class TA : public Faculty, public Student {
public:
TA(int x):Student(x), Faculty(x), Person(x) {
cout<<"TA::TA(int ) called"<< endl;
}
};
int main() {
TA ta1(30);
}
Output:
Person::Person(int ) called
Faculty::Faculty(int ) called
Student::Student(int ) called
TA::TA(int ) called
In general, it is not allowed to call the grandparents constructor directly, it has to be called
through parent class. It is allowed only when virtual keyword is used.
};
/* class C is multiple derived from its superclass A and B */
class C:public A, public B
{
};
int main()
{
C c;
c.show();
}
Ambiguous call:
For the above sample program, c.show() is ambiguous to get resolved among candidate
functionsB::show() and A::show()
Solution to ambiguous calls in multiple inheritance:
Use scope resolution operator to explicitly specify which base class's member function is to be
invoked.
Like, c.A::show();
What is a copy constructor & when it is invocked? Wap with a class Abc and one integer
data type member?overload the copy constructor and assignment operator for the class?
A copy constructor is a member function which initializes an object using another object of the
same class. A copy constructor has the following general function prototype:
ClassName (const ClassName &old_obj);
Following is a simple example of copy constructor.
#include<iostream>
using namespace std;
class Point
{
private:
int x, y;
public:
Point(int x1, int y1) { x = x1; y = y1; }
// Copy constructor
Point(const Point &p2) {x = p2.x; y = p2.y; }
int getX()
int getY()
{ return x; }
{ return y; }
};
int main()
{
Point p1(10, 15); // Normal constructor is called here
Point p2 = p1; // Copy constructor is called here
// Let us access values assigned by constructors
cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();
cout << "\np2.x = " << p2.getX() << ", p2.y = " << p2.getY();
return 0;
}
Output:
p1.x = 10, p1.y = 15
p2.x = 10, p2.y = 15
In this case, cNancy has already been created by the time the assignment is executed.
Consequently, the Cents assignment operator is called. The assignment operator must be
overloaded as a member function.
What happens if the object being copied into does not already exist? To understand what
happens in that case, we need to talk about the copy constructor.
The copy constructor
Consider the following example:
1
Because the second statement uses an equals symbol in it, you might expect that it calls the
assignment operator. However, it doesnt! It actually calls a special type of constructor called a
copy constructor. A copy constructor is a special constructor that initializes a new object from
an existing object.
The purpose of the copy constructor and the assignment operator are almost equivalent both
copy one object to another. However, the assignment operator copies to existing objects, and the
copy constructor copies to newly created objects.
The difference between the copy constructor and the assignment operator causes a lot of
confusion for new programmers, but its really not all that difficult. Summarizing:
If a new object has to be created before the copying can occur, the copy constructor is
used.
If a new object does not have to be created before the copying can occur, the assignment
operator is used.
There are three general cases where the copy constructor is called instead of the assignment
operator:
1. When instantiating one object and initializing it with values from another object (as in the
example above).
2. When passing an object by value.
3. When an object is returned from a function by value.
In each of these cases, a new variable needs to be created before the values can be copied
hence the use of the copy constructor.
Because the copy constructor and assignment operator essentially do the same job (they are just
called in different cases), the code needed to implement them is almost identical.
An overloaded assignment operator and copy constructor example
Now that you understand the difference between the copy constructor and assignment operator,
lets see how they are implemented. For simple classes such as our Cents class, it is very
straightforward.
Here is a simplified version of our Cents class:
1
class Cents
private:
4
5
int m_nCents;
public:
Cents(int nCents=0)
m_nCents = nCents;
9
10
}
};
First, lets add the copy constructor. Thinking about this logically, because it is a constructor, it
needs to be named Cents. Because it needs to copy an existing object, it needs to take a Cents
object as a parameter. And finally, because it is a constructor, it doesnt have a return type.
Putting all of these things together, here is our Cents class with a copy constructor.
1
class Cents
private:
4
5
int m_nCents;
public:
Cents(int nCents=0)
m_nCents = nCents;
10
11
// Copy constructor
12
13
14
m_nCents = cSource.m_nCents;
15
16
}
};
A copy constructor looks just like a normal constructor that takes a parameter of the class type.
However, there are two things which are worth explicitly mentioning. First, because our copy
constructor is a member of Cents, and our parameter is a Cents, we can directly access the
internal private data of our parameter. Second, the parameter MUST be passed by reference, and
not by value. Can you figure out why?
The answer lies above in the list that shows the cases where a copy constructor is called. A copy
constructor is called when a parameter is passed by value. If we pass our cSource parameter by
value, it would need to call the copy constructor to do so. But calling the copy constructor again
would mean the parameter is passed by value again, requiring another call to the copy
constructor. This would result in an infinite recursion (well, until the stack memory ran out and
the the program crashed). Fortunately, modern C++ compilers will produce an error if you try to
do this:
C:\\Test.cpp(431) : error C2652: 'Cents' : illegal copy constructor: first parameter must not be a
'Cents'
The first parameter in this case must be a reference to a Cents!
Now lets overload the assignment operator. Following the same logic, the prototype and
implementation are fairly straightforward:
1
class Cents
private:
4
5
int m_nCents;
public:
Cents(int nCents=0)
m_nCents = nCents;
10
11
// Copy constructor
12
13
14
m_nCents = cSource.m_nCents;
15
16
17
18
19
};
20
21
22
23
// do the copy
24
m_nCents = cSource.m_nCents;
25
26
27
return *this;
28
A couple of things to note here: First, the line that does the copying is exactly identical to the one
in the copy constructor. This is typical. In order to reduce duplicate code, the portion of the code
that does the actual copying could be moved to a private member function that the copy
constructor and overloaded assignment operator both call. Second, were returning *this so we
can chain multiple assigments together:
1
If you need a refresher on chaining, we cover that in the section on overloading the I/O
operators.
Finally, note that it is possible in C++ to do a self-assignment:
1
In these cases, the assignment operator doesnt need to do anything (and if the class uses
dynamic memory, it can be dangerous if it does). It is a good idea to do a check for selfassignment at the top of an overloaded assignment operator. Here is an example of how to do
that:
1
if (this == &cSource)
return *this;
7
8
// do the copy
m_nCents = cSource.m_nCents;
10
11
12
return *this;
13
Note that there is no need to check for self-assignment in a copy-constructor. This is because the
copy constructor is only called when new objects are being constructed, and there is no way to
assign a newly created object to itself in a way that calls to copy constructor.
Default memberwise copying
Just like other constructors, C++ will provide a default copy constructor if you do not provide
one yourself. However, unlike other operators, C++ will provide a default assignment
operator if you do not provide one yourself!
Because C++ does not know much about your class, the default copy constructor and default
assignment operators it provides are very simple. They use a copying method known as a
memberwise copy (also known as a shallow copy). We will talk more about shallow and deep
copying in the next lesson.
What are the c-type strings?How are they different from the string defined by the standard c++
string class?
C++ provides following two types of string representations:
The following declaration and initialization create a string consisting of the word "Hello". To
hold the null character at the end of the array, the size of the character array containing the string
is one more than the number of characters in the word "Hello."
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
If you follow the rule of array initialization, then you can write the above statement as follows:
char greeting[] = "Hello";
Following is the memory presentation of above defined string in C/C++:
Actually, you do not place the null character at the end of a string constant. The C++ compiler
automatically places the '\0' at the end of the string when it initializes the array. Let us try to print
above-mentioned string:
#include <iostream>
using namespace std;
int main ()
{
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
cout << "Greeting message: ";
cout << greeting << endl;
return 0;
}
When the above code is compiled and executed, it produces result something as follows:
Greeting message: Hello
C++ supports a wide range of functions that manipulate null-terminated strings:
strcpy(s1, s2);
Copies string s2 into string s1.
strcat(s1, s2);
Concatenates string s2 onto the end of string s1.
strlen(s1);
Returns the length of string s1.
strcmp(s1, s2);
Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater than 0 if s1>s2.
strchr(s1, ch);
Returns a pointer to the first occurrence of character ch in string s1.
strstr(s1, s2);
Returns a pointer to the first occurrence of string s2 in string s1.
When the above code is compiled and executed, it produces result something as follows:
strcpy( str3, str1) : Hello
strcat( str1, str2): HelloWorld
strlen(str1) : 10
The String Class in C++:
The standard C++ library provides a string class type that supports all the operations mentioned
above, additionally much more functionality. We will study this class in C++ Standard Library
but for now let us check following example:
At this point, you may not understand this example because so far we have not discussed Classes
and Objects. So can have a look and proceed until you have understanding on Object Oriented
Concepts.
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str1 = "Hello";
string str2 = "World";
string str3;
int len ;
// copy str1 into str3
str3 = str1;
cout << "str3 : " << str3 << endl;
// concatenates str1 and str2
str3 = str1 + str2;
cout << "str1 + str2 : " << str3 << endl;
// total lenghth of str3 after concatenation
len = str3.size();
cout << "str3.size() : " << len << endl;
return 0;
}
When the above code is compiled and executed, it produces result something as follows:
str3 : Hello
str1 + str2 : HelloWorld
str3.size() : 10
--notes
This page summarizes many of the things you may find it useful to know when working with
either C-strings or objects of the C++ string class.
The term string generally means an ordered sequence of characters, with a first character, a
second character, and so on, and in most programming languages such strings are enclosed in
either single or double quotes. In C++ the enclosing delimiters are double quotes. In this form
the string is referred to as a string literal and we often use such string literals in output
statements when we wish to display text on the screen for the benefit of our users. For example,
the usual first C++ program displays the string literal "Hello, world!" on the screen with the
following output statement:
cout << "Hello, world!" << endl;
However, without string variables about all we can do with strings is output string literals to the
screen, so we need to expand our ability to handle string data. When we talk about strings in
C++, we must be careful because the C language, with which C++ is meant to be backward
compatible, had one way of dealing with strings, while C++ has another, and to further
complicate matters there are many non-standard implementations of C++ strings. These should
gradually disappear as compiler vendors update their products to implement the string
component of the C++ Standard Library.
As a programmer, then, you must distinguish between the following three things:
1. An "ordinary" array of characters, which is just like any other array and has no special
properties that other arrays do not have.
2. A C-string, which consists of an array of characters terminated by the null character '\0',
and which therefore is different from an ordinary array of characters. There is a whole
library of functions for dealing with strings represented in this form. Its header file
is <cstring>. In some implementations this library may be automatically included when
you include other libraries such as the <iostream> library. Note that the null character
may very well not be the very last character in the C-string array, but it will be the first
character beyond the last character of the actual string data in in that array. For example
if you have a C-string storing "Hello" in a character array of size 10, then the letters of
the word "Hello" will be in positions with indices 0 to 4, there will be a null character at
index 5, and the locations with indices 6 to 9 will contain who-knows-what. In any case,
it's the null character at index 5 that makes this otherwise ordinary character array a Cstring.
3. A C++ string object, which is an instance of a "class" data type whose actual internal
representation you need not know or care about, as long as you know what you can and
can't do with variables (and constants) having this data type. There is a library of C++
string functions as well, available by including the <string> header file.
Both the C-string library functions and the C++ string library functions are available to C++
programs. But, don't forget that these are two *different* function libraries, and the functions of
the first library have a different notion of what a string is from the corresponding notion held by
the functions of the second library. There are two further complicating aspects to this situation:
first, though a function from one of the libraries may have a counterpart in the other library (i.e.,
a function in the other library designed to perform the same operation), the functions may not be
used in the same way, and may not even have the same name; second, because of backward
compatibility many functions from the C++ string library can be expected to work fine and do
the expected thing with C-style strings, but not the other way around.
The last statement above might seem to suggest we should use C++ strings and forget about Cstrings altogether, and it is certainly true that there is a wider variety of more intuitive operations
available for C++ strings. However, C-strings are more primitive, you may therefore find them
simpler to deal with (provided you remember a few simple rules, such as the fact that the null
character must always terminate such strings), and certainly if you read other, older programs
you will see lots of C-strings. So, use whichever you find more convenient, but if you choose
C++ strings and occasionally need to mix the two for some reason, be extra careful. Finally,
there are certain situations in which C-strings must be used.
To understand strings, you will have to spend some time studying sample programs. This study
must include the usual prediction of how you expect a program to behave for given input,
followed by a compile, link and run to test your prediction, as well as subsequent modification
and testing to investigate questions that will arise along the way. In addition to experimenting
with any supplied sample programs, you should be prepared to make up your own.
In the following examples we attempt to draw the distinction between the two string
representations and their associated operations. The list is not complete, but we do indicate how
to perform many of the more useful kinds of tasks with each kind of string. The left-hand column
contains examples relevant to C-strings and the right-hand column shows analogous examples in
the context of C++ strings.
C-strings (#include <cstring>)
C++ strings (#include <string>)
===============================
================================
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Declaring a C-string variable
Declaring a C++ string object
--------------------------------------------------------char str[10];
string str;
Initializing a C-string variable
Initializing a C++ string object
--------------------------------------------------------------char str1[11] = "Call home!";
string str1("Call home!");
char str2[] = "Send money!";
string str2 = "Send money!";
char str3[] = {'O', 'K', '\0'};
string str3("OK");
Last line above has same effect as:
char str3[] = "OK";
replaced with any open input stream, since file input with inFile, say, behaves in a manner
completely analogous to the corresponding behavior of cin. Analogously, in the output examples
given immediately above, cout could be replaced with any text output stream variable,
say outFile. In all cases, numCh is the maximum number of characters that will be read.
Input of a C-style string variable
Input of a C++ string object
------------------------------------------------------------cin >> s;
cin >> s;
cin.get(s, numCh+1);
cin.get(s, numCh+1,'\n');
cin.get(s, numCh+1,'x');
cin.getline(s, numCh+1);
getline(cin, s);
cin.getline(s, numCh+1, '\n');
cin.getline(s, numCh+1, 'x');
getline(cin, s, 'x');
A useful naming convention for C-strings is illustrated by examples like
typedef char String80[81];
typedef char String20[21];
in which the two numbers in each definition differ by 1 to allow for the null character '\0' to be
stored in the array of characters, but to *not* be considered as part of the string stored there. No
analog to this naming convention is necessary for C++ strings, since for all practical purposes,
each C++ string variable may contain a string value of virtually unlimited length.
What is a virtual function? How a virtual function is different from pure virtual function?
What is Virtual Functions in C++?
Explanation
Virtual Function is a function that is declared within a base class and redefined in the derived
class. Virtual functions are declared by preceding the class declaration with a keyword "virtual".
When a virtual function is declared C++ decides to execute a function based on the type of object
pointed by the base pointer and not on the type of pointer.
Example:
Result:
Base& rb = d;
// if Base::f() is virtual and Derived overrides it, Derived::f() will be called
rb.f();
A pure virtual function is a virtual function whose declaration ends in =0:
class Base {
// ...
virtual void f() = 0;
// ...
A pure virtual function makes the class it is defined for abstract. Abstract classes cannot be
instantiated. Derived classes need to override/implement all inherited pure virtual functions. If
they do not, they too will become abstract.
In C++, a class can define a pure virtual function that has an implementation. (What that's good
for is debatable.)
Abstract Class
Abstract Class is a class which contains atleast one Pure Virtual function in it. Abstract classes
are used to provide an Interface for its sub classes. Classes inheriting an Abstract Class must
provide definition to the pure virtual function, otherwise they will also become abstract class.
Characteristics of Abstract Class
1. Abstract class cannot be instantiated, but pointers and refrences of Abstract class type can
be created.
2. Abstract class can have normal functions and variables along with a pure virtual function.
3. Abstract classes are mainly used for Upcasting, so that its derived classes can use its
interface.
4. Classes inheriting an Abstract Class must implement all pure virtual functions, or else
they will become Abstract too.
Pure Virtual Functions
Pure virtual Functions are virtual functions with no definition. They start with virtual keyword
and ends with= 0. Here is the syntax for a pure virtual function,
virtual void f() = 0;
Example of Abstract Class
class Base
//Abstract base class
{
public:
virtual void show() = 0;
//Pure Virtual Function
};
class Derived:public Base
{
public:
void show()
{ cout << "Implementation of Virtual Function in Derived class"; }
};
int main()
{
Base obj;
//Compile Time Error
Base *b;
Derived d;
b = &d;
b->show();
}
Output : Implementation of Virtual Function in Derived class
In the above example Base class is abstract, with pure virtual show() function, hence we cannot
create object of base class.
Why can't we create Object of Abstract Class ?
When we create a pure virtual function in Abstract class, we reserve a slot for a function in the
VTABLE(studied in last topic), but doesn't put any address in that slot. Hence the VTABLE will
be incomplete.
As the VTABLE for Abstract class is incomplete, hence the compiler will not let the creation of
object for such class and will display an errror message whenever you try to do so.
Pure Virtual definitions
Pure Virtual functions can be given a small definition in the Abstract class, which you
want all the derived classes to have. Still you cannot create object of Abstract class.
Also, the Pure Virtual function must be defined outside the class definition. If you will
define it inside the class definition, complier will give an error. Inline pure virtual
definition is Illegal.
class Base
//Abstract base class
{
public:
virtual void show() = 0;
//Pure Virtual Function
};
#include<iostream.h>
#include<conio.h>
class base
{
int val1,val2;
public:
void get()
{
cout<<"Enter two values:";
cin>>val1>>val2;
}
friend float mean(base ob);
};
t.real=real+c.real;
t.img=img+c.img;
return t;
}
void show()
{
cout<<real<<"+i"<<img<<endl;
}
};
int main()
{
Complex c1(5,2),c2(7,3),c3;
c1.show();
c2.show();
c3=c1+c2;//need a default constructor to initialize the values for c3
c3.show();
getch();
}
What is an inline function? What it is used? In what situation inline function are not
recommended?
C++ inline function is powerful concept that is commonly used with classes. If a function is
inline, the compiler places a copy of the code of that function at each point where the function is
called at compile time.
Any change to an inline function could require all clients of the function to be recompiled
because compiler would need to replace all the code once again otherwise it will continue with
old functionality.
To inline a function, place the keyword inline before the function name and define the function
before any calls are made to the function. The compiler can ignore the inline qualifier in case
defined function is more than a line.
A function definition in a class definition is an inline function definition, even without the use of
the inlinespecifier.
Following is an example, which makes use of inline function to return max of two numbers:
#include <iostream>
using namespace std;
inline int Max(int x, int y)
{
Inline functions are faster because you don't need to push and pop things on/off the stack like
parameters and the return address; however, it does make your binary slightly larger.
Does it make a significant difference? Not noticeably enough on modern hardware for most. But
it can make a difference, which is enough for some people.
Marking something inline does not give you a guarantee that it will be inline. It's just a
suggestion to the compiler. Sometimes it's not possible such as when you have a virtual function,
or when there is recursion involved. And sometimes the compiler just chooses not to use it.
I could see a situation like this making a detectable difference:
inline int aplusb_pow2(int a, int b) {
return (a + b)*(a + b) ;
}
for(int a = 0; a < 900000; ++a)
for(int b = 0; b < 900000; ++b)
aplusb_pow2(a, b);
Inline function is the optimization technique used by the compilers. One can simply prepend
inline keyword to function prototype to make a function inline. Inline function instruct compiler
to insert complete body of the function wherever that function got used in code.
Advantages :-
Uses Guidelines :1) Always use inline function when your are sure it will give performance.
2) Always prefer inline function over macros.
3) Don't inline function with larger code size, one should always inline small code size function
to get performance.
4) If you want to inline a function in class, then prefer to use inkine keyword outside the class
with the function definition.
5) In c++, by default member function declared and defined within class get linlined. So no use
to specify for such cases.
6) Your function will not be inlined in case there is differences between exception handling
model. Like if caller function follows c++ structure handling and your inline function follows
structured exception handling.
7) For recursive function most of the compiler would not do in-lining but microsoft visual c++
compiler provides a special pragma for it i.e. pragma inline_recursion(on) and once can also
control its limit with pragma inline_depth.
8) If the function is virtual and its called virtually then it would not be inlined. So take care for
such cases, same hold true for the use of function pointers.
Container basics
Sequences
o User controls the order of elements.
o vector, list, deque
Associative containers
o The container controls the position of elements within it.
o Elements can be accessed using a key.
o set, multiset, map, multimap
Container concepts
There are three main container concepts:
Container concepts are not as important for generic programming as iterator concepts.
default constructor
copy constructor and assignment
o deep copy
swap
o a.swap(b) and swap(a, b)
o constant time
==, !=
o content-based equality: equal elements in same order
order comparisons
o lexicographic order: first inequal elements determine the order
vector<int> a, b;
// a = [1, 2, 3]
// b = [1, 3, 2]
assert(a < b);
begin(), end()
size(), empty(), max_size()
member types
o value_type
o reference (to the value type)
o const_reference
o iterator
o const_iterator
o difference_type (as with iterators)
o size_type (often unsigned type, usually size_t)
rbegin(), rend()
member types
o reverse_iterator
o const_reverse_iterator
Sequences
Common properties of all sequence containers:
constructors
o Fill constructor Container(n, val) fills container with n copies of val.
o Default fill constructor Container(n) fills container with n default constructed
values.
o Range constructor Container(i, j) fills container with the contents of the iterator
range [i,j).
assign
o fill assignment assign(n, val)
o
o
insert
o
o
o
insert(p, val) inserts val just before the position pointed by iterator p.
insert(p, n, val) inserts n copies.
insert(p, i, j) inserts the contents of range [i,j).
erase
vector
vector should be used by default as the (sequence) container:
v[i], at(i)
o v.at(i) checks that 0 <= i < v.size()
front(), back()
o return reference to the first and last element (not beyond last)
push_back(val)
o inserts val to the end
pop_back() removes
o removes the last element and returns it
resize
o change the number of elements in the vector
o resize(n) makes n the size; fills with default values if necessary
o resize(n, val) fills with val if necessary
capacity(), reserve(n) (see below)
Memory management
The elements are stored into a contiguous memory area on the heap.
o capacity() is the number of elements that fit into the area.
o size() is the actual number of elements. The remainder of the area is unused (raw
memory).
o reserve(n) increases the capacity to n without changing the size.
o The capacity is increased automatically if needed due to insertions.
Capacity increase may cause copying of all elements.
Limitations of vector
deque
deque stands for double-ended queue. It is much like vector.
Differences to vector
o Insertion and deletion in the beginning in (amortized) constant time.
push_front, pop_front
o Slower element access and iterators.
o No capacity() or reserve(n) but also less need for them.
o Insertions and deletions to the beginning and end do not invalidate pointers and
references to other elements.
But iterators may be invalidated.
o deque<int> d(5,1);
o deque<int>::iterator i = d.begin() + 2;
o int* p = &*i;
o d.push_front(2);
o int x = *p; // OK
Memory management
deque stores the elements something like this:
list
The third standard sequence container is list. The underlying data structure is a doubly-linked
list:
No random access.
Fast insertion and deletion anywhere.
Insertions and deletions do not invalidate iterators, pointers or references to other
elements.
push_front, pop_front
push_back, pop_back
splice
o c1.splice(i1, c2) removes all elements from list c2 and inserts them at
position i1 in list c1.
o c1.splice(i1, c2, i2) removes the element pointed by i2 from c2 and inserts it at
position i1 in list c1.
o c1.splice(i1, c2, i2, j2) removes the range [i2,j2) from c2 and inserts it at
position i1 in list c1.
o In the last two cases, c1 and c2 can be the same list.
o constant time
o Iterators, pointers and references keep pointing to the same element even if it is
moved to a different list.
template <class T, class A> // A is allocator
void catenate (list<T,A>& c1, list<T,A>& c2) {
c1.splice(c1.end(), c2);
}
list<int> c;
c.push_back(10);
c.push_back(20);
c.push_back(30);
list<int>::iterator i = c.begin();
assert(*i==10); // i points to the first element: 10
c.reverse();
assert(*i==10); // i continues to point to 10
// which is now to the last element
reverse(c.begin(), c.end());
assert(*i==30); // i still points to the last element
// which now contains 30
string
string class was designed before STL, but STL container properties were added to it later. It is
similar to vectors; the differences include:
vector<bool>
vector<bool> has some special properties.
Associative containers
The STL standard associative containers (set, multiset, map, multimap) allow access to elements
using a key:
struct my_less {
bool operator() (int a, int b) { return a < b; }
}
1.
2.
3.
4.
5.
6.
7.
8.
Common properties
In addition to properties of the Container concept, all associative containers have:
member types
o key_type
o key_compare
comparison operators
o key_comp() returns the key comparison operator
o value_comp() returns a comparison operator comparing elements not keys.
constructors
o Range constructor Container(i,j) fills container with the contents of the range [i,j).
o (All constructors accept a comparison object as an extra optional argument.)
insert
o insert(x)
o insert(i, x). Iterator i is a hint pointing to where the search for insertion position
should start.
Allows insert_iterator to operate on associative containers.
o range insert insert(i, j)
o For set and map insertions are not done if the key is already there.
erase
o erase(k) erases all elements with key k
o erase(i) erase element pointed to by i
o range erase erase(i,j)
searching
o find(k) returns iterator to the element with key k or end() if no such element
o count(k)
o lower_bound(k) find first element with key not less than k
o upper_bound(k) find first element with key greater than k
o equal_range(k) returns pair<iterator,iterator> representing the range of element
with key k
includes
set_intersection
set_union
set_difference
set_symmetric_difference
string str1("abcabcbac");
string str2("abcdabcd");
multiset<char> result;
set_intersection (mset1.begin(), mset1.end(),
mset2.begin(), mset2.end(),
inserter(result, result.begin()) );
multimap does not have operator[]. The helper function make_pair is useful:
multimap<string, string> children;
children.insert(make_pair("Jane","Ann"));
children.insert(make_pair("Jane","Bob"));
children.insert(make_pair("Bob","Xavier"));
// ...
o
Container adaptors
The container adaptors stack, queue, priority_queue are containers implemented on top of
another container.
They provide a limited set of container operations:
Stack
stack can be implemented on top of vector, deque or list.
Queue
queue can be implemented on top of deque or list.
Additional operations:
front()
back()
push(val)
pop()
Priority queue
priority_queue can be implemented on top of deque or vector.
range constructor
comparison object as an extra optional argument of constructors
push(val)
top() returns the largest element
pop() removes the largest element
There is no method for changing the priority of an element or removing an element that is not the
largest.
Hash tables
The standard has no containers using hashing, but they are a common extension. They are also
included in the Technical Report on C++ Standard Library Extensions, commonly known
as TR1, an extension of the standard library likely to be included in the next C++ standard:
unordered_set
unordered_multiset
unordered_map
unordered_multimap
default constructor
o default fill constructor Container(n)
equality comparisons
o containers's operator==
order comparisons
o container's operator<
o associative container with default order comparison
Pointers in containers
Pointers as container elements require special care. There two kinds of pointers:
struct animal {
virtual ~animal() {};
virtual void eat() =0;
// ...
}
struct baboon : animal {
// ...
}
struct lion : animal {
// ...
}
// ...
vector<animal*> zoo;
zoo.push_back(new baboon);
zoo.push_back(new lion);
zoo[1]->eat();
o Such pointers are problematic elements.
Containers take care that the destructor of an element is called, when the
element is erased (or the container is destroyed).
But an owning pointer's destructor does not do what it should: destroy the
pointed to object and release the memory.
The user of the container must ensure that the pointed to objects are
properly destroyed and freed. This is inconvenient and error-prone.
Achieving exception safety is difficult.
o Better to use a smart pointer, whose destructor does the right thing.
auto_ptr has the right kind of destructor, but unfortunately the wrong kind
of copy constructor and assignment.
Use boost::shared_ptr if possible.
o typedef boost::shared_ptr<animal> animal_ptr;
o vector<animal_ptr> zoo;
o
o
o
o
o
o
Exception safety
Exceptions are a common error reporting mechanism in C++. The elements of STL containers
are allowed to throw exceptions (except in destructors). In particular, if a copy of an element
fails and throws an exception during a container operation, one of the following guarantees are
provided:
Strong guarantee: The container operation is cancelled, and the container's state is as if
the operation was never called.
o Most list operations.
o All single element operations on lists and associative containers.
o push and pop operations on vector and deque.
Basic guarantee: There are no memory leaks, and the container is in a consistent s
...
int main ()
{
cout << "Value of PI :" << 3.14159 << endl;
return 0;
}
Function-Like Macros:
You can use #define to define a macro which will take argument as follows:
#include <iostream>
using namespace std;
#define MIN(a,b) (((a)<(b)) ? a : b)
int main ()
{
int i, j;
i = 100;
j = 30;
cout <<"The minimum is " << MIN(i, j) << endl;
return 0;
}
If we compile and run above code, this would produce the following result:
The minimum is 30
Conditional Compilation:
There are several directives, which can use to compile selectively portions of your program's source code. This
process is called conditional compilation.
The conditional preprocessor construct is much like the if selection structure. Consider the following preprocessor
code:
#ifndef NULL
#define NULL 0
#endif
You can compile a program for debugging purpose and can debugging turn on or off using a single macro as follows:
#ifdef DEBUG
cerr <<"Variable x = " << x << endl;
#endif
causes the cerr statement to be compiled in the program if the symbolic constant DEBUG has been defined before
directive #ifdef DEBUG. You can use #if 0 statment to comment out a portion of the program as follows:
#if 0
code prevented from compiling
#endif
Let us try the following example:
#include <iostream>
using namespace std;
#define DEBUG
#define MIN(a,b) (((a)<(b)) ? a : b)
int main ()
{
int i, j;
i = 100;
j = 30;
#ifdef DEBUG
cerr <<"Trace: Inside main function" << endl;
#endif
#if 0
/* This is commented part */
cout << MKSTR(HELLO C++) << endl;
#endif
cout <<"The minimum is " << MIN(i, j) << endl;
#ifdef DEBUG
cerr <<"Trace: Coming out of main function" << endl;
#endif
return 0;
}
If we compile and run above code, this would produce the following result:
Trace: Inside main function
The minimum is 30
Trace: Coming out of main function
x ## y
When CONCAT appears in the program, its arguments are concatenated and used to replace the macro. For
example, CONCAT(HELLO, C++) is replaced by "HELLO C++" in the program as follows.
#include <iostream>
using namespace std;
#define concat(a, b) a ## b
int main()
{
int xy = 100;
cout << concat(x, y);
return 0;
}
If we compile and run above code, this would produce the following result:
100
Let us see how it worked. It is simple to understand that the C++ preprocessor transforms:
cout << concat(x, y);
into the following line:
cout << xy;
Description
__LINE__
This contain the current line number of the program when it is being
compiled.
__FILE__
This contain the current file name of the program when it is being
compiled.
__DATE__
This contains a string of the form month/day/year that is the date of the
translation of the source file into object code.
__TIME__
()
<<
<<
<<
<<
"Value
"Value
"Value
"Value
of
of
of
of
__LINE__
__FILE__
__DATE__
__TIME__
:
:
:
:
"
"
"
"
<<
<<
<<
<<
__LINE__
__FILE__
__DATE__
__TIME__
<<
<<
<<
<<
endl;
endl;
endl;
endl;
return 0;
}
If we compile and run above code, this would produce the following result:
Value
Value
Value
Value
of
of
of
of
__LINE__
__FILE__
__DATE__
__TIME__
:
:
:
:
6
test.cpp
Feb 28 2011
18:52:48
// global variable
int main() {
char c = 'b';
//local variable
return 0;
}
void programming::output() {
cout << "Function defined outside the class.\n";
}
int main() {
programming x;
x.output();
return 0;
}
The above problem can be solved by general purpose pointer called void pointer.
Void pointer can be declared as follows:
void *v // defines a pointer of type void
The pointer defined in this manner do not have any type associated with them and can hold the address of any
type of variable.
Example:
void *v;
int *i;
int ivar;
char chvar;
float fvar;
v = &ivar; // valid
v = &chvar; //valid
v = &fvar; // valid
i = &ivar; //valid
i = &chvar; //invalid
i = &fvar; //invalid