OOPs | Object Oriented Design

Object oriented design started right from the moment computers were invented. Programming was there, and programming approaches came into the picture. Programming is basically giving certain instructions to the computer.

At the beginning of the computing era, programming was usually limited to machine language programming. Machine language means those sets of instructions that are specific to a particular machine or processor, which are in the form of 0’s and 1’s. These are sequences of bits (0100110…). But it’s quite difficult to write a program or develop software in machine language.

It’s actually impossible to develop software used in today’s scenarios with sequences of bits. This was the main reason programmers moved on to the next generation of programming languages, developing assembly languages, which were near enough to the English language to easily understand. These assembly languages were used in microprocessors. With the invention of the microprocessor, assembly languages flourished and ruled over the industry, but it was not enough. Again, programmers came up with something new, i.e., structured and procedural programming.

Structured Programming –
The basic principle of the structured programming approach is to divide a program into functions and modules. The use of modules and functions makes the program more understandable and readable. It helps to write cleaner code and to maintain control over the functions and modules. This approach gives importance to functions rather than data. It focuses on the development of large software applications, for example, C was used for modern operating system development. The programming languages: PASCAL (introduced by Niklaus Wirth) and C (introduced by Dennis Ritchie) follow this approach.

Procedural Programming Approach –
This approach is also known as the top-down approach. In this approach, a program is divided into functions that perform specific tasks. This approach is mainly used for medium-sized applications. Data is global, and all the functions can access global data. The basic drawback of the procedural programming approach is that data is not secured because data is global and can be accessed by any function. Program control flow is achieved through function calls and goto statements. The programming languages: FORTRAN (developed by IBM) and COBOL (developed by Dr Grace Murray Hopper) follow this approach.

These programming constructs were developed in the late 1970s and 1980s. There were still some issues with these languages, though they fulfilled the criteria of well-structured programs, software etc. They were not as structured as the requirements were at that time. They seem to be over-generalised and don’t correlate with real-time applications.

To solve such kinds of problems, OOP, an object-oriented approach was developed as a solution.

 

The Object-Oriented Programming (OOP) Approach –
The OOP concept was basically designed to overcome the drawback of the above programming methodologies, which were not so close to real-world applications. The demand was increased, but still, conventional methods were used. With the emergence of OOP, all conventional methods were thrown out the window. OOP methodology not only solved the modern-era problem, but also, it brought a revolution in the programming methodology field.

Object-oriented programming (OOP) is nothing but that which allows the writing of programs with the help of certain classes and real-time objects. We can say that this approach is very close to the real-world and its applications because the state and behaviour of these classes and objects are almost the same as real-world objects.

Let’s go deeper into the general concepts of OOP, which are given below:

What Are Class & Object?
It is the basic concept of OOP; an extended concept of the structure used in C. It is an abstract and user-defined data type. It consists of several variables and functions. The primary purpose of the class is to store data and information. The members of a class define the behaviour of the class. A class is the blueprint of the object, but also, we can say the implementation of the class is the object. The class is not visible to the world, but the object is.

Class car 
{ 
	int car_id; 
	char colour[4]; 
	float engine_no; 
	double distance; 

	void distance_travelled(); 
	float petrol_used(); 
	char music_player(); 
	void display(); 
} 

  Here, the class car has properties car_id, colour, engine_no and distance. It resembles the real-world car that has the same specifications, which can be declared public (visible to everyone outside the class), protected and private (visible to none). Also, there are some methods such as distance_travelled(), petrol_used(), music_player() and display(). In the code given below, the car is a class and c1 is an object of the car.

#include <iostream> 
using namespace std; 

class car { 
public: 
	int car_id; 
	double distance; 

	void distance_travelled(); 

	void display(int a, int b) 
	{ 
		cout << "car id is=\t" << a << "\ndistance travelled =\t" << b + 5; 
	} 
}; 

int main() 
{ 
	car c1; // Declare c1 of type car 
	c1.car_id = 321; 
	c1.distance = 12; 
	c1.display(321, 12); 

	return 0; 
} 

  Data Abstraction –
Abstraction refers to the act of representing important and special features without including the background details or explanation about that feature. Data abstraction simplifies database design.

 

  1. Physical Level:
    It describes how the records are stored, which are often hidden from the user. It can be described with the phrase, “block of storage.”
  2. Logical Level:
    It describes data stored in the database and the relationships between the data. The programmers generally work at this level as they are aware of the functions needed to maintain the relationships between the data.
  3. View Level:
    Application programs hide details of data types and information for security purposes. This level is generally implemented with the help of GUI, and details that are meant for the user are shown.

Encapsulation –
Encapsulation is one of the fundamental concepts in object-oriented programming (OOP). It describes the idea of wrapping data and the methods that work on data within one unit, e.g., a class in Java. This concept is often used to hide the internal state representation of an object from the outside.

Inheritance –
Inheritance is the ability of one class to inherit capabilities or properties of another class, called the parent class. When we write a class, we inherit properties from other classes. So when we create a class, we do not need to write all the properties and functions again and again, as these can be inherited from another class which possesses it. Inheritance allows the user to reuse the code whenever possible and reduce its redundancy.

import java.io.*; 

class GFG { 
	public static void main(String[] args) 
	{ 
		System.out.println("GfG!"); 

		Dog dog = new Dog(); 
		dog.name = "Bull dog"; 
		dog.color = "Brown"; 
		dog.bark(); 
		dog.run(); 

		Cat cat = new Cat(); 
		cat.name = "Rag doll"; 
		cat.pattern = "White and slight brownish"; 
		cat.meow(); 
		cat.run(); 

		Animal animal = new Animal(); 

		animal.name = "My favourite pets"; 

		animal.run(); 
	} 
} 

class Animal { 
	String name; 
	public void run() 
	{ 

		System.out.println("Animal is running!"); 
	} 
} 

class Dog extends Animal { 

/// the class dog is the child and animal is the parent 

	String color; 
	public void bark() 
	{ 
		System.out.println(name + " Wooh ! Wooh !"
						+ "I am of colour " + color); 
	} 
} 

class Cat extends Animal { 

	String pattern; 

	public void meow() 
	{ 
		System.out.println(name + " Meow ! Meow !"
						+ "I am of colour " + pattern); 
	} 
} 

  

Polymorphism –
Polymorphism is the ability for data to be processed in more than one form. It allows the performance of the same task in various ways. It consists of method overloading and method overriding, i.e., writing the method once and performing a number of tasks using the same method name.

#include <iostream> 
using namespace std; 

void output(float); 
void output(int); 
void output(int, float); 

int main() 
{ 
	cout << "\nGfG!\n"; 
	int a = 23; 
	float b = 2.3; 

	output(a); 
	output(b); 
	output(a, b); 

	return 0; 
} 

void output(int var) 
{ // same function name but different task 
	cout << "Integer number:\t" << var << endl; 
} 

void output(float var) 
{ // same function name but different task 
	cout << "Float number:\t" << var << endl; 
} 

void output(int var1, float var2) 
{ // same function name but different task 
	cout << "Integer number:\t" << var1; 
	cout << " and float number:" << var2; 
} 

  

Some important points to know about OOP:

  1. OOP treats data as a critical element.
  2. Emphasis is on data rather than procedure.
  3. Decomposition of the problem into simpler modules.
  4. Doesn’t allow data to freely flow in the entire system, ie localized control flow.
  5. Data is protected from external functions.

Advantages of OOPs –

  • It models the real world very well.
  • With OOP, programs are easy to understand and maintain.
  • OOP offers code reusability. Already created classes can be reused without having to write them again.
  • OOP facilitates the quick development of programs where parallel development of classes is possible.
  • With OOP, programs are easier to test, manage and debug.

Disadvantages of OOP –

  • With OOP, classes sometimes tend be over-generalised.
  • The relations among classes become superficial at times.
  • The OOP design is tricky and requires appropriate knowledge. Also, one needs to do proper planning and design for OOP programming.
  • To program with OOP, the programmer needs proper skills such as that of design, programming and thinking in terms of objects and classes etc.

 

Basic Concepts of Object Oriented Programming using C++

 

 

Object oriented programming – As the name suggests uses objects in programming. Object oriented programming aims to implement real world entities like inheritance, hiding, polymorphism etc in programming. The main aim of OOP is to bind together the data and the functions that operates on them so that no other part of code can access this data except that function.
Let us learn about different characteristics of an Object Oriented Programming language:
Object: Objects are basic run-time entities in an object oriented system, objects are instances of a class these are defined user defined data types.

class person 
{ 
	char name[20]; 
	int id; 
public: 
	void getdetails(){} 
}; 

int main() 
{ 
person p1; //p1 is a object 
} 

  

Object take up space in memory and have an associated address like a record in pascal or structure or union in C.

When a program is executed the objects interact by sending messages to one another.

Each object contains data and code to manipulate the data. Objects can interact without having to know details of each others data or code, it is sufficient to know the type of message accepted and type of response returned by the objects.



Class: Class is a blueprint of data and functions or methods. Class does not take any space.

Syntax for class:

class class_name 
{ 
private: 
	//data members and member functions declarations 
public: 
	//data members and member functions declarations 
protected: 
	//data members and member functions declarations 
};

  

Class is a user defined data type like structures and unions in C.

By default class variables are private but in case of structure it is public. in above example person is a class.



Encapsulation and Data abstraction: Wrapping up(combing) of data and functions into a single unit is known as encapsulation. The data is not accessible to the outside world and only those functions which are wrapping in the class can access it. This insulation of the data from direct access by the program is called data hiding or information hiding.

Data abstraction refers to, providing only needed information to the outside world and hiding implementation details. For example, consider a class Complex with public functions as getReal() and getImag(). We may implement the class as an array of size 2 or as two variables. The advantage of abstractions is, we can change implementation at any point, users of Complex class wont’t be affected as out method interface remains same. Had our implementation be public, we would not have been able to change it.



Inheritance: inheritance is the process by which objects of one class acquire the properties of objects of another class. It supports the concept of hierarchical classification. Inheritance provides re usability. This means that we can add additional features to an existing class without modifying it.



Polymorphism: polymorphism means ability to take more than one form. An operation may exhibit different behaviors in different instances. The behavior depends upon the types of data used in the operation.
C++ supports operator overloading and function overloading.
The process of making an operator to exhibit different behaviors in different instances is known as operator overloading.
Function overloading is using a single function name to perform different types of tasks.
Polymorphism is extensively used in implementing inheritance.



Dynamic Binding: In dynamic binding, the code to be executed in response to function call is decided at runtime. C++ has virtual functions to support this.



Message Passing: Objects communicate with one another by sending and receiving information to each other. A message for an object is a request for execution of a procedure and therefore will invoke a function in the receiving object that generates the desired results. Message passing involves specifying the name of the object, the name of the function and the information to be sent.

 

1) Friends should be used only for limited purpose. too many functions or external classes are declared as friends of a class with protected or private data, it lessens the value of encapsulation of separate classes in object-oriented programming.

 

2) Friendship is not mutual. If a class A is friend of B, then B doesn’t become friend of A automatically.

 

3) Friendship is not inherited (See this for more details)

 

4) The concept of friends is not there in Java.

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, B’s constructor is called before A’s 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; 
} 

  The destructors are called in reverse order of constructors.

 

an a C++ class have an object of self type?

 

A class declaration can contain static object of self type, it can also have pointer to self type, but it cannot have a non-static object of self type.

For example, following program works fine.

// A class can have a static member of self type 
#include<iostream> 

using namespace std; 

class Test { 
static Test self; // works fine 

/* other stuff in class*/

}; 

int main() 
{ 
Test t; 
getchar(); 
return 0; 
} 

  

And following program also works fine.

 
// A class can have a pointer to self type 
#include<iostream> 

using namespace std; 

class Test { 
Test * self; //works fine 

/* other stuff in class*/

}; 

int main() 
{ 
Test t; 
getchar(); 
return 0; 
} 

  

But following program generates compilation error “field `self’ has incomplete type

 

// A class cannot have non-static object(s) of self type. 
#include<iostream> 

using namespace std; 

class Test { 
Test self; // Error 

/* other stuff in class*/

}; 

int main() 
{ 
Test t; 
getchar(); 
return 0; 
} 

 

  If a non-static object is member then declaration of class is incomplete and compiler has no way to find out size of the objects of the class.
Static variables do not contribute to the size of objects. So no problem in calculating size with static variables of self type.
For a compiler, all pointers have a fixed size irrespective of the data type they are pointing to, so no problem with this also.

Pure Virtual Functions and Abstract Classes in C++

Sometimes implementation of all function cannot be provided in a base class because we don’t know the implementation. Such a class is called abstract class. For example, let Shape be a base class. We cannot provide implementation of function draw() in Shape, but we know every derived class must have implementation of draw(). Similarly an Animal class doesn’t have implementation of move() (assuming that all animals move), but all animals must know how to move. We cannot create objects of abstract classes.

A pure virtual function (or abstract function) in C++ is a virtual function for which we don’t have implementation, we only declare it. A pure virtual function is declared by assigning 0 in declaration. See the following example.

// An abstract class 
class Test 
{ 
	// Data members of class 
public: 
	// Pure Virtual Function 
	virtual void show() = 0; 
	
/* Other members */
}; 

  A complete example:
A pure virtual function is implemented by classes which are derived from a Abstract class. Following is a simple example to demonstrate the same.

#include<iostream> 
using namespace std; 

class Base 
{ 
int x; 
public: 
	virtual void fun() = 0; 
	int getX() { return x; } 
}; 

// This class inherits from Base and implements fun() 
class Derived: public Base 
{ 
	int y; 
public: 
	void fun() { cout << "fun() called"; } 
}; 

int main(void) 
{ 
	Derived d; 
	d.fun(); 
	return 0; 
} 

  

Output:

fun() called

Some Interesting Facts:
1) A class is abstract if it has at least one pure virtual function.
In the following example, Test is an abstract class because it has a pure virtual function show().

// pure virtual functions make a class abstract 
#include<iostream> 
using namespace std; 

class Test 
{ 
int x; 
public: 
	virtual void show() = 0; 
	int getX() { return x; } 
}; 

int main(void) 
{ 
	Test t; 
	return 0; 
} 

2) We can have pointers and references of abstract class type.
For example the following program works fine.

#include<iostream> 
using namespace std; 

class Base 
{ 
public: 
	virtual void show() = 0; 
}; 

class Derived: public Base 
{ 
public: 
	void show() { cout << "In Derived \n"; } 
}; 

int main(void) 
{ 
	Base *bp = new Derived(); 
	bp->show(); 
	return 0; 
}

  3) If we do not override the pure virtual function in derived class, then derived class also becomes abstract class.
The following example demonstrates the same.

#include<iostream> 
using namespace std; 
class Base 
{ 
public: 
	virtual void show() = 0; 
}; 

class Derived : public Base { }; 

int main(void) 
{ 
Derived d; 
return 0; 
}

  

4) An abstract class can have constructors.
For example, the following program compiles and runs fine.

 
#include<iostream> 
using namespace std; 

// An abstract class with constructor 
class Base 
{ 
protected: 
int x; 
public: 
virtual void fun() = 0; 
Base(int i) { x = i; } 
}; 

class Derived: public Base 
{ 
	int y; 
public: 
	Derived(int i, int j):Base(i) { y = j; } 
	void fun() { cout << "x = " << x << ", y = " << y; } 
}; 

int main(void) 
{ 
	Derived d(4, 5); 
	d.fun(); 
	return 0; 
} 

  

  

Can we make a class constructor virtual in C++ to create polymorphic objects? No. C++ being static typed (the purpose of RTTI is different) language, it is meaningless to the C++ compiler to create an object polymorphically. The compiler must be aware of the class type to create the object. In other words, what type of object to be created is a compile time decision from C++ compiler perspective. If we make constructor virtual, compiler flags an error. In fact except inline, no other keyword is allowed in the declaration of constructor.

posted on 2019-05-04 16:12  EMH1899  阅读(316)  评论(0编辑  收藏  举报

导航