87. C++da anonim sinf obyektlari
Sinf-struktura tushunchasi kengaytmasi sifatida. Sinflarni eng sodda holda quyidagicha tasvirlash mumkin:Sinf-kaliti Sinf-soni {komponentalar ro‘yxati}Sinf komponentalari sodda holda tiplangan ma’lumotlar va funksiyalardan iborat bo‘ladi. Figurali kavslarga olingan komponentalar ro‘yxati Sinf tanasi deb ataladi. Sinfga tegishli funksiyalar komponenta-funksiyalar yoki sinf funksiyalari deb ataladi.Sinf kaliti sifatida Struct xizmatchi so‘zi ishlatilishi mumkin. Masalan quyidagi konstruksiya kompleks son sinfini kiritadi.
struct complex
{
double real;
double imag;
void define (double re=0.0, double im=0.0)
{
real=re; imag=im;
}
void display (void)
{
cout<=”real=”<cout<=”imag=”<}
};
88. *this yashirin ko’rsatkichi
*this yashirin ko'rsatkichi. Quyida butun sonli qiymatni o'z ichiga olgan va konstruktor va yordamchi funksiyalari bo'lgan oddiy sinf. E'tibor bering, bu yerda destruktorga ehtiyoj yo'q, chunki C++ tili a'zo o'zgaruvchidan keyin xotirani o'zi o'chira oladi:
#include
class Another
{ private: int m_number;
public: Another(int number)
{ setNumber(number);
} void setNumber(int number)
{ m_number = number; }
int getNumber() { return m_number; } };
int main()
{ Another another(3);another.setNumber(4);
std::cout << another.getNumber() << '\n'; return 0; }
Another.setNumber (4) ni chaqirganda; C ++ tushunadiki, setNumber () funktsiyasi boshqa obyektda ishlaydi va m_number aslida another.m_number. Keling, hammasi qanday ishlashini batafsil ko'rib chiqaylik. Masalan, quyidagi qatorni oling: another.setNumber(4); Garchi bir qarashda bizda faqat bitta bahs bordek tuyulsa-da, aslida ikkita savol bor. Kompilyatsiya vaqtida another.setNumber(4) qatori kompilyator tomonidan quyidagilarga o'zgartiriladi: setNumber(&another, 4); //boshqa obyekt nuqta oldidan obyekt argumentiga aylantirildi! Bu endi faqat standart funktsiya chaqiruvi va another obyekti (ilgari alohida obyekt bo'lgan va nuqtadan oldin kelgan) endi funksiyaga argument sifatida manzilga uzatiladi. Funksiya chaqiruvida hozir ikkita argument mavjud bo'lgani uchun, metod mos ravishda o'zgartirilishi kerak (shuning uchun ikkita argument kerak bo'ladi). Shunday qilib, quyidagi metod:
void setNumber(int number) { m_number = number; }
Kompilyator tomonidan konvertatsiya qilingan:
void setNumber(Another* const this, int number) { this->m_number = number; }
Oddiy metodni tuzishda kompilyator unga *this parametrni bilvosita qo'shadi. *this ko'rsatkich sinf metodini chaqiradigan obyektning manzilini o'z ichiga olgan yashirin doimiy ko'rsatkichdir. Yana bitta tafsilot bor. Metod ichida siz sinfning barcha a'zolarini (funksiyalar va o'zgaruvchilar) yangilashingiz kerak, shunda ular ushbu metodni chaqiradigan obyektga murojaat qilishadi. Buni har biriga this-> prefiksini qo'shish orqali qilish oson. Shunday qilib, setNumber() funksiyasining tanasida m_number (sinfning a'zo o'zgaruvchisi) this->m_numberga aylanadi. Qachon *this boshqasining manzilini ko'rsatsa, this->m_number another.m_numberga ishora qiladi. Hammasini birlashtirish:–Another.setNumber(4) ga murojaat qilganda, kompilyator aslida setNumber(&another, 4) ni chaqiradi. –setNumber() ichida *this ko'rsatkich boshqasining manzilini o'z ichiga oladi. –setNumber () ichidagi har qanday a'zo o'zgaruvchilar bunga prefiks qilinadi >. Shunday qilib, biz m_number = raqam deb aytganimizda, kompilyator aslida buni bajaradi-> m_number = raqam, bu holda, boshqa.m_numberni raqamga yangilaydi.Muhim jihati shundaki, bularning barchasi bizdan (dasturchilar) yashiringan va bu qanday ishlashini eslaysizmi yoki yo'qmi, muhim emas. Shuni yodda tutish kerakki, barcha oddiy sinf usullarida * metodikasi chaqiruvi bilan bog'liq ob'ektni ko'rsatuvchi ko'rsatgich mavjud.
89. *this ko’rsatkichiga oshkor ko’rsatkich
Ko'pgina hollarda, *this ko'rsatkichni aniq ko'rsatish shart emas. Biroq, bu ba'zida foydali bo'lishi mumkin. Misol uchun, agar parametr o'zgaruvchisi bilan bir xil parametrga ega bo'lgan konstruktor (yoki metod) bo'lsa, uni *this ko'rsatkich yordamida ajratib ko'rsatish mumkin:
class Something { private: int data; public: Something(int data) { this->data = data; } };
Bu yerda konstruktor a'zo o'zgaruvchi bilan bir xil nomdagi parametrni oladi. Bunday holda, ma'lumotlar parametrga va this-> data a'zo o'zgaruvchiga tegishli. Bu qabul qilinadigan amaliyot bo'lsa-da, sinfingizdagi barcha a'zo o'zgaruvchilar nomlari uchun m_ prefiksidan foydalanish tavsiya etiladi, chunki bu nomlarning takrorlanishining oldini olishga yordam beradi!
90. Sinfning zanjirlash metodlari
Ba'zida sinf metodi uchun ishlayotgan obyektni qaytarish qiymati sifatida qaytarish foydalidir. Bu yerda asosiy nuqta - bitta obyekt ustida ishlayotganda bir nechta metodlarni bir -biriga bog'lab qo'yishdir! Aslida biz buni uzoq vaqtdan beri ishlatamiz. Masalan, ma'lumotlarni cout bilan qismlarga ajratganimizda:
cout << "Hello, " << userName;
Bunday holda, cout - bu obyekt, << operatori - bu shu obyektda ishlaydigan metod. Kompilyator yuqoridagi parchani quyidagicha ishlaydi: (cout << "Hello, ") << userName; Birinchidan, << operatori konsolga Salomni chop etish uchun cout va "Hello" satrini ishlatadi. Biroq, bu ifodaning bir qismi bo'lgani uchun << operatori ham qiymatni (yoki bo'shliqni) qaytarishi kerak. Agar << operatori bekor qilsa, quyidagilar olinadi:
(void)<< userName;
Bu hech qanday ma'noga ega emas (kompilyator xato qiladi). Biroq, buning o'rniga, << operatori * this ko'rsatkichini qaytaradi, bu kontekstda shunchaki cout. Shunday qilib, birinchi << operatorini qayta ishlagandan so'ng, biz:
(cout) << userName;
Natijada foydalanuvchi nomi (userName) chiqadi. Shunday qilib, biz obyektni (bu holda, cout) bir marta ko'rsatishimiz kerak va har bir funksiya chaqiruvi bu obyektni keyingi funksiyaga o'tkazadi, bu bizga bir nechta metodlarni birlashtirishga imkon beradi. O'zimiz bu xatti -harakatni amalga oshirishimiz mumkin. Quyidagi sinfni ko'rib chiqaylik: class Mathem { private: int m_value; public: Mathem() { m_value = 0; } void add(int value) { m_value += value; } void sub(int value) { m_value -= value; } void multiply(int value) { m_value *= value; } int getValue() { return m_value; } }; Agar siz 7 ni qo’shib, 5 ni ayirib, hammasini 3 ga ko'paytirmoqchi bo'lsangiz, quyidagilarni bajarishingiz kerak.
#include int main() { Mathem operation; operation.add(7); // возвращает void operation.sub(5); // возвращает void operation.multiply(3); // возвращает void std::cout << operation.getValue() << '\n'; return 0; }
Ammo, agar har bir funktsiya *this ko'rsatkichni qaytarsa, biz bu meotd chaqiruvlarini birgalikda zanjirlashimiz mumkin. Masalan:
class Mathem { private: int m_value; public: Mathem() { m_value = 0; } Mathem& add(int value) { m_value += value; return *this; } Mathem& sub(int value) { m_value -= value; return *this; } Mathem& multiply(int value) { m_value *= value; return *this; } int getValue() { return m_value; } }; add(), sub() va multiply() endi *this ko'rsatkichini qaytaradi, shuning uchun quyidagilar to'g'ri bo'ladi: #include int main() { Mathem operation; operation.add(7).sub(5).multiply(3); cout << operation.getValue() << '\n'; return 0; } Natija: 6 Biz bitta bayonotga uchta alohida qatorni joylashtirdik! Endi buni batafsil ko'rib chiqaylik: - Operation.add (7) birinchi bo'lib chaqiriladi, bu m_value maydoniga 7 ni qo'shadi. - Keyin add() operation obyektiga havola bo'lgan this* ko'rsatgichni qaytaradi. - Keyin operatorion.sub(5) ga chaqiruv m_value dan 5 ni olib tashlaydi va operationni qaytaradi. - multiply(3) m_value ni 3 ga ko'paytiradi va allaqachon e'tiborga olinmagan operation ni qaytaradi. - Biroq, har bir funksiya operation ni o'zgartirganligi sababli, operation obyektining m_value qiymati endi ((0 + 7) - 5) * 3) o'z ichiga oladi, demak natija 6.
91. Boshqa sinflarni o'z ichiga olgan sinflar
Boshqa sinflarni o'z ichiga olgan sinflar. Ba'zi sinflar a'zo o'zgaruvchilari sifatida boshqa sinflarni o'z ichiga olishi mumkin. Odatiy bo'lib, tashqi sinf yaratishda a'zo o'zgaruvchilar uchun standart konstruktorlar chaqiriladi. Bu konstruktor tanasi bajarilishidan oldin sodir bo'ladi. Buni quyidagicha ko'rsatish mumkin: #include class A { public: A() { std::cout << "A\n"; } }; class B { private: A m_a; // B a'zo o'zgaruvchi sifatida A ni o'z ichiga oladi public: B() { std::cout << "B\n"; } }; int main() { B b; return 0; }
Dasturni bajarish natijasi: A B
B o'zgaruvchisi yaratilganda, B() konstruktori chaqiriladi. Konstruktor tanasi bajarilishidan oldin m_a A sinfining standart konstruktorini chaqirib initsializatsiyalanadi. Bu A xulosasini beradi, keyin boshqaruv B konstruktoriga qaytadi va B konstruktorining tanasi bajarila boshlaydi. Bu yerda mantiqiy, chunki B() konstruktori m_a o'zgaruvchisini ishlatishni xohlashi mumkin, shuning uchun avval m_a ni initsializatsiyalash kerak.
92. Sinflarning boshqa sinflardan tashkil topishi
Sinflarning boshqa sinflardan tashkil topishi Obyekt maydon sifatida. Murakkab sinflarni hosil qilishda oldin uni tashkil etuvchi oddiyroq sinflarni e'lon qilib, keyin esa ularni birlashtirish orqali sinfni hosil qilish maqsadga muvofiq. Masalan, g'ildirak sinfi, motor sinfi, uzatish korobkasi sinfi va boshqa sinflarni hosil qilib, keyin esa ularni birlashtirish orqali avtomobil sinfini qurish oldimizga turgan masalani yechishni ancha osonlashtiradi. Ikkinchi misolm ko’rib chiqamiz. To’g'ri to'rtburchak chiziqlardan tashkil topgan. Chiziq esa ikki nuqta orqali aniqlanadi. Har bir nuqta x va y koordinatalar yordamida aniqlanadi. Quyidagi dasturda to'rtburchak sinfi ko'rsatilgan. To'g'ri to'rtburchak diagonal bo'yicha ikki nuqta va ikki tomon yordamida aniqlanadi. Shuning uchun oldin har bir nuqtaning x va y koordinatalarini saqlash uchun nuqta sinfi e’lon qilingan. Nuqta va to‘g‘ri to'rtburchakning e’lon qilinishi
#include
using namespace std;
class Point
{ public: Point(int xl=0, int yl=0) { x = xl; y=yl; }
int GetX() const {return x;}
int GetY() const {return y;}
private: int x; int y; };
class Rectangle { public: Rectangle(int xl, int yl, int x2, int y2):
p1(xl, yl), p2(x2, y2)
{ a=x2-xl; b=y2-yl; };
Rectangle(Point a1, Point a2):p1(a1), p2(a2)
{a=a2.GetX()-a1.GetX();
b=a2.GetY()-a1.GetY();};
int Per() {return 2*(a + b);}
int Sq() {return a*b;}
private: Point p1, p2; int a, b; };
intmain(){RectangleX(10,20,50,80); cout<<"Perimetr="<93. Lokal sinflar
Lokal sinflar. Sinf blok ichida, masalan, funksiya tomonida tarifilanishi mumkin. Bunday sinf lokal sinf deb ataladi. Lokal sinf komponentalariga shu sinf tariflangan blok yoki funksiya lashqarisida murojaat qilish mumkin emas. Lokal sinf statik komponentlarga ega bo'lishi mumkin emas. Lokal sinf ichida shu sinf aniqlangan soniga tegishli nomlari; statik (static) o'zgaruvchilar: tashqi (extern) o’zgaruvchilar va tashqi funksiyalardan foydalanish mumkin. Avtomatik xotira turiga tegishli o'zgaruvchilardan foydalanish mumkin emas. Lokal sinflar komponent funksiyalari faqat joylashuvchi (inline) funksiya bo'lishi mumkin. Quyidagi misolda moddiy nuqta sinfi yaratilib, uning ichida nuqta sinfiga ta’rif berilgan va nuqta sinfi obyekti maydon sifatida kelgan:
#include
using namespace std;
class FPoint { public: //Nuqta sinfi
class Point
{ public: Point(int x1 =0, int y1 =0)
{ x = x1; y=y1; }
int GetX() const {return x;}
int GetY() const {return y;}
private: int x; int y; };
FPoint(int xl, int yl, double wl):
p(xl, yl), w(wl){}; void show()
{ cout<<"koordinata x = "<
private: Point p; double w; }; int main() { cout<<"fizik nuqta"<int kk; cin>>kk; return 0; }
94. C++ da vorislik
Do'stlaringiz bilan baham: |