Partage
  • Partager sur Facebook
  • Partager sur Twitter

C++ ligne avec const char*, char_traits

C++

21 décembre 2018 à 16:09:55

romantik a écrit:

Emrak a écrit:

Je vois pas pourquoi s'obstiner à aider quelqu'un qui se permet de répondre de la sorte. OK c'est bientôt Noël, mais quand même.


J'avoue, t'abuse Deedolith ! YES,man se tue à t'aider et tu l'envoie paître, quelle ingratitude !

Gné ?

-
Edité par Emrak 21 décembre 2018 à 16:12:31

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 16:14:46

C'était évidemment de l'ironie, et je trouve que gbdivers a trouvé le qualificatif parfait pour décrire les agissements de YES,man : l'arrogance
(bien que l'autre n'était pas mal non plus :P)
  • Partager sur Facebook
  • Partager sur Twitter
Dream on, Dream on, Dream until your dream comes true
21 décembre 2018 à 16:17:45

@romantik, en matière d'arrogance , toi et tes amis êtes les champions

Après les enfantillsages de certains, je reviens à de la Science C++ sérieuse :

Est-ce que la ligne 

using ci_string = std::basic_string<char, ci_char_traits>;

dit donc que la fonction compare qui est déclarée dans ci_char_traits remplace celle par défaut de basic_string si on travaille sur des ci_string ?

https://en.cppreference.com/w/cpp/string/char_traits

?

En l'occurence, j'essaie de situer dans quel cas je suis par rapport au message détaillé de Deedolith.

J'ai l'impression que l'on est dans le premier cas du message de Deedolith , à savoir 

    // fonction d'origine
void print(Foo const& f)
{
    std::cout << "Printing Foo." << std::endl;
}
 
    // Surcharge
void print(Bar const& b)
{
    std::cout << "Printing Bar." << std::endl;
}
 
int main()
{
    Foo f;
    print(f);    // affiche: Printing Foo.
 
    Bar b;
    print(b);    // affiche: Printing Bar.
}

car à priori , je ne vois pas de fonction membre héritée et virtuelle.

Est-ce que c'est ça ? ou bien, nous sommes dans un autre cas ?

-
Edité par pseudo-simple 21 décembre 2018 à 16:20:13

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 16:17:59

Chut, c'est noel, on a dit qu'on est gentil.

YES, man a écrit:

dit donc que la fonction compare qui est déclarée dans ci_char_traits remplace celle par défaut de basic_string si on travaille sur des ci_string ?

Quelle fonction "compare" de basic_string ? Si tu parles de basic_string::compare, non.

Et pour t'expliquer ca... je dois avouer que je sèche. Je ne vois pas comment t'expliquer simplement comment cela fonctionne.

YES, man a écrit:

J'ai l'impression que l'on est dans le premier cas du message de Deedolith , à savoir

Non, aucun rapport.

YES, man a écrit:

je ne vois pas de fonction membre héritée et virtuelle.

Au moins, ca c'est correct, il n'y a pas d'heritage et de fonction virtuelle.

YES, man a écrit:

Est-ce que c'est ça ? ou bien, nous sommes dans un autre cas ?

C'est un autre cas. Ce sont des templates, donc aucun des mecanismes dont on a deja parlé.

En fait, le mecanisme est assez simple a deviner : ce sont des traits, comme le nom l'indique. Mais tu ne connais pas les classes de traits. Et probablement pas assez bien les templates.

-
Edité par gbdivers 21 décembre 2018 à 16:27:28

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 16:24:31

Ce topic ! :lol: Et tous les autres du même auteur d'ailleurs ! :lol:
  • Partager sur Facebook
  • Partager sur Twitter

Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

21 décembre 2018 à 16:30:55

@gbdivers : oui pour ta question :

Quelle fonction "compare" de basic_string ? Si tu parles de basic_string::compare, non.

Peux-tu m'expliquer , car je pense que je comprendrai ?

Je suis conscient qu'il y a une idée avec les classes de traits. D'ailleurs, depuis que je m'intéresse au C++ moderne, j'ai déjà eu l'occasion de lire de nombreuses choses sur les classes de traits et les templates, donc ça va me faire réviser car j'ai des notions bien avancées.

Et je serais intéressé si tu peux rentrer dans les détails pour comprendre comment la fonction définie dans ci_char_traits prend le dessus sur la fonction basic_string::compare  quand on travaille sur des ci_string

Merci  à toi

-
Edité par pseudo-simple 21 décembre 2018 à 16:33:55

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 16:36:37

C'est les templates qu'il faut que tu révises

Et aussi, d'après toi, que fais le mot-clef "using" ? Et que peux-tu en déduire sur la relation entre ci_string::compare et std::basic_string<char, ci_char_traits>::compare ?

EDIT : Oops, je fatigues, j'ai lu quelque chose qui n'est pas écrit, ma question est un peu à côté de la plaque pour le coup, mais je la laisse pour m'assurer qu'il n'y ait pas de problème sur cette petite étape

-
Edité par romantik 21 décembre 2018 à 16:43:48

  • Partager sur Facebook
  • Partager sur Twitter
Dream on, Dream on, Dream until your dream comes true
21 décembre 2018 à 16:38:51

Il suffit que tu lises la doc et en particulier "Possible implementation" pour comprendre comment fonctionne char_traits::compare avec basic_string::compare https://en.cppreference.com/w/cpp/string/basic_string/compare
  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 17:41:40

YES, man a écrit:

@gbdivers : oui pour ta question :

Quelle fonction "compare" de basic_string ? Si tu parles de basic_string::compare, non.

Peux-tu m'expliquer , car je pense que je comprendrai ?

Je suis conscient qu'il y a une idée avec les classes de traits. D'ailleurs, depuis que je m'intéresse au C++ moderne, j'ai déjà eu l'occasion de lire de nombreuses choses sur les classes de traits et les templates, donc ça va me faire réviser car j'ai des notions bien avancées.

Et je serais intéressé si tu peux rentrer dans les détails pour comprendre comment la fonction définie dans ci_char_traits prend le dessus sur la fonction basic_string::compare  quand on travaille sur des ci_string

Merci  à toi

-
Edité par YES, man il y a environ 1 heure


Je pinaille, les classes de traits existaient avant la norme de 98. C'est bien antérieur à ce que certains appellent "C++ moderne". Et en ce qui me concerne, le "C++ moderne" existait en 98, mais il consistait à brûler les livres qui commencent avec les pointeurs bruts au lieu des conteneurs de la SL et des pointeurs intelligents que boost allait bientôt nous offrir, etc. Cela nous ramène à 20 ans en arrière, enfin me ramène, car beaucoup d'entre vous n'étaient pas encore là. Mais au moins les critiques qu'émettaient Francis Glassborrow dans les revues de livres de l'ACCU trouvent maintenant de l'écho dans l'immense majorité des intervenants dans les communautés C++ en ligne, et même dans des proportions qui ne sont plus négligeables en dehors des accros aux BBS/forums/... Le marketing derrière "C++ moderne" et la norme de 2011 avec la standardisation des pointeurs intelligents ont bien aidé. \o/

Bref, je m'égare. La magie des vacances de Noël sans doute.

Les classes de traits sont l'étape 0 de la méta-programmation template. Sous entendu, il faut être plus (dans le sud, on prononce le 's' final pour bien insister qu'on en rajoute) que familier avec ces derniers pour bien l'assimiler. En toute honnêteté, une pause par des technos aliens comme le LISP ou le Prolog aident énormément à appréhender la meta-prog template. L'attaquer de façon frontale, c'est très dur.

Quant à "ci-string", vu de loin cela me rappelle des bidouilles avec lesquelles j'avais expérimenté il y a 15-20 ans. A l'époque, certains montraient comment détourner les traits des chaines pour faire de la comparaison case-insensitive. C'est un jouet qui n'a d'intérêt que la démo des possibilités. En vrai, c'est tout pourri et totalement inadapté car on commence à se retrouver avec un nouveau type de chaines de caractères pas entièrement compatibles avec les autres -- et on paie des copies à tout va. Et en plus, la notion de casse est tout sauf triviale. Entre majuscules et minuscules, un signe peut se dédoubler -- cf le cas du machin qui ressemble à un beta en allemand et qui devient 'SS' en majuscule. C'est probablement à cause de l'inutilité de cet exemple que la littérature n'en parle plus trop aujourd'hui. C'est comme le test anti-auto-affectation: une preuve de concept qui servaient uniquement à se la péter. Application pratique sérieuse: zéro.

  • Partager sur Facebook
  • Partager sur Twitter
C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
21 décembre 2018 à 19:02:31

Mon post précédent était quelque peu sarcastique, je n'ai jamais eu la moindre intention de modifier mon tuto (sauf pour remettre à jour les liens vers les distro de mingw, les liens actuels commencent sérieusement à dater :( ). L'objectif de ce tuto est de montrer comment remplacer le compilateur livré avec C::B, rien d'autre.

Expliquer le processus de génération de l'exécutable à partir du code source est en dehors du cadre que je m'étais fixé quand j'ai écris ce tuto et il l'est toujours, les bons cours sur C++ en parlent bien mieux que je ne saurais le faire.

Pour ce qui concerne la différence entre build et rebuild, build signifie construire, rebuild signifie reconstruire, ce n'est pas du C++, c'est de l'anglais...

-
Edité par int21h 21 décembre 2018 à 19:04:36

  • Partager sur Facebook
  • Partager sur Twitter
Mettre à jour le MinGW Gcc sur Code::Blocks. Du code qui n'existe pas ne contient pas de bug
21 décembre 2018 à 19:07:41

@lmghs : exactement, ça se voit que tu quelqu'un de posé, et j'apprécie toujours de voir tes messages.

@gbdivers et romantik, vos messages me font réfléchir et je commence à y voir plus clair :

je vais donc rédiger ce que j'ai compris en fonction de ce qu'il y a écrit dans "possible implementation"

1) déjà la ligne : 

struct ci_char_traits : public std::char_traits<char>

permet de comprendre que ci_char_traits est le nom d'une classe héritant elle-même de , et c'est là que je réponds à la question de gbdivers et romantik, je disais donc, d'une spécialisation de classe template 

https://cpp.developpez.com/faq/cpp/?page=Les-templates#Qu-est-ce-que-la-specialisation-de-template

Le nom de cette classe dont hérite char_traits est : std::char_traits<char>

D'après le conseil 9 de Monsieur Scott Meyers, il est préférable d'utiliser la déclaration d'alias using (ce qui répond partiellement à une autre question de romantik.)

Ainsi, donc, ci_string devient le nom d'une classe qui est 

 std::basic_string<char, ci_char_traits>

et qui est encore une spécialisation de la classe template 

 std::basic_string

avec pour type particulier, char et surtout ci_char_traits qui nous intéressait juste avant.

C'est donc l'argument de la spécialisation d'une classe template qui intervient ici, selon ma compréhension, car cela permet de rédéfinir tout ce que l'on veut dans la mesure où d'après la faq de dvpz.com qu'avait envoyée joe_link_noir, il y a quelques temps, le compilateur va d'abord chercher les spécialisations

https://cpp.developpez.com/faq/cpp/?page=Les-templates#Qu-est-ce-que-la-specialisation-de-template

En particulier,

Je cite :

"Lors de l'utilisation d'un template avec un type donné, le compilateur recherche s'il existe une spécialisation du template pour ce type. S'il en trouve une il utilise cette version spécialisée, sinon il se rabat sur la version générique de base du template.
On peut spécialiser une fonction, une fonction membre template de classe, ou une classe toute entière.
Voici la syntaxe à utiliser pour effectuer une spécialisation "

-
Edité par pseudo-simple 21 décembre 2018 à 19:08:15

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 19:18:51

YES, man a écrit:

permet de comprendre que ci_char_traits est le nom d'une classe héritant elle-même de , et c'est là que je réponds à la question de gbdivers et romantik, je disais donc, d'une spécialisation de classe template 

Non. C'est une instanciation de template, pas une spécialisation de template. Tu n'as pas vu que la syntaxe n'est pas la même que celle dans le lien que tu donnes ensuite ?

Du coup, tout le reste de ton message est a côté de la plaque.

-
Edité par gbdivers 21 décembre 2018 à 19:19:42

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 20:08:32

Apparemment, tu tu es à côté de la plaque toi-même.

Le lien que j'ai envoyé vers le paragraphe qui m'intéresse

https://cpp.developpez.com/faq/cpp/?page=Les-templates#Qu-est-ce-que-la-specialisation-de-template

donne une autre définition pour l'instantiation.

je pense que tu fais erreur :

std::char_traits<char>

est bien une spécialisation , pas une instantiation.

De même , cette ligne, :

using ci_string = std::basic_string<char, ci_char_traits>;

à ma connaissance, montre que nous sommes en présence d'une spécialisation de template, pas d'une instantiation de template.

En tout cas, le lien que j'ai envoyé , ne dit pas ce que tu avances

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 20:17:34

YES, man a écrit:

En tout cas, le lien que j'ai envoyé , ne dit pas ce que tu avances

Il faudra t'y habituer un jour : si je dis quelque chose en C++ et que tu penses le contraire, la plus souvent, ça sera moi qui a raison.

Je te copie-colle le code qui se trouve dans le lien que tu donnes :

// Spécialisation pour les int  
template <> 
void QuiSuisJe<int>...

Où vois tu, dans le code de char_traits, la déclaration "template<>" ?

Donc, je te confirme que tu te trompes.

Et on va encore revenir sur mon dénigrement habituel : ne pas connaitre correctement c'est qu'est un template, une instanciation de template, ou une spécialisation de template, c'est normal quand on est débutant. Faire sa tête de mule en considérant que tu as raison et que les autres ont tort, c'est stupide.

Donc me casse pas les pieds et va lire un cours.

-
Edité par gbdivers 21 décembre 2018 à 20:21:35

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 20:33:34

Certes, j'étais certain que tu me parlerais de 

template<>

Tu as peut-être raison, en tout cas, sur cette page de dvpz,

https://cpp.developpez.com/faq/cpp/?page=Les-templates#Qu-est-ce-que-la-specialisation-de-template

je n'ai pas vu explicitement parler d'instantiation de classe template (je ne parle pas des fonctions template pour lesquelles la notion d'instanciation me semble assez naturelle).

-
Edité par pseudo-simple 21 décembre 2018 à 20:41:09

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 20:47:57

YES, man a écrit:

je n'ai pas vu explicitement parler d'instantiation de classe template (je ne parle pas des fonctions template pour lesquelles la notion d'instanciation me semble assez naturelle).

Quelques lignes en dessous, dans la même FAQ.

template<> 
struct Modele<int>  ...

Donc pareil pour les classes, il faut "template<>" et il n'y a pas ça dans le code d'exemple de char_traits. 

YES, man a écrit:

Certes, j'étais certain que tu me parlerais de

[...]
me semble assez naturelle

Et jusqu'à maintenant, tu as montré que tu ne comprends pas correctement les choses une grande majorité du temps. Alors évites de la jouer en monde "j'avais compris". Tu n'as pas compris ce qu'est l'instanciation et la spécialisation, aussi bien pour les fonctions que pour les classes.

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 20:54:57

Je vais m'exprimer comme toi :

au lieu ne repartir dans les obsessions dévalorisantes montrant que tu es en train de progresser,

parle C++, sinon, ça veut dire que tu n'as pas le niveau pour parler normalement et que tu dois faire des progrès :

Dans le code qui est indiqué :

que ce soit ici :

struct ci_char_traits : public std::char_traits<char> 

ou ici :

using ci_string = std::basic_string<char, ci_char_traits>;

il n'y a pas template<> en effet.

Mais est-ce pour cela que c'est forcément une instantiation ?

Si tu as une page d'un cours qui l'explique formellement, ça serait mieux pour moi qu'un argument qui dit que c'est une instantiation parce que ce n'est pas une spécialisation (donc en raisonnemment par la négative)

-
Edité par pseudo-simple 21 décembre 2018 à 20:55:38

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 20:59:54

YES, man a écrit:

Je vais m'exprimer comme toi :

au lieu ne repartir dans les obsessions dévalorisantes montrant que tu es en train de progresser,

parle C++, sinon, ça veut dire que tu n'as pas le niveau pour parler normalement et que tu dois faire des progrès :

mon petit choux, je t'ai vexé ?

YES, man a écrit:

Mais est-ce pour cela que c'est forcément une instantiation ?

Oui

YES, man a écrit:

Si tu as une page d'un cours qui l'explique formellement

Tu fais (encore) les choses a l'envers. Tu ne dois pas lire un cours après être tombé sur un code que tu ne comprends pas. Tu dois lire un cours avant d'aller étudier des codes.

Cf C++ Primer, de Lippman et Moo.

-
Edité par gbdivers 21 décembre 2018 à 21:00:57

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 21:29:09

Là, je vais dans ton sens pour le livre de Mr Lippman,

je viens de faire des recherches dedans.

Je n'ai pas trouvé notion d'instanciation de tempate répondant précisément à ma problématique pour l'instantiation de class template précisément comme indiqué pour les classes dont il est question.

Pourrais-tu m'indiquer où c'est dans son livre ?

Merci

-
Edité par pseudo-simple 21 décembre 2018 à 21:36:57

  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 22:27:28

Et bien continue d'aller dans son sens et finis ce livre.
  • Partager sur Facebook
  • Partager sur Twitter
21 décembre 2018 à 23:34:10

Après 6 ans d'apprentissage du C++, je ne m'étais jamais penché sur cet aspect du langage qu'est le C++ scientifique !

@YES, man Faut-il forcément acheter ton livre scientifique pour connaître tous les petits secrets de la science C++ ? :)

J'ai bien peur de ne pas avoir étudié le langage correctement jusque là...

-
Edité par Maluna34 21 décembre 2018 à 23:34:47

  • Partager sur Facebook
  • Partager sur Twitter
22 décembre 2018 à 0:54:46

YES, man a écrit:

au lieu ne repartir dans les obsessions dévalorisantes montrant que tu es en train de progresser,

Mais !!!!
A toi de nous montrer que tu progresses, pour l'instant ce n'est pas le cas.
(ce que tu nous montre c'est une volonté d'en absorber le plus possible en un minimum de temps, peut importe que ce soit compris).

Et allez directement sur les explication du livre concernant le truc sur lequel tu bute, n'est pas la meilleur façon de progresser.
Il y a tout un bagage à acquérir d'abord.
En clair: La spécialisation des templates est obscure pour toi ?
Relis à partir du chapitre sur les templates, et assures toi de bien comprendre (fais des exercices).

Tu auras certainement l'impression que c'est une perte de temps (vu que tu es pressé), mais je peux te garantir que non.

-
Edité par Deedolith 22 décembre 2018 à 0:56:08

  • Partager sur Facebook
  • Partager sur Twitter
22 décembre 2018 à 1:27:15

YES, man a écrit:

Pourrais-tu m'indiquer où c'est dans son livre ?

Quel est l'intérêt de cette question ? Si je te dis que c'est le chapitre 27, tu ne vas pas lire le chapitre 26 avant ? Et le 25 ? Comment pourrais tu réussir à comprendre un chapitre si tu n'as pas lu les chapitres avant ?

Si tu veux apprendre sérieusement, tu commences par lire la page 1, puis la page 2, etc. jusqu'à temps que tu as ta réponse.

  • Partager sur Facebook
  • Partager sur Twitter
22 décembre 2018 à 11:01:01

@gbdivers

Est-ce que vous avez une information sûre concernant le fait que la sixième édition du livre de Mr Lippman sera publiée en janvier ?

car j'y pense depuis quelques semaines.

Et je voulais acheter la cinquième, mais si la sixième est publiée en janvier, autant attendre

L'information est-elle sûre ?

  • Partager sur Facebook
  • Partager sur Twitter
22 décembre 2018 à 15:58:45

Bonjour OC,

il y a encore une question que je n'ai pas clairement résolue :

c'est que dans le code suivant, la fonction compare a été spécialisée pour le traits ci_char_traits.

En fait, de mon point de vue, elle a bien été redéfinie from scratch dans le morceau de code qui suit.

Ce que j'aimerais comprendre, c'est que nulle part dans le code qui suit, elle a été explicitement appelée.

Pourriez-vous m'expliquer par quel process elle est appelée ? car d'après les tests que j'ai faits, quand je désactive compare, le code ne donne plus le résultat attendu.

Merci à vous

#include <string>
#include <iostream>
#include <cctype>
 
struct ci_char_traits : public std::char_traits<char> {
    static char to_upper(char ch) {
        return std::toupper((unsigned char) ch);
    }
    static bool eq(char c1, char c2) {
         return to_upper(c1) == to_upper(c2);
     }
    static bool lt(char c1, char c2) {
         return to_upper(c1) <  to_upper(c2);
    }
    static int compare(const char* s1, const char* s2, size_t n) {
        while ( n-- != 0 ) {
            if ( to_upper(*s1) < to_upper(*s2) ) return -1;
            if ( to_upper(*s1) > to_upper(*s2) ) return 1;
            ++s1; ++s2;
        }
        return 0;
    }
    static const char* find(const char* s, int n, char a) {
        auto const ua (to_upper(a));
        while ( n-- != 0 ) 
        {
            if (to_upper(*s) == ua)
                return s;
            s++;
        }
        return nullptr;
    }
};
 
using ci_string = std::basic_string<char, ci_char_traits>;
 
std::ostream& operator<<(std::ostream& os, const ci_string& str) {
    return os.write(str.data(), str.size());
}
 
int main()
{
    ci_string s1 = "Hello";
    ci_string s2 = "heLLo";
    if (s1 == s2)
        std::cout << s1 << " and " << s2 << " are equal\n";
}



  • Partager sur Facebook
  • Partager sur Twitter
22 décembre 2018 à 16:21:33

using ci_string = std::basic_string<char, ci_char_traits>;

Ca sert à quoi, a ton avis ?

Et as-tu noté que la structure hérite de std::char_traits<char> ?

-
Edité par Deedolith 22 décembre 2018 à 16:26:25

  • Partager sur Facebook
  • Partager sur Twitter
22 décembre 2018 à 16:34:02

YES, man a écrit:

c'est que dans le code suivant, la fonction compare a été spécialisée pour le traits ci_char_traits.

1. ca veut rien dire

2. si tu utilises "specialisé" dans le sens de la spécialisation template, je t'ai déjà dit que ce n'est pas ca

3. lmghs a déjà expliqué les termes, c'est une redéfinition

YES, man a écrit:

Ce que j'aimerais comprendre, c'est que nulle part dans le code qui suit, elle a été explicitement appelée.

Je t'avais donné un lien vers la doc de basic_string::compare, avec un code qui montre comment char_traits::compare est utilisé. Tu as juste à lire et comprendre le code.

  • Partager sur Facebook
  • Partager sur Twitter
22 décembre 2018 à 16:50:27

Allez, je t'aide:
class base
{
public:
    virtual void print() const
    {
        std::cout << "blah" << std::endl;
    }
};


class foo: public base
{
public:
    void print() const
    {
        std::cout << "bleh" << std::endl;
    }
};

class bar: public base
{
};

void print(base const& b)
{
    b.print();
}

int main()
{
    foo f;
    print(f);    // affiche: bleh

    bar b;
    print(b);    // affiche: blah
}
Pourquoi le deuxieme appel affiche "blah" alors qu'on a pas definit de fonction print dans la classe bar ?

Conclusion: Revoit tes notions de base.
Elle ne sont pas acquises (sinon tu n''aurais pas posé cette question).

-
Edité par Deedolith 22 décembre 2018 à 17:00:12

  • Partager sur Facebook
  • Partager sur Twitter
22 décembre 2018 à 17:10:57

(il n'y a pas de fonction virtuelle ici, c'est une classe de trait)
  • Partager sur Facebook
  • Partager sur Twitter