Class and Object
Class and Object
A class is used to specify the form of an object and it combines data representation and methods
for manipulating that data into one neat package. The data and functions within a class are called
members of the class.
class(Inside any member function of that same class). Moving ahead to type of access specifiers,
they are:
Public - The members declared as Public are accessible from outside the Class through an object
of the class.
Protected - The members declared as Protected are accessible from outside the class BUT only
in a class derived from it.
Private - These members are only accessible from within the class. No outside Access is
allowed.
class MyClass
{
public:
int a;
protected:
int b;
private:
int c;
};
int main()
{
MyClass obj;
obj.a = 10; //Allowed
obj.b = 20; //Not Allowed, gives compiler error
obj.c = 30; //Not Allowed, gives compiler error
}
Why make member variables private
In the previous lesson, we mentioned that class member variables are typically made private. We
are learning about object-oriented programming often have a hard time understanding why need
to make a member private. To answer that question, let’s start with an analogy.
In modern life, we have access to many electronic devices. TV has a remote control that we can
use to turn the TV on/off. We drive a car to work. We take a picture on our digital camera. All
three of these things use a common pattern: They provide a simple interface for us to use (a
button, a steering wheel, etc…) to perform an action. However, how these devices actually
operate is hidden away from us. When we press the button on our remote control, we don’t need
to know what it’s doing to communicate with our TV. When we press the gas pedal on our car,
we don’t need to know how the combustion engine makes the wheels turn. When we take a
picture, we don’t need to know how the sensors gather light into a pixelated image. This
separation of interface and implementation is extremely useful because it allows us to use objects
without understanding how they work. This vastly reduces the complexity of using these objects,
and increases the number of objects we’re capable of interacting with.
For similar reasons, the separation of implementation and interface is useful in programming.
Encapsulation
In C++, we implement encapsulation via access specifies. Typically, all member variables of the
class are made private (hiding the implementation details), and most member functions are made
public (exposing an interface for the user). Although requiring users of the class to use the public
interface may seem more burdensome than providing public access to the member variables
directly, doing so actually provides a large number of useful benefits that help encourage class
re-usability and maintainability.
Benefits of Encapsulation
1. Encapsulated classes are easier to use and reduce the complexity of your programs
Constructors
A constructor is a special kind of class member function that is automatically called when an
object of that class is instantiated. Constructors are typically used to initialize member variables
of the class to appropriate default or user-provided values, or to do any setup steps necessary for
the class to be used (e.g. open a file or database).
Unlike normal member functions, constructors have specific rules for how they must be named:
1. Constructors should always have the same name as the class (with the same
capitalization)
2. Constructors have no return type (not even void)
Note that constructors are only intended to be used for initialization. You should not try to call a
constructor to re-initialize an existing object. While it may compile, the results will not be what
you intended (instead, the compiler will create a temporary object and then discard it).
Example of Constructor
#include <iostream>
using namespace std;
class construct
{
public:
int a, b;
// Default Constructor
construct()
{
a = 10;
b = 20;
}
};
int main()
{
// Default constructor called automatically
// when the object is created
construct c;
cout << "a: "<< c.a << endl << "b: "<< c.b;
return 1;
}
Output:
a: 10
b: 20
When you instantiate a new object, the objects constructor is called implicitly by the C++
compiler. It’s not uncommon to have a class with multiple constructors that have overlapping
functionality.
class AB
{
public:
AB()
{
// code to do A
}
AB(int value)
{
// code to do A
// code to do B
}
};
This class has two constructors: a default constructor, and a constructor that takes an integer.
Because the “code to do A” portion of the constructor is required by both constructors, the code
is duplicated in each constructor.
As we’ve (hopefully) learned by now, having duplicate code is something to be avoided as much
as possible, so let’s take a look at some ways to solve this.
The obvious solution would be to have the AB(int) constructor call the AB() constructor to do the
A portion.
class AB
{
public:
AB()
{
// code to do A
}
AB(int value)
{
AB(); // use the above constructor to do A
// code to do B
}
};
Delegating constructors
Constructors are now allowed to call other constructors. This process is called delegating
constructors (or constructor chaining).
To have one constructor call another, simply call the constructor in the member initializer list.
This is one case where calling another constructor directly is acceptable.
class AB
{
private:
public:
AB()
{
// code to do A
}
AB(int value): AB() /* use AB() default constructor to do A*/
{
// code to do B
}
};
This works exactly as we’d expect. Make sure we’re calling the constructor from the member
initializer list, not in the body of the constructor.
Destructors
A destructor is another special kind of class member function that is executed when an object of
that class is destroyed. Whereas constructors are designed to initialize a class, destructors are
designed to help clean up.
When an object goes out of scope normally, or a dynamically allocated object is explicitly
deleted using the delete keyword, the class destructor is called (if it exists) to do any necessary
clean up before the object is removed from memory. For simple classes (those that just initialize
the values of normal member variables), a destructor is not needed because C++ will
automatically clean up the memory for you.
However, if our class object is holding any resources (e.g. dynamic memory, or a file or database
handle), or if we need to do any kind of maintenance before the object is destroyed, the
destructor is the perfect place to do so, as it is typically the last thing to happen before the object
is destroyed.
Destructor naming
Example of Destructor
class A
{
A()
{
cout << "Constructor called";
}
~A()
{
cout << "Destructor called";
}
};
int main()
{
A obj1; // Constructor Called
int x=1
if(x)
{
A obj2; // Constructor Called
} // Destructor Called for obj2
} // Destructor called for obj1
One of the questions about classes that new object-oriented programmers often ask is, “When a
member function is called, how does C++ keep track of which object it was called on?” The
answer is that C++ utilizes a hidden pointer named “this”! Let’s take a look at “this” in more
detail.
The following is a simple class that holds an integer and provides a constructor and access
functions. Note that no destructor is needed because C++ can clean up integer member variables
for us.
class Simple
{
private:
int m_id;
public:
Simple(int id)
{
setID(id);
}
void setID(int id) { m_id = id; }
int getID() { return m_id; }
};
int main()
{
Simple simple(1);
simple.setID(2);
cout << simple.getID() << '\n';
return 0;
}
The this pointer is a hidden const pointer that holds the address of the object the member
function was called on.
*this always points to the object being operated on
New programmers are sometimes confused about how many *this pointers exist. Each member
function has a *this pointer parameter that is set to the address of the object being operated on.
Consider:
int main()
{
Simple A(1); // *this = &A inside the Simple constructor
Simple B(2); // *this = &B inside the Simple constructor
A.setID(3); // *this = &A inside member function setID
B.setID(4); // *this = &B inside member function setID
return 0;
}
Note that the *this pointer alternately holds the address of object A or B depending on whether
we’ve called a member function on object A or B.
Because *this is just a function parameter, it doesn’t add any memory usage to our class (just to
the member function call, since that parameter goes on the stack while the function is executing).
The “this” pointer is a hidden parameter implicitly added to any member function. Most of the
time, we will not need to access it directly, but ywe can if needed. It’s worth noting that “this” is
a const pointer -- we can change the value of the underlying object it points to, but we can’t
make it point to something else!
By having functions that would otherwise return void return *this instead, we can make those
functions chainable. This is most often used when overloading operators for our classes
As we know that a class cannot access the private members of other class. Similarly a class that
doesn’t inherit another class cannot access its protected members.
A friend class is a class that can access the private and protected members of a class in which it
is declared as friend. This is needed when we want to allow a particular class to access the
private and protected members of a class.
Function Class Example
In this example we have two classes XYZ and ABC. The XYZ class has two private data
members ch and num, this class declares ABC as friend class. This means that ABC can access
the private members of XYZ, the same has been demonstrated in the example where the function
disp() of ABC class accesses the private members num and ch. In this example we are passing
object as an argument to the function.
#include <iostream>
using namespace std;
class XYZ {
private:
char ch='A';
int num = 11;
public:
Output:
A
11
Friend Function
Similar to friend class, this function can access the private and protected members of another
class. A global function can also be declared as friend as shown in the example below:
Output:
100
A friend function or class is a function or class that can access the private members of another
class as though it were a member of that class. This allows the friend or class to work intimately
with the other class, without making the other class expose its private members (e.g. via access
functions).
Friending is uncommonly used when two or more classes need to work together in an intimate
way, or much more commonly, when defining overloading operators.
Note that making a specific member function a friend requires the full definition for the class of
the member function to have been seen first.
Inline Functions in C++
Inline function is one of the important feature of C++. So, let’s first understand why inline
functions are used and what is the purpose of inline function?
When the program executes the function call instruction the CPU stores the memory address of
the instruction following the function call, copies the arguments of the function on the stack and
finally transfers control to the specified function. The CPU then executes the function code,
stores the function return value in a predefined memory location/register and returns control to
the calling function. This can become overhead if the execution time of function is less than the
switching time from the caller function to called function (callee). For functions that are large
and/or perform complex tasks, the overhead of the function call is usually insignificant compared
to the amount of time the function takes to run. However, for small, commonly-used functions,
the time needed to make the function call is often a lot more than the time needed to actually
execute the function’s code. This overhead occurs for small functions because execution time of
small function is less than the switching time.
C++ provides an inline functions to reduce the function call overhead. Inline function is a
function that is expanded in line when it is called. When the inline function is called whole code
of the inline function gets inserted or substituted at the point of inline function call. This
substitution is performed by the C++ compiler at compile time. Inline function may increase
efficiency if it is small.
The syntax for defining the function inline is:
Remember, inlining is only a request to the compiler, not a command. Compiler can ignore the
request for inlining. Compiler may not perform inlining in such circumstances like:
1) If a function contains a loop. (for, while, do-while)
2) If a function contains static variables.
3) If a function is recursive.
4) If a function return type is other than void, and the return statement doesn’t exist in function
body.
5) If a function contains switch or goto statement.
2. It also saves the overhead of push/pop variables on the stack when function is called.
5. Inline function may be useful (if it is small) for embedded systems because inline can
yield less code than the function call preamble and return.
1) The added variables from the inlined function consumes additional registers, After in-lining
function if variables number which are going to use register increases than they may create
overhead on register variable resource utilization. This means that when inline function body is
substituted at the point of function call, total number of variables used by the function also gets
inserted. So the number of register going to be used for the variables will also get increased. So if
after function inlining variable numbers increase drastically then it would surely cause an
overhead on register utilization.
2) If you use too many inline functions then the size of the binary executable file will be large,
because of the duplication of same code.
3) Too much inlining can also reduce your instruction cache hit rate, thus reducing the speed of
instruction fetch from that of cache memory to that of primary memory.
4) Inline function may increase compile time overhead if someone changes the code inside the
inline function then all the calling location has to be recompiled because compiler would require
to replace all the code once again to reflect the changes, otherwise it will continue with old
functionality.
5) Inline functions may not be useful for many embedded systems. Because in embedded
systems code size is more important than speed.
6) Inline functions might cause thrashing because inlining might increase size of the binary
executable file. Thrashing in memory causes performance of computer to degrade.
#include <iostream>
using namespace std;
inline int cube(int s)
{
return s*s*s;
}
int main()
{
cout << "The cube of 3 is: " << cube(3) << "\n";
return 0;
}
//Output: The cube of 3 is: 27
It is also possible to define the inline function inside the class. In fact, all the functions defined
inside the class are implicitly inline. Thus, all the restrictions of inline functions are also applied
here. If you need to explicitly declare inline function in the class then just declare the function
inside the class and define it outside the class using inline keyword.
For example:
class S
{
public:
inline int square(int s) // redundant use of inline
{
// this function is automatically inline
// function body
}
};
The above style is considered as a bad programming style. The best programming style is to just
write the prototype of function inside the class and specify it as an inline in the function
definition.
class S
{
public:
int square(int s); // declare the function
};
inline int S::square(int s) // use inline prefix
{
}
#include <iostream>
using namespace std;
class operation
{
private:
int a,b,add,sub,mul;
float div;
public:
void get();
void sum();
void difference();
void product();
void division();
};
inline void operation :: get()
{
cout << "Enter first value:";
cin >> a;
cout << "Enter second value:";
cin >> b;
}
inline void operation :: sum()
{
add = a+b;
cout << "Addition of two numbers: " << a+b << "\n";
}
inline void operation :: difference()
{
sub = a-b;
cout << "Difference of two numbers: " << a-b << "\n";
}
inline void operation :: product()
{
mul = a*b;
cout << "Product of two numbers: " << a*b << "\n";
}
inline void operation ::division()
{
div=a/b;
cout<<"Division of two numbers: "<<a/b<<"\n" ;
}
int main()
{
cout << "Program using inline function\n";
operation s;
s.get();
s.sum();
s.difference();
s.product();
s.division();
return 0;
}
Output