-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathC++.language.txt
1919 lines (1764 loc) · 122 KB
/
C++.language.txt
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
┏━━━━━━━━━━━━━━━━━━┓
┃ C++_SYNTHESE ┃
┗━━━━━━━━━━━━━━━━━━┛
┌─────────────────────────┐
│ DIFFERENCES C / C++ │
└─────────────────────────┘
COMPATIBILITE C/C++ ==> #C++ est un superset de C. Ainsi, il ajoute seulement
#des fonctionnalités à C, et un programme en C peut
#en général être compilé par g++ par exemple.
#C'est pourquoi toute la syntaxe appartenant à C n'a pas
#été reexpliquée ici, et seuls les ajouts le sont.
#Pour autant, il y a quelques différences entre C et C++
#Les voici :
# - il est interdit de faire un transtypage implicite
# entre un VOID_ADR et un TYPE_ADR. Par exemple :
# - char *STR = malloc(TOUINTVAL)
# doit être noté :
# - char *STR = (char*)malloc(TOUINTVAL)
# - NULL n'est pas (void*)0, mais une sorte de magic
# word utilisé par le compilateur. Utiliser donc
# explicitement NULL
# - les inline fonctions doivent être définies dans
# chaque fichier où elles apparaissent
# - sizeof(CHAR_LIT) vaut sizeof(CHAR_VAL) et non
# sizeof(INT_VAL)
# - il peut y avoir des conflits de noms, avec :
# - des keywords ou fonctions standards C++ étant
# utilisé comme identifiant dans un programme C
# - des fonctions redéfinies par C++, par exemple
# getline(), ou keywords, par exemple bool
# - on ne peut affecter à une ENUM_VAR que des VAL
# correspondant aux MOT... de sa définition
# - faire qu'un code C++ soit compilé avec du code C
# pose des problèmes de mangling (car différent).
# Il faut donc
# rajouter "extern "C"" devant le prototype de toute
# fonction C ou C++ devant être utilisée par un
# code écrit et compilé avec l'autre langage. Par
# exemple, pour qu'un header C puisse être compilé
# par un compilateur C++ et du code C++, il faut
# faire ceci pour toute fonction :
# - #ifdef __cplusplus
# extern "C" {
# #endif
# FONCTIONS...
# #idef _cplusplus
# }
# #endif
# - un goto ou switch ne peut pas sauter au-dessus
# d'une déclaration
# - noms de variables ne peuvent pas contenir plus de
# 2 underscores consécutifs
# - les mots clefs "struct", "union" et "enum" ne
# peuvent pas apparaître dans un prototype de
# fonction
# - plusieurs choses de C99
bool #Il s'agit d'une macro désignant un char en C, mais en
#C++, il s'agit d'un type fondamental, prenant un octet
#en mémoire, mais ne pouvant contenir que des 0 et des 1
#(tout autre valeur est castée vers 1)
wchar_t #Est aussi un type fondamental, et non un typedef
┌─────────────────┐
│ GENERALITES │
└─────────────────┘
STANDARDS ET #Inventé en 1980 par Bjarne Stoustrup.
IMPLANTATION ==> #Standards :
# - en 1998
# - en 2003, rajoutant peu de choses, en général
# désigné par "C++ standard"
# - un à venir, avec le nom C++0x.
# - en attendant, un premier draft a été lâché : TR1
# - puis un second : TR 24733
#Implémenté sous Linux par libstdc++
#Compilé sous Linux par g++, quasiment mêmes options que
#gcc
HEADERS ==> #L'extension est .h
#La standard library contient les seuls headers n'ayant
#pas d'extension. Tout autre header doit être .h
#La standard library maintient des headers de la
#standard library C, avec l'extension .h, qui pointent
#vers leur version sans extension .h et avec un c au
#début, juste pour la backward compatibility.
#La library standard C est donc contenue dans la library
#standard C++, en étant légèrement modifiée. Voici les
#modifications :
# - wchar_t est un type fondamental
# - toutes les fonctions mathématiques de <cmath> et
# de <cstdlib> (abs() et div()) sont overloadées,
# donc les suffixes et préfixes 'f' et 'l' deviennent
# inutiles. Il n'est plus nécessaire de faire -lm
# lors de la compilation pour les fonctions
# mathématiques
#Voici les headers de la library standard C, qui sont
#inutiles en C++, car C++ propose d'autres solutions
#(la solution suit) :
# - csignal, cassert, cerrno : <exceptions>
# - cwctype, cwchar : wstreams
# - cfloat, climits : <limits>
# - clocale : <locale>
# - cstddef : builtins
# - cstdio : <iostream>, etc.
#Solution partielle :
# - cstring : <string>
# - cstdarg : oveloadable fonctions
#Headers de toute façon peu utilisés :
# - ciso646
# - csetjmp
#Headers utiles même en C++ :
# - cmath
# - cstdlib
# - ctime
# - cctype
#Le répertoire des headers C++ est /usr/include comme en
#C, mais la library standard C++ est dans
#/usr/include/c++/{VERSION}/
.cpp
.cc #Extension d'un fichier source. Préférer le permier
_cplusplus #Variable globale définie si le compilateur est
#compatible C++
C++ STYLE #En C++, il est de bon ton de déclarer les variables
#juste avant leur utilisation, non en début de bloc
┌───────────────────┐
│ AJOUTS DIVERS │
└───────────────────┘
new TYPE #Equivaut à new TYPE[1]
new TYPE[TOUINTVAL] #Renvoie un TYPE_ADR avec une mémoire allouée
#dynamiquement de sizeof(TYPE) * TOUINTVAL octets
#Ainsi :
# - TYPE TYPE_ADR = new TYPE[TOUINTVAL]
#est une alternative à :
# - TYPE TYPE_ADR = malloc(sizeof(TYPE) * TOUINTVAL)
#Si TYPE est une CLASS, le constructor de CLASS est
#appelé TOUINTVAL fois (pour chaque CLASS créé dans
#l'array de CLASS donc)
#Forme souvent utilisée (pour le polymorphisme) :
# - CLASS CLASS_VAR = new CLASS2
#Une exception bad_alloc est lancée s'il n'arrive pas à
#allouer de la mémoire.
#Pour allouer les pointeurs d'une matrice dynamique :
# - TYPE** VAR = new TYPE*[TAILLE1]
# for ( int A(0) ; A < TAILLE1 ; A++ )
# {
# VAR[A] = new TYPE[TAILLE2];
# for ( int B(0) ; B < TAILLE2 ; B++ )
# VAR[A][B] = VAL;
# }
delete ADR #Equivalent de free(ADR) pour new.
#delete NULL n'est pas une erreur, mais ne fait rien
delete [] ADR #La première forme est à utiliser après un new TYPE, et
#la seconde après un new TYPE[TOUINTVAL], sinon erreur.
#De plus, si ADR est une CLASS_ADR appelle le destructor
#de CLASS TOUINTVAL fois.
AVANTAGES DE NEW ET #Différences de new et delete par rapport à malloc et à
DELETE ==> #free :
# - malloc renvoie un VOID_ADR, new un TYPE_ADR
# - new appelle le constructor, et delete le destructor
# - exception bad_alloc, et (nothrow) pour new
# - overloading operator possible de delete, delete[],
# new et new[]
# - ne pas mélanger les deux
TYPE VAR(VAL) #Equivaut à TYPE VAR = VAL, que TYPE soit un type
#fondamental ou une CLASS. Ne marche que pour une
#déclaration + définition.
TYPE FONC_NAME #Une déclaration + définition, ou une définition (mais
(TYPE VAR[ = VAL] #non une déclaration seule) de fonction peut indiquer
[, TYPE VAR2 = VAL2]...)# = VAL après un argument. Cette valeur est la valeur
#par défaut : il est alors possible d'appeler la
#fonction sans fournir cet argument.
#Ne marche que sur le dernier argument, ou si tous les
#arguments qui suivent ont aussi une valeur par défaut.
#Ne marche que compile-time = le mettre donc seulement
#dans la déclaration / le header.
#Notamment utile avec un constructor.
STRUCTURES ET UNIONS #Les structures et unions sont en fait considérées comme
==> #des classes, elles peuvent donc notamment utiliser :
# - des CLASSFK, dont constructors et destructors
# - des ACCESS
# - des templates
#la seule différence étant que :
# - l'ACCESS de leurs membres par défaut est public
#pour les structures uniquement :
# - l'ACCESS de l'héritage est public par défaut
#et pour les unions uniquement :
# - les CLASSDT (et non les CLASSFK) font référence à
# la même zone mémoire (comme en C)
# - ne peut pas être la parente ou l'enfant d'une
# autre classe
# - ne peut pas contenir de virtual CLASSFK ni de
# user-defined constructor ou destructor
MOTS FACULTATIFS ==> #Les mots struct, union et enum deviennent facultatifs
#dans :
# - les instantiations d'une STKT_VAR, etc.
# - la référence au TYPE complexe (par exemple
# sizeof(struct STKT) ou typedef struct STKT MOT)
#Cela reste cependant obligatoire dans la déclaration
#même de la structure, de l'union ou de l'enum
PLAIN OLD DATA ==> #Désigne un type C++ pouvant être utilisé en C.
#Désigne donc un builtin type ou une
#classe/struct/union contenant :
# - des operator=, constructor, copy constructor et destructor trivial
# - seulement des membres POD ou static non-POD
# - pas de membres protected ou private
# - pas de classe parente
#Une classe a un trivial assignment si :
# - elle n'a pas d'operator= user-defined
# - elle n'a pas de virtual CLASSFK ou virtual parent
# - ses parents et CLASSDT étant des CLASS_VAR ont eux aussi un trivial assignment
#Même chose pour trivial constructor, destructor et copy constructor.
return 0 #Il est optionnel dans le main()
┌────────────────┐
│ REFERENCES │
└────────────────┘
REFERENCES ==> #Les références ont les mêmes fonctions que les
#pointeurs, mais évite les problèmes des pointeurs dus à
#la manipulation de la mémoire. Une variable référence
#d'une autre variable désigne en fait la même valeur en
#mémoire. D'un point de vue technique, ce n'est pas
#exactement cela, c'est plus un lien qui unit les deux
#variables (mais peu importe), et qui fait que modifier
#l'une modifie l'autre.
TYPE& VAR = VAR2 #Déclaration et initialisation d'une référence. Une
#référence doit être initialisée à la déclaration. VAL à
#la place de VAR2 est illégal. VAR2 doit être de même
#type que VAR. VAR2 devient elle-même, réciproquement,
#une référence pour VAR.
#Pour initialiser une CLASSDT référence, il faut donc
#le mettre dans le constructor après ":"
#Il est impossible d'enlever à une VAR le fait qu'elle
#soit une référence, ou de le rajouter en dehors de sa
#déclaration + initialisation.
TYPE& *ADR = ADR2 #Les références pointeurs lient l'adresse qu'elles
#contiennent. Modifie l'adresse contenue par l'une
#modifie celle de l'autre. Evidemment, modifier la
#valeur pointée aura des conséquences sur les deux aussi
VAR = VAL #Affectation de VAL à une référence VAR, et à la VAR2 à
#laquelle est associée (ne modifie donc pas leur lien)
ADR = ADR2 #Même chose pour une référence pointeur
TYPE& #& fait partie du TYPE d'une référence, comme * pour un
#pointeur. & précède toujours * dans le TYPE d'une
#déclaration.
FONC_NAME(TYPE& VAR #Il est possible de déclarer les arguments d'une
[, TYPE[&] VAR]...) #fonction comme étant des références : il s'agit d'un
#call by reference. Ainsi, plutôt que de faire une copie
#de l'argument (call by value) ou de son adresse (call
#by adress), il s'agit de l'argument lui-même (en
#quelque sorte) qui est utilisé. Ainsi :
# - le modifier dans l'exécution de la fonction le
# modifiera même après la fin de la fonction.
# - c'est un bon moyen pour contourner la portée
# locale d'une fonction
# - contrairement au call by adress, on n'a pas
# besoin d'utiliser des pointeurs et donc de changer
# le corps de la fonction.
# - cela évite de faire une récréer un objet si VAR
# est une CLASS_VAR, c'est donc bien plus rapide,
# et vivement recommandé lorsque l'on passe une
# CLASS_VAR en argument d'une fonction donc
#Une référence peut être le TYPE& d'une fonction.
#Cependant, il faut prendre garde à utiliser
#immédiatement le retour de la fonction, et à ne plus
#l'utiliser ensuite (c'est-à-dire ne pas le mettre dans
#une VAR, mais faire à nouveau appel à la fonction si
#l'on le veut à nouveau) car sinon cela peut buguer.
VAL ET REFERENCES ==> #Il est impossible d'assigner une VAL temporaire à une
#référence non-const, ou de transtyper.
#Les choses suivantes sont donc interdites (soit VAR une
#référence non-const) :
# - VAR = VAL;
# - (TYPE&) VAL;
# - appeler une fonction demandant une valeur référence
# non-const avec un argument non-référence
#Cela ne vaut pas pour les références const.
DIFFERENCE POINTEURS #Les références sont en général implémentées (compilées)
ET REFERENCE ==> #comme des pointeurs. Cependant, contrairement aux
#pointeurs, le compilateur interdit plusieurs choses
#possibles avec les pointeurs, ce qui fait qu'ils sont
#plus safe (mais moins puissants) :
# - il n'est pas possible de réaffecter une référence,
# mais seulement la valeur qu'elle pointe (mais pas
# la VAR/zone mémoire qu'elle réfère)
# - ne sont donc pas copiable ni affectable. Ne peuvent
# donc pas être utilisées dans plusieurs cas, comme
# dans un std::vector
# - on doit initialiser une référence lors de la
# déclaration, alors qu'un pointeur peut rester NULL
# - une référence ne peut pas pointer NULL
# - on ne peut pas accéder à l'adresse mémoire de
# manière immédiate, comme avec un pointeur, et donc
# pas d'arithmétique des pointeurs
# - syntaxiquement : pas de * ni de ->
# - on ne peut pas avoir plusieurs degrés d'indirection
# avec les références, contrairement à **ADR_ADR
# - on ne peut pas faire d'arrays de références
TYPE(&VAR)[] #Déclare une référence vers une array statique.
#Le type est : TYPE(&)[]
#Les arrays statiques de référence sont par contre interdites.
┌─────────────────┐
│ OVERLOADING │
└─────────────────┘
OVERLOADING ==> #Il est possible de déclarer + définir plusieurs
#fonctions avec le même nom, mais des types et/ou
#nombre d'arguments différents.
#Le choix de la bonne fonction, lors de son exécution,
#se fera sur le type ou le nombre des arguments passés
#à la fonction overloaded
TYPE operator SYMBOLE #Définition d'un overloadable operator.
(ARGUMENTS) { #Il s'agit du CLASSFK lié à un SYMBOLE (operator
... #SYMBOLE est son FONC_NAME)
} #Elle :
# - peut renvoyer tout type de valeur
# - a un nombre d'arguments déterminés par le SYMBOLE
# choisi
# - a des types d'arguments libres ou non en fonction
# de l'opérateur
#Il peut s'agir d'une CLASSFK. Si c'est le cas, le
#premier argument n'est pas spécifié et est
#implicitement *this. De plus, certains overloadable
#operators ne peuvent être que des CLASSFK. Voici un
#résumé en fonction du SYMBOLE :
+------------------------------------------+----------------+-----------+---------------------+-------------------------------+
| SYMBOLE | ARGUMENTS | ARGUMENTS | EXECUTION | COMMENTAIRES |
| | (NON-CLASSFK) | (CLASSFK) | | |
+------------------------------------------+----------------+-----------+---------------------+-------------------------------+
| + - * & ! ~ ++ -- | CLASS | void | +CLASSE | |
| ++ -- | CLASS, int | int | CLASS++ | int non-utilisé (dummy) |
| + - * / % ^ & | < > == != <= >= << >> && | CLASS, TYPE ou | TYPE | CLASS + TYPE | |
| || , += -= *= /= %= ^= &= |= <<= >>= | TYPE, CLASS | | ou TYPE + CLASS | |
| ->* | CLASS, int | int | CLASS_ADR->*CLASSFK | Renvoie toujours this |
| -> | Impossible | void | CLASS->TYPE | Renvoie CLASS2_ADR. CLASS->VAR|
| | | | | effectue CLASS2_ADR->VAR |
| | | | | |
| Cast operator | Impossible | void | (TYPE) CLASS | |
| = | Impossible | TYPE | CLASS = TYPE | |
| [] | Impossible | TYPE | CLASS[VAL] | Utile de renvoyer une référnce|
| () | Impossible | [TYPE...] | CLASS( [TYPE...] ) | Fonctors |
+------------------------------------------+----------------+-----------+---------------------+-------------------------------+
#Notes :
# - ils ne peuvent pas avoir d'arguments par défaut, sauf l'operator ()
# - overloading possible
# - les arguments devraient toujours être const&.
# Pour une CLASSFK ils devraient aussi être CLASSFK const { } pour :
# - ==, <, etc., -, +, *, /, %, &&, ||, &, |, ^, <<, >>, ',', typecast overloading
# - il n'y a pas de lien nécessaire entre le SYMBOLE utilisé et les COMMANDES exécutées, mais c'est
# préférable
# - un overloadable operator est donc toujours ou dans une classe, ou avec une CLASS_VAR en
# argument : il n'est donc pas possible de l'utiliser entre deux TYPE fondamentaux
OPERATOR PRECEDENCE ==> #Voici :
+---------------------------------------------+-----------+----+----------+---------------+--------------+--------------+-----+
| BASE |ARITHMETIC |BIN1| TEST | BINARY 2 | LOGICS | ASSIGNATION | |
+----+--------------+-------------------+-----+-----+-----+----+-----+----+---+-----+-----+----+----+----+--------------+-----+
| | ++A --A () . | A++ A-- + - ! | .* | * | + | >> | < > | | | | | | | | = *= <<= ^= | |
| :: | [] -> typeid | ~ (type) * & | ->* | / | - | << | <= | == | & | ^ | | | && | || | ?: | += /= >>= |= | , |
| | *_cast<>() | sizeof new delete | | % | | | >= | | | | | | | | -= %= &= | |
+----+--------------+-------------------+-----+-----+-----+----+-----+----+---+-----+-----+----+----+----+--------------+-----+
EXTENSION ==> #Il est possible d'étendre facilement des classes déjà
#existantes (std::string, std::cout, etc.) avec les
#opérateurs non-CLASSFK, il suffit de :
# - définir un tel opérateur, avec en premier argument
# la classe existante, et en deuxième sa propre
# classe
# - mettre en friend cet opérateur sans sa propre
# classe, s'il doit utiliser des membres protected de
# la classe
EXECUTION ==> #Un overloadable operator peuvent s'exécuter sous la
#forme CLASS_VAR.operatorSYMBOLE([ARGUMENTS]), mais leur
#intérêt est d'être exécuté sous la forme décrite dans
#le tableau ci-dessus.
FRIENDSHIP ET #Un overloadable operator non-CLASSFK s'il veut utiliser
OVERLOADABLE OPERATOR #son premier argument CLASS_VAR devra souvent être amie
==> #avec sa classe.
#Je trouve que donc les overloadable operators
#non-CLASSFK sont peu recommandables, sauf par exemple
#si l'on veut pouvoir utiliser la syntaxe :
# - VAL SYMBOLE CLASSE_VAL
#notamment pour permettre le fait de mettre la CLASS_VAL
#ou à droite du symbole, ou à sa gauche (en overloadant
#la fonction), on ne peut le faire qu'avec un
#overloadable operator non-CLASSFK.
CHAINE D'OVERLOADABLE #Il est possible de créer des chaînes d'exécution
OPERATORS ==> #d'overloadable operators, comme :
# - CLASS_VAL SYMBOLE VAL [SYMBOLE VAL]...
#Pour ce faire, il suffit que l'overloadable operator
#renvoie une CLASS_VAL (notamment *this)
SEQUENCE POINT ==> #Moment où l'on est sûr que tous les side effects des opérations précédentes ont été résolus.
#Il y a :
# - EXPR && EXPR2 ; EXPR || EXPR2 ; EXPR, EXPR2
# - mais non EXPR + EXPR2 par exemple : EXPR est sûr d'être évalué avant EXPR2 que dans les cas du
# dessus
# - EXPR ? EXPR2 : EXPR3 (le ?, pas le :)
# - fin d'un statement ; avant le début d'un fonction call
# - et non entre les arguments, qui peuvent donc être appelés dans n'importe quel ordre, mais on
# est sûr qu'ils seront évalués avant le fonction call
┌─────────────┐
│ CLASSES │
└─────────────┘
CLASS #Désigne un nom de classe.
#CLASS est un TYPE complexe, précédé facultativement
#de "class", sauf dans une déclaration, où c'est
#obligatoire (je l'indique donc).
#Une classe est un modèle à partir duquel sont
#instantiés des objets, chaque objet ayant des data
#individuelles qui lui sont propres.
#Un objet est une instantiation de la classe : CLASS_VAR
#ou CLASS_ADR pour un pointeur de classe, ou CLASS_VAL
#pour une instantiation temporaire.
#Une classe n'a pas de data, mais des modèles de data :
#ce sont ses instantiations qui ont des data.
class CLASS #Déclare juste CLASS (ne pas mettre les inheritances).
#Ne me semble pas utile en tant que tel.
class CLASS { #Véritable déclaration de CLASS. C'est notamment celle à
[[ACCESS:] #mettre dans les headers.
TYPE CLASSDT #C'est similaire à une struct de C, sauf qu'en plus
[, CLASSDT2] #des data, CLASSDT, il est possible d'avoir des
...;]... #fonctions comme membre, CLASSFK, les "méthodes".
[[ACCESS:] #CLASSDT et CLASSFK constituent les membres d'une classe
[TYPE] CLASSFK #Chaque membre peut être suivi par une CLASSDT ou une
([ARGUMENTS]) #CLASSFK du même TYPE. Pour déclarer un nouveau membre
[, CLASSFK2 #d'un TYPE différent, il faut faire un nouveau ";"
([ARGUMENTS2])] #Si CLASSFK est un consructor ou un destructor, il n'y
...;]... #a pas de TYPE.
} [CLASS_VAR] #Il est possible d'instantier en même temps des
[, CLASS_VAR2]... ; #CLASS_VAR...
#ACCESS est "public", "private" ou "protected" : voir le
#sujet sur les droits d'accès.
#Ne pas oublier le ;
POINTEURS DE CLASSDT #CLASSDT peut être :
==> # - précédé de * pour en faire un pointeur
# - suivi de [TOUINTVAL] pour en faire une array
# - sous la forme (*CLASSDT)() pour être un pointeur de
# fonction
#Dans tous les cas, la mémoire doit être alloué (par
#exemple avec new dans le consructor) et désallouée
#(par exemple avec delete dans le destructor).
[TYPE] CLASSFK #Les CLASSDT ne peuvent pas être définies lors d'une
([ARGUMENTS]) { #déclaration de CLASS (mais on peut créer des
COMMANDES;... #constructors pour qu'elles le soient à chaque
[return VAL;] #instantiation de CLASS)
} #Cependant, une CLASSFK peut être ainsi définie en même
#temps que sa déclaration.
[TYPE] CLASS::CLASSFK #Elle peut aussi être définie en dehors de la classe
([ARGUMENTS]) { #sous cette forme. Elle doit alors avoir été
COMMANDES;... #prédécédemment déclarée dans CLASS, et cette
[return VAL;] #déclaration doit précéder, ainsi que de "inline" s'il
} #s'agit d'un header.
ACCES RELATIF AUX #L'accès (lecture/écriture) d'un CLASSFK à un autre
MEMBRES DE LA MÊME #CLASSFK ou à une CLASSDT de la même CLASS est relatif.
CLASSE ==> #Cela signifie qu'appartenant au même namespace, il
#faut juste écrire par exemple CLASSDT, et non
#CLASS::CLASSDT (qui marche, mais est inutile) ou
#CLASS.CLASSDT (qui est réservé à l'instantiation d'une
#CLASS, donc sous la forme CLASS_VAR.CLASSDT)
STATIC CLASSDT ET #Elles sont attachées à une classe entière, mais à
CLASSFK ==> #aucune de ses instantiations.
#Elles sont accédées en faisant CLASS::CLASSDT ou
#CLASS::CLASSFK uniquement.
#Elles ajoutent une sorte de portée globale à une classe
#et sont donc considérées parfois comme une mauvaise
#pratique.
static TYPE CLASSDT; #Déclaration d'une CLASSDT statique :
# - sa valeur est partagée par toutes les instances de
# la classe
# - elle doit être initialisée en dehors de tout bloc,
# après sa déclaration, mais avant son accès, et sans
# le mot "static". Cela donne donc :
# - TYPE CLASS::CLASSDT = VAL
# - elle peut toutefois être initialisée dans le bloc, à
# condition que la rvalue soit toujours évaluable en
# compile-time, et que ce soit soit const
# - ne peut pas être de TYPE void, ou mutable.
static TYPE CLASSFK #Déclaration d'une CLASSFK statique
([ARGUMENTS]) #Elle :
# - ne peut avoir accès qu'à des static CLASSDT
# - ne peut pas utiliser this, être virtual, const ou
# être de TYPE volatile
static TYPE CLASSFK
([ARGUMENTS]) { ... } #Déclaration et définition d'une CLASSFK statique
INSTANTIER UNE CLASSE
==> #Voici :
CLASS CLASS_VAR #Déclare CLASS_VAR en instantiant CLASS et en exécutant
#son constructor CLASS(void). CLASS CLASS_VAR() est une
#erreur syntaxique.
CLASS CLASS_VAR #Déclare CLASS_VAR en instantiant CLASS et en exécutant
(VAL[, VAL2]...) #son constructor CLASS(VAL[, VAL2]...).
CLASS CLASS_VAR = #Si un seul VAL, et que ce VAL est une CLASS_VAR de
CLASS(VAL[, VL2]...) #même type, utilise donc copy constructor par défaut,
#sauf s'il a été redéfini
CLASS CLASS_VAR = VAL #Exactement même chose, mais fait appel au constructor
#de manière implicite. Même chose pour ce qui est du
#copy constructor. Cependant, l'appel implicite a des
#restrictions :
# - le constructor ne peut avoir qu'un argument VAL
# - le constructor de CLASS ne doit pas être précédé du
# keyword explicit, par exemple :
# - explicit CLASS(VAL) { ... }
CLASS_VAR = CLASSE_VAR2 #Affectation utilisant l'overloadable operators =
#Seule affectation possible d'une CLASS_VAR, qui n'est
#pas vraiment une affectation mais l'utilisation de la
#fonction appelée par l'overloadable operator =
CLASS([VAL[, VAL2]...]) #Renvoie une CLASS_VAL, instantiation temporaire de
#CLASS avec le constructor CLASS(VAL[, VAL2]...).
#Il faut parfois mettre des parenthèses vides pour bien
#montrer qu'il s'agit d'une CLASS_VAL temporaire et non
#d'une CLASS (par exemple pour un fonctor temporaire
#utilisé comme argument d'une fonction)
#"CLASS_VAL" fait référence à une CLASS_VAR ou à une
#CLASS_VAL temporaire de ce genre.
#Utilité des CLASS_VAL temporaires :
# - être passés comme valeur à une fonction prenant
# une CLASS_VAL non référence comme argument, sans
# avoir besoin d'instantier une CLASS_VAR. Il faut
# prendre garde que cette CLASS_VAL ne soit pas
# ensuite retourner sous forme de référence, car cela
# buguerait.
# Elle peut aussi être passée sous la seule forme VAL
# par exemple pour une fonction définie telle que :
# - TYPE FONC_NAME(CLASS_VAR)
# On peut l'invoquer sous la forme :
# - FONC_NAME(VAL)
# Qui équivaut à :
# - FONC_NAME(CLASS(VAL))
# Il s'agit d'un appel au constructor de manière
# implicite : il ne peut donc y avoir qu'une seule
# VAL et le constructor de CLASS ne doit pas être
# "explicit"
# - être la valeur return par une fonction renvoyant
# une valeur non référence de type CLASS, sans avoir
# besoin d'instantier une CLASS_VAR. Exemple :
# - CLASS FONC_NAME(ARGUMENTS) {
# ...
# return CLASS(VAL...)
# }
CLASS() SYNTAXE ==> #Une instantiation de classe ne prenant pas
#d'arguments, doit être écrit :
# - s'il s'agit de la déclaration de la classe :
# CLASS CLASS_VAR;
# - s'il s'agit d'une classe temporaire utilisée comme
# seule argument d'un constructor (ou suivie par
# d'autres classes temporaires ne prenant pas
# d'arguments) :
# CLASS2 CLASS2_VAR( (CLASS()) )
# Sans les parenthèses, le compiler pense qu'il
# s'agit d'une fonction CLASS2_VAR prenant un
# pointeur de fonction comme argument.
ACCES AUX MEMBRES D'UNE #Dans ce qui suit, accès signifie lecture ou écriture.
CLASS_VAR ==> #Il suffit donc de rajouter = VAL à la fin (pour une
#CLASSDT) pour faire une affectation.
#Par ailleurs, pour une CLASS_ADR,
CLASS_VAR.CLASSDT_VAR #Accès à une une CLASSDT_VAR dans CLASS_VAR
*CLASS_VAR.ADR #Déférencement et accès à une ADR dans
*(CLASS_VAR.ADR) #CLASS_VAR
CLASS_VAR.ARR #Accès à la CLASS_VAR numéro TOUINTVAL de ARR,
[TOUINTVAL] #dans CLASS_VAR
CLASS_VAR.CLASSFK_VAR #Exécution d'une CLASSFK_VAR, dans CLASS_VAR. J'utilise
([ARGUMENTS]) #la notation courte : CLASSFK([ARGUMENTS]) pour cela,
#ou FONC_NAME([ARGUMENTS])
(*CLASS_VAR.ADR) #Exécution d'un pointeur de fonction ADR, dans
([ARGUMENTS]) #CLASS_VAR
TYPE FONC_VAR(CLASS #Déclaration d'une fonction prenant une CLASS_VAR comme
CLASS_VAR[, ARGUMENTS]) #argument. Il est préférable de faire un call by
#reference alors.
FONC_VAR(CLASS_VAL) #Exécution de cette fonction. CLASS_VAL doit être de
#type CLASS. CLASS_VAL doit être une CLASS_VAR s'il
#s'agit d'un call by refrence.
CLASSFK PAR DÉFAUT ==> #Par défaut, chaque CLASSE a quatre CLASSFK implicites
# - un constructor, sans arguments, qui ne fait rien.
# - un destructor, qui ne fait rien
# - un copy constructor, défini implicitement sous la
# forme :
# - CLASS(const CLASS& CLASS_VAR)
# - Un overloadable operator=, défini implicitement
# sous la forme :
# - CLASS& operator= (const CLASS& CLASS_VAR)
# et qui retourne *this
#Ils sont override par une CLASSFK identique (mêmes
#arguments, etc.), overloaded sinon. Exception : le
#constructor(void) par défaut est supprimé dès qu'un
#autre constructor pour la CLASS est créé, même s'il ce
#constructor prend des arguments. Il est donc alors
#conseillé souvent de recréer un constructor(void), au
#cas où.
COPY CONSTRUCTOR ET #Ils permettent tous deux de copier le contenu d'une
OVERLOADABLE OPERATOR= #CLASS_VAR2 vers une CLASS_VAR de même CLASS.
PAR DEFAUT ==> #Le premier s'exécute sous la forme :
# - CLASS CLASS_VAR(CLASS_VAR2)
# - CLASS CLASS_VAR = CLASS_VAR2
#et n'a donc lieu que lors de la déclaration de
#CLASS_VAR
#Le second s'exécute sous la forme :
# - CLASS CLASS_VAR = CLASS_VAR2
#mais n'a lieu que lors d'une affectation sans
#déclaration.
#Il y a deux manières de copier :
# - shallow copy : copie les valeurs de chaque CLASSDT.
# S'il s'agit de ADR, ADR est donc
# copié sans être déréférencé. CLASS_VAR et
# CLASS_VAR2 auront deux un pointeur vers la même
# zone mémoire, ce qui peut poser problème, si par
# exemple l'une des deux devient out of scope, mais
# pas l'autre, car la zone mémoire sera désallouée.
# Même chose pour les références.
# - deep copy : ici, pour copier un ADR, on
# créer de nouveaux pointeurs, pointant donc vers une
# nouvelle zone mémoire, mais avec une valeur
# identique. Cela évite les problèmes précédents.
# Mais cela implique que :
# - s'il s'agit d'une affectation sans déclaration
# - si la taille de la nouvelle zone mémoire
# pointée est susceptible d'être différente de
# l'ancienne
# Il faut réallouer de la mémoire, et donc :
# 1) checker que CLASS_VAR et CLASS_VAR2 ne font
# pas référence au même objet, auquel la copie
# est inutile, et les étapes qui suivent seront
# dangereuses ("self-assignement")
# 2) désallouer la mémoire de l'ancien pointeur de
# CLASS_VAR
# 3) lui réallouer la mémoire nécessaire en
# fonction de la nouvelle valeur pointée
# 4) que si le ADR de CLASS_VAR2 est NULL,
# on ne cherche pas à en déréférencer le contenu
# mais simplement à faire en sorte que le
# ADR de CLASS_VAR soit un NULL aussi
#L'overloadable operator= et le copy constructor font
#un shallow copy par défaut : les redéfinir donc pour
#toute classe ayant des CLASSDT & ou *
#Par ailleurs, pour empêcher de faire une copie d'une
#instantiation d'une CLASS, on peut mettre son copy
#constructor et overloadable operator= en private ou
#protected
OPERATOR= DE CLASSE #Si l'on définit l'operator= d'une classe enfant, plutôt que d'initialiser les membres hérités de cette
ENFANT ==> #classe soi-même, on peut faire : Base::operator=( ENFANT ) (ENFANT étant l'argument passé par
#référence)
DECLARATION DE CLASSES #Une classe doit être déclarée entière, avec tous ces
DANS LES HEADERS #membres déclarés (mais pas définis) dans un header :
==> # - class CLASS
# {
# CLASSFK1(...);
# CLASSFK2(...);
# }
#Le fichier .cpp doit contenir quant à lui la
#succession des définition des CLASSFK, isolées les
#unes aux autres, de cette classe (et non les
#CLASSDT) :
# - CLASS::CLASSFK1(...) { ... }
# - CLASS::CLASSFK2(...) { ... }, etc.
#1 classe doit = 1 header et 1 fichier .cpp, et
#inversement.
#Le fichier .cpp doit include cet header.
#Un autre fichier .cpp souhaitant utiliser la classe
#doit :
# - include cet header
# - se lier (= compiler ensemble) avec le .cpp de la
# classe
SEMANTIQUE DE VALEUR #Une classe a une sémantique de valeur si ses objets
ET D'ENTITE ==> #peuvent être comparés (et ont donc une valeur), et une
#sémantique d'entité si ses objets sont singuliers et
#ne peuvent être comparés. Dans le premier cas, on
#pourra par exemple définir les opérateurs +, -, *, /,
#=, ==, <, etc
┌───────────────┐
│ CONSTNESS │
└───────────────┘
const CLASS CLASS_VAR #Instantie CLASS de sorte que :
# - les CLASSDT de CLASS_VAR soient read-only. Ils
# peuvent juste être modifiés par le constructor.
# - seuls les CLASSFK const { } de CLASS_VAR sont
# utilisables
const CLASS CLASSDT #Déclarer une CLASSDT read-only.
#Elle ne pourra être initialisée que grâce à
#l'initialisation list du constructor.
mutable CLASS CLASS_VAR #Déclare une CLASS_VAR mutable. Elle n'est pas
#read-only. Son intérêt est qu'elle peut être modifiée
#par une CLASSFK const { }. Peu utilisé car plutôt que
#de la mettre mutable, on aurait pu enlever const de
#CLASSFK. Son intérêt est de permettre à une CLASSFK
#étant logiquement const de modifier malgré tout une
#CLASSDT, par exemple pendant un debuggage.
#Préférer cela à const_cast<>.
TYPE [CLASS::]CLASSFK #Déclare une CLASSFK const { }.
const { ...} ; #Les CLASSDT de la classe courante (qu'ils soient const
#ou non) ne pourront pas être modifiés dans le bloc de
#cette CLASSFK, à moins qu'elles soient mutable.
#Elles ne pourront donc pas non plus être converties en
#référence non-const.
#Revient en fait à mettre un const devant *this, le
#premier argument implicite.
#Ne marche pas sur un constructor ou destructor.
CONST * ET & ==> #Syntaxe :
# - TYPE const* (à préférer), ou const TYPE* : valeur
# pointée est const
# - TYPE const& (à préférer), ou const TYPE& : valeur
# référée est const
# - TYPE* const : pointeur est const.
# - TYPE& const : impossible de modifier une
# référence (seulement ce qu'elle réfère), donc
# inutile
UTILITE DE CONST ==> #Pour :
# - un argument :
# I) * ou & :
# 1) pas modifié par fonction -> mettre const :
# a) permet de passer en argument un const
# TYPE* ou const TYPE& (sinon impossible)
# b) pour &, permet de passer un TYPE non-&
# (sinon transtypage (non-const&) non-& est
# interdit)
# c) toujours possible de passer en argument un
# non-const TYPE* ou TYPE&
# d) indique dans documentation que l'argument
# ne sera pas modifié
# 2) modifié par fonction :
# a) intentionnel (setter) -> pas const (sera
# impossible donc de passer un argument
# const). Documenter qu'argument doit être
# mutable (et, si &, référence).
# b) non-intentionnel -> passer plutôt argument
# par valeur, ou éviter modification et
# mettre en const
# II) non * ni & -> const inutile, car il s'agit
# d'une copie, et le caller se fiche qu'elle
# soit modifiée.
# De plus, on peut transtyper tout [non-]const
# [non-]& vers tout [non-]const non-&, car
# copie.
# - CLASSFK : fonction avec comme premier argument
# implicite CLASS. Mettre un CLASSFK const { }
# revient à mettre CLASS en const. Si CLASS :
# - pas modifiée par fonction (getter) -> cf I)1).
# Sinon, instantiations const ne pourront pas
# utiliser CLASSFK (mais instantiations non-const
# peuvent toujours l'utiliser).
# Par contre, instantiation temporaire peuvent
# utiliser CLASSFK const ou non.
# - modifiée par fonction (setter) -> cf I)2)a). Un
# setter n'est pas supposé fonctionner avec une
# instantiation const de toute façon. Documenter
# que CLASS doit être mutable.
# - return value :
# - non-const (laisser caller faire ce qu'il veut),
# sauf :
# - * ou & pour des raisons de performance (getter
# ne voulant pas réinstancier un objet) (pas
# bonne pratique ?), mais pas censé être modifié
# -> const
# - * ou & provenant d'un argument (dont CLASSDT
# pour une CLASSFK)
# - problème : conversion entre argument const
# et non-const * ou &
# -> const overloading :
# - permet d'utiliser malgré tout un argument
# const (ou une instantiation const pour
# une CLASSFK), mais cela fera :
# - perdre la possibilité de modifier la
# return value : const TYPE&
# - ou perdre la possibité de passer par
# référence : TYPE
# - Très utilisé par les fonctions renvoyant
# un bout d'objet, tel operator[],
# operator(), etc.
# - Exemple :
# - const TYPE& FONC_VAR(const VAR);
# TYPE& FONC_VAR(VAR);
# - const TYPE& CLASSFK() const;
# TYPE& CLASSFK();
# - Ou :
# - TYPE CLASSFK() const;
# TYPE& CLASSFK();
RESUME ==> #Mettre const :
# - sur argument * ou & non-modifié par fonction
# - sur getter (CLASSFK() const { })
#( - sur return value * ou & pour raison de performance
# et non de modification)
# - const overloading sur return value * ou &
# provenant d'un argument et pouvant être
# intentionnellement modifiée
#Documenter que sont mutables :
# - Argument modifié par un setter
# - setter CLASSFK doivent avoir instantiations
# mutables
CONST OVERLOADING ==> #Cela ne marche que pour les CLASSFK() const { },
#pas pour les arguments (pas d'overloading possible
#entre deux fonctions avec comme seule différence la
#constness de leur arguments)
PERFORMANCE ==> #Tout est fait compile-time, donc pas de run-time
#perte de safety ou performance.
CONST ADR_ADR ==> #Ne pas caster un ADR_ADR vers un const ADR_ADR
#mais vers un const ADR const ADR. Non pas :
# - TYPE ** VAR;
# const TYPE ** VAR2(VAR);
#Mais :
# - TYPE const* const* VAR2(VAR);
VOLATILE ==> #De même que const, une volatile CLASS_VAR ne peut
#utiliser que des CLASSFK volatile { }
#Il est aussi impossible de convertir des non-volatile
#vers des volatile (mais l'inverse oui), sauf via un
#const_cast.
#Une classe volatile fait que ses CLASSDT deviennent
#volatile.
#volatile overloading : deux fonctions, une volatile
#si CLASS est volatile, et donc partagée par plusieurs
#threads, utilisant des procédés de synchronisation ;
#une seconde non-volatile, sans ces derniers.
┌─────────────────────────┐
│ POINTEURS DE CLASSE │
└─────────────────────────┘
ARRAY DE CLASSES ==> #Les arrays de classes ne peuvent pas utiliser toutes
#les possibilités des pointeurs de classes : ils ne
#peuvent pas être utilisés comme CLASS_ADR en tant que
#tels, mais seulement déférencés sous la forme :
#CLASS_ARR[TOUINTVAL]
CLASS CLASS_ARR
[TOUINTVAL] #Déclare un array de TOUINTVAL CLASS_VAR.
CLASS_ARR[TOUINTVAL] #Renvoie une CLASS_VAR, qui peut ensuite être utilisée
#dans toute occasion où CLASS_VAR est possible.
#Exemple :
# - CLASS_ARR[TOUINTVAL].CLASSDT
POINTEURS DE CLASSES #Pour accéder aux membres d'une CLASS_ADR, faire :
==> # - (*CLASS_ADR).CLASSDT
# - (*CLASS_ADR).CLASSFK
#ou :
# - CLASS_ADR->CLASSDT
# - CLASS_ADR->CLASSFK
#Par ailleurs, considérant que :
# - *CLASS_ADR et *CLASS_ADR2 font référence à un
# objet de type CLASS
# - *CLASS2_ADR fait référence à un objet de type
# CLASS2, et que CLASS2 hérite de CLASS.
# - *CLASS3_ADR fait référence à un objet de type
# CLASS3, et que CLASS3 n'a rien à voir avec CLASS
# ni CLASS2
#Peu importe le nombre de classes intermédiaires dans
#l'héritage de CLASS2 par rapport à CLASS : les classes
#intermédiaires ne sont pas prises en compte, et le
#degré d'héritage ne change rien. La modification d'une
#virtual CLASSFK dans CLASS_ADR ne dépend que de la
#CLASS_ADR qui lui est éventuellement affectée.
#Tous les exemples qui suivent peuvent être des
#déclaration + définition : il suffit de rajouter la
#classe du premier pointeur avant lui.
#Par ailleurs, s'il s'agit d'une déclaration, il est
#possible d'utiliser la notation :
# - CLASS CLASS_ADR( ... )
#à la place de :
# - CLASS CLASS_ADR = ...
#Dans les exemples qui suivent, le premier membre de
#l'assignation étant un pointeur, il n'appelle pas de
#de constructor. Cependant, le deuxième membre, quel
#qu'il soit, peut voir été initialisé ou non. Il y a
#trois cas en la matière :
# a) il n'a pas été initialisé. Dans ce cas :
# - Aucun constructor n'est donc appelé, et pas
# d'allocation mémoire
# - ni lui, ni le premier membre de l'assignation
# ne peut utiliser de virtual fonction, ou un
# homonyme d'une virtual fonction d'une classe
# dont il hérite
# b) il a été initialisé avec une instantiation de
# CLASS. Ainsi, le constructor de CLASS a été
# appelé. Exemple :
# - CLASS CLASS_VAR
# - CLASS3 *CLASS3_ADR = (CLASS3*) new CLASS
# Comme on le voit, l'important n'est pas le type du
# second membre, mais le fait qu'il ait été
# initialisé avec CLASS. Le constructor de CLASS
# initialisera éventuellement des CLASSDT propres à
# CLASS, et même si CLASS3 ne peut pas y accéder,
# cette initialisation n'est pas perdue.
# c) il a été initialisé avec une instantiation de
# CLASS2. Ainsi, le constructor de CLASS, puis celui
# de CLASS2 ont été appelés. Exemple :
# - CLASS *CLASS_ADR = new CLASS2
# d) il a été initialisé avec une instantiation de
# CLASS3.
DEFINITION
NON-POLYMORPHIQUE ==> #Voici :
CLASS *CLASS_ADR #*CLASS_ADR et *CLASS_ADR2 font alors référence à la
= CLASS_ADR2 #même instantiation de CLASS. Modifier l'un modifie
#l'autre.
#*CLASS_ADR est initialisé selon les valeurs des
#membres de *CLASS_ADR2.
CLASS *CLASS_ADR #Même chose : (CLASS2*) est ignoré.
= (CLASS2*) CLASS_ADR2 #Exception : si CLASS_ADR2 a été initialisé selon
#l'option c), il s'agira d'une initialisation
#polymorphique normale.
CLASS *CLASS_ADR #*CLASS_ADR fait alors référence à une instantiation de
= (CLASS*) CLASS3_ADR #CLASS, dont les virtual fonctions ne marchent pas.
#Si CLASS3_ADR a été initialisé selon l'option b) ou c):
# - les virtual fonctions marchent
# - la valeur des CLASSDT éventuellement initialisées
# par le constructor sont passées à *CLASS_ADR
DEFINITION
POLYMORPHIQUE NORMALE
==> #Voici :
CLASS_ADR = CLASS2_ADR # 1) Les CLASSDT de *CLASS_ADR, hérités par *CLASS2_ADR,
CLASS2_ADR = CLASS2_ADR # deviennent les mêmes CLASSDT en mémoire, qu'ils se
# trouvent dans *CLASS_ADR ou dans *CLASS2_ADR :
# a) Leur valeur est initialisée à partir de leur
# valeur dans *CLASS2_ADR, non de leur valeur
# dans *CLASS_ADR. Cette valeur peut avoir été
# initialisée par un constructor si CLASS2_ADR a
# été initialisé selon l'option b) ou c) et/ou
# peuvent avoir été modifiée entre-temps
# b) modifier leur valeur dans l'un modifie la
# valeur dans l'autre.
# 2) Les CLASSDT de *CLASS2_ADR propres à lui (non
# hérités de *CLASS_ADR), ne peuvent pas plus être
# accédées par *CLASS_ADR, si ce n'est par le biais
# de virtual CLASSFK.
# 3) Les private members de *CLASS_ADR :
# - sont éventuellement initialisés en fonction du
# constructor de CLASS, à condition que
# CLASS2_ADR ait été initialisé selon l'option b)
# ou c)
# - peuvent toujours autant être accédés par
# *CLASS_ADR
# - ne peuvent toujours pas plus être accédés par
# *CLASS2_ADR
# 4) Les virtual et abstraites CLASSFK de *CLASS_ADR
# ayant des homonymes dans *CLASS2_ADR :
# - sont redéfinies d'après leurs homonymes.
# - acquierent les mêmes accès que leurs homonymes.
# Ainsi, elles :