• В методе объектно-ориентированного проектирования система рассматривается как набор объектов (т. е. сущностей). Состояние распределяется между объектами, и каждый объект обрабатывает данные о своем состоянии…….(Посетите, чтобы узнать больше)
  • c++ — это простой, статический, скомпилированный, универсальный, высокоуровневый, объектно-ориентированный язык программирования.

Абстракция VS Инкапсуляция

Конструктор С++

  • Конструктор — это специальный тип функции-члена, который вызывается автоматически при создании объекта.
  • В C++ конструктор имеет то же имя, что и класс, и не имеет возвращаемого типа.
#include<iostream>
using namespace std;
class Base{
    public:
    // create constructor
    Base(){
        cout<<"This is Constructor function."<<endl;
    }
};
int main(){
    Base B;
    return 0;
}

Тип конструктора

  • Конструктор по умолчанию
  • Параметризованный конструктор
  • Копировать конструктор

Параметрический конструктор

  • В C++ конструктор с параметрами называется параметризованным конструктором. Это предпочтительный метод для инициализации данных членов.
// parameterized constructor
#include
using namespace std;
class Base{
    private:
        int length;
    public:
    // constructor
        Base(int len){
            length = len;
        }
        int getdata(){
            return length * 2;
        }
};
int main(){
    Base B(10);
    cout<<B.getdata()<<endl;
    return 0;
}  

Конструктор копирования

  • Конструктор копирования в C++ используется для копирования данных одного объекта в другой.
// copy constructor
#include
using namespace std;
class Base{
    private:
        int lenght;
        int height;
    public:
        Base(int len, int hei){
            lenght = len;
            height = hei;
        }
    // copy constructor
    Base(Base &obj){
        lenght = obj.length;
        height = obj.height;
    }
    int display(){
        return lenght * height;
    }
};
int main(){
    Base B(10,5);
    // copy costryctor
    Base b = B;
    cout<<b.display()<<endl;
    cout<<B.display()<<endl;
    
    return 0;
}

Деструктор С++

  • Дескруктор в С++ — это функция-член в классе, которая удаляет объект.
  • Они вызываются, когда объект класса выходит за пределы области видимости, например, при завершении функции, завершении программы, удалении переменной и т. д.
  • Деструктор отличается от других обычных мемер-функций тем, что он не принимает никаких аргументов и не возвращает ничего, как конструктор.
  • Desctructor имеет то же имя, что и имя класса, с предшествующим знаком тильды (~).
  • Деструктор вызывается автоматически, когда объекты уничтожаются или выходят за пределы области видимости.
#include<iostream>
using namespace std;
class Base{
    private:
        int length;
    public:
    // constructor
        Base(int len){
            length = len;
        }
        int getdata(){
            return length * 2;
        }
        // destructor called
        ~Base(){
            cout<<"Destructor called"<<endl;
         }
};

int main(){
    Base B(10);
    cout<<B.getdata()<<endl;
    return 0;
}

Запрограммируйте на С++, создав целое число класса с печатью всех простых чисел из класса

#include<iostream>
using namespace std;
class Integer{
    private:
        int n;
    public:
    void set(int n){
        this->n = n;
    }
    bool isprime(int n){
      if(n == 1 || n == 0)return false;
       for(int i = 2; i * i <= n; i++){
          if(n % i == 0)return false;
        }
    return true;
    }
      void show(){
            cout<<"Prime numbers are : ";
           for(int i = 1; i <= n; i++){
             if(isprime(i)){
              cout << i << " ";
              }
          }
      }
};
int main(){
    Integer i;
    int n;
    cout<<"Enter number"<<endl;
    cin>>n;
    i.set(n);
    i.show();
    return 0;
}

     ---------------------------------------------------------------
Enter number
20
Prime numbers are : 2 3 5 7 11 13 17 19 

Встроенная функция

  • Встроенная функция — это функция, которая раскрывается в строке при вызове.
  • Основное использование встроенной функции в C++ — экономия места в памяти. Всякий раз, когда функция вызывается, выполнение задач занимает много времени.
// Implementtation of inline function in c++
#include
using namespace std;
class Operation{
    int a,b,add,sub,mul;
public:
    void get();
    void sum();
    void diff();
    void prod();
};
// inline function for get methods
inline void Operation::get(){
    cout<<"Enter first value";
    cin>>a;
    cout<<"Enter second value";
    cin>>b;
}
// inline funcion for sum methods
inline void Operation::sum(){
    add = a+b;
    cout<<"Addition is : "<<add<<endl;
}
// inline function for diff methods
inline void Operation::diff(){
    sub = a-b;
    cout<<"Subtraction is :"<<sub<<endl;
}
// inline function for prod methods
inline void Operation::prod()
{
    mul = a*b;
    cout<<"Multiplication is :"<<mul<<endl;
}
int main()
{
    cout<<"Program using inline function"<<endl;
    Operation o;
    o.get();
    o.sum();
    o.diff();
    o.prod();
    return 0;
}

Функция друга

  • Сокрытие данных — фундаментальная концепция объектно-ориентированного программирования. Он ограничивает доступ приватных членов вне класса.
  • Точно так же защищенные члены доступны только производным классам и недоступны извне.
  • Однако в C++ есть функция, называемая дружественными функциями, которая нарушает это правило и позволяет нам получать доступ к функциям-членам извне класса.
  • Функция друга может получить доступ к личным и защищенным данным класса. Мы объявляем функцию friend, используя ключевое слово friend внутри тела класса.
#include
using namespace std;
// Private data in class
class Box{
    private:
        int lenght;
        // friend function called
        friend int printlenght(Box);
    public:
        // initilaized lenght with 5
        Box():lenght(5) {}
};
// define friend function
int printlenght(Box b){
    // access the private data from friend function
    b.lenght += 10;
    return b.lenght;
}
int main(){
    Box B;
    cout<<"Lenght of Box is :"<<printlenght(B)<<endl;
    return 0;
}

Наследование

  • Наследование — одна из ключевых особенностей объектно-ориентированного программирования на C++. Это позволяет нам создать новый класс (производный класс) из существующего класса (базового класса).
  • Производный класс наследует функции базового класса и может иметь собственные дополнительные функции.
#include
using namespace std;
// base class
class Cars{
    private:
    string model;
    int price;
    public:
    void color(){
        cout<<"black"<<endl;
    }
    void name(){
        cout<<"Farrari"<<endl;
    }
    void speed(){
        cout<<"250000KPH"<<endl;
    }
    void setModel(string m){
        model = m;
    }
    string getModel(){
        return model;
    }
    
};
// new class(derived class)
class Racing_cars : public Cars{
    public:
    void display(string c){
        cout<<c<<endl;
    }
    void design(){
        cout<<"Modren"<<endl;
    }
    void milage(){
        cout<<"good"<<endl;
    }
    
};
// we call derived class to base class not vice versa.
int main(){
    Racing_cars c;
    c.color();
    c.name();
    c.speed();
    c.setModel("XX1288");
    c.design();
    c.milage();
    c.display(c.getModel());
    return 0;
}

Переопределение функции-члена в наследовании

  • Предположим, что базовый класс и производный класс имеют функции-члены с одинаковыми именами и аргументами.
  • Если мы создадим объект производного класса и попытаемся получить доступ к этой функции-члену, вместо функции в базовом классе будет вызвана функция-член в производном классе.
  • Функция-член производного класса переопределяет функцию-член базового класса.
// function overriding in inheritance
#include
using namespace std;
// base class
class Base{
    public:
    void display(){
        cout<<"Base class here."<<endl;
    }
};
// derived class and inherited
class Derived : public Base{
    public:
    void display(){
        cout<<"Dericed class here."<<endl;
    }
};
// its call only derived class not base class.
int main(){
    Derived D;
    D.display();
    return 0;
}

Доступ к переопределенной функции в C++

  • Чтобы получить доступ к переопределенной функции базового класса, мы используем оператор разрешения области ::
  • Мы также можем получить доступ к переопределенной функции, используя указатель базового класса для указания на объект производного класса, а затем вызывая функцию из этого указателя.
// function overriding in inheritance
#include
using namespace std;
// base class
class Base{
    public:
    void display(){
        cout<<"Base class here."<<endl;
    }
};
// derived class and inherited
class Derived : public Base{
    public:
    void display(){
        cout<<"Dericed class here."<<endl;
        
        // call base class function though derived class
        Base :: display();
    }
};
// its call only derived class not base class.
int main(){
    Derived D;
    D.display();
    
    // access base class function by scode resolution operator
    D.Base::display();
    
    return 0;
}

Доступ к функции переопределения с помощью указателя

// function overriding in inheritance
#include
using namespace std;
// base class
class Base{
    public:
    void display(){
        cout<<"Base class here."<<endl;
    }
};
// derived class and inherited
class Derived : public Base{
    public:
    void display(){
        cout<<"Dericed class here."<<endl;
    }
};
// its call only derived class not base class.
int main(){
    Derived D;
    
    // Access overiding function using pointer
    Base *ptr = &D;
    // call function of  base class
    ptr -> display();
    
    D.display();
    return 0;
}

Тип наследства

Наследование — одна из основных функций объектно-ориентированного языка программирования. Это позволяет разработчикам программного обеспечения создавать новый класс из существующего класса. Производный класс наследует функции базового класса (существующего класса).

  • С++ Одиночное наследование
  • Множественное наследование C++
  • Многоуровневое наследование C++
  • Иерархическое наследование C++
  • Гибридное наследование C++

Единое наследство

  • При одиночном наследовании один класс может расширять функциональность другого класса. При одиночном наследовании существует только один родительский класс и один дочерний класс.
#include<iostream> 
using namespace std; 
// Parent class 
class Animal { 
public: 
  void eat() {
     cout << "eating" << endl; 
  } 
};
// child class
class Dog: public Animal {
public: 
  void bark() { 
    cout << "barking"; 
  } 
};

int main() {
 // Creating an object of the child class 
  Dog obj; 
  // calling methods 
  obj.eat(); 
  obj.bark(); 
  return 0;
}

Многоуровневое наследование

  • Вы можете не только получить класс от базового класса, но вы также можете (новый) получить класс от производного класса. Эта форма наследования известна как многоуровневое наследование.
#include
using namespace std;
// Base class
class Base{
    public:
    void add(){
        cout<<2+4<<endl;
    }
};
// derived class which inherit from base class
class Derive1 : public Base{
    public:
    void sub(){
        cout<<2-4<<endl;
    }
};
// Derived class which inherit fron derive1 class
class Derive2 : public Derive1{
    public:
    void mul(){
        cout<<2*4<<endl;
    }
};
int main(){
    Derive2 D;
    D.mul();
    D.sub();
    D.add();
    return 0;
}

Множественное наследование

  • В программировании на C++ класс может быть производным от более чем одного родителя.

Неоднозначность множественного наследования

  • Наиболее очевидная проблема с множественным наследованием возникает во время переопределения функции.
  • Предположим, два базовых класса имеют одну и ту же функцию, которая не переопределяется в производном классе.
  • Затем используйте оператор разрешения области действия, чтобы получить к нему доступ.
#include
using namespace std;
// base class 1
class Base_1{
    public:
    void display(){
        cout<<"This is Base class 1."<<endl;
    }
};
// Base class 2
class Base_2{
    public:
    void display(){
        cout<<"This is Base class 2."<<endl;
    }
};
// derive class which inherit though Base 1 class and also Base class 2
class Derive : public Base_1, public Base_2{
    public:
    void display(){
        cout<<"This is Derived class."<<endl;
    }
};
int main(){
    Derive D;
    D.display();
    
    // function overidding -> to access use scope resolution opeartor
    D.Base_1 :: display();
    D.Base_2 :: display();
    
    return 0;
}

Иерархическое наследование C++

  • Если от базового класса наследуется более одного класса, это называется иерархическим наследованием. При иерархическом наследовании все функции, общие для дочерних классов, включаются в базовый класс.
  • Например, физика, химия, биология являются производными от класса естественных наук.
#include
using namespace std;
// Base class
class Science{
    public:
    void display(){
        cout<<"Belong to Science Class."<<endl;
    }
};
// Derive class which inherit though science class
class Physics : public Science{
    public:
    void display(){
        cout<<"this is Physics class."<<endl;
    }
};
// Derive class which inherit though science class
class Biology : public Science{
    public:
    void display(){
        cout<<"this is biology class."<<endl;
    }
};
// Derive class which inherit though science class
class Chemistry : public Science{
    public:
    void display(){
        cout<<"this is Chemistry class."<<endl;
    }
};
int main(){
    Physics Ph;
    Ph.display();
    Ph.Science :: display();
    
    Biology B;
    B.display();
    B.Science :: display();
    
    Chemistry ch;
    ch.display();
    ch.Science :: display();
    return 0;
}

Гибридное наследование C++

  • Гибридное наследование представляет собой комбинацию нескольких типов наследования. Например, отношения дочернего и родительского классов, которые следуют множественному и иерархическому наследованию, можно назвать гибридным наследованием.

#include <iostream> 
using namespace std; 
// Parent class1 
class Vehicle {
public: 
  Vehicle() {
     cout << "This is a Vehicle" << endl; 
  } 
};
//Parent class2 
class Fare { 
public: 
  Fare() {
     cout << "Fare of Vehicle\n"; 
  } 
};
//Child class1 
class Car: public Vehicle {
 }; 

//Child class2 
class Bus: public Vehicle, public Fare { 
};

int main() { 
  // creating object of sub class will 
  // invoke the constructor of base class 
  Bus obj2; 
  return 0; 
}

Полиморфизм

  • Полиморфизм — важная концепция объектно-ориентированного программирования. Это просто означает более одной формы или много форм. То есть один и тот же объект (функция или оператор) ведет себя по-разному в разных сценариях. Например,
  • Оператор + в C++ используется для выполнения двух определенных функций. Когда он используется с числами (целыми числами и числами с плавающей запятой), он выполняет сложение
int a = 5;
int b = 6;
int sum = a + b;    // sum = 11

и Однако + также используется для объединения двух строковых операндов.

string firstName = "abc ";
string lastName = "xyz";

// name = "abc xyz"
string name = firstName + lastName;

Мы можем реализовать полиморфизм в C++ следующими способами:

  • Перегрузка функций
  • Перегрузка оператора
  • Переопределение функции
  • Виртуальные функции

Типы полиморфизмов

  • Полиморфизм времени выполнения
  • Пломорфизм времени компиляции

Полиморфизм времени компиляции

  • Этот тип полиморфизма достигается за счет перегрузки функций и перегрузки операторов.
  • Он также известен как "статический" или "раннее связывание".

Почему это называется полиморфизмом времени компиляции?

  • Перегруженные функции вызываются путем сравнения типов данных и количества параметров. Этот тип информации доступен компилятору во время компиляции. Таким образом, подходящая функция для вызова будет выбрана компилятором C++ во время компиляции.

Перегрузка функций

  • мы можем использовать две функции с одинаковым именем, если они имеют разные параметры (либо типы, либо количество аргументов).

Перегрузка функций может быть достигнута в следующих двух случаях:

  • Имена функций и типы возвращаемых значений совпадают, но различаются типом аргументов.
#include<iostream>
using namespace std;

class Base{
  private:
      int x = 10;
      double x1 = 10.1;
  public:
      void add(int y){
         cout << "Value of x + y is: " << x + y << endl;
      }
      // Differ in the type of argument.
      void add(double d){
         cout << "Value of x1+d is: " << x1 + d << endl;
      }
};

int main(){
  Base b;
  b.add(5);
  b.add(5.3);
  return 0;
}
  • Имена функций и типы возвращаемых значений одинаковы, но различаются количеством аргументов.
#include<iostream>
using namespace std;

class Base{
  private:
      int x = 10;
      double x1 = 10.1;
  public:
      void add(int y){
         cout << "Value of x + y is: " << x + y << endl;
      }
      // Differ in the number of argument.
      void add(int y, double d){
         cout << "Value of x1+d is: " << y + d << endl;
      }
};

int main(){
  Base b;
  b.add(5);
  b.add(5,5.3);
  return 0;
}
  • Перегруженные функции вызываются путем сопоставления типа и количества аргументов. Поскольку эта информация доступна на во время компиляции, компилятор выбирает правильную функцию на основе ее параметров.

Перегрузка оператора

  • В C++ мы можем перегружать оператор, пока работаем с пользовательскими типами, такими как объекты или структуры.
  • Перегрузка операторов — это в основном перегрузка функций, когда разные операторные функции имеют один и тот же символ, но разные операнды.
Note:

-> A user-defined type must be present in at least one operand.
-> ".", "::", typeid, size, ".*", and C++'s single ternary operator, "?:", 
are among the operators that cannot be overloaded.

These are some of the operators that can be overloaded in C++ :

Arithmetic operators : - , + , / , * , % and -=, +=, /= , *= , %=
Boolean algebra : !=, ==, > ,< ,>=, <= , && ,||
Bit manipulation : &, |, ^ ,<< ,>> and |=, &= ,>>=, <<=, ^=
Memory management : new[], new, delete[], delete
// C++ program to unary overload ++ when used as prefix
#include <iostream>
using namespace std;

class Count {
   private:
    int value;
   public:
    // Constructor to initialize count to 0
    Count() : value(0) {}

    // Overload ++ when used as prefix
    void operator ++() {
        value = value + 1;
    }
    void display() {
        cout << "Count: " << value << endl;
    }
};

int main() {
    Count count1;
    // Call the "void operator ++(object)" function
    ++count1;
    count1.display();
    return 0;
}
Before using ++ operator: 0
After using ++ operator: 1

Полиморфизм во время выполнения

  • Полиморфизм времени выполнения возникает, когда функции разрешаются во время выполнения, а не во время компиляции, когда вызов переопределенного метода разрешается динамически во время выполнения, а не во время компиляции.
  • Он также известен как поздняя привязка или динамическая привязка.
  • Полиморфизм во время выполнения достигается за счет сочетания переопределения функций и виртуальных функций.

Переопределение функции

  • В C++ Inheritance у нас может быть одна и та же функция как в базовом классе, так и в его производных классах. Ранее мы обсуждали переопределение функций-членов при наследовании.
// function overriding in inheritance
#include
using namespace std;
// base class
class Base{
    public:
    void display(){
        cout<<"Base class here."<<endl;
    }
};
// derived class and inherited
class Derived : public Base{
    public:
    void display(){
        cout<<"Derived class here."<<endl;
    }
};
// its call only derived class not base class.
int main(){
    Derived D;
    D.display();

    // for access use scope of resolution
    D.base :: display();

    // Access overiding function using pointer
    Base *ptr = &D;
    // call function of  base class
    ptr -> display();

    return 0;
}
  • Это полиморфизм времени выполнения, потому что вызов функции не разрешается компилятором, а вместо этого разрешается во время выполнения.

Перегрузка оператора с помощью функции друга

  • Это обеспечивает большую эффективность и гибкость класса. Эта функция не является членом класса и не имеет указателя this.
Note:

-> The this pointer in C++ stores the address of the class instance 
  (object) which is called from the member function, to enable functions 
  to access the correct object data members.
-> (To Know more Read article here....)
  • при перегрузке унарного (++,- -) оператора вы должны передать один аргумент.
  • при перегрузке бинарного (+,-) оператора у вас есть два аргумента.
// Operating overoading using friend function

#include <iostream>
using namespace std;
class Complex{
    private:
        int real;
        int img;
    public:
         // Default Constructor
        Complex (int r = 0, int i = 0){
            real = r;
            img = i;
        }
        void Display (){
            cout << real << "+i" << img;
        }
        // Friend Function with binary operator override and pass objects as arguments
        friend Complex operator + (Complex c1, Complex c2);
};
// Defination of friend function
Complex operator + (Complex c1, Complex c2){
    Complex temp;
    temp.real = c1.real + c2.real;
    temp.img = c1.img + c2.img;
    return temp;
}

int main (){
    Complex C1(5, 3), C2(10, 5), C3;
    C1.Display();
    cout << " + ";
    C2.Display();
    cout << " = ";
    C3 = C1 + C2;
    C3.Display();
}
// C1 => 5+i3
// C2 => 10+i5
// C3 => 15+i8 (Result)

Виртуальная функция

  • Виртуальная функция — это функция-член в базовом классе, которую мы ожидаем переопределить в производных классах.
  • По сути, виртуальная функция используется в базовом классе для обеспечения того, что функция переопределена. Это особенно относится к случаям, когда указатель базового класса указывает на объект производного класса.
#include <iostream>
using namespace std;

class Base {
   public:
    virtual void print() {
        cout << "Base Function" << endl;
    }
};

class Derived : public Base {
   public:
    void print() {
        cout << "Derived Function" << endl;
    }
};

int main() {
    Derived derived1;

    // pointer of Base type that points to derived1
    Base* base1 = &derived1;

    // calls member function of Derived class
    base1->print();

    return 0;
}

// Output => Derived Function
  • используя виртуальную функцию, мы получаем доступ к данным производного класса из базового класса.
// C++ program to demonstrate the use of virtual function

#include <iostream>
#include <string>
using namespace std;

class Animal {
   private:
    string type;

   public:
    // constructor to initialize type
    Animal() : type("Animal") {}

    // declare virtual function
    virtual string getType() {
        return type;
    }
};

class Dog : public Animal {
   private:
    string type;

   public:
    // constructor to initialize type
    Dog() : type("Dog") {}

    string getType() override {
        return type;
    }
};

class Cat : public Animal {
   private:
    string type;

   public:
    // constructor to initialize type
    Cat() : type("Cat") {}

    string getType() override {
        return type;
    }
};

void print(Animal* ani) {
    cout << "Animal: " << ani->getType() << endl;
}

int main() {
// Dynamically create using animal pointer
    Animal* animal1 = new Animal();
    Animal* dog1 = new Dog();
    Animal* cat1 = new Cat();

    print(animal1);
    print(dog1);
    print(cat1);

    return 0;
}

Виртуальный базовый класс

  • виртуальный базовый класс используется в виртуальном наследовании для предотвращения создания нескольких экземпляров данного класса появляется в иерархии наследования при использовании множественного наследования.
  • Виртуальный базовый класс в C++ — это функция-член базового класса, которую вы переопределяете в производном классе. Интерактивное ключевое слово используется для его объявления.
  • Он сообщает компилятору, должна ли функция быть связана динамически или с поздней привязкой.

  • Данные-члены/функциикласса Base дважды наследуются классом D, как показано на диаграмме. Первый проведет вас через класс B, а второй проведет вас через класс C. Когда объект класса D обращается к любому элементу данных или функции класса Base, неясно, какой элемент данных или функции будет назван. Один был унаследован через B, а другой — через C. Это зацикливает компилятор и вызывает ошибку.
#include <iostream>
using namespace std;
class Base{
public:
    int a;
    // contructor
    Base(){
        a = 10;
    }
};
class B : public virtual Base{
}; 
class C : public virtual Base{
}; 
class D : public B, public Base{
}; 

int main()
{
    D object; 
    cout << "a = " << object.a << endl;  
    return 0;
}

Виртуальная функция VS чистая виртуальная функция

Заключение

  • c++ — это простой, статический, скомпилированный, универсальный, высокоуровневый, объектно-ориентированный язык программирования.
  • Конструктор — это специальный тип функции-члена, который вызывается автоматически при создании объекта.
  • Тип конструктора: — конструктор по умолчанию, параметризованный и копирующий.
  • Встроенная функция — это функция, которая раскрывается в строке при вызове.
  • Функция друга может получить доступ к закрытым и защищенным данным класса. Мы объявляем функцию friend, используя ключевое слово friend внутри тела класса.
  • Наследование — одна из ключевых особенностей объектно-ориентированного программирования на C++. Это позволяет нам создать новый класс (производный класс) из существующего класса (базового класса).
  • Переопределение функций: базовый класс и производный класс имеют функции-члены с одинаковыми именами и аргументами.
  • Чтобы получить доступ к переопределенной функции базового класса, мы используем оператор разрешения области видимости : : & с помощью указателя.
  • Тип наследования: множественное, многоуровневое и иерархическое наследование.
  • Перегрузка функций: мы можем использовать две функции с одинаковыми именами, если они имеют разные параметры (либо типы, либо количество аргументов).
  • полиморфизм означает, что вызов функции-члена приведет к выполнению другой функции в зависимости от типа объекта, который вызывает функцию.
  • Тип полиморфизма: полиморфизм времени выполнения и времени компиляции.
  • Виртуальная функция — это функция-член в базовом классе, которую мы ожидаем переопределить в производных классах.
  • виртуальный базовый класс используется в виртуальном наследовании для предотвращения создания нескольких экземпляров данного класса появляется в иерархии наследования при использовании множественного наследования.