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

Абстракция срещу капсулиране

C++ конструктор

  • Конструкторът е специален тип членна функция, която се извиква автоматично при създаване на обект.
  • В 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;
}

C++ деструктор

  • Descructor в c++ е функция-член в клас, която изтрива обект.
  • Те се извикват, когато обектът на класа излезе извън обхвата, като например при край на функция, край на програма, изтриване на променлива и т.н.
  • Деструкторът се различава от другите нормални мемерни функции, тъй като не приема никакви аргументи и не връща нищо като конструктора.
  • Деструкторът има същото име на името на класа, предшествано от знак тилда(~).
  • Деструкторът се извиква автоматично, когатообектите са унищожени или излязат извън обхвата.
#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;
}

Програмирайте на c++, като създадете цяло число на клас с печат на всички прости числа от класа

#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++ йерархично наследяване
  • Хибридно наследяване на 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++ един клас може да бъде извлечен от повече от един родител.

Неяснота при множествено наследяване

  • Най-очевидният проблем с множественото наследяване възниква по време на отмяна на функция.
  • Да предположим, че два основни класа имат една и съща функция, която не е заменена в производния клас.
  • След това използвайте Operator за разрешаване на обхвата, за да получите достъп до него.
#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;
}
  • Това е полиморфизъм по време на изпълнение, защото извикването на функцията не се разрешава от компилатора, а вместо това се разрешава по време на изпълнение.

Претоварване на оператор чрез функция за приятел

  • Предлага по-добра ефективност и гъвкавост на класа. Тази функция не е член на класа и няма указател „това“.
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++ е функция член на базов клас, която предефинирате в производен клас. За декларирането му се използва ключовата дума interactive.
  • Той казва на компилатора дали функцията трябва да бъде динамично свързана или късно свързана.

  • Членовете на данните/функциите наклас 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;
}

Виртуална функция срещу чиста виртуална функция

Заключение

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