La position actuelle:Accueil du site>Classes et objets (1)

Classes et objets (1)

2022-07-23 07:36:39Rêve de bateau vide

Classes et objets

1.Connaissance préliminaire orientée objet et processus(L'orientation des objets et des processus exige une connaissance approfondie du processus d'apprentissage):

Comme un système de livraison:

L'objectif est de se concentrer sur les commerçants,Clients,Cavalier.L'accent est mis sur l'analyse de la relation entre les trois catégories.Diviser une chose en différents objets,Par l'interaction entre les objets.

L'orientation vers le processus est axée sur la façon de mettre en oeuvre:Articles en vente,Commander à emporter,Informer les commerçants,Contact Rider,Livraison,Commentaires.Comment réaliser ces fonctions par fonction.

CLe langage est orienté vers le processus,L'accent est mis sur le processus,Analyser les étapes pour résoudre le problème,Résoudre le problème étape par étape par un appel de fonction.

C++Est basé sur un objet orienté,Il s'agit de l'objet,Diviser une chose en différents objets,Par l'interaction entre les objets.

2.Introduction de classes

c++Ça a commencé parstructPour introduire,c++Compatible avecCLangues,Etc++C'est exact.structMise à jour.Oui.structMise à jour vers la classe.

En particulier::1.Le nom de la structure peut être utilisé comme classe(Il n'est pas nécessaire d'ajouterstructC'est) 2.Il peut définir des fonctions.

c++Définition de la structure:

struct ListNode

{

    int a;

    ListNode* next;

}Il n'y aura pas d'erreur..

Définir les fonctions:

struct student

{

    void Init(const char* name, const char* sex, int age)

    {

        strcpy(_name, name);

        strcpy(_sex, sex);

        _age = age;

    }

    void Print()

    {

        cout << _name << " " << _sex << " " << _age << endl;

    }

    char _name[20];

    //_ Il n'est pas nécessaire d'ajouter , Juste l'habitude plus , Utilisé pour représenter la variable membre .

    char _sex[5];

    int _age;

    // Le compilateur ne cherche que vers le haut , Mais la classe est un tout , .La variable membre à la recherche d'une classe se trouve dans l'ensemble de la classe .

};

int main()

{

    struct student s1

    //student s1C'est possible.

    s1.Init("zhangsan", "male", 18);

    // Cas d'utilisation de la classe

    s1.Print();

    return 0;

}

Le résultat est imprimé:zhangsan male 18

Bien questructC'est vrai.,Maisc++ J'aime toujours utiliser de nouveaux mots clés :class Pour définir une classe.

Dec++ Ça commence ici , On n'appelle pas ça une variable , Je préfère appeler un objet .student s1,studentC'est la classe,s1 Est l'objet défini par la classe .

Regarder le Code orienté processus, c'est regarder le processus d'implémentation de chaque fonction ;

Regarder le Code orienté objet, c'est regarder le marchand remplir la commande , Le Cavalier livre la commande , L'utilisateur soumet une commande . Beaucoup d'objets font un tel Multi - parcours .

3.Définition de la classe

structEtclass Il y a une différence dans la définition des classes .

classDéfinir la classe

class classname

{

    //Corps de classe:Se compose d'une fonction membre et d'une variable membre

};

Il y a aussi un qualificatif d'accès ,Qualificatif d'accès:public(Public),protected(Protection),private(Privé)

c++ Il y a un concept appelé Encapsulation . Le qualificatif d'accès est ainsi proposé , La signification du qualificatif d'accès est que , Corps de classe défini dans la classe , Il n'est pas nécessaire de tout vous donner . Je voulais t'en donner ,Défini comme public:

class student

{

public://publicC'est un nouveau mot clé,Représentantpublic Jusqu'à la fin, c'était public

    void Init(const char* name, const char* sex, int age)

    {

        strcpy(_name, name);

        strcpy(_sex, sex);

        _age = age;

    }

    void Print()

    {

        cout << _name << " " << _sex << " " << _age << endl;

    }

    char _name[20];

    char _sex[5];

    int _age;

};

int main()

{

    struct student s1

    s1.Init("zhangsan", "male", 18);//SiclassDans la classepublicEnlevez,Compiler les erreurs signalées

    s1.Print();

    return 0;

}

La raison de l'erreur est,class L'espace dans est privé par défaut , Il faut ajouter public,Etstruct L'espace est public par défaut .

Public est accessible en dehors de la classe , Ce qui est privé, c'est que les classes ne sont pas accessibles à l'extérieur .struct Peut également ajouter un qualificatif d'accès .

Si un qualificatif d'accès privé est ajouté , Cela inclut l'impression , Ne peut pas être fait en dehors de l'espace de classe .À ce stade,- Oui.protectedEtprivateC'est pareil.

4. Qualificatifs d'accès et Encapsulation

4.1Description du qualificatif d'accès:

    1. publicLes membres modifiés peuvent être accédés directement en dehors de la classe

    2. protectedEtprivateLes membres modifiés ne sont pas directement accessibles en dehors de la classe(Ici.protectedEtprivateC'est similaire)

    3. Le champ d'application des droits d'accès commence à l'endroit où le qualificatif d'accès apparaît jusqu'à ce que le qualificatif d'accès suivant apparaisse

    4. classL'accès par défaut estprivate,structPourpublic(Parce questructPour être compatibleC)

Attention!:Les qualificatifs d'accès ne sont utiles qu'au moment de la compilation,Lorsque les données sont cartographiées en mémoire,Aucune différence dans les qualificatifs d'accès

4.2Encapsulation

Trois caractéristiques orientées objet:Encapsulation,Succession,Polymorphisme

Pour comprendre l'emballage, il faut CComparaison linguistique, Comme la pile de structure de données .

C La langue à mettre en œuvre :

struct  Stack

{

    int* _p;

    int _top;

    int _capacity;

};

void StackInit(struct Stack* p1);

void StackPush(struct Stack* p1, int x);

int StackTop(struct Stack* p1);

Les données et les méthodes sont séparées.

Le plus gros problème avec la séparation est trop libre . Comme dans l'utilisation ,Prendre l'élément supérieur de la pile.

printf("%d ", StackTop(&st));C'est une méthode., Il y a aussi un moyen :

printf("%d ", st._p[st._top]);Alors la question se pose,C'esttop Est - ce l'emplacement de l'élément supérieur de la pile ou l'emplacement suivant de l'élément supérieur de la pile ? Selon l'initialisation de la pile .

C'est - à - dire, Si vous changez le Code de la pile ,Il y a un problème ici.

c++ Il n'y aurait pas d'abus de ce qui précède :

c++ Encapsuler les données et les méthodes , C'est - à - dire qu'à l'intérieur de la classe ; Le design que vous souhaitez utiliser est public , Designed not want access to private .

class Stack

{

public:

    void Init();

    // Les noms de fonctions peuvent également être simplifiés , Parce qu'il a été déterminé que c'est une fonction de la pile . Les paramètres peuvent également être simplifiés , Parce qu'il est possible d'accéder directement aux objets de la classe dans l'espace de la classe .

    void Push(int x);

    int Top();

private:

    int* _p;

    int _top;

    int _capacity;

}

Voilà.c++ Le Code est normalisé , Il n'y a qu'une seule façon d'accéder à l'élément supérieur de la pile .

Généralités,Classe Design, Les variables membres sont privées ou protégées . Les fonctions accessibles sont conçues pour être publiques , Les fonctions qui ne sont pas accessibles sont conçues pour être privées .

Encapsulation:Combiner organiquement les données et les méthodes de manipulation des données,Masquer les propriétés et les détails de mise en œuvre de l'objet,Seules les interfaces externes sont exposées pour interagir avec les objets.

L'essence de l'encapsulation est une conception de gestion plus stricte .

5.Portée de la classe

La portée de la classe est l'ensemble de la classe ,La classe définit une nouvelle portée, Appelé domaine de classe . Comme le domaine scope namespace d'un espace de noms , C'est un nouveau domaine .

class Stack

{

public:

    void push(int x)

    {}

};

class Queue

{

public:

    void push(int x)

    {}

};

Demande.:Ces deux - là.push Peut - il exister en même temps ?

C'est bon., Premièrement, il ne constitue pas une surcharge de fonction , La surcharge de fonction nécessite le même nom de fonction ,Les paramètres sont différents, Et la fonction est surchargée dans le même champ d'application . La seule raison pour laquelle ils peuvent coexister, c'est parce qu'ils ont des champs d'application différents .

Définition déclarée d'une fonction de classe

C Dans la langue, nous séparons les déclarations et les définitions des fonctions , Regardez la structure de l'implémentation de la fonction .

c++ C'est comme ça que :

Définitionstack.hFichier d 'en - tête, Écris - y :

class Stack

{

public:

    void Init();

    void Push(int x);

    void Top();

private:

    int* _a;

    int _top;

    int _capacity;

}

Définition:

#include"stack.h"

void Stack::Init()// Le champ de classe correspondant doit être déclaré

{

    _a = nullptr;// Le qualificatif d'accès restreint l'accès à partir de l'extérieur de la classe

    _top = 0;

    _capacity = 0;

}

……

Fonctions définies dans la classe ,Le compilateur par défaut estinlineFonctions.

Donc en réalité, la situation générale , Les fonctions courtes et petites peuvent être définies directement dans la classe ; Une fonction plus longue ,Séparation des déclarations et des définitions.

6. Instanciation de la fonction

Le processus de création d'objets avec le type de classe , Appelé l'Instanciation de la classe

La classe ne peut pas stocker de données , Les objets définis par la classe peuvent stocker des données ;

Comme le type de variable , Le type de variable ne peut pas stocker de données , Les variables définies par type de variable peuvent stocker des données .

class Stack

{

public:

    void Init();

    void Push(int x);

    void Top();

private:

    int* _a;

    int _top;

    int _capacity;

}

Questions:private La section suivante est une déclaration ,Ou définir?

Déclaration, La différence entre une déclaration de variable et une définition réside dans la question de savoir si l'espace est ouvert ou non .

int main()

{

    Stack st;

    st.Init();

    cout <<sizeof(st) << endl;

    // Quelle est la taille de la classe ?

    return 0;

}

Il y a trois membres dans la pile ,Trois fonctions, Par compréhension , La fonction doit contenir un pointeur de fonction ,Quand la fonction est appelée, Et construire un cadre de pile , Fonction dans le champ de classe de la classe , Ainsi, le calcul de la taille de la classe peut également tenir compte de la taille du cadre de pile de fonctions .

Publier d'abord les résultats :Produits12

En termes de résultats réels , Devrait être un membre de la classe seulement stocké . Pourquoi ne stocker que les membres de la classe , Et si vous ne stockez pas les fonctions d'une classe ?

La classe peut instancier plusieurs objets , Les valeurs sont différentes pour chaque membre de l'objet . Mais chaque objet appelle une fonction dans la classe , La fonction appelée est une fonction au même endroit . Est - il nécessaire d'enregistrer une fonction dans l'objet ?Non., Par conséquent, le pointeur de la fonction n'existe pas dans l'objet . La zone commune dans laquelle la fonction est réellement stockée en mémoire , Ça s'appelle un fragment de code .Comme le montre la figure:

int main()

{

    Stack st1;

    st1._top;//Supposons que_top Non défini comme privé

    st1.Init();

    Stack st2;

    st2._top;

    st2.Init();

    return 0;

}

Deux._top Dans différents objets créés séparément dans la même classe ,Appelez_top Est de chercher dans l'objet ;Et l'appelInit Est appelé du même endroit .Init Non stocké dans l'objet . Calculer la taille de la classe , Sans tenir compte des fonctions des membres .

classDestruct Qui a évolué ,class Les membres de in satisfont également à l'alignement de la mémoire .Règles etstruct Même alignement de mémoire pour .

Règles d'alignement des structures:

1.Le premier membre est décalé de la variable structure par0À l'adresse de

2. Les autres variables membres doivent être alignées à l'adresse du multiple entier du nombre aligné

    Nombre d'alignements=Un nombre par défaut d'alignement du compilateur est plus petit que la taille du membre

    vs Le nombre par défaut d'alignement pour est 8

    linux Il n'y a pas d'alignement par défaut dans l'environnement ,Le nombre d'alignement est la taille du membre lui - même

3.La taille totale de la structure est le nombre maximal d'alignements ( Chaque variable a un numéro d'alignement ) Nombre entier de fois de

4. Si une structure imbriquée se produit ,Les structures imbriquées sont alignées à un multiple entier de leur alignement maximum, La taille globale de la structure est de tous les alignements (Comprend le nombre d'alignements pour les structures imbriquées)Nombre entier de fois le maximum d'alignement.

Alors...

class A1

{

public: 

    void f();

private:

    int _a;

    char _b;

};

A1La taille de8

class A2

{

public: 

    void f();

};

class A3//Il n'y a rien dans la classe, Appelé classe vide

{};

A2,A3Et la taille??

TechniquementA2,A3C'est pareil.- Oui.0C'est ça??Si oui0,Alors il y a un problèmeA2 aa;ParA2 Quelle est la taille de l'objet créé pour la classe ?Si oui0,AlorsaaQuelle est l'adresse de? Comment prouver l'existence de cet objet ,S'il n'existe pas, Comment appeler une fonction dans une classe ?Donc cet endroit,aaLa taille de1, C'est - à - dire une classe sans variable membre , Au moins ça ouvrira 1Octets,Pas pour stocker des données, Indique simplement que l'objet existe .

ImplicitethisPointeur

Prenez une classe de date ( Ensuite, vous vous concentrerez sur la classe de date ):

class Date

{

public:

    void Print()

    {

        cout << _year << '-' << _mouth <<'-' << _day << endl;

    }

    void Init(int day, int mouth, int year)

    {

        _year = year;

        _mouth = mouth;

        _day = day;

    }

private:

    int _year;

    int _mouth;

    int _day;

};

int main()

{

    Date d1;

    d1.Init(2022, 5, 26);

    Date d2;

    d2.Init(2022, 5, 27);

    d1.Print();

    d2.Print();

    //Deux objets sont définis,MaisPrint La fonction n'est pas dans l'objet ,AlorsPrint Comment la fonction trouve - t - elle l'espace correspondant pour imprimer les données correspondantes ?

    return 0;

}

PrintDémontage de la fonction, Vous pouvez voir l'appel Print La fonction est la même .

C'est ce qui arrive c++ Le compilateur a fait une chose ,Oui.PrintFonction pour le traitement, Compilé par le compilateur et traité comme :

void Print(Date* this)//this Est le nouveau mot - clé ,C'est un paramètre

{

    cout << this->_year << '-' << this->_mouth <<'-' << this->_day << endl;

}

L'endroit où l'appel est fait sera également traité comme ceci :d1.Print(&d1);

Implicitethis Le pointeur est fait par le compilateur ,Impossible d'ajouter àPrintAller dans la fonction. Mais il y a une utilisation thisCas du pointeur,C'est - à - direthis Le pointeur peut être utilisé .

Par exemple,:

void Print()//this Écrire qui peut être utilisé mais ne peut pas être affiché à la position des arguments et des paramètres

{

    cout << this << endl;

    //this- Oui.Date* constType,Non modifiable 

    cout << this->_year << '-' << this->_mouth <<'-' << this->_day << endl;

    // Vous pouvez ajouter , Mais le compilateur ajoutera automatiquement , Donc normalement, il n'y a pas de

}

Si le programme suivant fonctionne ,Quel est le résultat??a.Erreur de compilationb.Crash du programmec.Fonctionnement normal

class A

{

public:

    void Show()

    {

        cout<<"Show()"<<endl;

    }

private:

    int _a;

};

int main()

{

    A* p = nullptr;

    p->Show();

}

D'abord, ce n'est pas a, Un problème de pointeur vide n'est possible qu'au moment de l'exécution , Visitez avant de découvrir . C'est - à - dire qu'un pointeur vide ne signale certainement pas d'erreur au stade de la compilation .

Ensuite, ajoutez une connaissance :

A d1;

A* p = &d1;

p->Show();//Le compilateur vap->Show()Traité commep->Show(p)

Ce code fonctionnera normalement .

La raison en est que,Show La fonction n'est pas d1Moyenne,Alors...p->Show()Non, c'est vrai.pFaire une référence.p->Show() Comme un appel de fonction .this Le pointeur est également simplement initialisé à 00000000.Si vous ajoutezp->_a = 0;Il va s'écraser.

this Le pointeur est généralement utilisé comme paramètre de fonction , Donc il existe dans la pile . Selon le compilateur , Il est également possible que dans le registre ,Comme dans la figure ci - dessous..

Le pointeur est le résultat de la numérotation de la mémoire ,De0x00000000À0xFFFFFFFF, De petit en grand , Un pointeur vide est l'adresse du premier octet d'espace , Le premier octet est normalement réservé ,Ne pas stocker de données, Donc le pointeur vide est inaccessible . Un pointeur vide est une adresse virtuelle , Adresse physique il n'y a pas d'adresse inaccessible .

Mentions de copyright
Auteur de cet article [Rêve de bateau vide],Réimpression s’il vous plaît apporter le lien vers l’original, merci
https://fra.chowdera.com/2022/204/202207222043442272.html

Recommandé au hasard