2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Edellisessä luvussa mainitsimme lyhyesti joitakin luokkien ja objektien käsitteitä. Tarkastellaanpa niitä nyt yhdessä.
class on määrittävä luokan avainsana, jota seuraa määrittävän luokan nimi, {} on luokan pääosa, jota seuraa ";", ja luokassa määritetyt jäsenfunktiot laajennetaan oletusarvoisesti (inline)
Kapselointimuoto, joka on jaettu kolmeen tyyppiin: julkinen, yksityinen ja suojattu Käyttöoikeuksien laajuus alkaa kohdasta, jossa käyttötunnistin tulee näkyviin, jos myöhempää käyttötunnusta ei ole päättyy } eli luokkaan.
Luokka määrittelee uuden laajuuden Kaikki luokan jäsenet ovat luokan ulkopuolella.
Seuraava on pitkä elokuva///
• Objektin luomista fyysiseen muistiin käyttämällä luokkatyyppiä kutsutaan luokan ilmentymiseksi.
• Luokka on abstrakti kuvaus objektista. Se rajoittaa vain luokan jäsenmuuttujia
Se on ilmoitus, eikä tilaa varata vain, kun objekti instantoidaan luokan avulla.
• Luokka voi instantoida useita objekteja. Instantoidut objektit vievät todellista fyysistä tilaa ja tallentavat luokan jäsenmuuttujia.
Yhteenvetona yhteen lauseeseen: vain kun objektit on toteutettu luokilla, ne varaavat tilaa (Aivan kuin talon rakentaminen piirroksista vie tilaa).
- class Date
- {
- public:
- void Init(int year, int month, int day)
- {
- _year = year;
- _month = month;
- _day = day;
- }
- void Print()
- {
- cout << _year << "/" << _month << "/" << _day << endl;
- }
- private:
- // 这⾥只是声明,没有开空间
- int _year;
- int _month;
- int _day;
- };
Yllä olevassa koodissa jäsenmuuttujat vain määritellään, eikä uutta tilaa avata ja
- // Date类实例化出对象d1和d2
- Date d1;
- Date d2;
Sitten kaksi uutta objektia instantoidaan, joten uusi tila avautuu.
• Ensimmäinen jäsen on osoitteen offsetissa 0 rakenteesta.
• Muut jäsenmuuttujat tulee yhdistää osoitteisiin, jotka ovat tietyn luvun (logaritmin) kokonaislukukertoja.
• Huomautus: logaritmi = pienempi kääntäjän oletuslogaritmi ja jäsenen koko.
• VS:n oletuslogaritmi on 8
• Rakenteen kokonaiskoko on: suurimman parittaisen luvun kokonaislukukerrannainen (suurin kaikista muuttujatyypeistä ja pienin oletuspariparametri).
• Jos rakenne on sisäkkäinen, sisäkkäinen rakenne kohdistuu maksimilogaritminsa ja rakenteen kokonaiskoon kokonaislukukerrokseen.
Se on kaikkien suurimpien logaritmien (mukaan lukien sisäkkäisten rakenteiden logaritmit) kokonaislukukerrannainen.
Tämän tiedämme C-kielellä. Otetaan esimerkkinä seuraavat kysymykset:
- // 计算⼀下A实例化的对象是多⼤?
- class A
- {
- public:
- void Print()
- {
- cout << _ch << endl;
- }
- private:
- char _ch;
- int _i;
- };
Funktiota ei ole kutsuttu, joten katsokaa vain jäsenmuuttujia. _ch on 1-tavuinen merkkityyppi. _i on int-tyyppi, jonka koko on 4 tavua tasausnumero, joten se on _ Aseta ch kohtaan, jossa on alaindeksi 0, jätä kolme välilyöntiä tyhjäksi ja laita sitten _i Se vie yhteensä 8 tavua väliltä 0-7, mikä on tasausluvun kokonaislukukerrannainen. Se täyttää ehdot, joten vastaus tähän kysymykseen on 8 .
Entä jos nämä kaksi kysymystä?
- class B
- {
- public:
- void Print()
- {
- //...
- }
- };
-
- class C
- {
- };
Voimme havaita, että luokassa B on tyhjä funktio eikä luokassa C jäseniä. C-kielessä molemmat luokat vievät 1 tavun tilaa.
• DAte-luokassa on kaksi jäsenfunktiota, funktion rungossa ei ole eroa eri objektien välillä. Kun d1 kutsuu Init ja Print,
Kuinka funktio tietää tulostaessaan funktiota, tuleeko sen käyttää d1- vai d2-objektia?Sitten tässä näemme, että C++ antaa
Tämä implisiittinen osoitin ratkaisee ongelman tässä
• Kun kääntäjä on käännetty, luokan jäsenfunktiot lisäävät oletusarvoisesti muodollisen parametrin ensimmäiseen paikkaan nykyisen luokkatyypin osoittimen, jota kutsutaan nimellä tämä osoitin. Esimerkiksi Init of Date -luokan todellinen prototyyppi on, void Init(Date* const this, int year,
int kuukausi, int päivä)
• Kun päästään luokan jäsenfunktioiden jäsenmuuttujiin, niihin päästään olennaisesti tämän osoittimen kautta. Esimerkiksi, kun määritetään arvo _yearille Init-funktiossa, tämä-.
>_vuosi = vuosi;
• C++ edellyttää, että tätä osoitinta ei voi kirjoittaa eksplisiittisesti todellisten parametrien ja muodollisten parametrien paikkaan (kääntäjä käsittelee tämän kääntämisen aikana), mutta tätä osoitinta voidaan käyttää eksplisiittisesti funktion rungossa.
esimerkiksi
- class Date
- {
- public:
- // void Init(Date* const this, int year, int month, int day)
- void Init(int year, int month, int day)
- {
- // 编译报错:error C2106: “=”: 左操作数必须为左值
- // this = nullptr;
- // this->_year = year;
- _year = year;
- this->_month = month;
- this->_day = day;
- }
- void Print()
- {
- cout << _year << "/" << _month << "/" << _day << endl;
- }
- private:
- // 这⾥只是声明,没有开空间
- int _year;
- int _month;
- int _day;
- };
-
- int main()
- {
- // Date类实例化出对象d1和d2
- Date d1;
- Date d2;
- // d1.Init(&d1, 2024, 3, 31);this指针
- d1.Init(2024, 3, 31);
-
- // d1.Init(&d2, 2024, 7, 5);
- d2.Init(2024, 7, 5);
- //不能自己写
- return 0;
- }
Varsinaisten parametrien kirjoittamista varten Init-funktiossa C++ lisää tämän osoittimen näkymättömän vakion (jota ei voi muokata) funktion ensimmäiseen muuttujaan, kuten funktion kommenteissa näkyy.
Niin kauan kuin nollaosoittimen viittausta ei poisteta, virhettä ei raportoida.
- class A
- {
- public:
- void Print()
- {
- cout << "A::Print()" << endl;
- }
- private:
- int _a;
- };
-
- int main()
- {
- A* p = nullptr;
- p->Print();
- return 0;
- }
Vaikka p:lle on määritetty nollaosoitin ja se osoitti Tulosta-toimintoa, sitä ei poisteta, joten tässä ei raportoida virhettä. Ja tämä ohjelma:
- class A
- {
- public:
- void Print()
- {
- cout << "A::Print()" << endl;
- cout << _a << endl;//这个地方多了一句
- }
- private:
- int _a;
- };
-
- int main()
- {
- A* p = nullptr;
- p->Print();
- return 0;
- }
Edelliseen ohjelmaan verrattuna on vain yksi lause lisää << _a << endl, mutta tällä hetkellä nollaosoitin osoittaa jäsenmuuttujaan ja nollaosoittimesta poistetaan viittaus, joten ohjelma ilmoittaa virheestä.
Oletusjäsenfunktio on jäsenfunktio, jota käyttäjä ei ole erikseen toteuttanut ja jonka kääntäjä luo automaattisesti. Sitä kutsutaan oletusjäsenfunktioksi. Luokalle, jos emme kirjoita sitä, kääntäjä luo seuraavat 6 oletusjäsenfunktiota oletuksena, jotka ovat seuraavat 6
Konstruktori on erityinen jäsenfunktio On huomattava, että vaikka konstruktorin nimeä kutsutaan konstruktoriksi, rakentajan päätehtävä ei ole avata tilaa objektien luomiseksi (usein käyttämämme paikallinen objekti on pinon tila. kehys luodaan) ), objekti alustetaan sen sijaan, kun objekti instantoidaan. Tavoitteena on korvata alustus Init-funktio.
1. Funktion nimi on sama kuin luokan nimi.
2. Ei palautusarvoa. (Ei tarvitse kirjoittaa tyhjää)
3. Kun objekti on instantoitu, järjestelmä kutsuu automaattisesti vastaavaa rakentajaa.
4. Rakentajat voivat olla ylikuormitettuja.
5. Jos luokassa ei ole erikseen määriteltyä konstruktoria, C++-kääntäjä luo automaattisesti parametrittoman oletuskonstruktorin Kun käyttäjä on nimenomaisesti määrittänyt sen, kääntäjä ei enää luo sitä.
Ensimmäiset viisi kohdetta ovat suhteellisen yksinkertaisia, annetaan esimerkki:
- class Date
- {
- public:
- //1.⽆参构造函数,无需写void
- Date()//若不写,则构造函数会写出这一中无参构造函数
- {
- _year = 1;
- _month = 1;
- _day = 1;
- }
- //2.全缺省构造函数
- Date(int year = 1, int month = 1, int day = 1)
- {
- _year = year;
- _month = month;
- _day = day;
- }
- private:
- int _year;
- int _month;
- int _day;
- }
-
- int main()
- {
- Date d1;//此时相当于已经自动调用了Init函数
- Date d2;
-
- return 0;
- }
Ohjelmaan on kirjoitettu kaksi konstruktoria, toinen on parametriton konstruktori ja toinen on täysin oletuskonstruktori kaksi toimintoa ovat ylikuormitettuja funktioita, koska kutsumisen epäselvyyden vuoksi nämä kaksi toimintoa eivät voi olla olemassa samanaikaisesti.
6. Parametrittomia konstruktoreita, täydellisiä oletuskonstruktoreita ja kääntäjän oletusarvoisesti luomia konstruktoreita, kun emme kirjoita konstruktoria, kutsutaan kaikkia oletuskonstruktoreiksi. Kuitenkin yksi ja vain yksi näistä kolmesta toiminnosta on olemassa eikä voi olla olemassa samanaikaisesti. Vaikka parametriton konstruktori ja täysi oletuskonstruktori muodostavat funktion ylikuormituksen, niitä kutsuttaessa esiintyy epäselvyyttä. On huomattava, että monet opiskelijat ajattelevat, että oletuskonstruktori on kääntäjän luoma oletuskonstruktori. Itse asiassa parametriton konstruktori ja koko oletuskonstruktori ovat myös oletuskonstruktoreja sitä kutsutaan oletusrakenteeksi.
Kuudes ominaisuus on monimutkaisempi: parametrittomat konstruktorit, kaikki oletuskonstruktorit ja kääntäjän oletusarvoisesti luomat konstruktorit, kun emme kirjoita konstruktoria, kaikkia kutsutaan oletuskonstruktoreiksi, ja oletuskonstruktoreita voi olla vain yksi oletusarvoisesti kääntäjän luomana rakentajana!
7. Jos emme kirjoita, kääntäjän luomalla konstruktorilla ei ole oletuksena vaatimuksia sisäänrakennettujen jäsenmuuttujien alustamiselle. Toisin sanoen on epävarmaa, onko se alustettu vai ei, se riippuu kääntäjästä . Mukautetun tyypin jäsenmuuttujien osalta on kutsuttava tämän jäsenmuuttujan oletuskonstruktori sen alustamiseksi. Jos tällä jäsenmuuttujalla ei ole oletuskonstruktoria, raportoidaan virhe. Jos haluamme alustaa tämän jäsenmuuttujan, meidän on käytettävä alustusluetteloa ongelman ratkaisemiseksi .
Destruktorin toiminto on päinvastainen kuin rakentajan. Esimerkiksi paikallisella objektilla on pinokehys, kun se tuhoutuu vapautettu Meidän ei tarvitse hallita sitä. Destruktorin toiminto on samanlainen kuin aiemmin Stackissa toteuttamamme Destroy-funktio. Esimerkiksi Date ei sisällä Destroyta destructor on aivan kuten Destroy-funktio. Sitä tulisi käyttää tietorakenteissa, jotka vaativat ei-paikallisia objekteja, kuten pinoja ja jonoja.
1. Destruktorin nimeä edeltää merkki ~ ennen luokan nimeä. (Samanlainen kuin bittikohtainen negaatio C-kielessä)
2. Ei parametreja eikä palautusarvoa. (Tämä on samanlainen kuin rakenne, eikä siihen tarvitse lisätä tyhjää)
3. Luokassa voi olla vain yksi tuhoaja. Ellei sitä ole erikseen määritelty, järjestelmä luo automaattisesti oletushävittäjän.
4. Kun kohteen elinkaari päättyy, järjestelmä kutsuu automaattisesti tuhoajaa.
5. Samoin kuin rakentaja, jos emme kirjoita kääntäjän automaattisesti luomaa destruktoria, se ei käsittele sisäänrakennettuja mukautetun tyypin jäseniä, jotka kutsuvat tuhoajiaan.
6. On myös huomattava, että kun kirjoitamme eksplisiittisesti destructorin, kutsutaan myös mukautetun tyypin jäsenen tuhoajaa, toisin sanoen mukautetun tyypin jäsenen tuhoajaa kutsutaan automaattisesti tilanteesta riippumatta.
7. Jos luokassa ei ole haettuja resursseja, destruktoria ei tarvitse kirjoittaa, vaan kääntäjän luomaa oletusdestruktoria, kuten Date, voidaan käyttää suoraan. sitä ei tarvitse näyttää. Kirjoita tuhoaja, kuten MyQueue, mutta kun on olemassa resurssisovellus, sinun on kirjoitettava tuhoaja itse, muuten se aiheuttaa resurssivuotoja, kuten Stack.
8. Useille paikallisen toimialueen objekteille C++ edellyttää, että myöhemmin määritellyt tuhotaan ensin.
Kuten yllä oleva konstruktori, C++:n automaattisesti luomasta oletusdestruktorista ei yleensä ole meille suurta apua, mutta se on helpompaa joissain harvoissa tapauksissa, kuten käyttämällä kahta pinoa jonon toteuttamiseen:
- public:
- Stack(int n = 4)//相当于Init
- {
- _a = (STDataType*)malloc(sizeof(STDataType) * n);
- if (nullptr == _a)
- {
- perror("malloc fail!");
- return;
- }
- _capacity = n;
- _top = 0;
- }
- ~Stack()//相当于Destroy
- {
- cout << "~Stack()" << endl;
- free(_a);
- _a = nullptr;
- _top = _capacity = 0;
- }
- private:
- STDataType* _a;
- size_t _capacity;
- size_t _top;
- };
-
- class MyQueue
- {
- public:
- //编译器默认⽣成MyQueue的析构函数调⽤了Stack的析构,释放的Stack内部的资源
- // 显⽰写析构,也会⾃动调⽤Stack的析构
-
- private:
- Stack pushst;
- Stack popst;
- };
Tällä hetkellä MyQueuen kääntäjä kutsuu automaattisesti pinon rakentajaa (alustus) ja tuhoajaa (destruction).