C + + inheritance and overloaded polymorphic encapsulation

Posted by Solarpitch on Thu, 09 Sep 2021 00:57:01 +0200

c + + inheritance
Inheritance allows us to define a class based on another class, which makes it easier to create and maintain an application. This also achieves the effect of reusing code functions and improving execution time.
When creating a class, you do not need to rewrite new data members and member functions. You only need to specify that the new class inherits the members of an existing class. The existing class is called the base class, and the new class is called the derived class.

A class can derive from multiple classes, which means that it can inherit data and functions from multiple base classes. To define a derived class, we use a class derived list to specify the base class. The class derivation list is named after one or more base classes as follows:

Class name: access modifier base class name
Access modifier scope:

If it is not written, it defaults to private

For example:

#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);
 
   // Area of output object
   cout << "Total area: " << Rect.getArea() << endl;
 
   return 0;
}

Output is:

Total area: 35

Access control and inheritance
Derived classes can access all non private members in the base class. Therefore, if the base class member does not want to be accessed by the member function of the derived class, it should be declared as private in the base class.

A derived class inherits all base class methods, except for the following cases:

Constructors, destructors, and copy constructors for base classes.
Overloaded operator of base class.
Friend function of the base class.
Inheritance type
When a class derives from a base class, the base class can be inherited as public, protected or private. The inheritance type is specified by the access modifier explained above.

public inheritance is usually used. When using different types of inheritance, follow the following rules:

Public inheritance: when a class derives from a public base class, the public member of the base class is also the public member of the derived class, and the protected member of the base class is also the protected member of the derived class. The private member of the base class cannot be directly accessed by the derived class, but can be accessed by calling the public and protected members of the base class.
Protected inheritance: when a class derives from a protected base class, the public and protected members of the base class will become the protected members of the derived class.
Private inheritance: when a class derives from a base class, the public and protected members of the base class will become private members of the derived class.
Multiple inheritance
Multiple inheritance means that a subclass can have multiple parent classes, which inherits the characteristics of multiple parent classes. C + + classes can inherit members from multiple classes. The syntax is as follows:

Class < derived class name >: < inheritance method 1 > < base class name 1 >, < inheritance method 2 > < base class name 2 >
{
< derived class body >
};
//The inheritance method of access modifier is one of public, protected or private. It is used to modify each base class, which is separated by commas

#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();
   
   // Area of output object
   cout << "Total area: " << Rect.getArea() << endl;
 
   // Total output cost
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;
 
   return 0;
}

The result is:

Total area: 35
Total paint cost: $2450

C + + overloading
Function overload (method overload)
Overload declaration refers to a declaration with the same name as the function or method previously declared in the scope, but their parameter list and definition (Implementation) are different.
When you call an overloaded function or operator, the compiler determines the most appropriate definition by comparing the parameter type you use with the parameter type in the definition. The process of selecting the most appropriate overloaded function or operator is called overloaded decision.
In the same scope, you can declare several functions with the same name with similar functions, but the formal parameters (referring to the number, type or order of parameters) of these functions with the same name must be different. Functions cannot be overloaded only by different return types.

#include <iostream>
using namespace std;
 
class printData
{
   public:
      void print(int i) {
        cout << "Integer is: " << i << endl;
      }
 
      void print(double  f) {
        cout << "Floating point number is: " << f << endl;
      }
 
      void print(char c[]) {
        cout << "String is: " << c << endl;
      }
};
 
int main(void)
{
   printData pd;
 
   // Output integer
   pd.print(5);
   // Output floating point number
   pd.print(500.263);
   // Output string
   char c[] = "Hello C++";
   pd.print(c);
 
   return 0;
}

Output is:

Integer is: 5
 Floating point number is: 500.263
 String is: Hello C++

Operator overloading
Operator overloading is a characteristic overload of a few C + +, which is not available in java or python. Through operator overloading, we can redefine most of the built-in operators of C + +.
Overloaded operators are functions with special names. The function name is composed of the keyword operator and the operator symbols to be overloaded. Like other functions, the overloaded operator has a return type and a parameter list. For example, the addition + of two Box objects can overload the + sign as follows:

Box operator+(const Box&);

In this case:

Box b1,b2,b3;
b1 = b2+b3;
//It can be used in this way. The + operator is overloaded here

#include <iostream>
using namespace std;
 
class Box
{
   public:
 
      double getVolume(void)
      {
         return length * breadth * height;
      }
      void setLength( double len )
      {
          length = len;
      }
 
      void setBreadth( double bre )
      {
          breadth = bre;
      }
 
      void setHeight( double hei )
      {
          height = hei;
      }
      // Overload the + operator to add two Box objects
      Box operator+(const Box& b)
      {
         Box box;
         box.length = this->length + b.length;
         box.breadth = this->breadth + b.breadth;
         box.height = this->height + b.height;
         return box;
      }
   private:
      double length;      // length
      double breadth;     // width
      double height;      // height
};
// Main function of program
int main( )
{
   Box Box1;                // Declare Box1, type Box
   Box Box2;                // Declare Box2, type Box
   Box Box3;                // Declare Box3, type Box
   double volume = 0.0;     // Store the volume in this variable
 
   // Box1 details
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);
 
   // Box2 details
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);
 
   // Volume of Box1
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
 
   // Volume of Box2
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;
 
   // Add the two objects to get Box3
   Box3 = Box1 + Box2;
 
   // Volume of Box3
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;
 
   return 0;
}

Output:

Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400

Overloadable Operators

Non overloadable operator

polymorphic

Basic concepts of polymorphism
 Polymorphism is a variety of implementations of an interface, which is divided into class polymorphism and function polymorphism.
Polymorphism of function(heavy load)A function is defined as a function with multiple different parameters.

Add the virtual keyword (i.e. virtual function) before the function of the base class, and override the function in the derived class,
The runtime will call the corresponding function according to the actual type of the object. If the object type
If it is a derived class, call the function of the derived class; If the object type is a base class, the function of the base class is called

#include<iostream>
using namespace std;
float Sum(float a, float b)
{
	return a + b;
}
int Sum(int a, int b)
{
	return a + b;
}
int main()
{
	int var1, var2;
	float var3, var4;
	cin >> var1 >> var2;
	cin >> var3 >> var4;
	cout << Sum(var1, var2) << endl << Sum(var3, var4) << endl;
	system("pause");
	return 0;
}

result:

It can be seen from the program code that two functions Sum with the same name are defined. Their differences lie in the different function parameter types and return value types.
When compiling the program, the compiler does not report an error, and the running result of the program is what we expect. Because the function is used in this program
Polymorphism (overloading), so that the compiler will select and call functions with the same name through different function parameters during code compilation,
Select the most appropriate function type. This is the convenience of function polymorphism

Class polymorphism

#include<iostream>
using namespace std;
class Mammal {
public:
	void speak() {
		cout << " Mammal::speak " << endl;
	}
};
class Dog :public Mammal {
public:
	void speak()
	{
		cout << " Dog::speak " << endl;
	}
};
int main()
{
	Dog a;
	a.speak();
	Mammal *b = &a;
	b->speak();
	system("pause");
	return 0;
}

Operation results:

In the above code, we define a base class MMAL and derive a class Dog from it. Both of them have the function speak()
In the main function, first call the speak function of Dog class, and then assign the address of a of Dog class to b of MMAL class,
We don't want to call the function of the derived class through the base class in this way, but judging from the results of the program running, this way
Not desirable.

If we want to get the desired results, we need to use class polymorphism. We just need to
The speak function in the base class is declared as a virtual function, that is, plus

virtual
keyword:

class Mammal {
public:
        virtual void speak() {
		cout << " Mammal::speak " << endl;
	}
};

Run the program again:

So we get the result we want.

There are pure virtual functions in class polymorphism. Classes containing pure virtual functions are also called abstract classes:
Use of pure virtual functions:
1. When you want to abstract a method from a base class, and the base class can only be inherited, not instantiated;
2. This method must be implemented in the derived class;

To construct a pure virtual function, you only need to add to the right of the definition of the virtual function

"= 0"
The format is OK.
The following is a program that uses class inheritance to calculate the area and perimeter of rectangles and circles (pure virtual function):

#include<iostream>
using namespace std;
#define PI 3.1415926
class Shape {
public:
	virtual double getArea() = 0;
	virtual double getPerim() = 0;
};
class Rectangle :public Shape {
public:
	virtual double getArea();
	virtual double getPerim();
	Rectangle(double a = 1, double b = 1) :r1(a), r2(b) {

	}
private:
	double r1;
	double r2;
};
double Rectangle::getArea() {
	return r1 * r2;
}
double Rectangle::getPerim() {
	return 2 * (r1 + r2);
}
class Circle : public Shape {
public:
	virtual double getArea();
	virtual double getPerim();
	Circle(double a) :r(a) {

	}
private:
	double r;
};
double Circle::getArea()
{
	return PI * r*r;
}
double Circle::getPerim()
{
	return 2 * PI*r;
}
int main()
{
	Rectangle a(1.2, 3.4);
	Circle b(3);
	cout << "Rectangle Area:" << a.getArea() << endl;
	cout << "Rectangle Perimeter of:" << a.getPerim() << endl;
	cout << "Circle Area:" << b.getArea() << endl;
	cout << "Circle Perimeter of:" << b.getPerim() << endl;
	system("pause");
	return 0;
}

Because the perimeter and area of rectangle and circle are calculated differently, the base class can be defined as an abstract class here. Here
An abstract class Shape is defined in the program, based on which classes Retangle and Circle are derived. These two derived classes
Both inherit the pure virtual function getArea() and getPerim() in the abstract class, which are functions for calculating area and perimeter respectively.
Since pure virtual functions cannot be inherited directly in derived classes, pure virtual functions are redefined in both classes.

The following is the running result of the program:


Strictly speaking, python is not polymorphic

In this program, the advantages of pure virtual functions are directly reflected.

Topics: C++