NIT KURUKSHETRA
C++ ASSIGNMENT
Name:-Nishant Sharma
Roll No.:-11912090
Section:-CS-B(6)
TOPIC-1:INLINE FUNCTIONS:
In C++ you can create short fxns that are not actually called rather their
code is expanded in line at each point where the fxn is called at compile
time.
To inline a fxn, place the keyword inline before the fxn name and define
the fxn before any calls are made to the fxn. The compiler can ignore the
inline qualifier in case defined fxn is more than a line.
A fxn definition in a class definition is an inline function definition(if
possible), even without the use of the inline specifier.
Example:-
#include <iostream>
using namespace std;
inline int Max(int x, int y)
{
return (x > y)? x : y;
}
int main()
{
cout << "Max (20,10): " << Max(20,10) << endl;
cout << "Max (99,88): " << Max(0,200) << endl;
return 0;
}
Output:-
Max (20,10): 20
Max (99,88): 99
The reason that inline fxn are an important to C++ is that they allow you
to create very efficient code. As you know each time a fxn is called, a
significant amount of overhead is generated while the calling & its return
mechanism typically argument are pushed onto the steps & various
registers are saved when a fxn is called & then restored when the fxn
returns, the trouble is that these instructions take time however when a
fxn expanded inline none of the operations occurs. Expanding fxn call
inline can produce faster runtime. Inline is actually just a request not a
command to the compiler. The compiler can choose to ignore it. It is
common for a compiler not to inline a recursive fxn.
If a fxn can’t be inline it is simply called as normal function.
TOPIC-2:FRIEND FUNCTIONS & FRIEND CLASSES:
FRIEND FUNCTIONS:-
It is possible to grant a non-member fxn access by using a friend keyword.
A friend fxn has access to all private & protected members of the class for
which it is a friend.
To declare a friend fxn includes its prototype within the class preceding
with the keyword friend.
Example:-
#include <iostream>
using namespace std;
class myclass
{
int a, b;
public:
friend int sum(myclass x);
void set_ab(int i, int j);
};
void myclass::set_ab(int i, int j)
{
a = i;
b = j;
}
// Note:- sum() is not a member function of any class.
int sum(myclass x)
{
/* Because sum() is a friend of myclass, it can directly access a and b. */
return x.a + x.b;
}
int main()
{
myclass n;
n.set_ab(3, 4);
cout << sum(n)<<endl;
return 0;
}
Output:-
FRIEND CLASSES:-
It is possible for one class to be a friend of another class, when this is the
case, the friend class & all of its member fxns have access to the private
members define within other class.
Example:-
#include <iostream>
using namespace std;
class TwoValues
{
int a;
int b;
public:
TwoValues(int i, int j) { a = i; b = j; }
friend class Min;
};
class Min {
public:
int min(TwoValues x);
};
int Min::min(TwoValues x)
{
return x.a < x.b ? x.a : x.b;
}
int main()
{
TwoValues ob(10, 20);
Min m;
cout << m.min(ob)<<endl;
return 0;
}
Output:-
In this example, class Min has access to the private variables a and b
declared within the TwoValues class.
When one class is friend of another class, it has access to names defined
within the other class, it doesn’t inherit the other class, the members of
the first class don’t become members of the friend class.
Friend classes are seldom used. They are supported to allow certain
special case situations to be handled.
TOPIC-3:STATIC DATA MEMBERS & STATIC MEMBER
FUNCTIONS:
STATIC DATA MEMBERS:-
When you proceed a member variables declaration with static, you are
telling the compiler that only one copy of that variable will exist & all the
objects of the class will share that variable, unlike regular data members
individuals copies of a static member variable is not made for each object.
No matter how many objects of a class are created only one copy of a
static data member will exist. Thus all objects of that class use that same
variable.
All static variables are initialized to zero before the first object is created.
When you declare a static data member within a class you are not
defining it thus you have to provide a global definition for it outside the
class. This is done by redeclaring the static variable using the scope
resolution operator to identify the class to which it belongs this will
create the storage for the variable to be allocated.
Example:-
#include <iostream>
using namespace std;
class shared
{
static int a;
int b;
public:
void set(int i, int j)
{
a=i; b=j;
}
void show();
};
int shared::a; // define a
void shared::show()
{
cout << "This is static a: " << a;
cout << "\nThis is non-static b: " << b;
cout << "\n";
}
int main()
{
shared x, y;
x.set(1, 1); //set a to 1
x.show();
y.set(2, 2); //change a to 2
y.show();
x.show(); //here a has been changed for both x & y because a is shared
by both objects.
return 0;
}
Output:-
STATIC MEMBER FUNCTIONS:-
Member functions may also be declared as static.
There are several restrictions on static member functions:-
They may only refer to other static member of the class.
Static member doesn’t have this pointer.
There can’t be static & non static version of the same function.
A static member function may not be virtual.
They can’t be declared as const or volatile.
Example:-
#include <iostream>
using namespace std;
class static_type
{
static int i;
public:
static void init(int x)
{
i = x;
}
void show()
{
cout << i;
}
};
int static_type::i; // define i
int main()
{
// init static data before object creation
static_type::init(100);
static_type x;
x.show(); // displays 100
cout<<endl;
return 0;
}
Output:-
TOPIC-4:INHERITANCE:
The capability of a class to derive properties & characteristics from
another class is called inheritance.
The class that inherits properties from another class is called Derived
Class. The class whose properties are inherited by sub class is called Base
Class.
When a class inherits another, the members of the base class become
members of the derived class. The general form that is used by class
inheritance is:
class deived_class_name:access-specifier base_class_name{
//body of class
};
The access status of the base-class members inside the derived class is
determined by access-specifier. The base-class access specifier must be
either public, private, or protected. If no access specifier is present, the
access specifier is private by default if the derived class is a class.
There are types of inheritance on the basis of access-specifier as
mentioned above:
Public Inheritance:- If we derive a class from a public base class. Then
the public member of the base class will become public in the derived
class and protected members of the base class will become protected
in derived class. A base class's private members are never accessible
directly from a derived class, but can be accessed through calls to the
public and protected members of the base class.
Protected Inheritance:- When deriving from a protected base class,
public and protected members of the base class become protected
members of the derived class.
Private Inheritance:- When deriving from a private base class, public
and protected members of the base class become private members of
the derived class.
Multiple Inheritance:-In this inheritance a class can inherit from more
than one classes. Syntax for this is:
class derived-class: access baseA, access baseB....{
//body of class
};
Where access is one of public, protected, or private and would be given
for every base class and they will be separated by comma.
Multilevel Inheritance:- In this type of inheritance, a derived class is
created from another derived class.
Hierarchical Inheritance:- In this type of inheritance, more than one sub
class is inherited from a single base class. i.e. more than one derived class
is created from a single base class.
Granting access:-
When a base class is inherited as private, all public and protected
members of that class become private members of the derived class.
To restore one or more inherited members to their original access
specification i.e. to grant certain public members of the base class public
status in the derived class even though the base class is inherited as
private we can use two ways:-
1.We can use using statement.
Syntax:-using base-class::member;//declared in derived class.
2. To employ an access declaration within the derived class. Access
declarations are currently supported by Standard C++, but they are
deprecated. This means that they should not be used for new code.
General form for access declaration is :
base-class::member;
Example:-
#include <iostream>
using namespace std;
class base {
int i; // private to base
public:
int j, k;
void seti(int x) { i = x; }
int geti() { return i; }
};
// Inherit base as private.
class derived: private base {
public:
/* The next three statements override
base's inheritance as private and restore j,
seti(), and geti() to public access. */
using base::j; // make j public again - but not k
using base::seti; // make seti() public
using base::geti; // make geti() public
// base::i; // illegal, you cannot elevate access
int a; // public
};
int main()
{
derived ob;
//ob.i = 10; // illegal because i is private in derived
ob.j = 20; // legal because j is made public in derived
//ob.k = 30; // illegal because k is private in derived
ob.a = 40; // legal because a is public in derived
ob.seti(10);
cout << ob.geti() << " " << ob.j << " " << ob.a<<endl;
return 0;
}
Output:-
Let’s an example of a derived class with two base classes and these two
base classes have one common base class. An ambiguity can arise in this
type of inheritance.
#include<iostream>
using namespace std;
class base
{
public:
int i;
};
class derived1:public base
{
public:
int j;
};
class derived2:public base
{
public:
int k;
};
class derived3:public derived1,public derived2
{
public:
int sum;
};
int main()
{
derived3 ob;
ob.i=5;//this will be a error as i is a non-static member and is found in
multiple base-class sub-objects of type base.//ambiguity will arise here
i.e. which i is referred here.
ob.j=10;
ob.k=15;
ob.sum=ob.i+ob.j+ob.k;//error.
return 0;
}
There are two ways to avoid this ambiguity:
1. Use scope resolution operator.
2. Use virtual base class.
Avoiding ambiguity using scope resolution operator:
#include <iostream>
using namespace std;
class base {
public:
int i;
};
// derived1 inherits base.
class derived1 : public base {
public:
int j;
};
// derived2 inherits base.
class derived2 : public base {
public:
int k;
};
/* derived3 inherits both derived1 and derived2.
This means that there are two copies of base
in derived3! */
class derived3 : public derived1, public derived2 {
public:
int sum;
};
int main()
{
derived3 ob;
ob.derived1::i = 10; // scope resolved, use derived1's i
ob.j = 20;
ob.k = 30;
// scope resolved
ob.sum = ob.derived1::i + ob.j + ob.k;
// also resolved here
cout << ob.derived1::i << " ";
cout << ob.j << " " << ob.k << " ";
cout << ob.sum;
return 0;
}
Output:-
Avoiding ambiguity using virtual base class:
#include<iostream>
using namespace std;
class base
{
public:
int i;
};
class derived1:virtual public base
{
public:
int j;
};
class derived2:virtual public base
{
public:
int k;
};
class derived3:public derived1,public derived2
{
public:
int sum;
void showall()
{
cout<<"i="<<i<<endl<<"j="<<j<<endl<<"k="<<k<<endl;
}
};
int main()
{
derived3 ob;
ob.i=5;//this is unambiguous as virtual base class has been used thus no
two copies of i are there (**imp)but also in derived1 and derived2 base is
still present in object of either type.
ob.j=10;
ob.k=15;
ob.sum=ob.i+ob.j+ob.k;
ob.showall();
cout<<"sum of i.j & k is:"<<endl<<ob.sum<<endl;
return 0;
}
Output:-
TOPIC-5:VIRTUAL FUNCTIONS:
A virtual function is a member function within the base class that we
redefine in a derived class. It is declared using the virtual keyword. When
a class containing virtual function is inherited, the derived class redefines
the virtual function to suit its own needs.
They are always defined in a base class and overridden in derived class
but it is not mandatory to override in the derived class.
The virtual functions must be declared in the public section of the class.
They cannot be static or friend function also cannot be the virtual
function of another class.
The virtual functions should be accessed using a pointer to achieve run
time polymorphism.
When a base pointer points to a derived object that contains a virtual
function, C++ determines which version of that function to call based
upon the type of object pointed to by the pointer. And this determination
is made at run time. Thus, when different objects are pointed to, different
versions of the virtual function are executed.
Example:-
#include <iostream>
using namespace std;
class base {
public:
virtual void vfunc() {
cout << "This is base's vfunc().\n";
}
};
class derived1 : public base {
public:
void vfunc() {//function overriding
cout << "This is derived1's vfunc().\n";
}
};
class derived2 : public base {
public:
void vfunc() {//function overriding
cout << "This is derived2's vfunc().\n";
}
};
int main()
{
base *p, b;
derived1 d1;
derived2 d2;
// point to base
p = &b;
p->vfunc(); // access base's vfunc()
// point to derived1
p = &d1;
p->vfunc(); // access derived1's vfunc()
// point to derived2
p = &d2;
p->vfunc(); // access derived2's vfunc()
return 0;
}
Output:-
When a virtual function is inherited, its virtual nature is also inherited.
This means that when a derived class that has inherited a virtual function
is itself used as a base class for another derived class, the virtual function
can still be overridden. Put differently, no matter how many times a
virtual function is inherited, it remains virtual.
When a function is declared as virtual by a base class, it may be
overridden by a derived class. However, the function does not have to be
overridden. When a derived class fails to override a virtual function, then
when an object of that derived class accesses that function, the function
defined by the base class is used. This implies that virtual functions are
hierarchical.
Pure virtual function:-
A pure virtual function in C++ is a virtual function for which we don’t have
an implementation, we only declare it. A pure virtual function is declared
by assigning 0 in the declaration.
Example:-
virtual void sound() = 0;
Here sound() is a pure virtual function.
Abstract class:-
A class that contains at least one pure virtual function is said to be
abstract. Because an abstract class contains one or more functions for
which there is no definition (i.e. pure virtual function), no objects of an
abstract class may be created. You cannot create objects of an abstract
class, you can create pointers and references to an abstract class. This
allows abstract classes to support run-time polymorphism.
One of the most powerful and flexible ways to implement the "one
interface, multiple methods" approach is to use virtual functions, abstract
classes, and run-time polymorphism. Using these features, you create a
class hierarchy that moves from general to specific (base to derived).
Example that illustrates the value of the "one interface, multiple
methods" philosophy:-
#include<iostream>
using namespace std;
class convert
{
protected:
double val1;//initial value.
double val2;//converted value.
public:
convert(double i)
{
val1=i;
}
virtual void compute()=0;//pure virtual function.
double getinit_val()
{
return val1;
}
double getcon_val()
{
return val2;
}
};
class derived_l_to_g:public convert//litres to gallons.
{
public:
derived_l_to_g(double i):convert(i){}
void compute()
{
val2=val1/3.7854;
}
};
class derived_f_to_c:public convert//farenheit to celsius.
{
public:
derived_f_to_c(double i):convert(i){}
void compute()
{
val2=(val1-32)/1.8;
}
};
int main()
{
convert *p;
derived_l_to_g ltg(5);
derived_f_to_c ftc(50);
p=<g;
p->compute();
cout<<p->getinit_val()<<"_litres="<<p-
>getcon_val()<<"_gallons"<<endl<<endl;
p=&ftc;
p->compute();
cout<<p->getinit_val()<<"℉="<<p->getcon_val()<<"℃"<<endl;
return 0;
}
Output:-
Binding:- Binding for functions means that matching the call with the right
function definition by the compiler. It takes place either at compile time
or at runtime.
It is of two types:
1. Early Binding:- Early binding refers to events that occur at compile
time. Early binding occurs when all information needed to call a
function is known at compile time. (Early binding means that an object
and a function call are bound during compilation.) Examples of early
binding include normal function calls, overloaded function calls, and
overloaded operators. The main advantage to early binding is
efficiency. Because all information necessary to call a function is
determined at compile time, these types of function calls are very fast.
2. Late Binding:- Late binding refers to function calls that are not resolved
until run time. Virtual functions are used to achieve late binding. As
you know, when access is via a base pointer or reference, the virtual
function actually called is determined by the type of object pointed to
by the pointer. Because in most cases this cannot be determined at
compile time, the object and the function are not linked until run time.
The main advantage to late binding is flexibility. Unlike early binding,
late binding allows you to create programs that can respond to events
occurring while the program executes. As function call is not resolved
until run time, late binding can make slower execution times.
THANK YOU