IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Mots clé "Virtuel"


Sujet :

C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Octobre 2007
    Messages
    487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 487
    Par défaut Mots clé "Virtuel"
    Salut a tous
    Je suis entrain de lire des cours sur le langage C++ mais j’arrive pas a comprendre le role du mots clé virtuel
    http://cpp.developpez.com/faq/cpp/?p...explicite_base
    merci d’avance

  2. #2
    Membre Expert
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Par défaut
    Prends le cas suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    class A {
    public:
       int f() { cout << "A::f" << endl; }
       virtual int g() { cout << "A::g" << endl; }
    };
     
    class B : public A
    {
    public:
       int f() { cout << "B::f" << endl; }
       virtual int g() { cout << "B::g" << endl; }
    };
     
    int main()
    {
       A a1;
       B b;
       A& a2 = b;
       a1.f();
       a1.g();
       b.f();
       b.g();
       a2.f();
       a2.g();
    }
    Te donnera l'affichage suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    A::f
    A::g
    B::f
    B::g
    A::f
    B::g
    Comme B dérive A, on peut faire l'affectation suivante A& a2 = b. comme f n'est pas virtuelle, quand on appelle a2.f(), on appelle f de A. Comme g est virtuelle, quand on appelle a2.g(), on regarde le type "réel" (plutôt, le type runtime) de a2, c'est à dire B, et on appelle du coup a2.B::g().

    En espérant que c'est plus clair maintenant.

  3. #3
    Rédacteur

    Inscrit en
    Novembre 2006
    Messages
    1 272
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 272
    Par défaut
    A ne pas négliger en POO les méthodes virtuel c'est vraiment très pratiques.

    PS: Très bonne explication de white_tentacle
    Vous voulez participer aux Tutoriels, FAQ ou Traductions et faire partie de l'équipe Qt de Developpez.
    N'hésitez pas à me contacter par MP.

  4. #4
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Le mot clé virtual (attention, bien que l'on parle d'une méthode virtuelle en francais, le mot clé est virtual (en anglais) ) a pour but de prévenir le compilateur que le comportement impliqué par la méthode est susceptible d'être modifié en fonction du type réel de l'objet au départ duquel on invoque cette méthode.


    En effet, il arrive que tu veuille disposer d'un type de données qui peut être considéré comme la spécialisation d'un type moins "spécialisé".

    Par exemple, un chien pourrait être considéré comme la spécialisation d'un type "animal", car le chien est un animal, mais certains de ses comportements (par exemple un comportement générique que nous nommerions "crier") sont propres... au chien (un chien aboie alors qu'un chat... miaule )

    Il arrive aussi que tu souhaite pouvoir faire cohabiter plusieurs animaux de types différents, en disposant d'une collection dans laquelle tu aurait des chiens, des chats, des éléphants et des corbeaux.

    Pour arriver à faire cohabiter tous ces animaux dans une même collection, il faut qu'ils puissent tous être considérés comme... des animaux (de manière plus générique que chiens, chats, éléphants ou autres).

    Tu va donc mettre en oeuvre une relation dite "d'héritage" entre, d'un coté, ta classe animaux et de l'autre tes classes "spécialisées" (chien, chat, ...).

    Mais il est vraisemblable, si tu demande à chaque animal présent dans cette collection de crier, que tu souhaites que les chiens aboient, que les chats miaulent, que les éléphants barrissent et que les corbeaux croassent... Et c'est là que le mot clé virtual va intervenir.

    En effet, pour que tous tes animaux soient en mesure de crier, il faut que tu prévienne le compilateur qu'il existe un tel comportement dans la classe animaux.

    Mais tu dois aussi prévenir le compilateur que ce comportement est susceptible d'être modifié en fonction du type réel de l'animal auquel tu demande de crier.

    Ainsi, dans la classe animal, tu pourrais prévoir un comportement qui s'applique à tous, comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Animal
    {
        public:
            void crier() const
            {
                std::cout<<"Pousse son cri";
            }
    };
    Ca pourrait suffire à tous les animaux (même si on peut se poser la question de ce qu'est le cri d'un poisson rouge ) mais, il faut avouer que cela manque un tout petit peu de précision...

    L'idéal serait que ce comportement soit utilisé sauf si on indique autre chose de "plus adapté" par rapport au type réel de l'animal.

    Nous allons donc prévenir le compilateur que ce comportement est susceptible d'être modifé.

    La classe Animal deviendrait donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Animal
    {
        public:
            virtual void crier() const
            {
                std::cout<<"Pousse son cri";
            }
    };
    et nous allons créer plusieurs spécialisations d'animal, pour correspondre aux animaux que nous voulons gérer, par exemple:
    un chine
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Chien : public Animal
    {
        public:
            /* nous voulons que le chien aboie */
            virtual void crier() const
            {
                std::cout<<"aboie méchamment";
            }
    };
    un chat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class Chat : public Animal
    {
        public:
            /* nous voulons que le chat miaule */
            virtual void crier() const
            {
                std::cout<<"miaule tendrement";
            }
    };
    Une souris... Elle a aussi un cri (un couinement, je crois), mais "pousse son cri" me va très bien
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class Souris : public Animal
    {
        public:
            /* Le comportement prévu pour la classe de base correspond à ce que
             * je veux... je ne dois donc pas le redéfinir pour la souris
             */
    };
    et nous pourrions prévoir une foule d'autres animaux (éléphants, corbeaux, dauphins, panthère, ...) et décider de spécialiser, ou non, le comportement qui consiste en "crier" pour chacun d'eux.

    De cette manière, si on crée une collection d'animaux, par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<Animal> tab;
    que nous y mettons différents animaux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    tab.push_back(Elephant());
    tab.push_back(Chien());
    tab.push_back(Chat());
    tab.push_back(Souris());
    tab.push_back(Panthere());
    tab.push_back(PoissonRouge());
    /*...*/
    et que nous leur demandons tour à tour de crier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(std::vector<Animal>::iterator it=tab.begin();it!=tab.end():++it)
        (*it).crier();
    tous les animaux pourront répondre, soit en adaptant le comportement crier selon leur type réel, soit en utilisant le comportement prévu par défaut ("pousse son cri")
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Pour être plus précis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    vector<Animal*> tab;
     
    tab.push_back(new Chat());
    tab.push_back(new Souris());
    ...
    D'autant que c'est avec les pointeurs (et le polymorphisme) que le mot clé virtual prend tout son sens.

  6. #6
    Membre éclairé Avatar de Trunks
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2004
    Messages
    534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2004
    Messages : 534
    Par défaut
    Citation Envoyé par Noxen Voir le message
    Pour être plus précis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    vector<Animal*> tab;
     
    tab.push_back(new Chat());
    tab.push_back(new Souris());
    ...
    D'autant que c'est avec les pointeurs (et le polymorphisme) que le mot clé virtual prend tout son sens.
    Oui faut le passer sous forme de pointeurs, mais là, tu as une fuite mémoire. Comment sont détruits tes objets.

    Il aurait fallu faire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    	std::vector<Animal*> tab;
     
    	Chien* chien = new Chien();
    	tab.push_back(chien);
     
    	Chat* chat = new Chat();
    	tab.push_back(chat);
     
    	Souris* souris = new Souris();
    	tab.push_back(souris);
     
    	for (std::vector<Animal*>::iterator it = tab.begin(); it != tab.end(); ++it)
    		(*it)->crier();
     
    	delete souris;
    	delete chat;
    	delete chien;

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Trunks Voir le message
    Oui faut le passer sous forme de pointeurs, mais là, tu as une fuite mémoire. Comment sont détruits tes objets.

    Il aurait fallu faire:
    <sniped code>
    Pas forcément...

    Tu peux très bien invoquer delete sur la valeur d'un itérateur, si ton conteneur contient des pointeurs
    un code du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int main()
    {
        vector<Animal*> tab;
     
        tab.push_back(new Chat());
        tab.push_back(new Souris());
        /* ...*/
        // faisons crier les animaux
        for(vector<Animal*>::iterator it = tab.begin();it!=tab.end();++it)
            (*it)->crier();
        // libérons correctement la mémoire
        for(vector<Animal*>::iterator it = tab.begin(); it!=tab.end();++it)
        {
            delete (*it);
            // nous pourrions même prévoir de remettre le pointeur à null ;)
            (*it) = NULL;
        }
        //si nous avons remis les pointeurs à null
        std::remove_if(tab.begin(), tab.end(), isNull);
    }
    Evitera les fuites de mémoires

    Le tout avec une fonction libre isNull qui prend la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool isNull(Animal* an)
    {
        return an==NULL;
    }
    que nous pourrions même généraliser sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <typename T>
    bool isNull(T* t)
    {
        return t==NULL;
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre éclairé Avatar de Trunks
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2004
    Messages
    534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2004
    Messages : 534
    Par défaut
    Exact, je n'y avais pas pensé. C'est vrai que les adresses mémoires sont stockées dans le vecteur.

  9. #9
    Membre très actif
    Avatar de buggen25
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    554
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Août 2008
    Messages : 554
    Par défaut
    Salut tt le monde !
    je donnerai plus un exemple concret :
    Dans le MFC il existe une class qui s'appelle CButton, qui possede une methode DrawItem(LPDRAWITEMSTRUCT lpDIS) (si je m'en souviens bien) qui est une methode Virtuelle, cette methode est reprise par une autre classe CBitmapButton en mode virtuel. ensuite tu peux utiliser cette fonction pour redessiner la forme du bouton.

  10. #10
    Membre éclairé Avatar de Trunks
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2004
    Messages
    534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2004
    Messages : 534
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Pas forcément...

    Tu peux très bien invoquer delete sur la valeur d'un itérateur, si ton conteneur contient des pointeurs
    un code du genre de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int main()
    {
        vector<Animal*> tab;
     
        tab.push_back(new Chat());
        tab.push_back(new Souris());
        /* ...*/
        // faisons crier les animaux
        for(vector<Animal*>::iterator it = tab.begin();it!=tab.end();++it)
            (*it)->crier();
        // libérons correctement la mémoire
        for(vector<Animal*>::iterator it = tab.begin(); it!=tab.end();++it)
        {
            delete (*it);
            // nous pourrions même prévoir de remettre le pointeur à null ;)
            (*it) = NULL;
        }
        //si nous avons remis les pointeurs à null
        std::remove_if(tab.begin(), tab.end(), isNull);
    }
    Evitera les fuites de mémoires

    Le tout avec une fonction libre isNull qui prend la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool isNull(Animal* an)
    {
        return an==NULL;
    }
    que nous pourrions même généraliser sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template <typename T>
    bool isNull(T* t)
    {
        return t==NULL;
    }
    Pour info, comment on fait appel à la forme template de isNull?
    J'essaie de refaire l'exemple, mais je n'y arrive pas.

    De plus, j'affiche la taille du tableau après le remove_if(), et j'ai toujours 3

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    #include <iostream>
    #include <vector>
    #include <algorithm>
     
    class Animal
    {
        public:
    		virtual ~Animal() {}
     
            virtual void crier() const
            {
                std::cout<<"Pousse son cri"<<std::endl;
            }
    };
     
    class Chien : public Animal
    {
        public:
    		~Chien()
    		{
                std::cout<<"Destructeur de Chien"<<std::endl;
    		}
     
            /* nous voulons que le chien aboie */
            virtual void crier() const
            {
                std::cout<<"aboie mechamment"<<std::endl;
            }
    };
     
    class Chat : public Animal
    {
        public:
    		~Chat()
    		{
                std::cout<<"Destructeur de Chat"<<std::endl;
    		}
     
            /* nous voulons que le chat miaule */
            virtual void crier() const
            {
                std::cout<<"miaule tendrement"<<std::endl;
            }
    };
     
    class Souris : public Animal
    {
        public:
    		~Souris()
    		{
                std::cout<<"Destructeur de Souris"<<std::endl;
    		}
     
            /* Le comportement prévu pour la classe de base correspond à ce que
             * je veux... je ne dois donc pas le redéfinir pour la souris
             */
    };
     
    bool isNull(Animal* an)
    {
        return an==NULL;
    }
     
    int main()
    {
    	std::vector<Animal*> tab;
     
    	tab.push_back(new Chien());
     
    	tab.push_back(new Chat());
     
    	tab.push_back(new Souris());
     
    	for (std::vector<Animal*>::iterator it = tab.begin(); it != tab.end(); ++it)
    	{
    		(*it)->crier();
    		delete *it;
    		*it = NULL;
    	}
     
    	//si nous avons remis les pointeurs à null
        std::remove_if(tab.begin(), tab.end(), isNull);
     
    	std::cout << "Taille: " << tab.size() << std::endl;
     
    	return 0;
    }

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    410
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 410
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Pas forcément...

    Tu peux très bien invoquer delete sur la valeur d'un itérateur, si ton conteneur contient des pointeurs
    un code du genre de
    ...
    ou mieux! utiliser boost::prt_vector

  12. #12
    Membre très actif
    Avatar de buggen25
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    554
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Août 2008
    Messages : 554
    Par défaut
    Salut,
    essaye ça;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
     
    #include <iostream>
    #include <vector>
    #include <algorithm>
     
    class Animal
    {
        public:
    		virtual ~Animal() {}
     
            virtual void crier() const
            {
                std::cout<<"Pousse son cri"<<std::endl;
            }
    };
     
    class Chien : public Animal
    {
        public:
    		~Chien()
    		{
                std::cout<<"Destructeur de Chien"<<std::endl;
    		}
     
            /* nous voulons que le chien aboie */
            virtual void crier() const
            {
                std::cout<<"aboie mechamment"<<std::endl;
            }
    };
     
    class Chat : public Animal
    {
        public:
    		~Chat()
    		{
                std::cout<<"Destructeur de Chat"<<std::endl;
    		}
     
            /* nous voulons que le chat miaule */
            virtual void crier() const
            {
                std::cout<<"miaule tendrement"<<std::endl;
            }
    };
     
    class Souris : public Animal
    {
        public:
    		~Souris()
    		{
                std::cout<<"Destructeur de Souris"<<std::endl;
    		}
     
            /* Le comportement prévu pour la classe de base correspond à ce que
             * je veux... je ne dois donc pas le redéfinir pour la souris
             */
    };
     
    bool isNull(const Animal* an)
    {
        return an==NULL;
    }
     
    int main()
    {
    	std::vector<Animal*> tab;
     
    	tab.push_back(new Chien());
     
    	tab.push_back(new Chat());
     
    	tab.push_back(new Souris());
     
    	for (std::vector<Animal*>::iterator it = tab.begin(); it != tab.end(); ++it)
    	{
    		(*it)->crier();
    		*it = NULL;
    	}
     
    	//si nous avons remis les pointeurs à null
            tab.erase (std::remove_if(tab.begin(), tab.end(), isNull), tab.end ());
     
    	std::cout << "Taille: " << tab.size() << std::endl;
     
    	return 0;
    }
    Resultat : avec g++ MinGW
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    aboie mechamment
    miaule tendrement
    Pousse son cri
    Taille: 0

  13. #13
    Membre éclairé Avatar de Trunks
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2004
    Messages
    534
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2004
    Messages : 534
    Par défaut
    Pour ça, c'est réglé.

    Et pour l'appel du pédicat isNull() templétisé?

    Au boulot, je dois développer en Win32, mais j'ai envie d'apprendre le standard qui est plus interressant à mon humble avis.

  14. #14
    Membre très actif
    Avatar de buggen25
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    554
    Détails du profil
    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Août 2008
    Messages : 554
    Par défaut
    "Mon humble avis" Fausse medestie, aha je plaisante,
    Pour Win32 tu peux lire le bouquin "Programming Windows", c'est tout en C c'est tres interressant

  15. #15
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Citation Envoyé par Trunks Voir le message
    Pour ça, c'est réglé.

    Et pour l'appel du pédicat isNull() templétisé?

    Au boulot, je dois développer en Win32, mais j'ai envie d'apprendre le standard qui est plus interressant à mon humble avis.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    template <class T> bool isNull(T* t) i{return t==NULL;}
     
    foo(){
        Animal* a = new Animal();
    // Ces 2 écritures sont valables, la première permet de lever des ambigüités dans certaines situations.
        bool b1 = isNull<Animal>(a);
        bool b2 = isNull(a);
     
        vector<Animal*> zoo;
        zoo.push_back(new Lion);
        for(vector<Animal*>::iterator it = zoo.begin(); it!=zoo.end(); ++it)
            bool b3 = isNull(*it);
     
        // delete & Cie
    }

  16. #16
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Un conteneur de pointeurs c'est le bon truc pour faire du code non exception-safe...
    Un delete (ou toute autre libération de ressource), ça doit être dans un destructeur. Quand est-ce que les gens comprendront ça ?

  17. #17
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Ici c'est seulement pour montrer des exemples sur un point précis qui n'est pas directement lié à la gestion de la mémoire.

    Mais il y a des cas où les conteneurs de pointeurs sont inévitables ; par exemple :
    - si on veut tirer pleinement partie du polymorphisme ;
    - si l'objet à stocker ne dispose pas d'un constructeur par copie (constructeur par copie déclaré private).

    Mais même dans ces cas là je ne conçois pas de ne pas les encapsuler dans une classe pour assurer le RAII. D'autant que quand on doit gérer des objets de cette façon, c'est généralement qu'il y a un concept fort qui englobera le problème qui sera la réelle interface, le vector de pointeur sera seulement de l'implémentation interne.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo