Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
54 views

Class and Object

C++ classes define data types that bundle together data representation and methods. A class definition uses the class keyword followed by the class name and a list of members enclosed in curly braces. Class members can be declared as public, protected, or private to control access. Constructors initialize objects, destructors clean them up, and the this pointer references the current object from within member functions. Encapsulation through private members hides implementation details while public interfaces expose functionality to users.

Uploaded by

Fateha Hasan
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
54 views

Class and Object

C++ classes define data types that bundle together data representation and methods. A class definition uses the class keyword followed by the class name and a list of members enclosed in curly braces. Class members can be declared as public, protected, or private to control access. Constructors initialize objects, destructors clean them up, and the this pointer references the current object from within member functions. Encapsulation through private members hides implementation details while public interfaces expose functionality to users.

Uploaded by

Fateha Hasan
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 16

C++ Classes and Objects

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.

C++ Class Definitions or Declaration


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

Accessing member from Class or Access Control


There are 3 access specifiers for a class in C++. These access specifiers define how the members
of the class can be accessed. Of course, any member of a class is accessible within that

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.

An Source Code Example:

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 object-oriented programming, Encapsulation (also called information hiding) is the process


of keeping the details about how an object is implemented hidden away from users of the object.
Instead, users of the object access the object through a public interface. In this way, users are
able to use the object without having to understand how it is implemented.

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

2. Encapsulated classes help protect your data and prevent misuse

3. Encapsulated classes are easier to change

4. Encapsulated classes are easier to debug

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

Overlapping and delegating constructors

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.

Consider the following class:

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.

Applied to our example above:

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

Like constructors, destructors have specific naming rules:


1) The destructor must have the same name as the class, preceded by a tilde (~).
2) The destructor can’t take arguments.
3) The destructor has no return type.

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

The hidden “this” pointer

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;
}

As we would expect, this program produces the result: 2

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).

Summary of *this Pointer

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

Friend Class and Friend Functions

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:

/* This statement would make class ABC


a friend class of XYZ, this means that
ABC can access the private and protected
members of XYZ class.
*/

friend class ABC;


};
class ABC {
public:
void disp(XYZ obj){
cout<<obj.ch<<endl;
cout<<obj.num<<endl;
}
};
int main() {
ABC obj;
XYZ obj2;
obj.disp(obj2);
return 0;
}

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:

Friend Function Example


#include <iostream>
using namespace std;
class XYZ {
private:
int num=100;
char ch='Z';
public:
friend void disp(XYZ obj);
};
//Global Function
void disp(XYZ obj){
cout<<obj.num<<endl;
cout<<obj.ch<<endl;
}
int main() {
XYZ obj;
disp(obj);
return 0;
}

Output:

100

Summary of Friend function and class

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:

inline return-type function-name(parameters)


{
// function code
}

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.

Inline functions provide following advantages:

1. Function call overhead doesn’t occur.

2. It also saves the overhead of push/pop variables on the stack when function is called.

3. It also saves overhead of a return call from a function.


4. When you inline a function, you may enable compiler to perform context specific
optimization on the body of function. Such optimizations are not possible for normal
function calls. Other optimizations can be obtained by considering the flows of calling
context and the called context.

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.

Inline function disadvantages:

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.

The following program demonstrates the use of use of inline function.

#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

Inline function and classes

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
{
 
}

The following program demonstrates this concept:

#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

Enter first value: 45


Enter second value: 15
Addition of two numbers: 60
Difference of two numbers: 30
Product of two numbers: 675
Division of two numbers: 3

You might also like