- При обектно-ориентирания метод на проектиране системата се разглежда като колекция от обекти (т.е. обекти). Състоянието се разпределя между обектите и всеки обект обработва своите данни за състоянието…….(Посетете за още)
- 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++. Позволява ни да създадем нов клас (производен клас) от съществуващ клас (базов клас)
- Отмяна на функцията: основният клас и производният клас имат функции-членове с едно и също име и аргументи.
- За достъп до заменената функция на базовия клас използваме оператора за разделяне на обхват : : & използване на указател.
- Тип наследяване: Множествено, многостепенно и йерархично наследяване.
- Претоварване на функция: можем да използваме две функции с едно и също име, ако имат различни параметри (или типове, или брой аргументи).
- полиморфизъм означава, че извикването на членска функция ще доведе до изпълнение на различна функция в зависимост от типа обект, който извиква функцията.
- Тип полиморфизъм: Полиморфизъм по време на изпълнение и по време на компилиране.
- Виртуална функция е функция член в основния клас, която очакваме да предефинираме в производни класове.
- Виртуален базов клас се използва при виртуално наследяване по начин за предотвратяване на множество „Инстанции“ на даден клас, появяващ се в йерархия на наследяване, когато се използва множествено наследяване.