le mie informazioni di contatto
Posta[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Sommario
Orientato al processo e orientato agli oggetti
Programmazione orientata agli oggetti
Formato di definizione della classe
2. Qualificatori di accesso alle classi e incapsulamento
Caratteristiche di questo puntatore
La programmazione orientata ai processi è un'idea di programmazione centrata sul processo. Nella programmazione orientata ai processi, un programma è visto come una raccolta di funzioni o procedure eseguite in un determinato ordine per completare un'attività specifica.
vantaggio:
- Prestazioni efficienti : poiché la programmazione orientata al processo esegue direttamente le attività in base al processo e non richiede un'eccessiva creazione e gestione di oggetti, ha una maggiore efficienza di esecuzione in alcuni scenari con requisiti di prestazioni più elevati, come la programmazione del sistema sottostante, la programmazione incorporata, ecc. Ad esempio, nel kernel del sistema operativo, la programmazione orientata ai processi può essere utilizzata per ottimizzare meglio le prestazioni per l'implementazione di funzioni come la pianificazione dei processi e la gestione della memoria.
- logica chiara : Per una logica di programma semplice, viene implementata passo dopo passo in base al processo. La struttura logica del codice è chiara e facile da capire, facile da comprendere e mantenere. Ad esempio, un semplice programma che calcola la somma di due numeri può definire direttamente una funzione per il calcolo utilizzando la programmazione orientata al processo.
discordanza:
- Scarsa manutenibilità : Quando la dimensione del programma aumenta e le funzioni diventano complesse, il codice orientato alla programmazione procedurale può diventare difficile da mantenere ed estendere. Poiché l'accoppiamento tra le varie funzioni è elevato, la modifica di una funzione può influire su altre funzioni correlate.
- Riutilizzabilità del codice ridotta: Il riutilizzo del codice viene solitamente ottenuto tramite chiamate di funzioni, ma per moduli funzionali complessi il riutilizzo è più difficile e le funzioni non possono essere ben incapsulate e astratte.
La programmazione orientata agli oggetti è un'idea di programmazione centrata sugli oggetti. Un oggetto è un'entità che contiene dati (proprietà) e metodi (comportamenti) per manipolare tali dati. Incapsulando dati e metodi correlati in un oggetto, si ottiene l'integrazione di dati e operazioni.
vantaggio:
- Elevata manutenibilità : Incapsula le funzioni negli oggetti, nascondendo l'implementazione interna degli oggetti dal mondo esterno e riducendo l'accoppiamento tra i moduli. Quando è necessario modificare una funzione, è necessario modificare solo l'implementazione interna dell'oggetto corrispondente senza influenzare altre parti non correlate. Ad esempio, in un'applicazione con interfaccia grafica, se si desidera modificare la funzione di un pulsante, è sufficiente modificare il metodo corrispondente dell'oggetto pulsante senza influenzare gli altri elementi dell'interfaccia.
- Forte riusabilità del codice : Il riutilizzo e l'espansione del codice possono essere facilmente ottenuti tramite ereditarietà, polimorfismo e altre funzionalità.Ad esempio, crea una classe base
Shape
(forma) e poi derivareCircle
(girare),Rectangle
(Rettangolo) e altre sottoclassi, le sottoclassi possono riutilizzare gli attributi e i metodi della classe base e creare estensioni specifiche.- Buona flessibilità: La programmazione orientata agli oggetti supporta il polimorfismo, che consente al programma di selezionare ed eseguire dinamicamente metodi corrispondenti in base al tipo effettivo dell'oggetto durante il runtime, aumentando la flessibilità e la scalabilità del programma.
discordanza:
- Sovraccarico delle prestazioni: poiché la creazione di oggetti, la chiamata di metodi e altre operazioni richiedono un certo sovraccarico, in alcuni scenari con requisiti di prestazioni estremamente elevati, ciò potrebbe influire sull'efficienza di esecuzione del programma.
- Costo di apprendimento elevato: I concetti e le caratteristiche della programmazione orientata agli oggetti sono relativamente complessi, rendendo difficile l'apprendimento e la comprensione per i principianti.
• class è la parola chiave che definisce la classe, Data è il nome della classe e {} è il corpo della classe. Si noti che il punto e virgola finale non può essere omesso alla fine della definizione della classe. I contenuti nel corpo della classe sono chiamati membri della classe: le variabili nella classe sono chiamate attributi o variabili membro della classe sono chiamate metodi o funzioni membro della classe;
• Per distinguere le variabili membro, è generalmente consuetudine aggiungere un identificatore speciale alla variabile membro, ad esempio iniziare con _ o m prima o dopo la variabile membro. Nota che questo non è obbligatorio in C++, si tratta solo di alcune convenzioni .
• In C++, struct può anche definire classi. C++ è compatibile con l'uso di struct in C. Allo stesso tempo, struct è stato aggiornato a una classe. Il cambiamento ovvio è che le funzioni possono essere definite in struct si consiglia di utilizzare class per definire le classi.
• Le funzioni membro definite in una classe sono inline per impostazione predefinita.
class Date { public: void Init(int year, int month, int day) { _year = year; _month = month; _day = day; } private: // 为了区分成员变量,⼀般习惯上成员变量 // 会加⼀个特殊标识,如_ 或者 m开头 int _year; // year_ m_year int _month; int _day; }; int main() { Date d; d.Init(2024, 3, 31); return 0; }
• La classe definisce un nuovo ambito. Tutti i membri della classe rientrano nell'ambito della classe. Quando si definiscono membri esterni alla classe, è necessario utilizzare l'operatore ::scope per indicare a quale dominio della classe appartiene il membro.
• Il dominio della classe influisce sulle regole di ricerca della compilazione. Se Init nel programma seguente non specifica il dominio della classe Stack, il compilatore tratterà Init come una funzione globale. Quindi durante la compilazione, la dichiarazione/definizione di membri come l'array non può esserlo trovato, verrà segnalato un errore. Specificare il dominio della classe Stack significa sapere che Init è una funzione membro. Se non è possibile trovare membri come l'array nel dominio corrente, verranno cercati nel dominio della classe.
- #include<iostream>
- using namespace std;
- class Stack
- {
- public:
- // 成员函数
- void Init(int n = 4);
- private:
- // 成员变量
- int* array;
- size_t capacity;
- size_t top;
- };
- // 声明和定义分离,需要指定类域
- void Stack::Init(int n)
- {
- array = (int*)malloc(sizeof(int) * n);
- if (nullptr == array)
- {
- perror("malloc申请空间失败");
- return;
- }
- capacity = n;
- top = 0;
- }
- int main()
- {
- Stack st;
- st.Init();
- return 0;
- }
• C++ è un modo per implementare l'incapsulamento, utilizzando classi per combinare le proprietà ei metodi di un oggetto per rendere l'oggetto più completo e fornire selettivamente le sue interfacce agli utenti esterni tramite autorizzazioni di accesso.
• È possibile accedere direttamente ai membri modificati da public all'esterno della classe; i membri modificati da protected e private non sono accessibili direttamente all'esterno della classe. Protected e private sono la stessa cosa e le loro differenze verranno riportate nel capitolo sull'ereditarietà successivo.
• L'ambito delle autorizzazioni di accesso inizia dalla posizione in cui appare il qualificatore di accesso fino a quando non viene visualizzato il qualificatore di accesso successivo. Se non esiste un qualificatore di accesso successivo, l'ambito termina con }, ovvero la classe.
• Quando un membro della definizione di classe non viene modificato da un qualificatore di accesso, il suo valore predefinito è privato.
• la struttura per impostazione predefinita è pubblica
• Generalmente, le variabili membro saranno limitate a private/protette e le funzioni membro che devono essere utilizzate da altri saranno rese pubbliche.
Le tre caratteristiche principali dell'orientamento agli oggetti: incapsulamento, ereditarietà e polimorfismo.
Nella fase di classe e oggetto, studiamo principalmente le caratteristiche di incapsulamento delle classi. Allora, cos'è l'incapsulamento?
Incapsulamento: combina organicamente dati e metodi di dati operativi, nasconde le proprietà e i dettagli di implementazione dell'oggetto ed espone solo l'interfaccia per interagire con l'oggetto.
L'incapsulamento è essenzialmente un tipo di gestione che semplifica l'utilizzo delle classi da parte degli utenti. Ad esempio: per un dispositivo complesso come un computer, le uniche cose fornite all'utente sono i tasti di accensione e spegnimento, l'input da tastiera, il monitor, la presa USB, ecc., consentendo all'utente di interagire con il computer e completare le attività quotidiane. Ma in realtà il vero lavoro del computer è la CPU, la scheda grafica, la memoria e altri componenti hardware.
Gli utenti di computer non devono preoccuparsi dei componenti interni principali, ad esempio come sono disposti i circuiti sulla scheda madre, come è progettata la CPU, ecc. Gli utenti devono solo sapere come accendere il computer e come accenderlo. interagire con il computer tramite tastiera e mouse. Pertanto, quando i produttori di computer lasciano la fabbrica, mettono un guscio all'esterno per nascondere i dettagli di implementazione interna e forniscono solo interruttori di alimentazione, jack per mouse e tastiera all'esterno in modo che gli utenti possano interagire con il computer.
Per implementare l'incapsulamento nel linguaggio C++, dati e metodi per i dati operativi possono essere combinati organicamente attraverso le classi e le autorizzazioni di accesso possono essere utilizzate per nascondere i dettagli di implementazione interna degli oggetti e controllare quali metodi possono essere utilizzati direttamente all'esterno della classe.
• Il processo di creazione di un oggetto nella memoria fisica utilizzando un tipo di classe è chiamato creazione di istanze di classe.
• Una classe è una descrizione astratta di un oggetto. È qualcosa come un modello, che limita le variabili membro della classe. Queste variabili membro vengono solo dichiarate e non allocano spazio. Lo spazio verrà allocato quando un oggetto viene istanziato con a classe.
• Una classe può istanziare più oggetti. Gli oggetti istanziati occupano lo spazio fisico effettivo e memorizzano le variabili dei membri della classe. Ad esempio: istanziare oggetti da una classe è come utilizzare disegni di progettazione architettonica per costruire una casa nella realtà. Una classe è come un disegno di progettazione che pianifica quante stanze ci sono, le dimensioni e le funzioni della stanza, ecc., ma lì non è un oggetto fisico. Anche se un edificio esiste, non può ospitare persone. Solo quando una casa è costruita utilizzando i disegni di progetto la casa può essere ospitata. La stessa classe è come un disegno di progettazione e non può archiviare dati. L'oggetto istanziato alloca memoria fisica per archiviare dati.
Analizzare quali membri ci sono nell'oggetto della classe? Ogni oggetto istanziato da una classe ha uno spazio dati indipendente, quindi l'oggetto deve contenere variabili membro. Quindi sono incluse le funzioni membro? Innanzitutto, dopo che la funzione è stata compilata, si tratta di una sezione di istruzioni che non può essere memorizzata nell'oggetto. Queste istruzioni vengono memorizzate in un'area separata (segmento di codice), quindi se devono essere memorizzate nell'oggetto, possono solo esserlo puntatori alle funzioni membro. Analizziamo di nuovo, è necessario memorizzare i puntatori nell'oggetto? Date istanzia due oggetti d1 e d2 Sia d1 che d2 hanno le proprie variabili membro indipendenti _year/_month/_day per memorizzare i propri dati, ma la funzione membro Init/Print. i puntatori di d1 e d2 sono gli stessi, quindi memorizzarli negli oggetti è sprecato. Se si utilizza Date per creare un'istanza di 100 oggetti, il puntatore alla funzione membro verrà archiviato 100 volte, il che è troppo dispendioso. In effetti, non è necessario memorizzare il puntatore alla funzione. Il puntatore alla funzione è un indirizzo. La funzione chiamante viene compilata in un'istruzione assembly [indirizzo di chiamata]. Infatti, il compilatore deve trovare l'indirizzo della funzione durante la compilazione e il collegamento , non in fase di esecuzione. In fase di esecuzione viene trovato solo il polimorfismo dinamico e gli indirizzi delle funzioni devono essere memorizzati.
Sopra abbiamo analizzato che solo le variabili membro sono archiviate negli oggetti. Il C++ stabilisce che anche gli oggetti istanziati dalle classi devono rispettare le regole di allineamento della memoria.
Regole di allineamento della memoria
Le regole di allineamento della memoria sono esattamente le stesse del linguaggio CArticolo di riferimento:Linguaggio C per calcolare l'allineamento della memoria
Il primo membro si trova all'indirizzo offset 0 dalla struttura.
• Le altre variabili membro dovrebbero essere mappate su indirizzi che sono multipli interi di un certo numero (numero di allineamento).
• Nota: Logaritmo = il più piccolo tra il numero di allineamento predefinito del compilatore e la dimensione del membro.
•Il logaritmo predefinito in VS è 8
• La dimensione totale della struttura è: un multiplo intero del numero massimo di allineamento (il più grande di tutti i tipi di variabile e il più piccolo parametro di allineamento predefinito).
• Se una struttura è annidata e la struttura annidata è allineata a un multiplo intero del suo logaritmo massimo, la dimensione complessiva della struttura è il numero massimo di allineamento di tutti i numeri (incluso l'allineamento della struttura annidata).
Se non c'è nessuna variabile membro, deve essere dato 1 byte, perché se non viene dato nemmeno un byte, come si può dimostrare che l'oggetto è esistito? Quindi 1 byte viene fornito qui esclusivamente per l'identificazione segnaposto dell'esistenza dell'oggetto.
Ci sono due funzioni membro, Init e Print, nella classe Date. Non c'è distinzione tra diversi oggetti nel corpo della funzione. Quindi, quando d1 chiama le funzioni Init e Print, come fa la funzione a sapere se deve accedere all'oggetto d1 o l'oggetto d2?Poi qui vedremo che il C++ fornisce implicitamente un puntatore this per risolvere il problema qui.
• Dopo la compilazione del compilatore, le funzioni membro della classe aggiungeranno un puntatore del tipo di classe corrente, chiamato puntatore, alla prima posizione del parametro formale per impostazione predefinita. Ad esempio, il vero prototipo della classe Init of Date è,void Init(Date* const this, int anno, int mese, int giorno) • Quando si accede alle variabili membro nelle funzioni membro della classe, si accede essenzialmente tramite questo puntatore. Ad esempio, quando si assegna un valore a _anno nella funzione Init, this - >_anno = anno;
• Il C++ stabilisce che questo puntatore non può essere scritto esplicitamente nella posizione dei parametri effettivi e dei parametri formali (il compilatore lo gestirà durante la compilazione), ma può essere utilizzato esplicitamente nel corpo della funzione.
- #include<iostream>
- using namespace std;
- 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(2024, 7, 1); // d1.Init(&d1, 2024, 7, 1);
- d1.Print(); // d1.Print(&d1);
- d2.Init(2024, 7, 10); // d2.Init(&d2, 2024, 7, 10);
- d2.Print(); // d2.Print(&d2);
- return 0;
- }