0% ont trouvé ce document utile (0 vote)
812 vues2 549 pages

Devwin 32

dff

Transféré par

Radovan Jaic
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
812 vues2 549 pages

Devwin 32

dff

Transféré par

Radovan Jaic
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

RAD Studio

Copyright© 2008 Embarcadero Technologies, Inc. Tous droits réservés.


RAD Studio

Sommaire

Concepts 1
Débogage d'applications C++ avec les rapports d'erreurs CodeGuard 3
Erreurs CodeGuard 3
Erreurs d'accès 4
Erreurs d'exceptions 5
Erreurs d'échec de fonction 6
Erreurs de ressources 7
Présentation de CodeGuard 9
Avertissements CodeGuard 10
Avertissements pour la comparaison de blocs mémoire 11
Avertissements sur la fusion et la scission de noms de chemins 11
Avertissements de comparaison de chaînes 12

Développement d'applications de bases de données pour la plate-forme Win32 13


Présentation de dbGo 14
Présentation de BDE 15
Composants dbExpress 16
Introduction à InterBase Express 17
Présentation des nouvelles fonctionnalités de dbExpress 4 22
Présentation de la migration BDP 26
Concepteurs de composants ADO.NET 30
Déploiement d'applications de bases de données pour le .NET Framework 33
Framework dbExpress 35
Compatibilité du framework dbExpress 37

Développement des applications interopérables 39


Développement d'applications COM 39

Développement d'états pour vos applications Win32 45


Utilisation de Rave Reports dans RAD Studio 45

Développement d'applications avec des composants VCL 46


Présentation de la VCL 46
Utilisation de TEncoding pour les fichiers Unicode 48

Développement d'applications Web avec WebSnap 51


Présentation des applications Web Win32 51

Développement de services Web avec des applications Win32 54

iii
RAD Studio

Présentation des services Web 54

Développement d'applications Windows 55


Présentation de Windows 55

Procédures 57
Procédures CodeGuard 58
Utilisation de CodeGuard 58

Procédures de bases de données 60


Accès aux informations de schéma 61
Configuration d'une connexion TSQL 62
Connexion au serveur d'applications à l'aide de composants DataSnap 64
Débogage d'applications dbExpress à l'aide de TSQLMonitor 65
Exécution des commandes à l'aide de TSQLDataSet 65
Récupération des données à l'aide de TSQLDataSet 67
Spécification des données à afficher à l'aide de TSQLDataSet 68
Spécification du fournisseur à l'aide d'un composant TLocalConnection ou TConnectionBroker 69
Utilisation du BDE 70
Utilisation de DataSnap 70
Utilisation de TBatchMove 71
Connexion aux bases de données avec TDatabase 72
Utilisation de TQuery 73
Utilisation de TSQLQuery 75
Utilisation de TSQLStoredProc 76
Utilisation de TSQLTable 77
Gestion des sessions de bases de données avec TSession 78
Utilisation de TSimpleDataSet 78
Utilisation de TSimpleObjectBroker 79
Utilisation de TStoredProc 80
Utilisation de TTable 81
Utilisation de TUpdateSQL pour mettre à jour un ensemble de données 83
Utilisation de dbExpress 83
Utilisation de l'explorateur de données pour obtenir des informations de connexion 84

Procédures d'applications interopérables 86


Utilisation des experts COM 86

Procédures de génération d'états 88


Ajout de Rave Reports à RAD Studio 88

iv
RAD Studio

Procédures VCL 89
Construction d'une application console "Hello World" Windows 96
Développement d'une application Windows 97
Construction des menus d'applications 97
Construction d'une application Fiches VCL avec des composants d'aide à la décision 99
Construction d'applications Fiches VCL avec graphiques 101
Construction d'une application MDI Fiches VCL à l'aide d'un expert 101
Construction d'une application MDI Fiches VCL sans utiliser d'expert 102
Construction d'une application SDI Fiches VCL 104
Création d'un nouveau composant VCL 105
Conception d'une application Fiches VCL de base de données ADO 106
Construction d'une application Fiches VCL 108
Création d'actions dans une application Fiches VCL 108
Construction d'une application Fiches VCL "Hello World" 109
Utilisation de ActionManager pour créer des actions dans une application Fiches VCL 110
Conception d'une application Fiches VCL de base de données dbExpress 111
Construction d'une application avec des composants XML 113
Copie de données d'un flux vers un autre 115
Copie de la totalité d'une liste de chaînes 116
Création de chaînes 118
Création d'une instance de fiche VCL en utilisant une variable locale 119
Suppression de chaînes 121
Affichage d'une fiche VCL créée automatiquement 122
Affichage d'une image bitmap dans une application Fiches VCL 124
Affichage d'une image bitmap plein écran dans une application Fiches VCL 125
Dessin d'un polygone dans une application Fiches VCL 126
Dessin de rectangles et d'ellipses dans une application Fiches VCL 127
Dessin d'un rectangle arrondi dans une application Fiches VCL 128
Dessin de lignes droites dans une application Fiches VCL 128
Création dynamique d'une fiche VCL modale 129
Création dynamique d'une fiche VCL non modale 131
Parcours des chaînes d'une liste 132
Construction d'une application multithread 134
Ecriture du code de nettoyage 134
Eviter les accès de threads simultanés dans la même mémoire 134
Définition de l'objet thread 136
Gestion des exceptions 139
Initialisation d'un thread 139
Utilisation du thread VCL principal 140

v
RAD Studio

Attente des threads 142


Ecriture de la fonction Thread 144
Insertion d'une image bitmap dans un contrôle d'une application Fiches VCL 144
Lecture d'une chaîne et écriture de cette chaîne dans un fichier 145
Renommage de fichiers 146
Ajout et tri de chaînes 147
Création d'un bouton ActiveX Fiches VCL 148
Création d'une fiche active VCL ActiveX 150
Construction d'une application de navigateur Web Fiches VCL 151
Création d'une application qui utilise les contrôles ruban 152
Ajout de commandes au ruban 153

Procédures WebSnap 157


Construction d'une application WebSnap 157
Construction d'une application "Hello world" WebSnap 158
Débogage d'une application WebSnap à l'aide du débogueur d'application Web 160

Procédures de services Web 162


Construction d'une application de services Web "Hello World" 162
Accès à une application services Web "Hello World" 164
Construction d'une application de services Web "Hello World" ASP.NET 165

Référence 167
Référence C++ 168
Utilitaires en ligne de commande 168
BCC32, le compilateur C++ en ligne de commande 171
BRC32, le Shell de ressources 176
BRCC32.EXE, le compilateur de ressources 177
COFF2OMF.EXE, l'outil de conversion d'une bibliothèque d'importation 178
CPP32.EXE, le préprocesseur du compilateur C 179
DCC32.EXE, le compilateur en ligne de commande Delphi. 181
DCCIL.EXE, le compilateur en ligne de commande Delphi pour .NET 183
GREP.EXE, l'utilitaire de recherche de texte 184
ILINK32.EXE, le lieur incrémentiel 189
IMPDEF.EXE, le gestionnaire de définition de module 194
IMPLIB.EXE, l'outil bibliothèque d'importation 196
Utilisation des fichiers d'inclusion 197
MAKE 198
Directives MAKE 201
Macros MAKE 206

vi
RAD Studio

Commandes et règles (explicites et implicites) de MAKE 208


Options des messages 212
Fichiers de définition de module 214
Fichiers en-tête précompilés 219
RLINK32.DLL, le lieur de ressources (C++) 220
TDUMP.EXE, l'utilitaire de vidage de fichier 221
TLIB.EXE, le gestionnaire de bibliothèques 224
Utilisation de TOUCH.EXE 227
TRIGRAPH 228
Liste de tous les avertissements et erreurs du compilateur C++ 229
E2066: Héritage MOM invalide 272
E2525: Vous devez définir _PCH_STATIC_CONST avant d'inclure xstring afin d'utiliser cette fonctionnalité 272
E2526: La propriété 'nom' utilise une autre propriété comme getter/setter ; non autorisé 272
E2008: Les fonctions d'accès à la propriété publiée doivent utiliser la convention d'appel __fastcall 272
E2122: L'appel de fonction s'est terminé par une exception non gérée 'valeur' à l'adresse 'adresse' 273
E2506: La spécialisation explicite de 'spécificateur' est ambiguë : des arguments modèles doivent être 273
spécifiés
E2483: La dimension du tableau 'spécificateur' n'a pas pu être déterminée 273
E2509: Valeur hors limites 273
E2510: Non concordance de taille d'opérande 273
E2050: La classe __declspec(delphireturn) 'classe' doit avoir exactement une donnée membre 273
E2530: Option non reconnue ou aide indisponible 274
E2527: L'option 'nom' ne peut pas être définie via 'nom' 274
E2528: L'option 'nom' doit être définie avant la compilation 274
E2074: La valeur après -g ou -j doit être comprise entre 0 et 255 inclus 274
E2492: Les propriétés peuvent uniquement être affectées en utilisant une instruction simple, par exemple 274
\"prop = valeur;\"
E2505: L'instanciation explicite requiert un spécificateur de type élaboré (par exemple, "class foo<int>") 275
E2100: Liste de déclarateurs de modèles incorrecte 275
E2102: Impossible d'utiliser le modèle 'modèle' sans spécifier des paramètres de spécialisation 275
E2107: Utilisation incorrecte du modèle 'modèle' 275
E2105: Le qualificateur 'modèle' doit spécifier un nom de modèle membre 276
E2066: Information non disponible 276
E2471: pragma checkoption a échoué : les options ne sont pas celles attendues 276
E2504: 'dynamic' ne peut être utilisé qu'avec des fonctions membre non modèle 277
E2191: '__far16' ne peut être utilisé qu'avec '__pascal' ou '__cdecl' 277
E2199: La fonction amie modèle 'fonction' doit être préalablement déclarée 277
E2502: Erreur de résolution de #import : problème 277
E2501: Impossible d'ouvrir le fichier d'importation 'nom_fichier' 278
E2494: Modificateur __declspec non reconnu 278

vii
RAD Studio

E2493: Chaîne GUID incorrecte 278


E2499: Format __declspec(uuid(GuidString)) non valide 278
E2496: Appel non valide à uuidof(struct type|variable) 278
E2511: Argument de macro non terminé 278
E2489: Profondeur maximum de répétitions d'options dépassée ; vérifiez la récursivité 279
E2488: Profondeur maximum de réponse dépassée ; vérifiez la récursivité 279
E2491: Compte VIRDEF maximum dépassé ; vérifiez la récursivité 279
E2230: L'initialisation de données membre en ligne nécessite une expression constante intégrale 279
E2241: Les classes de style VCL ont besoin de destructeurs virtuels 279
E2524: Les unions/structs anonymes ne sont pas autorisées à avoir des membres anonymes en C++ 280
E2246: x n'est pas une hiérarchie de classes d'héritage simples, publiques, abstraites sans données 280
E2249: = attendu 280
E2267: La première base doit être une classe VCL 280
E2472: Impossible de déclarer une fonction membre via une instanciation 280
E2515: Impossible de spécialiser explicitement un membre d'une classe modèle générique 281
E2474: 'fonction' ne peut pas être déclarée comme static ou inline 281
E2498: Définition préalable de la structure du GUID requise 281
E2295: Trop de spécialisations de modèle candidat depuis 'spécificateur' 282
E2475: 'fonction' ne peut pas être une fonction modèle 282
E2299: Impossible de créer une spécialisation de modèle à partir de 'spécificateur' 282
E2300: Impossible de générer un type correspondant de spécialisation pour 'spécificateur' 282
E2497: Aucun GUID associé au type 'type' 282
E2522: Fonction non const 'fonction' appelée pour un objet const 283
E2523: Fonction non volatile 'nom' appelée pour un objet volatile 283
E2513: Impossible d'émettre des informations RTTI pour 'paramètre' dans 'fonction' 283
E2512: Impossible d'émettre des informations RTTI pour le type renvoyé par 'fonction' 283
E2507: 'classe' n'est pas une classe de base directe de 'classe' 283
E2529: Le chemin 'chemin' dépasse la taille maximale 'n' 283
E2495: Redéfinition de uuid non identique 283
E2500: __declspec(selectany) ne s'adresse qu'aux variables initialisées et visibles de façon externe 284
E2482: Constante chaîne attendue 284
E2481: Constante chaîne inattendue 284
E2386: Impossible d'impliquer le paramètre 'paramètre' dans une expression de spécialisation partielle 284
complexe
E2387: Les spécialisations partielles ne peuvent pas spécialiser les paramètres dépendants non-typés 284
('paramètre')
E2388: La liste d'arguments de spécialisation ne peut pas être identique à la liste de paramètres de 284
modèle primaire
E2389: Non concordance dans le type d'argument de substitution et le paramètre modèle 'paramètre' 285

viii
RAD Studio

E2480: Impossible d'impliquer des paramètres de modèle dans les arguments de spécialisation partielle 285
complexe
E2392: L'instance du modèle 'template' est déjà instanciée 285
E2393: Impossible de prendre l'adresse du paramètre modèle non-typé, non-référencé 'paramètre' 286
E2399: Impossible de référencer de cette façon l'argument 'arg' du modèle dans la classe modèle 'classe' 286
E2397: L'argument du modèle ne peut pas avoir une liaison statique ou locale 286
E2485: Impossible d'utiliser l'élément adresse de tableau comme un argument de modèle non typé 286
E2402: Type de classe de base incorrect : type formel 'type' résolu en 'type' 286
E2403: Le spécificateur d'appel dépendant produit une non-fonction 'nom' 287
E2404: Le qualificateur de type dépendant 'qualificateur' n'a aucun type membre nommé 'nom' 287
E2405: La référence de modèle dépendante 'identificateur' fournit un symbole non modèle 287
E2406: Le qualificateur de type dépendant 'qualificateur' n'est pas un type class ou struct 287
E2407: Le qualificateur de type dépendant 'qualificateur' n'a aucun symbole membre nommé 'nom' 288
E2408: Les valeurs par défaut doivent être spécifiées seulement dans les déclarations de modèle de 288
classe primaire
E2409: Impossible de trouver une spécialisation correcte pour 'spécificateur' 288
E2410: Paramètres de modèle manquants pour le modèle ami 'modèle' 288
E2486: Impossible d'utiliser l'adresse du membre de classe comme un argument de modèle non typé 288
E2411: La déclaration des paramètres par défaut d'une fonction membre après une spécialisation a déjà 289
été développée
E2412: Tentative de lier une référence membre à un type dépendant 289
E2414: Les destructeurs ne peuvent pas être déclarés comme fonctions modèles 289
E2473: Spécialisation explicite de 'spécificateur' incorrecte 289
E2490: Spécialisation dans des classes modèle non encore implémentées 289
E2416: Déclaration de fonction modèle incorrecte 290
E2417: Impossible de spécifier des paramètres de modèle dans la spécialisation explicite de 'spécificateur' 290
E2418: Profondeur d'instanciation maximum dépassée ; vérifiez la récursivité 290
E2420: Une instanciation explicite ne peut être utilisée que sur l'étendue globale 290
E2422: Le type d'argument ne correspond pas dans la redéclaration du paramètre modèle 'paramètre' 290
E2423: Spécialisation ou instanciation explicite d'un modèle non existant 'modèle' 291
E2479: Impossible d'avoir à la fois une classe modèle et une fonction appelée 'nom' 291
E2484: Le nom de la classe modèle 'classe' ne peut pas être surchargé 291
E2426: La spécialisation explicite de 'spécificateur' nécessite une déclaration 'template<>' 291
E2487: Impossible de spécifier des arguments de fonction par défaut pour des spécialisations explicites 291
E2427: 'main' ne peut pas être une fonction modèle 292
E2429: Ce n'est pas une spécialisation partielle correcte de 'spécificateur' 292
E2430: Le nombre de paramètres de modèles ne correspond pas dans la redéclaration de 'spécificateur' 292
E2477: Trop peu de paramètres de modèle ont été déclarés pour le modèle 'modèle' 292
E2478: Trop de paramètres de modèle ont été déclarés pour le modèle 'modèle' 292
E2431: Les paramètres de modèle non-typé ne peuvent pas être de type virgule flottante, classe ou void 293

ix
RAD Studio

E2434: Les paramètres de modèle manquent dans la déclaration de modèle ('template<...>') 293
E2435: Trop d'ensembles de paramètres de modèles ont été spécifiés 293
E2436: Le type par défaut de l'argument modèle 'arg' ne nomme pas une classe modèle primaire 293
E2437: 'typename' doit être suivi par un nom de type dépendant qualifié 293
E2438: Les arguments du modèle template doivent nommer une classe 294
E2439: 'typename' n'est autorisé que dans les déclarations modèle 294
E2440: Impossible de créer une spécialisation depuis 'spécificateur' car ce type n'est pas encore défini 294
E2441: Instanciation de 'spécificateur' 294
E2503: Version manquante ou incorrecte de TypeLibImport.dll 294
E2470: Il faut inclure l'en-tête <typeinfo> pour utiliser typeid 294
E2514: Impossible (pour le moment) d'utiliser la résolution des surcharges de membre pendant 295
l'instanciation de modèle
E2508: 'using' ne peut pas faire référence à une spécialisation de modèle 295
E2462: 'virtual' ne peut être utilisé qu'avec des fonctions membre non modèle 295
W8086: Utilisation incorrecte de l'alias #pragma "NomAlias"="NomSubstitué" 295
W8099: main statique n'est pas traité comme un point d'entrée 296
W8093: Utilisation incorrecte de #pragma codeseg [nom_seg] ["classe_seg"] [groupe] 296
W8094: Utilisation incorrecte de #pragma comment( <type> [,"chaîne"] ) 296
W8085: Fonction 'fonction' redéfinie comme non-en ligne 296
W8105: Membre %s '%s' dans la classe sans constructeur 297
W8095: Utilisation incorrecte de #pragma message( "chaîne" ) 297
W8098: Constante caractère multicaractère 297
W8096: Utilisation incorrecte de #pragma code_seg(["nom_seg"[,"classe_seg"]]) 297
W8083: Pragma pack pop sans pack push correspondant 297
W8097: Toutes les options ne peuvent pas être restaurées pour l'instant 298
W8084: Nous suggérons des parenthèses pour clarifier la priorité 298
W8092: L'argument 'type' 'spécificateur' transmis à 'fonction' n'est pas un itérateur : itérateur 'type' requis 298
W8087: 'opérateur::opérateur==' doit être publiquement visible pour être contenu par un 'type' 298
W8090: 'type::opérateur<' doit être publiquement visible pour être utilisé avec 'type' 299
W8089: 'type::opérateur<' doit être publiquement visible pour être contenu par un 'type' 299
W8091: L'argument 'type' 'spécificateur' transmis à 'fonction' est un itérateur 'catégorie d'itérateur' : 299
itérateur 'catégorie d'itérateur' requis
W8076: L'instance du modèle 'spécificateur' est déjà instanciée 299
W8077: La spécialisation explicite d'un membre de classe explicitement spécialisé n'a pas de sens 299
Messages d'information 299
E2196: Impossible de prendre l'adresse de la fonction membre 'fonction' 300
F1002: Impossible de créer le fichier de sortie 'nomfichier' 300
F1003: Erreur de directive : 'message' 300
F1004: Erreur interne du compilateur 300
F1006: Appel incorrect d'une fonction intrinsèque 300

x
RAD Studio

F1007: Arborescence d'expression irréductible 301


F1009: Impossible d'ouvrir le fichier d'entrée 'nomfichier' 301
F1011: Echec d'allocation de registre 301
F1012: Débordement de pile du compilateur 301
F1013: Erreur d'écriture du fichier de sortie 301
F1000: Limite de la table du compilateur dépassée 301
F1005: Fichiers d'inclusion imbriqués trop profondément 302
F1008: Plus de mémoire 302
F1010: Impossible d'ouvrir 'nomfichier' 302
E2000: Instructions 286/287 non activées 302
Fin de programme anormale 302
E2009: Tentative d'accorder ou de réduire l'accès à 'identificateur' 302
E2011: Il est incorrect de prendre l'adresse d'un champ de bits 303
E2010: Impossible d'ajouter ou de soustraire des symboles relogeables 303
E2013: 'fonction1' ne peut pas être distinguée de 'fonction2' 303
E2014: Membre ambigu : 'membre1' et 'membre2' 303
E2015: Ambiguïté entre 'fonction1' et 'fonction2' 303
E2017: Nom de membre 'nom' ambigu 303
E2019: 'identificateur' ne peut pas être déclaré dans une union anonyme 304
E2020: Union anonyme globale non statique 304
E2022: Taille de tableau trop grande 304
E2024: Impossible de modifier un objet const 304
E2025: Affectation de 'this' non autorisée, utilisez plutôt l'opérateur X:: new 304
E2026: Instruction d'assembleur trop longue 304
E2001: Constructeurs et destructeurs non autorisés dans la section __automated 305
E2002: Seules les fonctions __fastcall sont autorisées dans la section __automated 305
E2003: Définition de données membre non autorisée dans la section __automated 305
E2004: Seule la clause read (lecture) ou write (écriture) est autorisée dans la déclaration de propriété de la 305
section __automated
E2005: Redéclaration de propriété non autorisée dans la section __automated 306
E2027: L'adresse d'un emplacement mémoire est obligatoire 306
E2028: L'opérateur -> doit renvoyer un pointeur ou une classe 306
E2029: 'identificateur' doit être une classe ou une structure précédemment définie 306
E2030: Caractère de fin de ligne mal placé 306
E2031: Transtypage impossible de 'type1' en 'type2' 307
E2033: Instruction continue mal placée 308
E2034: Impossible de convertir 'type1' en 'type2' 308
E2036: L'opérateur de conversion ne peut pas avoir de spécification de type de retour 308
E2037: Le constructeur 'constructeur' n'est pas autorisé 308

xi
RAD Studio

E2039: Séparateur décimal mal placé 309


E2041: Utilisation incorrecte du mot clé default 309
E2042: Déclarer l'opérateur delete (void*) ou (void*, size_t) 309
E2044: L'opérateur delete doit retourner void 309
E2045: Le nom du destructeur doit correspondre au nom de la classe 309
E2048: Directive de préprocesseur inconnue : 'identificateur' 310
E2046: Format de nom de fichier incorrect dans la directive include OU format de nom de fichier incorrect 310
dans la directive line
E2051: Utilisation incorrecte du point 310
E2053: Directive elif mal placée 311
E2054: Instruction else mal placée 311
E2055: Directive else mal placée 311
E2056: Directive endif mal placée 311
E2059: Langage inconnu, doit être du C ou du C++ 311
E2060: Utilisation incorrecte de la virgule flottante 311
E2061: Les amis doivent être des fonctions ou des classes 312
E2062: Indirection incorrecte 312
E2063: Initialisation incorrecte 312
E2064: Impossible d'initialiser 'type1' avec 'type2' 312
E2068: 'identificateur' n'est pas une donnée membre non statique et ne peut pas être initialisé ici 312
E2069: Utilisation incorrecte d'un pointeur de membre 312
E2071: L'opérateur new doit avoir un paramètre initial de type size_t 313
E2072: L'opérateur new[] doit renvoyer un objet de type void 313
E2075: Option 'type' incorrecte : option 314
E2076: Opérateur surchargeable attendu 314
E2080: La fonction 'fonction' doit être déclarée avec un paramètre 314
E2077: 'opérateur' doit être déclaré avec un ou sans paramètre 314
E2079: 'fonction' doit être déclarée sans paramètres 314
E2078: 'opérateur' doit être déclaré avec un ou deux paramètres 315
E2081: 'fonction' doit être déclarée avec deux paramètres 315
E2082: 'identificateur' doit être une fonction membre ou avoir un paramètre de type classe 315
E2083: Le dernier paramètre de 'opérateur' doit être de type 'int' 315
E2084: Les noms de paramètres sont utilisés seulement avec un corps de fonction 315
E2085: Addition de pointeurs incorrecte 315
E2086: Soustraction de pointeurs incorrecte 316
E2087: Utilisation incorrecte du pointeur 316
E2088: Syntaxe incorrecte pour la définition de fonctions pures 316
E2089: L'identificateur 'identificateur' ne peut pas avoir un qualificateur de type 316
E2090: Le qualificateur 'identificateur' n'est pas un nom de classe ou d'espace de nommage 317

xii
RAD Studio

E2092: La classe de stockage 'classe de stockage' n'est pas autorisée ici 317
E2096: Opération de structure incorrecte 317
E2104: Utilisation incorrecte du mot clé template 317
E2108: Utilisation incorrecte de typedef 'identificateur' 317
E2109: Type non autorisé 317
E2110: Conversion de type incompatible 317
E2113: Conflits de fonction virtuelle 'fonction1' avec la classe de base 'base' 318
E2114: Plusieurs classes de base nécessitent des noms de classes explicites 318
E2115: Champ de bits trop grand 318
E2116: Les champs de bits doivent contenir au moins un bit 318
W8005: Les champs de bits doivent être des entiers signés ou non signés 318
E2119: Pause utilisateur 318
E2111: Le type 'nomtype' ne peut pas être défini ici 319
E2121: ) manquante dans l'appel de fonction 319
E2123: La classe 'classe' ne doit pas contenir des fonctions pures 319
E2126: Case a contourné l'initialisation d'une variable locale 319
E2127: Instruction case manquante : 319
E2128: Case en dehors du switch 319
E2129: Constante caractère trop longue (ou vide) 319
E2133: Impossible d'exécuter la commande 'commande' 320
E2134: Accolade fermante manquante dans une instruction composée 320
E2137: Un destructeur pour 'classe' est nécessaire dans l'expression conditionnelle 320
E2135: Un constructeur/destructeur ne peut pas être déclaré 'const' ou 'volatile' 320
E2138: Conflit de modificateurs de type 320
E2136: Un constructeur ne peut pas avoir de spécification de type de retour 320
E2038: Impossible de déclarer ou de définir 'identificateur' ici : espace de nommage incorrect 321
E2154: Impossible de définir 'identificateur' en utilisant un alias d'espace de nommage 321
E2421: Impossible d'utiliser le type local 'identificateur' comme argument modèle 321
E2035: Les conversions d'une classe en elle-même ou en classe de base ne sont pas autorisées 321
E2139: ; manquant dans la déclaration 321
E2140: La déclaration n'est pas autorisée ici 321
E2141: Erreur de syntaxe de déclaration 321
E2142: La classe de base 'classe' contient des fonctions qui peuvent être réparties de façon dynamique 322
E2143: La fonction 'fonction' de classe de base correspondante a un numéro de répartition différent 322
E2144: La fonction de classe de base correspondante 'fonction' n'est pas dynamique 322
E2145: Les fonctions 'fonction1' et 'fonction2' utilisent le même numéro de répartition 322
E2146: Vous devez fournir un identificateur à déclarer 322
E2147: 'identificateur' ne peut pas démarrer une déclaration de paramètre 322
E2150: Mauvaise correspondance de type dans la valeur de l'argument par défaut 323

xiii
RAD Studio

E2152: L'expression par défaut ne doit pas utiliser des variables locales 323
E2153: La directive define nécessite un identificateur 323
E2155: Trop d'instructions default 323
E2156: Default en dehors du switch 323
E2158: L'opérande de 'delete' doit être un pointeur non-const 323
E2159: Tentative de dériver une classe far depuis la base huge 'base' 324
E2160: Tentative de dériver une classe far depuis la base near 'base' 324
E2161: Tentative de dériver une classe huge depuis la base far 'base' 324
E2162: Tentative de dériver une classe huge depuis la base near 'base' 324
E2163: Tentative de dériver une classe near depuis la base far 'base' 324
E2164: Tentative de dériver une classe near depuis la base huge 'base' 324
E2165: Un destructeur ne peut pas avoir de spécification de type de retour 324
E2166: Le destructeur de 'classe' n'est pas accessible 325
E2167: 'fonction' a été précédemment déclarée avec le langage 'langage' 325
E2168: Division par zéro 325
E2169: 'identificateur' spécifie des accès multiples ou dupliqués 325
E2170: La classe de base 'classe' est incluse plusieurs fois 325
E2171: Le corps a déjà été défini pour la fonction 'fonction' 325
E2172: Case dupliqué 326
E2175: Trop de classes de stockage dans la déclaration 326
E2176: Trop de types dans la déclaration 326
E2179: virtual spécifié plusieurs fois 326
E2007: Dispid n'est autorisé que dans les sections __automated 326
Erreur de division 327
E2182: Paramètre incorrect pour __emit__ 327
E2183: Le fichier doit contenir au moins une déclaration externe 327
E2184: Erreur de syntaxe pour une énumération 327
E2185: La valeur de 'identificateur' n'est pas un entier 327
E2186: Fin de fichier inattendue dans le commentaire qui commence à la ligne 'numéro de ligne' 327
E2187: Fin de fichier inattendue dans l'instruction conditionnelle qui commence à la ligne 'numéro de ligne' 327
E2188: Syntaxe de l'expression 328
E2190: Accolade fermante inattendue 328
E2189: La variable extern ne peut pas être initialisée 328
E2344: Déclaration précédente de 'identificateur' 328
E2192: Trop peu de paramètres dans l'appel 328
E2193: Trop peu de paramètres dans l'appel à 'fonction' 329
E2194: Impossible de trouver le fichier 'nomfichier' 329
E2197: Nom de fichier trop long 329
E2195: Impossible d'évaluer l'appel de fonction 329

xiv
RAD Studio

E2198: Ce n'est pas un type de format d'expression correct 329


E2200: Les fonctions ne peuvent pas faire partie d'une structure ou d'une union 329
Erreur de calcul à virgule flottante : Erreur de division par 0 OU de calcul à virgule flottante : Erreur de 329
domaine ou de calcul à virgule flottante : Dépassement de capacité
Erreur de calcul à virgule flottante : Faute de pile 330
Erreur de calcul à virgule flottante : Perte de précision partielle OU Erreur de calcul à virgule flottante : 330
Débordement inférieur
E2201: Trop de données globales définies dans le fichier 330
E2203: Goto évite l'initialisation d'une variable locale 330
E2204: Le groupe a dépassé la taille maximum : 'nom' 330
E2206: Caractère 'caractère' (0x'valeur') incorrect 331
E2207: Conversion implicite de 'type1' en 'type2' non autorisée 331
E2208: Impossible d'accéder à une portée inactive 331
E2209: Impossible d'ouvrir le fichier include 'nomfichier' 331
E2210: Le membre de référence 'membre' n'est pas initialisé 331
E2212: La fonction a été définie inline après avoir été utilisée comme extern 332
E2211: L'assemblage en ligne n'est pas autorisé dans les fonctions inline et template 332
F1001: Erreur du générateur de code interne 332
E2413: Déclaration de modèle incorrecte 332
E2070: Utilisation incorrecte de l'espace de nommage 'identificateur' 332
E2214: Impossible d'avoir des 'données fonction/statique non inline' dans une classe locale 333
E2215: Spécification de lien non autorisée 333
E2216: Impossible de créer turboc.$ln 333
E2218: Les modèles ne peuvent être déclarés qu'au niveau d'un espace de nommage ou d'une classe 333
E2217: Les données locales dépassent la limite de taille du segment 333
E2219: Nombre incorrect d'arguments dans l'appel de la macro 'macro' 333
E2220: Séparateur d'arguments de macro incorrect 334
E2221: Erreur de syntaxe dans l'argument de macro 334
E2222: Développement de macro trop long 334
E2223: Trop de séparateurs décimaux 334
E2224: Trop d'exposants 334
E2225: Trop d'initialiseurs 334
E2226: Paramètre supplémentaire dans l'appel 334
E2227: Paramètre supplémentaire dans l'appel de fonction 334
E2228: Trop de messages d'erreur ou d'avertissement 335
E2233: Impossible d'initialiser un membre de classe ici 335
E2232: Membre 'membre' constante/référence dans la classe sans constructeur 335
E2229: Le membre 'membre' a le même nom que sa classe 335
E2234: Référence mémoire attendue 335
E2231: Le membre 'membre' ne peut pas être utilisé sans objet 335

xv
RAD Studio

E2235: Une fonction membre doit être appelée ou son adresse prise 336
O2237: Les programmes DPMI doivent utiliser le modèle de mémoire large 336
E2238: Plusieurs déclarations pour 'identificateur' 336
E2239: 'identificateur' doit être une fonction membre 337
E2240: Conversion de pointeur near non autorisée 337
E2243: Un tableau alloué avec 'new' ne peut pas avoir d'initialisateur 337
E2244: 'new' et 'delete' ne sont pas gérés 337
E2245: Impossible d'allouer une référence 337
E2309: Assembleur Inline non autorisé 337
E2250: Aucune classe de base à initialiser 338
E2254: : attendu après private/protected/private 338
E2255: Utiliser :: pour prendre l'adresse d'une fonction membre 338
E2256: Pas de : qui suit le ? 338
E2257: , attendue 338
E2258: Une déclaration était attendue 338
E2259: Valeur par défaut manquante 339
E2260: Une valeur par défaut manque après le paramètre 'paramètre' 339
E2263: La gestion des exceptions n'est pas activée 339
E2264: Expression attendue 339
E2266: Aucun nom de fichier donné 339
E2265: Aucun signe de fin dans le nom de fichier 339
E2271: Il manque un libellé à l'instruction goto 339
E2272: Identificateur attendu 339
E2275: Accolade ouvrante attendue 340
E2276: ( attendue 340
E2274: < attendu 340
E2277: Lvalue nécessaire 340
E2278: Les classes de base multiples ne sont pas gérées pour les classes Delphi 340
E2280: Identificateur de membre attendu 340
E2279: Impossible de trouver le constructeur par défaut pour initialiser le membre 'identificateur' 341
E2310: Seules les fonctions membre peuvent être 'const' ou 'volatile' 341
E2311: La fonction non-virtuelle 'fonction' est déclarée pure 341
E2283: Utilisez . ou -> pour appeler 'fonction' 341
E2284: Utilisez . ou -> pour appeler 'membre', ou & pour prendre son adresse 341
E2285: Impossible de trouver une correspondance pour le(s) 'argument(s)' 342
E2286: Résolution de fonction surchargée non gérée 342
E2287: Nom manquant dans le paramètre 'numéro' 342
E2288: Pointeur sur structure nécessaire du côté gauche de -> ou ->* 342
E2290: ] manquant dans 'code' 342

xvi
RAD Studio

E2291: Accolade attendue 342


E2292: La fonction doit renvoyer une valeur 343
E2293: ) attendue 343
E2294: Structure nécessaire sur le côté gauche de . ou .* 343
E2312: 'constructeur' n'est pas une classe de base non ambiguë de 'classe' 343
E2313: Expression constante nécessaire 343
E2296: Modèles non gérés 343
E2314: Appel d'une non fonction 343
E2321: La déclaration ne spécifie pas un repère ou un identificateur 344
E2297: 'this' ne peut être utilisé que dans une fonction membre 344
E2316: 'identificateur' n'est pas un membre de 'structure' 344
E2317: 'identificateur' n'est pas un paramètre 344
E2319: 'identificateur' n'est pas une classe de base publique de 'type de classe' 344
E2320: Expression de type scalaire attendue 344
E2302: Pas d'informations de type 345
E2303: Nom de type attendu 345
E2304: La variable 'variable' Constant/Reference doit être initialisée 345
E2305: Impossible de trouver 'class::class' ('class' &) pour copier un vecteur OU Impossible de trouver 345
'class'::operator=('class'&) pour copier un vecteur
E2306: Les classes de base virtuelles ne sont pas gérées par les classes Delphi 346
E2308: L'instruction 'do' doit avoir un 'while' 346
E2322: Format numérique incorrect 346
E2324: Constante numérique trop grande 346
E2282: Nom d'espace de nommage attendu 347
E2334: Le membre de l'espace de nommage 'identificateur' a été déclaré en dehors de son espace de 347
nommage
E2325: Chiffre octal incorrect 347
E2329: Combinaison incorrecte d'instruction et d'opérandes 347
E2327: Les opérateurs ne doivent pas avoir de valeurs d'argument par défaut 347
E2330: Un opérateur doit être déclaré comme une fonction 347
E2333: Le membre de classe 'membre' a été déclaré en dehors de sa classe 348
E2335: 'fonction' surchargée ambiguë dans ce contexte 348
E2339: Impossible de surcharger 'main' 348
E2336: Le pointeur sur la fonction surchargée 'fonction' ne correspond pas à 'type' 348
E2337: Seule une fonction d'un ensemble de fonctions surchargées peut être "C" 348
E2338: Les overlays ne sont supportés que dans les modèles mémoire medium, large et huge 348
E2340: Non concordance de type dans le paramètre 'nombre' 349
E2341: Non concordance de type dans le paramètre 'numéro' dans l'appel à 'fonction' 349
E2342: Non concordance de type dans le paramètre 'paramètre' 349
E2343: Non concordance de type dans le paramètre 'paramètre' dans l'appel à 'fonction' 349

xvii
RAD Studio

E2345: L'accès peut seulement être changé en public ou protected 350


E2349: Conversion de pointeur non portable 350
E2350: Impossible de définir un pointeur ou une référence sur une référence 350
E2352: Impossible de créer une instance de la classe abstraite 'classe' 350
E2354: Deux opérandes doivent être évalués de même type 351
E2355: Fonction modèle récursive : 'x' a instancié 'y' 351
E2356: Non concordance de type dans la redéclaration de 'identificateur' 351
E2357: Référence initialisée avec 'type1', nécessite lvalue de type 'type2' 352
E2358: Le membre référence 'membre' a besoin d'un temporaire pour l'initialisation 352
E2360: Combinaison de registre incorrecte (ex : [BP+BX]) 352
E2361: 'spécificateur' a déjà été inclus 352
E2362: Le nombre de répétitions a besoin d'une lvalue 352
E2363: Tentative de renvoyer une référence à la variable locale 'identificateur' 353
E2364: Tentative de renvoyer une référence à un objet local 353
E2365: Un pointeur membre est nécessaire à droite de .* ou ->* 353
E2366: Impossible d'hériter une classe non-RTTI depuis la base RTTI (E2367) OU Impossible d'hériter une 353
classe RTTI depuis la base non-RTTI
E2368: RTTI non disponible pour une évaluation d'expression 353
E2371: sizeof ne peut pas être appliqué à un champ de bits 354
E2372: sizeof ne peut pas être appliqué à une fonction 354
E2373: Un champ de bits ne peut pas être statique 354
E2374: La fonction 'fonction' ne peut pas être statique 354
Débordement de pile 354
E2376: ( manquante dans l'instruction 354
E2377: ) manquante dans l'instruction 354
E2378: ; manquant dans l'instruction do-while ou for 355
E2379: ; manquante dans l'instruction 355
E2380: Constante chaîne ou caractère non terminée 355
E2381: Taille de la structure trop grande 355
E2382: Les effets de bord ne sont pas autorisés 355
E2383: L'expression de sélection switch doit être de type entier 355
E2433: Spécialisation après la première utilisation du modèle 355
E2384: Impossible d'appeler une fonction membre de classe near avec un pointeur de type 'type' 355
E2390: Non concordance de type dans le paramètre 'numéro' du nom de classe modèle 'modèle' 356
E2391: Non concordance de type dans le paramètre 'paramètre' du nom de classe modèle 'modèle' 356
E2394: Trop peu d'arguments passés au modèle 'modèle' 356
E2395: Trop d'arguments passés au modèle 'modèle' 356
E2396: L'argument du modèle doit être une expression constante 356
E2401: Liste des arguments de modèles incorrecte 356

xviii
RAD Studio

E2400: L'argument de modèle non typé doit être de type scalaire 357
E2415: Les fonctions modèle doivent avoir seulement des 'arguments de type' 357
E2425: 'membre' n'est pas un membre de type modèle correct 357
E2428: Les modèles doivent être des classes ou des fonctions 357
E2432: Le qualificateur 'template' doit nommer une classe modèle ou une instance de fonction 357
E2442: Deux points consécutifs 357
E2443: La classe de base 'classe' est initialisée plus d'une fois 357
E2444: Le membre 'membre' est initialisé plus d'une fois 358
E2445: La variable 'identificateur' est initialisée plus d'une fois 358
E2446: La définition de fonction ne peut pas être une déclaration typedef 358
E2132: Les modèles et les opérateurs surchargés ne peuvent pas avoir de lien C 358
E2447: 'identificateur' doit être un repère d'énumération précédemment défini 358
E2448: Etiquette non définie 'identificateur' 358
E2449: La taille de 'identificateur' est inconnue ou zéro 358
E2450: Structure 'structure' non définie 359
E2451: Symbole 'identificateur' non défini 359
E2453: La taille du type 'identificateur' est inconnue ou égale à zéro 359
E2452: La taille du type est inconnue ou zéro 359
E2454: Une union ne peut pas être un type de base 359
E2455: Une union ne peut pas avoir un type de base 360
E2456: Le membre de l'union 'membre' est de classe type avec 'constructeur' (ou destructeur ou opérateur 360
=)
E2461: '%s' nécessite une initialisation/finalisation d'exécution 360
E2464: 'virtual' ne peut être utilisé qu'avec des fonctions membre 360
E2465: Les unions ne peuvent pas avoir de fonctions membre virtuelles 360
E2466: void & n'est pas un type correct 360
E2467: Une fonction Void ne peut pas renvoyer une valeur 361
E2468: Une valeur de type void n'est pas autorisée 361
E2469: Impossible d'utiliser le modèle mémoire tiny ou huge avec Windows 361
E2006: Les programmes protégés par CodeGuard doivent utiliser le modèle de mémoire large et être 361
prévus pour Windows
E2269: La fonction 'fonction' n'est pas disponible 361
E2124: Appel de fonction incorrect 361
E2213: 'expression' incorrecte dans la redéfinition de portée 361
E2236: 'identificateur' manquant dans la redéfinition de portée 362
Fonction virtuelle pure appelée 362
E2095: Littéral chaîne non autorisé dans ce contexte 362
Fin anattendue pendant la compilation [Module Seg#:offset] OU Fin inattendue pendant la liaison [Module 362
Seg#:offset]
E2012: Impossible de prendre l'adresse de 'main' 362

xix
RAD Studio

E2016: Redéfinition ambiguë du membre de base virtuel 'fonction_de_base': 'fonction_dérivée' 362


E2021: Un tableau doit avoir au moins un élément 363
E2023: Tableau de références non autorisé 363
E2032: Utilisation incorrecte d'un pointeur de clôture (closure) 363
E2040: Terminaison de déclaration incorrecte 363
E2047: Syntaxe de la directive 'directive' incorrecte 364
E2049: Le type de classe 'type' ne peut pas être marqué comme __declspec(delphireturn) 364
E2052: Conflits de la fonction dynamique 'fonction' avec la classe de base 'classe' 364
E2057: Spécification d'exception non autorisée ici 364
E2058: La variable de gestion des exceptions ne peut pas être utilisée ici 364
E2065: L'utilisation du symbole d'espace de nommage 'symbole' crée un conflit avec un intrinsèque du 365
même nom
E2067: Le type renvoyé par 'main' doit être int 365
E2073: Rien n'est autorisé après l'option pragma pop 365
E2091: Les fonctions ne peuvent pas renvoyer des tableaux ou des fonctions 365
E2093: Opérateur 'opérateur' non implémenté dans le type 'type' pour les arguments du même type 365
E2094: Opérateur 'opérateur' non implémenté dans le type 'type' pour les arguments de type 'type' 365
E2097: Instanciation explicite uniquement autorisée dans les fichiers ou les espaces de nommage 366
E2098: Un déclarateur de spécialisation explicite "template<>" est maintenant nécessaire 366
E2099: Spécialisation explicite uniquement autorisée dans les fichiers ou les espaces de nommage 366
E2101: Le mot clé 'export' doit précéder une déclaration de modèle 366
E2103: Une instanciation explicite doit être utilisée avec une classe ou une fonction modèle 366
E2106: Une spécialisation explicite doit être utilisée avec une classe ou une fonction modèle 366
E2112: Directive d'unité inconnue : 'directive' 366
E2118: Les champs de bits doivent être de type entier 367
E2120: Impossible d'appeler 'main' depuis le programme 367
E2125: Le compilateur n'a pas pu générer de constructeur de copie pour la classe 'classe' OU Le 367
compilateur n'a pas pu générer de constructeur par défaut pour la classe 'classe' OU Le compilateur n'a
pas pu générer d'opérateur = pour la classe 'classe'
E2130: Définition de propriété circulaire 367
E2131: Les objets de type 'type' ne peuvent pas être initialisés avec des { } 367
E2148: La valeur de l'argument par défaut a été redéclarée pour le paramètre 'paramètre' 367
E2149: La valeur de l'argument par défaut a été redéclarée 368
E2151: Mauvaise correspondance de type dans la valeur par défaut pour le paramètre 'paramètre' 368
E2157: La suppression d'un objet nécessite exactement une conversion en opérateur de pointeur 368
E2173: Le gestionnaire dupliqué pour 'type1' avait déjà 'type2' 368
E2174: Le gestionnaire spécifié doit être le dernier 368
E2177: Redéclaration de #pragma package avec différents arguments 369
E2178: Conflit de nom VIRDEF pour 'fonction' 369
E2180: Numéro dispid déjà utilisé par l'identificateur 369

xx
RAD Studio

E2181: Impossible de redéfinir une fonction 'dynamique/virtuelle' avec une fonction 'dynamique/virtuelle' 369
E2202: Goto est interdit dans un gestionnaire d'exception 369
E2205: Type 'type' incorrect dans la section __automated 369
E2242: Le spécificateur a besoin d'un type de classe de style Delphi 370
E2247: 'membre' n'est pas accessible 370
E2248: Impossible de trouver un constructeur par défaut pour initialiser un élément de tableau de type 371
'classe'
E2251: Impossible de trouver un constructeur par défaut pour initialiser la classe de base 'classe' 371
E2252: 'catch' attendu 371
E2253: La convention d'appel doit être attribuée au type de fonction, non au closure 371
E2261: L'utilisation d'un dispid avec une propriété nécessite un getter ou un setter 372
E2262: '__except' ou '__finally' attendu après '__try' 372
E2270: > attendu 372
E2273: 'main' ne peut pas être déclaré comme statique ou en ligne 372
E2281: Identificateur1 nécessite la définition de Identificateur2 comme type pointeur 372
E2289: Les sections __published ou __automated ne sont gérées que par les classes Delphi 372
E2298: Impossible de créer 'fonction' à partir de la fonction modèle 'modèle' 373
E2301: Impossible d'utiliser des modèles dans les arguments closure ; utilisez un typedef 373
E2307: Le type 'type' n'est pas une classe définie avec des fonctions virtuelles 373
E2315: 'Membre' n'est pas un membre de 'classe', car le type n'est pas encore défini 373
E2318: 'type' n'est pas un type de classe polymorphe 374
E2323: Suffixe numérique incorrect 374
E2326: Utilisez __declspec(spec1[, spec2]) pour combiner plusieurs __declspecs 374
E2328: Les classes avec des propriétés ne peuvent pas être copiées par valeur 374
E2331: Nombre de contextes d'option admissibles dépassé 374
E2332: La variable 'variable' a été optimisée et n'est pas disponible 375
E2476: Impossible de surcharger 'fonction' 375
E2346: Le spécificateur d'accès 'x' de la propriété 'propriété' doit être une fonction membre 375
E2347: Non concordance de paramètre dans le spécificateur d'accès 'spécificateur' de la propriété 375
'propriété'
E2348: Spécificateur de stockage non autorisé pour les propriétés de tableau 375
E2351: Membres de données statiques non autorisés dans les sections __published ou __automated 376
E2353: La classe 'classe' est abstraite car 'membre = 0' 376
E2359: Le membre référence 'membre' a été initialisé avec un paramètre non-référence 376
E2369: Impossible d'utiliser le résultat d'une affectation de propriété comme une rvalue 377
E2370: Nom de type simple attendu 377
E2398: L'argument 'argument' de la fonction modèle n'est pas utilisé dans les types d'argument 377
E2419: Erreur pendant l'instanciation du modèle 'modèle' 377
E2424: Classe modèle imbriquée trop profondément : 'class' 377
E2457: Les classes de style Delphi doivent être prises par référence 378

xxi
RAD Studio

E2458: Les classes Delphi doivent être dérivées de classes Delphi 378
E2459: Les classes de style Delphi doivent être construites en utilisant l'opérateur new 378
E2460: Les classes de style Delphi nécessitent que la gestion d'exception soit activée 379
E2463: 'base' est une classe de base virtuelle indirecte de 'classe' 379
Affectation de pointeur Null 379
E2268: Appel à une fonction 'fonction' non définie 379
E2375: Débordement de pile assembleur 379
Initialisation d'une énumération avec un type 379
<nom> n'est pas un identificateur correct 380
Exemple pour les messages d'erreur d'"utilisation temporaire..." 380
Application en cours d'exécution 380
Formats en virgule flottante Printf/Scanf non liés 380
W8000: Les opérateurs ambigus requièrent des parenthèses 381
W8060: Affectation peut-être incorrecte 381
W8002: Redémarrage de la compilation avec l'assembleur 381
W8003: Instruction assembleur inconnue 381
W8052: Initialisation de base sans nom de classe maintenant obsolète 382
E2117: Les champs de bits doivent être des entiers signés ou non signés 382
W8064: Appel à une fonction sans prototype 382
W8065: Appel à la fonction 'fonction' sans prototype 382
W8009: La constante est longue 382
W8008: La condition est toujours vraie OU W8008 La condition est toujours fausse 383
W8012: Comparaison de valeurs signées et non signées 383
W8010: Caractère de continuation \ trouvé dans un commentaire // 383
W8080: 'identificateur' est déclaré mais jamais utilisé 383
W8014: Déclaration ignorée 384
W8068: Constante hors limites dans la comparaison 384
W8016: Taille de tableau ignorée pour 'delete' 384
W8082: Division par zéro 385
W8018: Affectation de 'type' à 'énumération' 385
W8006: Initialisation de 'identificateur' avec 'identificateur' 385
W8001: & superflu avec une fonction 385
W8020: 'identificateur' est déclaré à la fois externe et statique 385
W8007: La valeur hexadécimale contient plus de trois chiffres 386
W8024: La classe de base 'classe1' est aussi une classe de base de 'classe2' 386
W8022: 'fonction1' cache la fonction virtuelle 'fonction2' 386
W8023: La variable tableau 'identificateur' est near 386
W8061: L'initialisation est partiellement entre accolades 387
W8038: Le membre constante 'identificateur' n'est pas initialisé 387

xxii
RAD Studio

W8071: La conversion peut perdre des chiffres significatifs 387


W8043: Définition de macro ignorée 387
W8017: La redéfinition de 'x' n'est pas identique 387
W8079: Mélange de pointeurs de plusieurs types 'char' 387
W8067: Instructions de retour avec et sans valeur utilisées 388
W8048: Utilisez un nom qualifié pour accéder au type membre 'identificateur' 388
W8039: Liste d'initialiseurs de constructeurs ignorée 388
W8040: Corps de fonction ignoré 388
W8042: Initialiseur pour l'objet 'x' ignoré 388
W8044: Directive #undef ignorée 389
W8037: Fonction non const 'fonction' appelée pour un objet const 389
W8051: Fonction non volatile 'fonction' appelée pour un objet volatile 389
W8019: Le code n'a pas d'effet 389
W8057: Paramètre 'paramètre' jamais utilisé 390
W8070: La fonction doit renvoyer une valeur 390
W8047: Déclaration de la fonction statique function ignorée 390
W8041: Valeur non signée rendue négative 390
W8054: Ce style de définition de fonction est maintenant obsolète 390
W8025: Pragma mal formé 391
W8063: Opérateur de préfixe surchargé 'opérateur' utilisé comme un opérateur de suffixe 391
W8015: Déclarez 'type' avant de l'utiliser dans le prototype 391
W8069: Conversion de pointeur non portable 391
W8066: Code inatteignable 392
W8029: Un temporaire a été utilisé pour le paramètre '???' 392
W8031: Temporaire utilisé pour le paramètre 'paramètre' OU W8029 Temporaire utilisé pour le paramètre 392
'numéro' OU W8030 Temporaire utilisé pour le paramètre 'paramètre' dans l'appel à 'fonction' OU W8032
Temporaire utilisé pour le paramètre 'numéro' dans l'appel à 'fonction'
W8032: Un temporaire a été utilisé pour le paramètre 2 dans l'appel à '???' 392
W8028: Variable temporaire utilisée pour initialiser 'identificateur' 393
W8074: Structure transmise par valeur 393
W8011: Comparaison de pointeur non portable 393
W8075: Conversion de pointeur suspecte 394
W8059: La taille de la structure a changé 394
8045: Pas de déclaration pour la fonction 'fonction' 394
W8073: Structure 'structure' non définie 395
W8013: Utilisation possible de 'identificateur' avant sa définition 395
W8004: 'identificateur' a une valeur qui n'est jamais utilisée 395
W8081: Les fonctions void ne peuvent pas renvoyer de valeur 395
W8078: L'expression throw viole la spécification d'exception 396
W8021: Le gestionnaire de 'type1' est caché par le gestionnaire précédent de 'type2' 396

xxiii
RAD Studio

W8056: Débordement arithmétique d'entiers 396


W8035: Message défini par l'utilisateur 396
W8049: Utilisez '> >' pour les modèles imbriqués au lieu de '>>' 396
W8026: Les fonctions avec des spécifications d'exception ne sont pas développées en ligne 397
W8058: Impossible de créer un en-tête précompilé : 'raison' 397
W8046: Option pragma pop sans option push correspondante 397
W8050: Aucun fichier OBJ présent. Désactivation de l'option des types externes. 397
W8027: Les fonctions contenant 'instruction' ne sont pas développées en ligne 398
W8036: Mot clé non ANSI utilisé : 'mot clé' 398
W8053: 'identificateur' obsolète 399
W8103: Le chemin 'chemin' et le nom de fichier 'nomfichier' dépassent la taille maximale 'n' 399
W8062: Options et avertissements précédents non restaurés 399
W8055: Débordement possible dans une opération shift 399
W8072: Arithmétique de pointeur suspecte 399
W8033: La conversion en 'type' échouera pour les membres de la base virtuelle 'classe' 400
W8034: Précision maximum utilisée pour le type pointeur membre 'type' 400
Exemples C++ 400
Exemple Remove et MessageDlg 400
Guide du langage C++ 401
Spécificités du C++ 401
Liste alphabétique des mots clés 519
Mots clés par catégorie 583
Structure du langage 590
Eléments lexicaux 666
Le préprocesseur 692
C Runtime Library Reference 717
alloc.h 718
assert.h 736
conio.h 738
ctype.h 772
delayimp.h 793
direct.h 796
dirent.h 798
dir.h 805
dos.h 824
errno.h 837
except.h 844
fastmath.h 848
fcntl.h 850

xxiv
RAD Studio

float.h 859
io.h 870
limits.h 922
locale.h 924
malloc.h 929
math.h 930
mem.h 968
new.h 977
process.h 980
setjmp.h 1002
share.h 1005
signal.h 1006
stdarg.h 1012
stddef.h 1013
stdio.h 1015
stdlib.h 1087
string.h 1146
sys\stat.h 1193
sys\timeb.h 1197
sys\types.h 1199
time.h 1200
typeinfo.h 1218
utime.h 1220
values.h 1221

Guide du développeur Win32 1224


Guide du concepteur de composants 1224
Création d'un composant graphique 1225
Création d'événements 1239
Création de méthodes 1250
Création de propriétés 1255
Personnalisation d'une grille 1268
Extensions de l'EDI 1287
Gestion des messages 1310
Présentation de la création d'un composant 1323
Contrôles orientés données 1339
Accessibilité des composants au moment de la conception 1355
Transformation d'une boîte de dialogue en composant 1375
Modification d'un composant existant 1380
Programmation orientée objet et écriture des composants 1384

xxv
RAD Studio

Graphiques et composants 1394


Développement d'applications COM 1400
Principes de COM 1401
Création d'une page Active Server 1419
Utilisation des contrôles ActiveX 1426
Création de clients COM 1438
Création de serveurs COM simples 1453
Utilisation des bibliothèques de types 1468
Développement d'applications de bases de données 1496
Utilisation des composants ADO 1496
Connexion aux bases de données 1524
Création d'applications multiniveaux 1540
Création d'états avec Rave Reports 1584
Conception d'applications de bases de données 1589
Présentation des ensembles de données 1607
Utilisation du moteur de bases de données Borland 1677
Utilisation d'ensembles de données client 1743
Utilisation de contrôles de données 1790
Utilisation de composants d'aide à la décision 1831
Utilisation des composants fournisseur 1859
Utilisation des composants dbExpress 1876
Utilisation de XML dans les applications de bases de données 1897
Manipulation des composants champ 1907
Programmation avec Delphi 1939
Création d'applications, de composants et de bibliothèques 1940
Création d'applications internationales 1983
Principes de la programmation en Delphi 1999
Déploiement des applications 2002
Conception de l'interface utilisateur des applications 2021
Gestion des exceptions 2083
Types de contrôles 2098
Présentation de la bibliothèque de composants 2121
Utilisation du modèle objet 2130
Utilisation de la VCL/RTL 2152
Utilisation des composants 2212
Manipulation des contrôles 2219
Utilisation des graphiques et du multimédia 2240
Utilisation des packages et des composants 2282
Ecriture d'applications multithreads 2299

xxvi
RAD Studio

Ecriture d'applications Internet 2318


Création d'applications serveur Internet 2319
Utilisation d'IntraWeb 2330
Utilisation de WebBroker 2337
Utilisation de services Web 2367
Utilisation de WebSnap 2390
Utilisation des sockets 2417
Utilisation de documents XML 2434

Index a

xxvii
1 RAD Studio

1 Concepts
Rubriques
Nom Description
Débogage d'applications C++ avec les rapports d'erreurs CodeGuard ( see CodeGuard permet de déboguer l'exécution des applications C++ développées
page 3) avec RAD Studio. CodeGuard signale les erreurs non détectées par le
compilateur parce qu'elles n'outrepassent pas les règles de syntaxe. CodeGuard
assure le suivi des bibliothèques d'exécution et prend totalement en charge les
applications multithread.
Développement d'applications de bases de données pour la plate-forme Win32 Les applications de bases de données permettent aux utilisateurs d'interagir
( see page 13) avec les informations stockées dans les bases de données. Les bases de
données permettent de structurer les informations et de les partager entre
plusieurs applications.
Delphi permet de gérer les applications de bases de données relationnelles. Les
bases de données relationnelles organisent les informations en tables, qui
contiennent des lignes (enregistrements) et des colonnes (champs). Ces tables
peuvent être manipulées par des opérations simples appelées calculs
relationnels.
Développement des applications interopérables ( see page 39) RAD Studio fournit des experts et des classes qui facilitent l'implémentation
d'applications basées sur le modèle COM (Component Object Model) de
Microsoft. Grâce à ces experts, vous pouvez créer des classes et des
composants basés sur COM que vous utiliserez dans des applications, ou vous
pouvez créer des clients ou des serveurs COM complètement fonctionnels qui
implémentent des objets COM sophistiqués, des serveurs Automation (y
compris, des objets Active Server), des contrôles ActiveX ou des fiches
ActiveForms.
Développement d'états pour vos applications Win32 ( see page 45) RAD Studio est livré avec Rave Reports de Nevrona. A l'aide des composants
d'états, vous pouvez construire des états complets pour vos applications. Vous
pouvez construire des solutions incluant des fonctionnalités de génération
d'états, qui pourront être utilisées et personnalisées par vos clients. De plus, les
outils ComponentOne livrés avec RAD Studio incluent des composants
permettant de créer et de générer des états.
Développement d'applications avec des composants VCL ( see page 46) La VCL (Visual Component Library) est un ensemble de composants visuels
permettant le développement rapide d'applications Windows dans le langage
Delphi.
La VCL contient une gamme étendue de classes utilitaires visuelles ou non
visuelles pour des tâches telles que la construction d'applications Windows,
d'applications web, d'applications de bases de données et d'applications de
consoles.

1
RAD Studio 1

Développement d'applications Web avec WebSnap ( see page 51) Cette section fournit l'arrière-plan conceptuel de construction des applications
WebSnap avec RAD Studio. WebSnap facilite la construction d'applications
serveur Web fournissant des pages Web complexes orientées données. La prise
en charge par WebSnap des modules multiples et des scripts côté serveur
facilite le développement et la maintenance pour les équipes de développeurs et
de concepteurs Web.
Veuillez noter que WebSnap est en cours de dépréciation dans RAD Studio.
Bien que WebSnap soit toujours documenté dans l'aide en ligne, le produit
WebSnap n'est plus entièrement supporté. En alternative, commencez à utiliser
IntraWeb (VCL pour le Web). IntraWeb ( see page 2330) est documenté dans
cette... suite ( see page 51)
1 Développement de services Web avec des applications Win32 ( see page 54) Les services Web sont des applications modulaires indépendantes qui peuvent
être publiées ou invoquées sur Internet. Les services Web fournissent des
interfaces bien définies qui décrivent les services fournis. A la différence des
applications de serveur Web qui génèrent des pages Web pour les navigateurs
client, les services Web ne sont pas conçus pour une interaction humaine
directe. Ils sont plutôt destinés à être appelés par programme de la part
d'applications client. Cette section contient une présentation des services web et
de leur prise en charge.
Développement d'applications Windows ( see page 55) Windows propose une approche traditionnelle du développement d'interfaces
utilisateur, d'applications client/serveur, de contrôles et de la logique applicative.
Cette section propose une présentation du développement d'applications
Windows utilisant RAD Studio pour Win32 et décrit les étapes de construction
d'un projet Windows simple.

2
1.1 Débogage d'applications C++ avec les RAD Studio Erreurs CodeGuard

1.1 Débogage d'applications C++ avec les


rapports d'erreurs CodeGuard
CodeGuard permet de déboguer l'exécution des applications C++ développées avec RAD Studio. CodeGuard signale les
1
erreurs non détectées par le compilateur parce qu'elles n'outrepassent pas les règles de syntaxe. CodeGuard assure le suivi des
bibliothèques d'exécution et prend totalement en charge les applications multithread.

Rubriques
Nom Description
Erreurs CodeGuard ( see page 3) CodeGuard signale quatre types d'erreurs d'exécution.
Présentation de CodeGuard ( see page 9) CodeGuard permet de déboguer l'exécution des applications C++ développées
avec RAD Studio. CodeGuard signale les erreurs non détectées par le
compilateur parce qu'elles n'outrepassent pas les règles de syntaxe. CodeGuard
assure le suivi des bibliothèques d'exécution et prend totalement en charge les
applications multithread.
CodeGuard couvre principalement deux domaines :

• Utilisation de la mémoire et des ressources


• Validation des appels de fonctions
Avertissements CodeGuard ( see page 10) CodeGuard signale les cas où votre application accède à de la mémoire au-delà
de la taille maximale d'un tampon. Les avertissements concernent trois types de
fonctions des bibliothèques d'exécution.

1.1.1 Erreurs CodeGuard


CodeGuard signale quatre types d'erreurs d'exécution.

Rubriques
Nom Description
Erreurs d'accès ( see page 4) Les erreurs d'accès proviennent d'une gestion incorrecte de la mémoire.
Lorsque CodeGuard détecte des accès à des blocs mémoire libérés ou à des
objets supprimés, il peut identifier l'endroit où chaque bloc a été alloué et
supprimé. Activez l'option Retarder "Free" dans la boîte de dialogue
Configuration CodeGuard pour utiliser cette fonctionnalité.
Voici les types d'erreurs d'accès possibles :

• Accès à de la mémoire libérée


• Accès dans une pile non initialisée
• Accès dans une pile invalide
Erreurs d'exceptions ( see page 5) Lorsqu'une exception système survient, CodeGuard signale l'erreur d'exécution à
l'aide d'informations données par le système d'exploitation. Si possible, le journal
CodeGuard indique l'endroit où votre application a provoqué l'exception.
CodeGuard n'intercepte pas l'exception, ne la redirige pas et n'interfère en
aucune manière avec le comportement normal du programme.
Les exceptions suivantes illustrent la façon dont CodeGuard signale les
exceptions :

• Erreur de protection générale


• Division par zéro

3
Erreurs CodeGuard RAD Studio 1.1 Débogage d'applications C++ avec les

Erreurs d'échec de fonction ( see page 6) CodeGuard signale tous les appels de fonctions qui ont échoué, d'après leur
valeur de retour.
Dans l'exemple suivant, la fonction close reçoit un descripteur de fichier invalide
qui la conduit à renvoyer une valeur indiquant qu'elle n'est pas parvenue à fermer
un fichier.
Erreurs de ressources ( see page 7) Les ressources sont des blocs mémoire (alloués par des fonctions telles que
malloc, GlobalAlloc) et des tableaux d'objets, tels que des descripteurs de
fichiers, des descripteurs de flux, des modules et des éléments renvoyés par
new[].
Les exemples d'erreurs d'exécution suivants montrent la manière dont
1 CodeGuard signale une utilisation incorrecte des ressources.

• Paramètre incorrect
• Référence à une ressource libérée
• Incompatibilité entre types de ressources
• Pertes de ressources
• Ressource d'une bibliothèque d'exécution différente

1.1.1.1 Erreurs d'accès


Les erreurs d'accès proviennent d'une gestion incorrecte de la mémoire.

Lorsque CodeGuard détecte des accès à des blocs mémoire libérés ou à des objets supprimés, il peut identifier l'endroit où
chaque bloc a été alloué et supprimé. Activez l'option Retarder "Free" dans la boîte de dialogue Configuration CodeGuard
pour utiliser cette fonctionnalité.

Voici les types d'erreurs d'accès possibles :

• Accès à de la mémoire libérée


• Accès dans une pile non initialisée
• Accès dans une pile invalide
Accès à de la mémoire libérée
Dans l'exemple suivant, CodeGuard identifie la ligne sur laquelle se produit un accès invalide. CodeGuard indique ensuite où le
bloc mémoire a été alloué puis libéré.
Error 00004. 0x100430 (Thread 0xFFF87283):
Access in freed memory: Attempt to access 19 byte(s) at 0x00B423DC.
strcpy(0x00B423DC, 0x004091CA ["Copie vers un bloc libre"])
| lang.cpp line 106:
|
| free(buf_h);
|> strcpy(buf_h, "Copie vers un bloc libre");
|
| //-----------------------//
Call Tree:
0x004011F1(=LANG.EXE:0x01:0001F1) lang.cpp#106
0x00407EE5(=LANG.EXE:0x01:006EE5)

The memory block (0x00B423DC) [size: 21 bytes] was allocated with malloc
| lang.cpp line 80:
| char * pad = (char *) malloc(200);
| // Un tableau dans le tas de la RTL.
|> char * buf_h = (char *) malloc(21);
| char * p;
| // Un tampon de travail.
Call Tree:
0x004011A1(=LANG.EXE:0x01:0001A1) lang.cpp#80
0x00407EE5(=LANG.EXE:0x01:006EE5)

4
1.1 Débogage d'applications C++ avec les RAD Studio Erreurs CodeGuard

The memory block (0x00B423DC) was freed with free


| lang.cpp line 105:
| //-------------//
|
|> free(buf_h);
| strcpy(buf_h, "Copie vers un bloc libre");
|
Call Tree:
0x004011E5(=LANG.EXE:0x01:0001E5) lang.cpp#105
0x00407EE5(=LANG.EXE:0x01:006EE5) 1
Accès dans une pile non initialisée
Dans l'exemple suivant, le pointeur p est devenu incorrect lorsque getBadLocal a été renvoyé après exécution. Aucune
information supplémentaire n'est fournie, car le cadre de pile pour getBadLocal a été automatiquement supprimé.
Error 00005. 0x120400 (Thread 0xFFF87283):
Access in uninitialized stack: Attempt to access 20 byte(s) at 0x0072FC88.
memcpy(0x0072FCC4, 0x0072FC88, 0x14 [20])
| lang.cpp line 112:
| //-----------------------//
| p = getBadLocal();
|> memcpy(buffer, p, 20);
|
| //-------------//
Call Tree:
0x00401208(=LANG.EXE:0x01:000208) lang.cpp#112
0x00407EE5(=LANG.EXE:0x01:006EE5)
Accès dans une pile invalide
Dans l'exemple suivant, une allocation a été effectuée pour buf_s dans la pile. Toutefois, la fonction strcpy écrit juste en
dessous du début de la région valide de la pile. CodeGuard identifie cela comme une erreur même si la longueur de la chaîne de
caractères n'est que d'un octet.
Error 00002. 0x110400 (Thread 0xFFF87283):
Access in invalid stack: Attempt to access 22 byte(s) at 0x0072FD8F.
strcpy(0x0072FD8F, 0x00409188 ["Cette chaîne est longue!\n"])
| LANG.CPP line 93:
|
| // Déficit de pile:
|> strcpy(buf_s -1, "Cette chaîne est longue!\n");
|
| // Débordement des données globales:
Call Tree:
0x004011C5(=LANG.EXE:0x01:0001C5) LANG.CPP#93
0x00407EED(=LANG.EXE:0x01:006EED)

1.1.1.2 Erreurs d'exceptions


Lorsqu'une exception système survient, CodeGuard signale l'erreur d'exécution à l'aide d'informations données par le système
d'exploitation. Si possible, le journal CodeGuard indique l'endroit où votre application a provoqué l'exception. CodeGuard
n'intercepte pas l'exception, ne la redirige pas et n'interfère en aucune manière avec le comportement normal du programme.

Les exceptions suivantes illustrent la façon dont CodeGuard signale les exceptions :

• Erreur de protection générale


• Division par zéro
Erreur de protection générale
Dans l'exemple suivant, CodeGuard fournit des informations sur une erreur de protection générale (exception système Intel
0xD). En plus de l'emplacement du code source qui a provoqué l'exception, le journal indique où la mémoire a été allouée puis

5
Erreurs CodeGuard RAD Studio 1.1 Débogage d'applications C++ avec les

libérée. La valeur fausse signalée résulte de l'accès à un pattern d'octets que CodeGuard utilise pour identifier des
emplacements mémoire invalides.
Error 00003. 0x400003 (Thread 0x0090):
Exception 0xC0000005: Access violation at 0x80828082.
| gpfault.c line 32:
| {¬
| q = p[3];
|> *q = 1;
| }
1 | }
Call Tree:
0x004010E5(=GPFAULT.EXE:0x01:0000E5) gpfault.c#32
0x00406B29(=GPFAULT.EXE:0x01:005B29)

The bogus value (0x80828082) was most likely retrieved by accessing a(n)
memory block that has already been freed
The memory block (0x008322A4) [size: 16 bytes] was allocated with malloc
| gpfault.c line 17:
| int *q;
|
|> p = malloc(sizeof(*p) * 4);
|
| /* Initialise p */
Call Tree:
0x00401094(=GPFAULT.EXE:0x01:000094) gpfault.c#17
0x00406B29(=GPFAULT.EXE:0x01:005B29)

The memory block (0x008322A4) was freed with free


| gpfault.c line 17:
| int *q;
|
|> p = malloc(sizeof(*p) * 4);
|
| /* Initialise p */
Call Tree:
0x00401094(=GPFAULT.EXE:0x01:000094) gpfault.c#17
0x00406B29(=GPFAULT.EXE:0x01:005B29)
Division par zéro
Dans l'exemple suivant, CodeGuard identifie l'endroit exact dans le code source où la division par zéro s'est produite (exception
système Intel 0x0).
Error 00001. 0x400000 (Thread 0x008B):
Exception 0xC0000094:
| ZERODIV.C line 9:
| {¬
| x = 1;
|> return x / y;
| }
|
Call Tree:
0x0040109C(=ZERODIV.EXE:0x01:00009C) ZERODIV.C#9
0x00406321(=ZERODIV.EXE:0x01:005321)

1.1.1.3 Erreurs d'échec de fonction


CodeGuard signale tous les appels de fonctions qui ont échoué, d'après leur valeur de retour.

Dans l'exemple suivant, la fonction close reçoit un descripteur de fichier invalide qui la conduit à renvoyer une valeur indiquant
qu'elle n'est pas parvenue à fermer un fichier.
Error 00009. 0x820000 (r) (Thread 0xFFF840F1):
Function failure:

6
1.1 Débogage d'applications C++ avec les RAD Studio Erreurs CodeGuard

close(0x80868086 [-2138668922])=0xFFFFFFFF [-1]


| lang.cpp line 125:
| // utilisation de données non initialisées //
| //--------------------------//
|> close(m->handle);
|
|
Call Tree:
0x00401236(=LANG.EXE:0x01:000236) lang.cpp#125
0x00407EED(=LANG.EXE:0x01:006EED)
1
1.1.1.4 Erreurs de ressources
Les ressources sont des blocs mémoire (alloués par des fonctions telles que malloc, GlobalAlloc) et des tableaux d'objets,
tels que des descripteurs de fichiers, des descripteurs de flux, des modules et des éléments renvoyés par new[].

Les exemples d'erreurs d'exécution suivants montrent la manière dont CodeGuard signale une utilisation incorrecte des
ressources.

• Paramètre incorrect
• Référence à une ressource libérée
• Incompatibilité entre types de ressources
• Pertes de ressources
• Ressource d'une bibliothèque d'exécution différente
Paramètre incorrect
Lorsqu'une ressource est transmise à une fonction, CodeGuard vérifie les arguments d'exécution. CodeGuard vous avertit s'il
trouve un paramètre erroné.
Error 00017. 0x310000 (Thread 0xFFF87283):
Bad parameter: A bad file handle (0xEA) has been passed to the function.
close(0xEA [234])
| lang.cpp line 170:
| // utilisation d'un mauvais handle //
| //--------------------//
|> close(234);
|
| //----------------------//
Call Tree:
0x00401456(=LANG.EXE:0x01:000456) lang.cpp#170
0x00407EE5(=LANG.EXE:0x01:006EE5)
Référence à une ressource libérée
Dans l'exemple suivant, CodeGuard signale une tentative de lecture dans un fichier déjà fermé. Le journal CodeGuard montre
où le fichier a été ouvert puis fermé.
Error 00020. 0x310030 (Thread 0xFFF840F1):
Reference to freed resource:
read(0x3 [3], 0x0072FCC4, 0x5 [5])
| lang.cpp line 177:
| int i = open("lang.cpp", 0);
| close(i);
|> read (i, buffer, 5);
|
| //--------------//
Call Tree:
0x00401487(=LANG.EXE:0x01:000487) lang.cpp#177
0x00407EED(=LANG.EXE:0x01:006EED)

The file handle (0x00000003) [name: 'lang.cpp'] was opened with open

7
Erreurs CodeGuard RAD Studio 1.1 Débogage d'applications C++ avec les

| lang.cpp line 175:


| // utilisation d'un handle libéré //
| //----------------------//
|> int i = open("lang.cpp", 0);
| close(i);
| read (i, buffer, 5);
Call Tree:
0x0040146C(=LANG.EXE:0x01:00046C) lang.cpp#175
0x00407EED(=LANG.EXE:0x01:006EED)

1 The file handle (0x00000003) was closed with close


| lang.cpp line 176:
| //----------------------//
| int i = open("lang.cpp", 0);
|> close(i);
| read (i, buffer, 5);
|
Call Tree:
0x00401477(=LANG.EXE:0x01:000477) lang.cpp#176
0x00407EED(=LANG.EXE:0x01:006EED)
Incompatibilité entre types de ressources
Dans l'exemple suivant, un bloc mémoire alloué avec l'opérateur new[], et qui doit donc être libéré avec l'opérateur delete[], est
libéré à la place par un appel à la fonction free.
Error 00024. 0x350010 (Thread 0xFFF840F1):
Resource type mismatch: a(n) memory block was expected.
free(0x00B42464)
| lang.cpp line 188:
| //---------------//
| char * ss = new char[21];
|> free(ss);
|
| #ifdef __WIN32__
Call Tree:
0x0040149F(=LANG.EXE:0x01:00049F) lang.cpp#188
0x00407EED(=LANG.EXE:0x01:006EED)

The object array (0x00B42464) [size: 21 bytes] was created with new[]
| lang.cpp line 187:
| // incompatibilité de types //
| //---------------//
|> char * ss = new char[21];
| free(ss);
|
Call Tree:
0x00401498(=LANG.EXE:0x01:000498) lang.cpp#187
0x00407EED(=LANG.EXE:0x01:006EED)
Pertes de ressources
Dans l'exemple suivant, de la mémoire a été allouée mais elle n'est jamais libérée.
The memory block (0x00B42310) [size: 200 bytes] was allocated with malloc
| lang.cpp line 78:
| // Un tableau sur la pile.
| char buf_s[21];
|> char * pad = (char *) malloc(200);
| // Un tableau dans le tas de la RTL.
| char * buf_h = (char *) malloc(21);
Call Tree:
0x00401199(=LANG.EXE:0x01:000199) lang.cpp#78
0x00407EE5(=LANG.EXE:0x01:006EE5)
Ressource d'une bibliothèque d'exécution différente
CodeGuard signale une erreur si votre application alloue, utilise ou libère des ressources de différentes versions de la

8
1.1 Débogage d'applications C++ avec les RAD Studio Présentation de CodeGuard

bibliothèque d'exécution. Cela peut arriver, comme le montre l'exemple suivant, si vous effectuez une liaison avec une
bibliothèque d'exécution statique mais que vous appelez une DLL.

Remarque: CodeGuard détecte les incompatibilités entre types de ressources avant de détecter les différences de versions de
la bibliothèque d'exécution. Lorsque les deux types d'erreur sont combinés, CodeGuard ne signale pas les bibliothèques
d'exécution différentes tant que vous n'avez pas corrigé l'incompatibilité entre les types de ressources.

Error 00001. 0x340010 (Thread 0x0062): 1


Resource from different RTL:
close(0x3 [3])
| testdll.cpp line 23:
| {¬
| MessageBox(NULL,"RTLMixHandle: DLL closing EXE handle", "TESTDLL.CPP", MB_OK );
|> close( handle );
| return 1;
| }
Call Tree:
0x0032115A(=testdll.dll:0x01:00015A) testdll.cpp#23
0x00401660(=WINAPI.EXE:0x01:000660) filescg.cpp#33
0x00401271(=WINAPI.EXE:0x01:000271) winapi.cpp#122
0x77EA15B3
0x00408B9A(=WINAPI.EXE:0x01:007B9A)

The file handle (0x00000003) [name: 'test2.dat'] was opened with open
| filescg.cpp line 32:
|
| MessageBox(NULL,"FilesMixCG: Mixing RTL file handles", "FILESCG.CPP", MB_OK );
|> i = open("test2.dat", O_CREAT, S_IREAD | S_IWRITE );
| RTLMixHandle( i );
| }
Call Tree:
0x00401657(=WINAPI.EXE:0x01:000657) filescg.cpp#32
0x00401271(=WINAPI.EXE:0x01:000271) winapi.cpp#122
0x77EA15B3
0x00408B9A(=WINAPI.EXE:0x01:007B9A)

1.1.2 Présentation de CodeGuard


CodeGuard permet de déboguer l'exécution des applications C++ développées avec RAD Studio. CodeGuard signale les
erreurs non détectées par le compilateur parce qu'elles n'outrepassent pas les règles de syntaxe. CodeGuard assure le suivi des
bibliothèques d'exécution et prend totalement en charge les applications multithread.

CodeGuard couvre principalement deux domaines :

• Utilisation de la mémoire et des ressources


• Validation des appels de fonctions
Utilisation de la mémoire et des ressources
CodeGuard vérifie les utilisations incorrectes de la mémoire, les allocations ou les libérations de mémoire incorrectes, les flux ou
les descripteurs de fichiers incorrects et les pertes de ressources provoquées par une utilisation incorrecte des flux ou des
descripteurs de fichiers. CodeGuard vérifie le déférencement des pointeurs et leur arithmétique. CodeGuard peut signaler une
erreur si votre programme tente d'accéder à de la mémoire ou à des ressources qui ont déjà été libérées.

Validation des appels de fonctions


CodeGuard vérifie les arguments d'une fonction et signale l'échec de leur exécution tel qu'il est rapporté par la valeur de retour
de cette fonction. Il valide les descripteurs de ressources Windows utilisés dans les appels de fonctions.

9
Avertissements CodeGuard RAD Studio 1.1 Débogage d'applications C++ avec les

Voir aussi
Erreurs signalées par CodeGuard ( see page 3)

Avertissements signalés par CodeGuard ( see page 10)

Utilisation de CodeGuard ( see page 58)

1
1.1.3 Avertissements CodeGuard
CodeGuard signale les cas où votre application accède à de la mémoire au-delà de la taille maximale d'un tampon. Les
avertissements concernent trois types de fonctions des bibliothèques d'exécution.

Rubriques
Nom Description
Avertissements pour la comparaison de blocs mémoire ( see page 11) Chacune des fonctions suivantes possède un paramètre qui détermine le nombre
maximal d'octets qu'elle compare :

1. memcmp
2. memicmp
3. _fmemcmp
4. _fmemicmp
Lorsque l'option Avertissements est activée pour les
fonctions de la liste ci-dessus, CodeGuard vérifie qu'une
comparaison peut être effectuée pour chaque bloc
mémoire transmis à la fonction. Si un bloc mémoire est
trop grand (d'après le paramètre transmis à la fonction),
CodeGuard génère un avertissement.
Lorsque l'option Avertissements est activée pour les
fonctions de la liste ci-dessus, CodeGuard vérifie le
premier octet de chaque bloc mémoire transmis à la
fonction. Si le bloc mémoire est invalide, CodeGuard
génère un message d'erreur.... suite ( see page 11)
Avertissements sur la fusion et la scission de noms de chemins ( see page 11) Chacune des fonctions suivantes utilise les constantes définies dans dir.h pour
déterminer le nombre maximal d'octets à copier depuis ou vers un tampon
mémoire :

1. fnmerge
2. fnsplit
3. getcurdir

10
1.1 Débogage d'applications C++ avec les RAD Studio Avertissements CodeGuard

Avertissements de comparaison de chaînes ( see page 12) Chacune des fonctions suivantes possède un paramètre qui détermine le nombre
maximal d'octets qu'elle compare :

• strncmp
• strnicmp
• strncmpi
• _fstrncmp
• _fstrnicmp 1
Lorsque l'option Avertissements est activée pour les
fonctions de la liste ci-dessus, CodeGuard vérifie qu'une
comparaison de chaîne peut être effectuée pour chaque
bloc mémoire transmis à la fonction. Si le tampon est trop
grand (d'après le paramètre transmis à la fonction) et si le
tampon ne possède pas de zéro terminal, CodeGuard
génère un avertissement.
Lorsque l'option Avertissements est activée pour les
fonctions de la liste ci-dessus, CodeGuard vérifie le
premier octet de chaque bloc mémoire transmis à la...
suite ( see page 12)

1.1.3.1 Avertissements pour la comparaison de blocs mémoire


Chacune des fonctions suivantes possède un paramètre qui détermine le nombre maximal d'octets qu'elle compare :

1. memcmp
2. memicmp
3. _fmemcmp
4. _fmemicmp
Lorsque l'option Avertissements est activée pour les fonctions de la liste ci-dessus, CodeGuard vérifie qu'une comparaison
peut être effectuée pour chaque bloc mémoire transmis à la fonction. Si un bloc mémoire est trop grand (d'après le paramètre
transmis à la fonction), CodeGuard génère un avertissement.
Lorsque l'option Avertissements est activée pour les fonctions de la liste ci-dessus, CodeGuard vérifie le premier octet de
chaque bloc mémoire transmis à la fonction. Si le bloc mémoire est invalide, CodeGuard génère un message d'erreur.

1.1.3.2 Avertissements sur la fusion et la scission de noms de


chemins
Chacune des fonctions suivantes utilise les constantes définies dans dir.h pour déterminer le nombre maximal d'octets à
copier depuis ou vers un tampon mémoire :

1. fnmerge
2. fnsplit
3. getcurdir
fnmerge
Si l'option Avertissements est activée, le tampon de sortie est validé par rapport à MAXPATH avant l'appel à fnmerge.

Si l'option Avertissements est désactivée, le tampon de sortie est validé après l'appel à fnmerge à l'aide de la chaîne de
caractères à zéro terminal, pour déterminer sa longueur.

11
Avertissements CodeGuard RAD Studio 1.1 Débogage d'applications C++ avec les

fnsplit
Si l'option Avertissements est activée, les tampons d'entrée sont validés par rapport à MAXDRIVE, MAXDIR, MAXFILE et
MAXEXT avant l'appel à fnsplit.

Si l'option Avertissements est désactivée, les tampons d'entrée sont validés après l'appel à fnsplit à l'aide de la chaîne de
caractères à zéro terminal, pour déterminer sa longueur.

getcurdir
1
Si l'option Avertissements est activée, le tampon de sortie est validé par rapport à MAXDIR avant l'appel à getcurdir.

Si l'option Avertissements est désactivée, le tampon de sortie est validé après l'appel à getcurdir à l'aide de la chaîne de
caractères à zéro terminal, pour déterminer sa longueur.

1.1.3.3 Avertissements de comparaison de chaînes


Chacune des fonctions suivantes possède un paramètre qui détermine le nombre maximal d'octets qu'elle compare :

• strncmp
• strnicmp
• strncmpi
• _fstrncmp
• _fstrnicmp
Lorsque l'option Avertissements est activée pour les fonctions de la liste ci-dessus, CodeGuard vérifie qu'une comparaison de
chaîne peut être effectuée pour chaque bloc mémoire transmis à la fonction. Si le tampon est trop grand (d'après le
paramètre transmis à la fonction) et si le tampon ne possède pas de zéro terminal, CodeGuard génère un avertissement.
Lorsque l'option Avertissements est activée pour les fonctions de la liste ci-dessus, CodeGuard vérifie le premier octet de
chaque bloc mémoire transmis à la fonction. Si le bloc mémoire est invalide, CodeGuard génère un message d'erreur.

12
1.2 Développement d'applications de RAD Studio

1.2 Développement d'applications de bases de


données pour la plate-forme Win32
Les applications de bases de données permettent aux utilisateurs d'interagir avec les informations stockées dans les bases de
1
données. Les bases de données permettent de structurer les informations et de les partager entre plusieurs applications.

Delphi permet de gérer les applications de bases de données relationnelles. Les bases de données relationnelles organisent les
informations en tables, qui contiennent des lignes (enregistrements) et des colonnes (champs). Ces tables peuvent être
manipulées par des opérations simples appelées calculs relationnels.

Rubriques
Nom Description
Présentation de dbGo ( see page 14) dbGo offre aux développeurs un modèle objet puissant et logique pour accéder
par programme aux données, les éditer et les mettre à jour à partir d'une grande
variété de sources de données par l'intermédiaire d'interfaces système OLE DB.
L'utilisation la plus courante de dbGo consiste à envoyer une requête à une ou
plusieurs tables d'une base de données relationnelle, pour ensuite récupérer les
résultats dans une application et permettre éventuellement aux utilisateurs de
modifier les données et de sauvegarder leurs modifications.
La couche ADO d'une application ADO comprend la dernière version de
Microsoft ADO, un fournisseur OLE ... suite ( see page 14)
Présentation de BDE ( see page 15) Le moteur de bases de données Borland (BDE) est un mécanisme d'accès aux
données pouvant être partagé entre plusieurs applications. Le BDE définit une
puissante bibliothèque d'appels API qui peuvent créer, restructurer, mettre à jour,
interroger ou manipuler des serveurs de bases de données locaux ou distants.
Le BDE fournit une interface uniforme permettant d'accéder à une grande variété
de serveurs, en utilisant des pilotes pour se connecter aux différentes bases de
données. Les composants de la catégorie BDE de la palette d'outils permettent
une connexion aux informations de la base de données avec le BDE.
Durant son déploiement, vous... suite ( see page 15)
Composants dbExpress ( see page 16) dbExpress est un ensemble de composants de base de données légers qui
permettent d'accéder rapidement aux serveurs de base de données SQL. Pour
chaque base de données prise en charge, dbExpress fournit un framework de
pilote qui adapte le logiciel serveur à un ensemble d'interfaces dbExpress
uniformes. Lorsque vous déployez une application de base de données qui
utilise dbExpress, vous incluez une bibliothèque de liaison dynamique (le pilote
propre au serveur) avec les fichiers d'application que vous créez.
dbExpress vous permet d'accéder aux bases de données à l'aide d'ensembles
de données unidirectionnels. Ceux-ci ont été conçus pour un accès léger... suite
( see page 16)
Introduction à InterBase Express ( see page 17) InterBase Express (IBX) est un ensemble de composants d'accès aux données
qui permet d'accéder à des données de bases de données InterBase. Les
composants Administration InterBase, qui requièrent InterBase 6, sont décrits
après les composants d'accès aux données InterBase.
Présentation des nouvelles fonctionnalités de dbExpress 4 ( see page 22) Le framework de niveau supérieur de dbExpress et le support des métadonnées
a été réécrit dans Delphi.
Il comporte un nouveau support de métadonnées enrichi.
Le pilote DbxClient traite à distance l'interface de framework dbExpress 4 sur un
transport réseau.
Ce document traite les fonctionnalités suivantes :

• Framework dbExpress
• Améliorations des métadonnées dbExpress
• Pilote DBXClient
• Pilote DBXDynalink
• DBTest

13
Présentation de dbGo RAD Studio 1.2 Développement d'applications de

Présentation de la migration BDP ( see page 26) BDP (Borland Data Provider, Fournisseur de données Borland) étant en cours de
dépréciation, n'utilisez pas BDP pour vos nouveaux développements. En
revanche, utilisez AdoDbx Client. Cette rubrique décrit les différences et les
équivalences entre BDP et AdoDbx Client.
En conséquence de la dépréciation de BDP :

• BDP sera retiré du produit dans une future release.


• Il n'y aura pas d'autre développement BDP et seulement
un effort de contrôle qualité (QA) minimal. Seuls les
1 bogues critiques seront corrigés.
• Aucune documentation supplémentaire ne sera fournie et
la documentation existante n'a pas encore été retirée.
BDP était basé sur ADO.NET 1.1. De... suite ( see page 26)
Concepteurs de composants ADO.NET ( see page 30) Presque toutes les applications distribuées se ramènent à lire et actualiser des
informations dans des bases de données. Les applications que vous développez
en utilisant ADO.NET ont des exigences différentes pour manipuler les données.
Vous pouvez, par exemple, développer une application qui affiche simplement
des données dans une fiche. Ou vous pouvez développer une application qui
propose le moyen de partager des informations avec une autre entreprise. Dans
tous les cas, vous devez comprendre certains concepts fondamentaux sur
l'approche des données dans ADO.NET.
En utilisant ces concepteurs, vous pouvez travailler efficacement pour lire,
exposer et modifier des données par l'intermédiaire... suite ( see page 30)
Déploiement d'applications de bases de données pour le .NET Framework ( Pour déployer des applications de bases de données avec RAD Studio, copiez
see page 33) les assemblages d'exécution et les DLL de pilotes pour le déploiement à un
emplacement spécifié. Les sections suivantes indiquent le nom des assemblages
et des DLL et l'emplacement où chacun doit être placé.
Framework dbExpress ( see page 35) Le framework dbExpress (framework DBX) est un ensemble de classes
abstraites fournies dans l'unité DBXCommon. Les applications peuvent
s'interfacer avec le framework de différentes façons : en utilisant le framework
directement pour les applications natives et managées, et en utilisant les
composants dbExpress VCL disposés en couches au sommet du framework
pour les applications natives et managées.
Bien que de nombreuses applications s'interfacent avec les pilotes dbExpress via
les composants dbExpress VCL, le framework DBX offre une option utile et
légère pour communiquer avec un pilote de base de données. Vous pouvez
également créer un pilote de base de... suite ( see page 35)
Compatibilité du framework dbExpress ( see page 37) Certains logiciels dbExpress développés avant le framework de pilote dbExpress
(framework de pilote DBX) ont été modifiés pour fonctionner avec le framework
de pilote DBX. A cause de ces modifications, certains problèmes de compatibilité
se produisent.

1.2.1 Présentation de dbGo


dbGo offre aux développeurs un modèle objet puissant et logique pour accéder par programme aux données, les éditer et les
mettre à jour à partir d'une grande variété de sources de données par l'intermédiaire d'interfaces système OLE DB. L'utilisation
la plus courante de dbGo consiste à envoyer une requête à une ou plusieurs tables d'une base de données relationnelle, pour
ensuite récupérer les résultats dans une application et permettre éventuellement aux utilisateurs de modifier les données et de
sauvegarder leurs modifications.

La couche ADO d'une application ADO comprend la dernière version de Microsoft ADO, un fournisseur OLE DB ou un pilote
ODBC pour l'accès au stockage de données, le logiciel client propre au système de base de données utilisé (dans le cas des
bases de données SQL), un système de base de données dorsal accessible à l'application (dans le cas des systèmes de bases
de données SQL) et une base de données. Tous ces éléments doivent être accessibles à l'application ADO pour que celle-ci soit
totalement opérationnelle.

La catégorie dbGo de la palette d'outils héberge les composants dbGo. Ces composants permettent de se connecter à un
stockage de données ADO, d'exécuter des commandes et d'extraire des données de tables de bases de données utilisant le
modèle ADO. Les composants requièrent la dernière version de ADO sur l'ordinateur hôte. De plus, il faut que le logiciel client

14
1.2 Développement d'applications de RAD Studio Présentation de BDE

pour le système de bases de données cible (par exemple, Microsoft SQL Server) soit installé ainsi qu'un pilote OLE DB ou
ODBC spécifique à ce système de bases de données.

La plupart des composants dbGo ont des homologues directs dans les composants disponibles pour d'autres mécanismes
d'accès aux données : un composant connexion de base de données, TADOConnection et différents types d'ensembles de
données. En outre, dbGo comprend TADOCommand, simple composant qui n'est pas un ensemble de données mais qui
représente une commande SQL à exécuter sur le stockage de données ADO.

Les principaux composants dbGo sont les suivants :


1
Composants Fonction
TADOConnection Composant de connexion de base de données qui établit une connexion avec un stockage de données
ADO.
Plusieurs composants ensembles de données et commandes ADO peuvent partager cette connexion pour
exécuter des commandes, obtenir des données et agir sur des métadonnées.
TRDSConnection Composant de connexion base de données permettant de marshaler les données d'applications de bases
de données multiniveaux élaborées à l'aide de serveurs d'applications ADO.
TADODataSet Ensemble de données de base utilisé pour obtenir et transformer les données.
TADODataSet peut obtenir les données d'une ou de plusieurs tables ; il peut se connecter directement à
un stockage de données ou utiliser un composant TADOConnection.
TADOTable Ensemble de données de type table pour la lecture et la manipulation d'un ensemble d'enregistrements
produit par une table de base de données unique.
TADOTable peut se connecter directement à un stockage de données ou utiliser un composant
TADOConnection.
TADOQuery Ensemble de données de type requête pour la lecture et la manipulation d'un ensemble d'enregistrements
produit par une instruction SQL valide.
TADOQuery peut également exécuter des instructions SQL du langage de définition de données (DDL). Il
peut se connecter directement à un stockage de données ou utiliser un composant TADOConnection.
TADOStoredProc Ensemble de données de type procédure stockée pour l'exécution des procédures stockées.
TADOStoredProc exécute des procédures stockées qui peuvent ou non récupérer des données. Il peut
se connecter directement à un stockage de données ou utiliser un composant TADOConnection.
TADOCommand Composant simple pour l'exécution de commandes (instructions SQL ne renvoyant pas d'ensembles de
résultats).
TADOCommand peut être utilisé avec un composant ensemble de données de prise en charge ou
récupérer un ensemble de données à partir d'une table. Il peut se connecter directement à un stockage de
données ou utiliser un composant TADOConnection.

Voir aussi
Utilisation des composants dbGo ( see page 1522)

1.2.2 Présentation de BDE


Le moteur de bases de données Borland (BDE) est un mécanisme d'accès aux données pouvant être partagé entre plusieurs
applications. Le BDE définit une puissante bibliothèque d'appels API qui peuvent créer, restructurer, mettre à jour, interroger ou
manipuler des serveurs de bases de données locaux ou distants. Le BDE fournit une interface uniforme permettant d'accéder à
une grande variété de serveurs, en utilisant des pilotes pour se connecter aux différentes bases de données. Les composants
de la catégorie BDE de la palette d'outils permettent une connexion aux informations de la base de données avec le BDE.

Durant son déploiement, vous devez inclure le BDE avec votre application. Bien que cela augmente la taille de l'application et la

15
Composants dbExpress RAD Studio 1.2 Développement d'applications de

complexité du déploiement, le BDE peut être partagé avec d'autres applications BDE et assurer un support plus large pour la
manipulation des bases de données. Même s'il est possible d'utiliser directement l'API du BDE dans votre application, les
composants de la catégorie BDE de la palette d'outils regroupent la plupart de ces fonctionnalités.

Les principaux composants BDE sont les suivants :

Composants Fonction
TTable Récupère les données d'une table physique, via le BDE, et les fournit à un ou plusieurs composants
1 orientés données par le biais d'un composant DataSource. Inversement, envoie les données reçues d'un
composant vers une base de données physique, via le BDE.
TQuery Utilise des instructions SQL pour récupérer les données d'une table physique, via le BDE, et les fournir à un
ou plusieurs composants orientés données par le biais d'un composant DataSource. Inversement, il utilise
des instructions SQL pour envoyer les données reçues d'un composant vers une base de données
physique, via le BDE.
TStoredProc Permet à une application d'accéder à des procédures stockées sur serveur. Il envoie les données reçues
d'un composant vers une base de données physique via le BDE.
TDatabase Met en place une connexion persistante à une base de données, en particulier à une base de données
distante nécessitant un nom de connexion utilisateur et un mot de passe.
TSession Assure le contrôle global d'un groupe de composants de base de données. Un composant TSession par
défaut est créé automatiquement pour chaque application base de données. Vous ne devez utiliser le
composant TSession que si vous créez une application de base de données multithread. Chaque thread de
la base de données doit avoir son propre composant Session.
TBatchMove Copie une structure de table et ses données. Il peut être utilisé pour transformer des tables entières d'un
format de base de données dans un autre.
TUpdateSQL Vous permet d'utiliser le support du cache pour les mises à jour des ensembles de données en lecture
seule.
TNestedTable Récupère les données d'un champ ensemble de données imbriqué et les fournit à des contrôles orientés
données via un composant source de données.

Voir aussi
Utilisation du BDE ( see page 70)

Moteur de bases de données Borland ( see page 2010)

1.2.3 Composants dbExpress


dbExpress est un ensemble de composants de base de données légers qui permettent d'accéder rapidement aux serveurs de
base de données SQL. Pour chaque base de données prise en charge, dbExpress fournit un framework de pilote qui adapte le
logiciel serveur à un ensemble d'interfaces dbExpress uniformes. Lorsque vous déployez une application de base de données
qui utilise dbExpress, vous incluez une bibliothèque de liaison dynamique (le pilote propre au serveur) avec les fichiers
d'application que vous créez.

dbExpress vous permet d'accéder aux bases de données à l'aide d'ensembles de données unidirectionnels. Ceux-ci ont été
conçus pour un accès léger et rapide aux informations de la base, avec des temps système réduits. Comme les autres
ensembles de données, ils peuvent envoyer une commande SQL au serveur de la base de données et, si la commande renvoie
un ensemble d'enregistrements, ils peuvent récupérer ces enregistrements. Les ensembles de données unidirectionnels ne
placent pas les données dans un tampon de mémoire, ce qui les rend plus rapides et moins consommateurs de mémoire que
les autres types d'ensembles de données. Mais, parce qu'ils ne mettent pas les enregistrements dans un tampon, les ensembles
de données unidirectionnels sont moins flexibles que les autres ensembles de données.

16
1.2 Développement d'applications de RAD Studio Introduction à InterBase Express

Les connexions, les tables, les vues et les procédures stockées dbExpress qui apparaissent dans une vue arborescente
prennent en charge les glisser-déplacer avec les fiches vcl managées et natives.

La catégorie dbExpress de la palette d'outils contient les composants qui utilisent dbExpress pour accéder aux informations
d'une base de données. Ce sont :

Composants Fonction
TSQLConnection Encapsule une connexion dbExpress à un serveur de base de données
TSQLDataSet Représente n'importe quelles données disponibles via dbExpress ou permet d'envoyer des 1
commandes à une base de données accessible via dbExpress.
TSQLQuery Un ensemble de données de type requête qui encapsule une instruction SQL et permet aux
applications d'accéder aux enregistrements trouvés, s'il y en a.
TSQLTable Un ensemble de données de type table qui représente toutes les lignes et colonnes d'une table de
base de données
TSQLStoredProc Un ensemble de données de type procédure stockée qui exécute une procédure stockée définie
sur un serveur de bases de données
TSQLMonitor Intercepte les messages transmis entre un composant connexion SQL et un serveur de base de
données, et les enregistre dans une liste de chaînes
TSimpleDataSet Un ensemble de données client qui utilise un TSQLDataSet et un TDataSetProvider internes
pour récupérer des données et appliquer des mises à jour.

Voir aussi
Utilisation de dbExpress ( see page 83)

Utilisation des ensembles de données dbExpress ( see page 1879)

Configuration d'une connexion TSQL ( see page 62)

Utilisation de l'explorateur de données pour obtenir des informations de connexion ( see page 84)

1.2.4 Introduction à InterBase Express


InterBase Express (IBX) est un ensemble de composants d'accès aux données qui permet d'accéder à des données de bases
de données InterBase. Les composants Administration InterBase, qui requièrent InterBase 6, sont décrits après les composants
d'accès aux données InterBase.

Composants IBX
Les composants suivants sont situés sur l'onglet InterBase de la palette des composants.

TIBTable

TIBQuery

TIBStoredProc

TIBDatabase

TIBTransaction

TIBUpdateSQL

TIBDataSet

17
Introduction à InterBase Express RAD Studio 1.2 Développement d'applications de

TIBSQL

TIBDatabaseInfo

TIBSQLMonitor

TIBEvents

TIBExtract
1
TIBCustomDataSet

Bien que leurs noms soient similaires à ceux des composants BDE, les composants IBX sont quelque peu différents. Les
sections ci-dessous présentent ces différences pour les composants ayant un équivalent BDE.

Il n'existe pas de migration simple d'applications BDE vers des applications IBX. Vous devrez généralement remplacer les
composants BDE par les composants IBX comparables, puis recompiler vos applications. Toutefois, la vitesse gagnée et les
puissantes fonctionnalités InterBase auxquelles vous pouvez alors accéder justifient pleinement la migration.

IBDatabase

Utilisez un composant TIBDatabase pour établir des connexions à des bases de données susceptibles d'impliquer une ou
plusieurs transactions simultanées. A la différence de BDE, IBX possède un composant transaction distinct qui permet de
séparer les transactions des connexions de base de données.

Pour définir une connexion de base de données :

1. Déposez un composant IBDatabase sur une fiche ou un module de données.


2. Initialisez la propriété DatabaseName. Pour une connexion locale, il s'agit du lecteur, du chemin et du nom du fichier de la
base de données. Initialisez la propriété Connected à true.
3. Entrez un nom d'utilisateur et un mot de passe corrects puis cliquez sur OK pour établir la connexion à la base de données.
Avertissement: Astuce : Vous pouvez stocker le nom de l'utilisateur et son mot de passe dans la propriété Params du
composant IBDatabase en initialisant la propriété LoginPrompt à false après l'ouverture de la session. Par exemple, après
avoir ouvert une session en tant qu'administrateur système et avoir initialisé la propriété LoginPrompt à false, vous pourrez
voir les informations suivantes en éditant la propriété Params :

user_name=sysdba
password=masterkey
IBTransaction

A la différence de Borland Database Engine, IBX contrôle les transactions avec un composant séparé, TIBTransaction. Cette
fonctionnalité puissante vous permet de séparer les transactions des connexions de base de données pour pouvoir bénéficier du
mécanisme de validation à deux phases d'InterBase (les transactions s'étendant sur plusieurs connexions) et de plusieurs
transactions simultanées utilisant la même connexion.

Utilisez un composant IBTransaction pour gérer les contextes de transactions, qui peuvent mettre en jeu une ou plusieurs
connexions de base de données. Dans la plupart des cas, un modèle simple avec une base de données et une transaction fera
l'affaire.

Pour définir une transaction :

1. Définissez une connexion IBDatabase comme décrit ci-dessus.


2. Déposez un composant IBTransaction sur la fiche ou le module de données.
3. Affectez à la propriété DefaultDatabase le nom de votre composant IBDatabase.
4. Initialisez la propriété Active à true pour démarrer la transaction.

18
1.2 Développement d'applications de RAD Studio Introduction à InterBase Express

Composants ensemble de données IBX


Il existe plusieurs composants ensembles de données parmi lesquels vous pouvez faire votre choix avec IBX ; chacun possède
ses caractéristiques propres et est adapté à des tâches particulières :
IBTable
Utilisez un composant TIBTable pour définir un ensemble de données dynamique sur une table ou une vue sans avoir à entrer
d'instructions SQL.
Les composants IBTable sont faciles à configurer :
1
1. Ajoutez un composant IBTable à votre fiche ou votre module de données.
2. Spécifiez les composants base de données et transaction associés.
3. Spécifiez le nom de la relation à partir de la liste déroulante TableName.
4. Initialisez la propriété Active à true.
IBQuery
Utilisez un composant TIBQuery pour exécuter n'importe quelle instruction DSQL InterBase, restreindre votre ensemble de
résultats à certaines colonnes et certaines lignes, utiliser des fonctions d'agrégation et effectuer des jointures entre plusieurs
tables.
Les composants IBQuery fournissent un ensemble de données en lecture seule et s'adaptent bien à l'environnement
client-serveur d'InterBase. Pour définir un composant IBQuery :
1. Définissez une connexion IBDatabase comme décrit ci-dessus.
2. Définissez une connexion IBTransaction comme décrit ci-dessus.
3. Ajoutez un composant IBQuery à votre fiche ou votre module de données.
4. Spécifiez les composants base de données et transaction associés.
5. Entrez dans l'éditeur de listes de chaînes une instruction SQL valide pour la propriété SQL du composant IBQuery.
6. Initialisez la propriété Active à true.
IBDataSet
Utilisez un composant TIBDataSet pour exécuter n'importe quelle instruction DSQL InterBase, restreindre votre ensemble de
résultats à certaines colonnes et certaines lignes, utiliser des fonctions d'agrégation et effectuer des jointures entre plusieurs
tables. Les composants IBDataSet sont similaires aux composants IBQuery, mis à part qu'ils prennent en charge les
ensembles de données dynamiques sans nécessiter un composant IBUpdateSQL.
L'exemple suivant fournit un ensemble de données dynamique pour la table COUNTRY dans employee.gdb :
1. Définissez une connexion IBDatabase comme décrit ci-dessus.
2. Spécifiez les composants base de données et transaction associés.
3. Ajoutez un composant IBDataset à votre fiche ou votre module de données.
4. Entrez des instructions SQL pour les propriétés suivantes :

SelectSQL SELECT Country, Currency FROM Country


RefreshSQL SELECT Country, Currency FROM Country WHERE Country = :Country
ModifySQL UPDATE Country SET Country = :Country, Currency = :Currency WHERE Country = :Old_Country
DeleteSQL DELETE FROM Country WHERE Country = :Old_Country
InsertSQL INSERT INTO Country (Country, Currency) VALUES (:Country, :Currency)

1. Initialisez la propriété Active à true.


2.

19
Introduction à InterBase Express RAD Studio 1.2 Développement d'applications de

Remarque: Remarque : Les paramètres et les champs transmis aux fonctions sont sensibles à la casse dans le dialecte 3.
Par exemple,

FieldByName(EmpNo)
ne renvoie rien dans le dialecte 3 si le champ est spécifié sous la forme 'EMPNO'.

IBStoredProc
1 Utilisez TIBStoredProc pour les procédures exécutables InterBase : les procédures qui renvoient au plus une ligne
d'informations. Pour les procédures stockées renvoyant plus d'une ligne de données ou les procédures "Select", utilisez des
composants IBQuery ou IBDataSet.

IBSQL

Utilisez un composant TIBSQL pour les opérations qui doivent être rapides et légères. Des opérations telles que la définition de
données et la copie de données d'une base de données vers une autre sont bien adaptées aux composants IBSQL.

Dans l'exemple suivant, un composant IBSQL est utilisé pour renvoyer la valeur suivante à partir d'un générateur :

1. Définissez une connexion IBDatabase comme décrit ci-dessus.


2. Positionnez un composant IBSQL sur la fiche ou le module de données et affectez le nom de la base de données à sa
propriété Database.
3. Ajoutez une instruction SQL dans l'éditeur de listes de chaînes pour la propriété SQL, par exemple :
SELECT GEN_ID(MyGenerator, 1) FROM RDB$DATABASE
IBUpdateSQL

Utilisez un composant TIBUpdateSQL pour mettre à jour des ensembles de données en lecture seule. Vous pouvez mettre à
jour une sortie IBQuery avec un composant IBUpdateSQL :

1. Définissez un composant IBQuery comme décrit ci-dessus.


2. Ajoutez un composant IBUpdateSQL à votre fiche ou votre module de données.
3. Entrez des instructions SQL pour les propriétés suivantes : DeleteSQL, InsertSQL, ModifySQL et RefreshSQL.
4. Affectez le nom du composant IBUpdateSQLà la propriété UpdateObject du composant IBQuery.
5. Initialisez la propriété Active du composant IBQuery à true.
IBSQLMonitor
Utilisez un composant TIBSQLMonitor pour développer des outils de diagnostic permettant de surveiller les communications
entre votre application et le serveur InterBase. Quand les propriétés TraceFlags d'un composant IBDatabase sont activées,
les composants TIBSQLMonitor actifs peuvent surveiller l'activité de la connexion et envoyer le résultat vers un fichier ou un
contrôle.
Un bon exemple consisterait à créer une application séparée avec un composant TIBSQLMonitor et un contrôle Memo. Lancez
cette deuxième application, puis dans l'application principale, activez les propriétés TraceFlags du composant IBDatabase.
Travaillez avec l'application principale et observez le contrôle Memo de la deuxième application se remplir de données.
IBDatabaseInfo
Utilisez un composant TIBDatabaseInfo pour lire des informations sur une base de données particulière, comme son intervalle
de nettoyage, sa version ODS et les noms des utilisateurs actuellement connectés à cette base de données.
Par exemple, pour définir un composant IBDatabaseInfo affichant les utilisateurs actuellement connectés à la base de données,
procédez comme suit :
1. Définissez une connexion IBDatabase comme décrit ci-dessus.
2. Placez un composant IBDatabaseInfo sur la fiche ou le module de données et affectez à sa propriété Database le nom de la
base de données.
3. Placez un composant Memo sur la fiche.

20
1.2 Développement d'applications de RAD Studio Introduction à InterBase Express

4. Placez un composant Timer sur la fiche et définissez son intervalle.


5. Double-cliquez sur le champ de l'événement OnTimer du composant Timer et entrez un code de la forme :
Memo1.Text := IBDatabaseInfo.UserNames.Text; // Exemple Delphi
Memo1->Text = IBDatabaseInfo->UserNames->Text; // Exemple C++
IBEvents

Utilisez un composant IBEvents pour demander la notification et traiter de manière asynchrone les événements transmis par un
serveur InterBase.
1
Pour définir un composant IBEvents :

1. Définissez une connexion IBDatabase comme décrit ci-dessus.


2. Positionnez un composant IBEvents sur la fiche ou le module de données et affectez le nom de la base de données à sa
propriété Database.
3. Entrez des événements dans l'éditeur de listes de chaînes de la propriété Events, par exemple :
IBEvents.Events.Add('EVENT_NAME'); // Exemple Delphi
IBEvents->Events->Add("EVENT_NAME"); // Exemple C++
1. 4. Initialisez la propriété Registered à true.
2. Composants Administration InterBase
Si vous avez installé InterBase 6, vous pouvez utiliser les composants Administration InterBase 6, qui vous permettent d'accéder
aux puissants appels à l'API des services InterBase.
Les composants suivants sont situés sur l'onglet d'administration d'InterBase de l'EDI :

TIBConfigService

TIBBackupService

TIBRestoreService

TIBValidationService

TIBStatisticalService

TIBLogService

TIBSecurityService

TIBLicensingService

TIBServerProperties

TIBInstall

TIBUnInstall

Remarque : Pour utiliser ces fonctionnalités, vous devez installer InterBase 6.

IBConfigService

Utilisez un objet TIBConfigService pour configurer les paramètres d'une base de données, y compris les tampons de pages, le
mode asynchrone, l'espace de réserve et l'intervalle de balayage.

IBBackupService

Utilisez un objet TIBBackupService pour effectuer une copie de sauvegarde de votre base de données. Cet objet vous permet
de définir des paramètres tels que le facteur de blocage, le nom du fichier de sauvegarde et les options de sauvegarde de la
base de données.

IBRestoreService

21
Présentation des nouvelles fonctionnalités RAD Studio 1.2 Développement d'applications de

Utilisez un objet TIBRestoreService pour restaurer votre base de données. Cet objet vous permet de définir des options telles
que les tampons de pages, la taille des pages et les options de restauration de la base de données.

IBValidationService

Utilisez un objet TIBValidationService pour valider votre base de données et réconcilier vos transactions de base de données.
Cet objet vous permet de définir l'action de transaction par défaut, de renvoyer des informations sur les transactions limbo et de
définir d'autres options de validation de la base de données.

1 IBStatisticalService

Utilisez un objet TIBStatisticalService pour afficher les statistiques sur la base de données, par exemple les pages de données,
le journal de la base de données, les pages d'en-tête, les pages d'index et les relations système.

IBLogService

Utilisez un objet TIBLogService pour créer un fichier journal.

IBSecurityService

Utilisez un objet TIBSecurityService pour gérer l'accès des utilisateurs au serveur InterBase. Cet objet vous permet de créer, de
supprimer et de modifier des comptes utilisateur, d'afficher tous les utilisateurs et de définir des groupes de travail en utilisant
des rôles SQL.

IBLicensingService

Utilisez un composant TIBLicensingService pour ajouter ou supprimer des certificats d'activation logiciels InterBase.

IBServerProperties

Utilisez un composant TIBServerProperties pour renvoyer des informations sur le serveur, y compris les paramètres de
configuration, les informations relatives à la version et à la licence.

IBInstall

Utilisez un composant TIBInstall pour définir un composant d'installation InterBase, y compris les répertoires d'installation source
et de destination et les composants à installer.

IBUnInstall

Utilisez un composant TIBUnInstall pour définir un composant de désinstallation.

1.2.5 Présentation des nouvelles fonctionnalités de


dbExpress 4
Le framework de niveau supérieur de dbExpress et le support des métadonnées a été réécrit dans Delphi.

Il comporte un nouveau support de métadonnées enrichi.

Le pilote DbxClient traite à distance l'interface de framework dbExpress 4 sur un transport réseau.

Ce document traite les fonctionnalités suivantes :

• Framework dbExpress
• Améliorations des métadonnées dbExpress
• Pilote DBXClient
• Pilote DBXDynalink

22
1.2 Développement d'applications de RAD Studio Présentation des nouvelles fonctionnalités

• DBTest
Framework dbExpress

VCL
L'implémentation du composant VCL dbExpress a été modifiée avec des changements minimaux de l'API. La plupart des
applications ne sont pas affectées par les modifications apportées à la bibliothèque VCL dbExpress. Toutefois, des méthodes,
propriétés, événements, constantes et énumérations sont nouvelles. 1

Compatibilité d'interface de l'unité DBXCommon (classes "Ex")


Dans l'unité DbxCommon, plusieurs nouvelles classes étendent des classes existantes et ont le suffixe "Ex". Des classes
temporaires ont été introduites pour éviter d'interrompre la compatibilité d'interface avec les versions livrées début 2007. Dans la
prochaine release, ces méthodes et champs supplémentaires seront déplacés vers la version non-Ex des classes.

Améliorations des métadonnées dbExpress


Les métadonnées dbExpress 3 n'étaient pas assez riches pour les outils de base de données et ne prenaient pas en charge
tous les types de métadonnée attendus depuis un pilote ADO.NET 2.0. De nouveaux fournisseurs de métadonnées fournissent
des capacités accrues.

De nouveaux fournisseurs de métadonnées pour 9 dorsaux de base de données différents sont entièrement écrits dans Delphi.
Le code source complet de tous les fournisseurs de métadonnées est inclus dans le produit.

Séparation des capacités de lecture et d'écriture des métadonnées


Chaque fournisseur est composé d'une implémentation de lecteur et d'écrivain de métadonnée. Les lecteurs de métadonnée
résident dans le nouveau package DbxReadOnlyMetaData et les écrivains de métadonnée se trouvent dans le package
DbxMetaData. Les pilotes dbExpress et le nouveau pilote AdoDbx client ADO.NET ne nécessitent que les capacités de lecteur
de métadonnée. De nombreuses applications de base de données ont seulement besoin de lire les métadonnées, pas de les
écrire. En séparant les capacités de lecture et d'écriture, la taille des déploiements d'applications sont réduites.

Approche basée sur les fournisseurs


Les fournisseurs de métadonnées sont détachés du pilote, de telle sorte qu'un fournisseur de métadonnée peut être utilisé pour
plusieurs implémentations de pilote tant que le dorsal de base de données reste le même. L'explorateur de données profite
également des fournisseurs de métadonnées pour fournir le support des métadonnées à d'autres pilotes ADO.NET de base de
données.

Le fournisseur n'est pas lié à un pilote, mais à un dorsal de base de données. La nouvelle propriété
TDBXPropertyNames.MetaDataPackageLoader des fichiers dbxdrivers.ini peut être définie sur un objet TDBXCommandFactory.
Cette implémentation de fabrique de commande crée un TDBXCommand pouvant exécuter des commandes de métadonnée.
Cette approche permet à plusieurs implémentations de pilotes d'un dorsal de base de données spécifique d'utiliser le même
fournisseur de métadonnées. L'explorateur de données profite également de cette architecture pour fournir des métadonnées
structurées dbExpress 4 pour les pilotes ADO.NET des autres fournisseurs. Le découplage du pilote et du fournisseur de
métadonnées permet des implémentations de pilotes "légères". Si les commandes des métadonnées peuvent être traitées sur
un serveur, il n'est pas nécessaire d'avoir la logique de fournisseur de métadonnées sur le client.

Répertoire source du fournisseur


Il existe plusieurs répertoires pour le code source du fournisseur de métadonnées. Les unités ayant un intérêt pour les
applications ont été placées dans le répertoire "provider". Les applications doivent éviter de créer des dépendances sur les
unités hors de ce répertoire. Toutefois, les implémenteurs de métadonnées dbExpress doivent se développer à partir de classes
de base de lecteur et d'écrivain abstraites situées hors du répertoire provider.

23
Présentation des nouvelles fonctionnalités RAD Studio 1.2 Développement d'applications de

Lecture des métadonnées


La nouvelle unité DBXMetaDataNames a été fournie pour lire les métadonnées. La classe dbExpress existante
TDBXMetaDataCommands fournit un ensemble de constantes pour lire divers types de métadonnées. Définissez la propriété
TDBXCommand.CommandType sur TDBXCommandTypes.DBXMetadata et définissez TDBXCommand.Text sur une des
constantes de TDBXMetaDataCommands pour acquérir la métadonnée désignée. TDBXCommand.ExecuteQuery renvoie un
TDBXReader pour accéder à la métadonnée. Les nouvelles classes de DBXMetaDataNames décrivent et fournissent un accès
1 aux colonnes de cette métadonnée.

Ecriture des métadonnées


Le support de la création des instructions CREATE, ALTER et DROP sensibles au dialecte SQL est fourni dans l'explorateur de
données. dbExpress expose également une classe DbxMetaDataProvider qui couvre cette capacité pour les applications. Cela
augmente légèrement la taille de l'application, puisque les écrivains de métadonnées doivent être inclus. La capacité de création
générique des tables est utile pour de nombreuses applications. L'interface vous permet de décrire l'aspect d'une table et de ses
colonnes et de passer cette description à la méthode TdbxMetaDataProvider.CreateTable. Voici un exemple simple qui montre
comment créer une table avec une colonne int32 nommée "C1", un décimal avec une précision de 10 et une échelle de 2
nommé "C2", et une colonne basée sur les caractères avec une précision de 32 nommée "C3".
var
MetaDataTable: TDBXMetaDataTable;
DataGenerator: TDbxDataGenerator;
Command: TDBXCommand;
Row: Integer;
begin
MetaDataTable := TDBXMetaDataTable.Create;
MetaDataTable.TableName := 'QCXXX_TABLE';
MetaDataTable.AddColumn(TDBXInt32Column.Create('C1'));
MetaDataTable.AddColumn(TDBXDecimalColumn.Create('C2', 10, 2));
MetaDataTable.AddColumn(TDBXUnicodeCharColumn.Create('C3', 32));
MetaDataProvider.CreateTable(MetaDataTable);
end
Remarque: DBXMetaDataProvider est seulement supporté pour le code managé sur la plate-forme .NET.

Déploiement
Pour le déploiement basé sur les packages, les packages suivants doivent être inclus :

• Borland.Data.DBXClient.dll
• Borland.Data.DBXReadOnlyMetaData.dll
• Borland.Data.DBXCommonDriver.dll
• Borland.Data.DBXMetaData.dll

Création de nouveaux fournisseurs de métadonnées


La plus grande partie du travail dans la création de nouveaux fournisseurs de métadonnées est l'extension des classes de base
abstraites TDBXMetaDataReader et TDBXMetaDataWriter.

Compatibilité
Les composants VCL de l'unité SqlExpr travaillent toujours avec des pilotes qui fournissent les métadonnées dbExpress 3 plus
limitées. Toutefois, l'explorateur de données travaille seulement avec les métadonnées dbExpress 4.

Notez que Delphi inclut des métadonnées pour 9 dorsaux de base de données différents. Toute implémentation de pilote
dbExpress pour les 9 dorsaux supportés peuvent ainsi réutiliser le fournisseur de métadonnées avec leur implémentation de
pilote.

24
1.2 Développement d'applications de RAD Studio Présentation des nouvelles fonctionnalités

Pilote DBXClient
DBXClient est un pilote dbExpress 4 léger qui traite à distance l'interface de framework dbExpress 4 sur un transport réseau
pluggable. Dans cette release, un protocole de transport TCP/IP est pris en charge. Le pilote utilise un protocole de flux
JSON/RPC (Java Script Object Notation).

Le DBXClient est implémenté en 100% Pascal Objet. Son code source est inclus dans le produit.

Blackfish SQL 1
Dans cette release, DBXClient peut seulement se connecter à Blackfish SQL. Blackfish SQL est une version Delphi pour .NET
du JDataStore de JBuilder.

Pour utiliser le pilote DBXClient avec Blackfish SQL, ajoutez l'unité DBXClient à la clause uses.

Déploiement
DBXClient ne nécessite pas l'installation d'une bibliothèque client de base de données lors du déploiement de votre application.
DBXClient est 100% Delphi et peut être directement lié dans votre application sous forme d'un fichier .exe unique.

Si vous préférez utiliser un déploiement basé sur les packages, vous devez inclure les packages suivants :

• DBXClient100.bpl
• DBXReadOnlyMetaData100.bpl
• DBXCommonDriver100.bpl
Pilote DBXDynalink
L'unité de pilote DBXDynalink a été déplacée du package DBXCommonDriver vers le package DBXDynalinkDriver. Avec
l'introduction du pilote DBXClient, CodeGear fournit à présent des pilotes non-Dynalink.

Nouvelles unités
De nouvelles unités ont été ajoutées dans le package DbxDynalinkDriver pour les 8 pilotes Dynalink :

• DBXDb2
• DBXInformix
• DBXInterbase
• DBXMsSql
• DBXMySql
• DBXOracle
• DBXSybaseASA
• DBXSybaseASE

Déploiement
Les pilotes Dynalink peuvent être liés dans un exécutable unique, mais vous devez toujours déployer les bibliothèques Dynalink
elles-mêmes et les bibliothèques client du fournisseur de base de données.

Pour le déploiement basé sur les packages, les packages suivants doivent être inclus :

• DBXCommonDriver100.bpl
• DBXReadOnlyMetaData100.bpl
• DBXDynalinkDriver100.bpl

25
Présentation de la migration BDP RAD Studio 1.2 Développement d'applications de

Pour le déploiement basé sur les packages sur la plate-forme .NET, les assemblages suivants doivent être inclus :
• Borland.Data.DBXCommonDriver.dll
• Borland.Data.DBXReadOnlyMetaData.dll
• Borland.Data.DBXDynalinkDriver.dll
DBTest
C'est une collection de classes qui étendent les capacités de Dunit afin de faciliter le test des bases de données. Les tests Dunit
1 exemple qcreport et cts fournissent de bons exemples sur l'utilisation de DBTest. TestCaseExtension contient les extensions
non-base de données à Dunit et l'unité DBXTest contient les extensions base de données.

Propriétés de ligne de commande


De nouvelles unités ont été ajoutées au package DbxDynalinkDriver pour les 8 pilotes Dynalink :

Sélection de test
La ligne de commande -s:<TestName> peut être utilisée pour exécuter une seule méthode dans un cas de test Dunit. Cela est
utile pour déboguer un seul bogue. Voir l'unité TestCaseExtension.

Méthodes pratiques
Plusieurs méthodes permettent de créer une connexion par défaut et un fournisseur de métadonnées. Voir l'unité DBXTest.

Générateur de données
Il existe également un générateur de données simple et extensible. Voir l'unité DBXDataGenerator.

Voir aussi
Framework dbExpress ( see page 35)

TDBXMetaDataCommands

TDBXMetaDataCommands

1.2.6 Présentation de la migration BDP


BDP (Borland Data Provider, Fournisseur de données Borland) étant en cours de dépréciation, n'utilisez pas BDP pour vos
nouveaux développements. En revanche, utilisez AdoDbx Client. Cette rubrique décrit les différences et les équivalences entre
BDP et AdoDbx Client.

En conséquence de la dépréciation de BDP :

• BDP sera retiré du produit dans une future release.


• Il n'y aura pas d'autre développement BDP et seulement un effort de contrôle qualité (QA) minimal. Seuls les bogues critiques
seront corrigés.
• Aucune documentation supplémentaire ne sera fournie et la documentation existante n'a pas encore été retirée.
BDP était basé sur ADO.NET 1.1. De nombreuses fonctionnalités différentes de BDP, comme l'indépendance du fournisseur et
les métadonnées étendues, ont été ajoutées à ADO.NET 2 en utilisant différentes approches, incompatibles avec BDP. En
outre, ADO.NET 2 utilise les classes de base abstraites et a déprécié les interfaces ADO.NET 1.1. Cela a rendu difficilement
applicable l'extension de BDP à ADO.NET 2.0.
AdoDbx Client est basé sur ADO.NET 2.0 et fournit la plupart des capacités de BDP.
BDP est constitué de trois espaces de nommage :

26
1.2 Développement d'applications de RAD Studio Présentation de la migration BDP

Espace de nommage Description


de BDP

Borland.Data.Common Contient les objets communs à tout BDP.NET, y compris les classes d'erreur et d'exception, les
énumérations de type de données, les options de fournisseur et les interfaces pour concevoir vos
propres classes commande, connexion et curseur.
Borland.Data.Provider Contient les classes BDP.NET essentielles comme BdpCommand, BdpConnection, BdpDataAdapter,
BdpDataReader et d'autres qui permettent d'interagir avec des sources de données externes comme 1
les serveurs de bases de données Oracle, DB2, Interbase et MS SQL Server.
Borland.Data.Schema Contient les interfaces permettant de construire vos propres classes de manipulation de schéma de
base de données ainsi que divers types et énumérateurs définissant des métadonnées.

Ce document décrit la migration pour chacun de ces espaces de nommage.

Migration Borland.Data.Provider
Deux classes de cet espace de nommage fournissent la gestion distante des données et n'ont pas été dépréciées. Elles ne
nécessitent donc pas de migration, ce sont :

• DataHub
• DataSync

Classes correspondantes dans BDP et AdoDbx Client


La plupart des classes BDP de cet espace de nommage sont des implémentations des classes ADO.NET. Ces classes sont
également implémentées dans AdoDbx Client. La plupart du code source utilisant ces classes devrait être converti en AdoDbx
Client avec un effort minimal.

Le tableau suivant présente la correspondance entre les classes ADO.NET, BDP et AdoDbx Client :

ADO.NET BDP.NET Client AdoDbx


DbCommand BdpCommand TAdoDbxCommand
DbCommandBuilder BdpCommandBuilder TAdoDbxCommandBuilder
DbConnection BdpConnection TAdoDbxConnection
DbDataAdapter BdpDataAdapter TAdoDbxDataAdapter
DbDataReader BdpDataReader TAdoDbxDataReader
DbTransaction BdpTransaction TAdoDbxTransaction

La conversion des classes BDP de ce groupe est plutôt simple. Consultez la documentation pour voir si la méthode utilisée est
prise en charge dans la classe AdoDbx Client correspondante. Si elle l'est, vous n'avez probablement rien à faire. Si la méthode
n'est pas prise en charge, vous devez alors modifier votre code afin d'utiliser les méthodes prises en charge dans AdoDbx Client
ou ADO.NET lui-même.

Par exemple, la classe BdpDataReader accède aux enregistrements de base de données. La plupart de ses méthodes d'accès
aux données ont des méthodes TAdoDbxDataReader correspondantes, comme décrit à la section ISQLCursor.
BdpDataReader.GetSchemaTable peut être utilisée pour récupérer la métadonnée curseur en tant que DataTable.
Reportez-vous à la section ISQLExtendedMetaData et ISQLMetaData pour obtenir la description d'un accès aux métadonnées
pour AdoDbx Client.

Classes BDP sans classes AdoDbx Client correspondantes


La classe BdpCopyTable n'a pas de classe correspondante dans AdoDbx Client. Cette capacité n'est donc pas disponible dans

27
Présentation de la migration BDP RAD Studio 1.2 Développement d'applications de

AdoDbx Client.

Migration Borland.Data.Common
Cet espace de nommage a sept classes et trois interfaces.

BdpConnectionString
La classe TAdoDbxConnection a une propriété ConnectionString. Cette classe prend également en charge le pooling de
connexion.
1
BdpError et BdpErrorCollection
Comme toutes les erreurs sont gérées comme des exceptions dans la classe TAdoDbxException de AdoDbx Client, ces classes
ne sont donc pas nécessaires.

BdpException, BdpParameter et BdpParameterCollection


Ces classes sont des implémentations des classes ADO.NET. Ces classes sont également implémentées dans AdoDbx Client.
La plupart du code source utilisant ces classes devrait être converti en AdoDbx Client avec un effort minimal.

La conversion des classes BDP de ce groupe est plutôt simple. Consultez la documentation pour voir si la méthode utilisée est
prise en charge dans la classe AdoDbx Client correspondante. Si elle l'est, vous n'avez probablement rien à faire. Si la méthode
n'est pas prise en charge, vous devez alors modifier votre code afin d'utiliser les méthodes prises en charge dans AdoDbx Client
ou ADO.NET lui-même.

Le tableau suivant présente la correspondance entre les classes ADO.NET, BDP et AdoDbx Client :

ADO.NET BDP.NET Client AdoDbx


DbException BdpException TAdoDbxException
DbParameter BdpParameter TAdoDbxParameter
DbParameterCollection BdpParameterCollection TAdoDbxParameterCollection

DbResolver
DbResolver est une implémentation de l'interface ISQLResolver de l'espace de nommage Borland.Data.Schema, décrite plus
loin dans cette rubrique.

ISQLCommand, IAQLConnection et ISQLCursor


Ces interfaces sont principalement utilisées par les concepteurs de pilotes et il n'y a pas d'équivalent AdoDbx Client. Vous
devrez réécrire le pilote à l'aide du framework dbExpress.

Migration Borland.Data.Schema
Cet espace de nommage contient cinq interfaces.

ISQLDataSource
La méthode GetProviders renvoie une liste des fournisseurs de données. Une capacité similaire est fournie par
TAdoDbxProviderFactory.CreateDataSourceEnumerator, qui crée un énumérateur pour tous les fournisseurs. Il n'y a pas
d'analogie pour les méthodes GetConnections et GetDbObjectTypes dans AdoDbx Client.

ISQLExtendedMetaData et ISQLMetaData
Utilisez la méthode GetSchema de TAdoDbxConnection pour obtenir une collection de métadonnées. Le paramètre Name de
GetSchema spécifie le type de métadonnée à obtenir. Les noms standard supportés par DbConnection.GetSchema sont pris en

28
1.2 Développement d'applications de RAD Studio Présentation de la migration BDP

charge dans AdoDbx Client.

En outre, vous pouvez spécifier une des constantes de nom dans TDBXMetaDataCollectionName pour obtenir une collection de
métadonnées particulière. Vous pouvez ensuite utiliser la classe correspondante dans l'espace de nommage
DBXMetaDataNames pour obtenir les informations de colonne que vous voulez pour cette collection de métadonnées.

Par exemple, pour obtenir le code source de procédure d'une base de données, utilisez la constante ProcedureSources pour
obtenir un DataTable avec les informations de source de procédure. Utilisez les classes TDBXProcedureSourcesColumns et
TDBXProcedureSourcesIndex de DBXMetaDataNames avec le DataTable renvoyé pour accéder aux informations de source de
procédure par nom ou ordinal.
1

ISQLResolver
Cette classe résout les commandes SQL.

L'analogie la plus proche est la classe TAdoDbxDataAdapter pour les méthodes ISQLResolver. Ce tableau présente les
propriétés qui correspondent aux méthodes.

ISQLResolver TAdoDbxDataAdapter
Méthode GetDeleteSQL Propriété DeleteCommand
Méthode GetInsertSQL Propriété InsertCommand
GetSelectSQL Propriété SelectCommand
GetUpdateSQL Propriété UpdateCommand

Pour les propriétés ISQLResolver, les analogies les plus proches sont les propriétés que TAdoDbxCommandBuilder hérite de la
classe ADO.NET DbCommandBuilder et une propriété TAdoDbxDataReader.

ISQLResolver Client AdoDbx


Propriété QuotePrefix Propriété TAdoDbxCommandBuilder.QuotePrefix
Propriété QuoteSuffix Propriété TAdoDbxCommandBuilder.QuoteSuffix
Propriété Row Propriété TAdoDbxDataReader.Item

ISQLSchemaCreate
Cette interface vous permet de créer un schéma de base de données dans votre propre fournisseur. Le client AdoDbx n'offre
pas cette capacité.

Voir aussi
Présentation de ADO.NET

Guide ADO.NET du développeur .NET Framework (MSDN)

TAdoDbxCommand

TAdoDbxCommandBuilder

TAdoDbxConnection

TAdoDbxDataAdapter

TAdoDbxDataReader

TAdoDbxException

TAdoDbxParameter

29
Concepteurs de composants ADO.NET RAD Studio 1.2 Développement d'applications de

TAdoDbxParameterCollection

TAdoDbxProviderFactory

TAdoDbxTransaction

TDBXMetaDataCollectionName

1
1.2.7 Concepteurs de composants ADO.NET
Presque toutes les applications distribuées se ramènent à lire et actualiser des informations dans des bases de données. Les
applications que vous développez en utilisant ADO.NET ont des exigences différentes pour manipuler les données. Vous
pouvez, par exemple, développer une application qui affiche simplement des données dans une fiche. Ou vous pouvez
développer une application qui propose le moyen de partager des informations avec une autre entreprise. Dans tous les cas,
vous devez comprendre certains concepts fondamentaux sur l'approche des données dans ADO.NET.

En utilisant ces concepteurs, vous pouvez travailler efficacement pour lire, exposer et modifier des données par l'intermédiaire
d'objets de schémas propres au serveur de base de données comme les tables, les vues et les index. Ces concepteurs vous
permettent d'utiliser ces objets de schéma pour vous connecter à différentes bases de données courantes et d'effectuer des
opérations de bases de données d'une manière cohérente et fiable.

Cette rubrique comprend :

• Relations de concepteur de composant


• Editeur de connexions
• Editeur de texte de commande
• Boîte de dialogue Procédure stockée
• Génération d'ensembles de données
• Configuration d'adaptateur de données
• Explorateur de données
Relations de concepteur de composant
ANCIENNE IMAGE

NOUVELLE IMAGE

Les principaux éléments des concepteurs de composants de bases de données sont les suivants :

• L'éditeur de connexion permet de définir une connexion dynamique à une source de données
• La fenêtre Editeur de texte de commande permet de construire du texte de commande pour des composants de
commandes.

30
1.2 Développement d'applications de RAD Studio Concepteurs de composants ADO.NET

• La boîte de dialogue de configuration de l'adaptateur de données permet de configurer des commandes pour un
adaptateur de données.
• La boîte de dialogue Procédure stockée permet de visualiser et d'indiquer des valeurs pour les paramètres Input ou
InputOutput à utiliser avec les composants de commandes.
• La boîte de dialogue de génération d'un ensemble de données est utilisée pour construire des ensembles de données
personnalisés.
• L'explorateur de données vous permet de parcourir les objets de schémas spécifiques aux serveurs de bases de données
et d'utiliser le glisser-déplacer pour remplir automatiquement de données une source de données de votre projet Delphi pour 1
.NET.
Editeur de connexions
L'éditeur de connexion gère les chaînes de connexion et les options de connexion propres aux bases de données. Au moyen
de l'éditeur de connexions, vous pouvez ajouter, retirer, supprimer, renommer et tester vos connexions de bases de données.
Les modifications apportées aux informations de connexion sont enregistrées dans le fichier ADoDbxConnections.xml, où
elles sont accessibles dès que vous devez créer un nouvel objet de connexion. Lorsque vous avez choisi une connexion
particulière, l'éditeur de connexions génère la chaîne de connexion ainsi que toutes les options de connexion, puis les affecte
respectivement aux propriétés ConnectionString et ConnectionOptions.

Affichez la boîte de dialogue Editeur de connexions en faisant glisser le composant TAdoDbxConnection de la palette d'outils
vers la fiche, puis en cliquant sur le verbe du concepteur de composants dans le bas de l'inspecteur d'objets.

Editeur de texte de commande


L'éditeur de texte de commande peut être utilisé pour construire le texte de commande pour les composants commande qui
possèdent une propriété CommandText. Un contrôle d'édition multiligne de l'éditeur vous permet d'éditer manuellement la
commande ou de construire le texte de la commande en sélectionnant des tables ou des colonnes. Affichez la boîte de dialogue
Editeur de texte de commande en faisant glisser le composant TAdoDbxCommand de la palette d'outils vers la fiche, puis en
cliquant sur le verbe du concepteur dans le bas de l'inspecteur d'objets.

L'éditeur de texte de commande est une version simplifiée d'un concepteur SQL capable de générer du code SQL pour une
table unique. Les objets de bases de données sont filtrés par la propriété SchemaName définie dans ISQLSchemaCreate et
seules les tables faisant partie de ce schéma sont utilisées. Si aucune propriété SchemaName n'est listée, tous les objets
disponibles pour l'utilisateur de la connexion en cours sont listés. Le paramètre QuoteObjects de la propriété ConnectionOptions
détermine si les objets sont délimités par le caractère guillemet spécifique aux bases de données. Par exemple, ceci est
important lors de la récupération de tables à partir de bases de données qui autorisent les espaces dans les noms de tables.

Pour remplir les boîtes listes Tables et Colonnes avec des éléments ou construire des instructions SQL, vous devez avoir défini
une connexion TAdoDbxConnection active. Sinon, les données ne sont pas récupérables. L'éditeur de texte de commande
vous permet de choisir des noms de colonne et de table dans la liste des colonnes et des tables disponibles. A l'aide de ces
informations, l'éditeur génère une instruction SQL. Pour générer l'instruction SQL, l'éditeur utilise une instance de la classe
TAdoDbxCommandBuilder. Lorsque vous demandez le SQL optimisé, l'éditeur utilise les informations d'index pour générer la
clause WHERE pour les instructions SELECT, UPDATE et DELETE ; sinon, la clause WHERE est constituée par les colonnes
non BLOB et les colonnes autorisant les recherches.

Lorsque l'instruction SQL est générée, la propriété TAdoDbxCommand. CommandText est définie sur l'instruction SQL générée.

Boîte de dialogue Procédure stockée


La boîte de dialogue Procédure stockée est utilisée pour visualiser et entrer des paramètres Input et InputOutput pour une
procédure stockée et pour exécuter cette procédure. Affichez la boîte de dialogue Procédure stockée en faisant glisser un
composant TAdoDbxCommand de la palette d'outils vers la fiche, en réglant la propriété CommandType du composant
TAdoDbxCommand sur StoredProcedure, puis en cliquant sur le verbe du concepteur Editeur de texte de commande dans la
partie inférieure de l'inspecteur d'objet.

La boîte de dialogue Procédure stockée vous permet de sélectionner une procédure stockée à partir d'une liste des procédures

31
Concepteurs de composants ADO.NET RAD Studio 1.2 Développement d'applications de

stockées disponibles, qui est déterminée par le TAdoDbxConnection spécifié dans la propriété Connection pour le composant
TAdoDbxCommand. Lorsque vous sélectionnez une procédure stockée, la boîte de dialogue affiche les paramètres associés à
la procédure stockée et les métadonnées des paramètres pour le paramètre sélectionné. Vous pouvez spécifier des valeurs
pour les paramètres Input ou InputOutput et exécuter la procédure stockée. Si la procédure stockée renvoie des résultats,
comme des paramètres Output, des paramètres InputOutput, des valeurs de retour, un (ou plusieurs) curseur(s) de retour, ils
sont tous remplis dans un DataGrid en bas de la boîte de dialogue lorsque la procédure stockée est exécutée. Après
l'initialisation des propriétés CommandText et Parameters pour TAdoDbxCommand, la procédure stockée peut être exécutée
lors de l'exécution au moyen d'un seul appel à la méthode ExecuteReader or ExecuteNonQuery.
1
Génération d'ensembles de données
Le concepteur Génération d'un ensemble de données est utilisé pour construire un ensemble de données. L'utilisation de cet
outil a pour résultat un typage strict, un code plus clair et la possibilité d'utiliser l'achèvement de code. Un ensemble de données
dérive d'abord de la classe de base DataSet puis utilise les informations d'un fichier schéma XML (un fichier .xsd) pour générer
une nouvelle classe. Les informations du schéma (tables, colonnes, etc.) sont générées et compilées dans cette nouvelle classe
dataset comme un ensemble de propriétés et d'objets "first-class". Affichez cette boîte de dialogue en faisant glisser un
composant TAdoDbxDataAdapter de la palette d'outils vers la fiche, puis en cliquant sur le verbe du concepteur de composants
dans le bas de l'inspecteur d'objet. Si ce composant n'est pas affiché, choisissez Composants Composants .NET installés
pour l'ajouter à la palette d'outils.

Configuration d'adaptateur de données


Le concepteur de configuration de l'adaptateur de données est utilisé pour générer les instructions SQL SELECT, INSERT,
UPDATE et DELETE. Après une génération SQL réussie, le concepteur Configuration de l'adaptateur de données crée de
nouveaux objets TAdoDbxCommand et les ajoute aux propriétés TAdoDbxDataAdapterSelectCommand, DeleteCommand,
InsertCommand et UpdateCommand.

Après une génération réussie d'une instruction SELECT de SQL, vous pouvez prévisualiser les données et générer un nouveau
DataSet. Vous pouvez également utiliser un DataSet existant pour remplir un nouveau DataTable. Si vous créez un nouveau
DataSet, il sera ajouté automatiquement à l'hôte du concepteur. Vous pouvez également générer des DataSet typés.

Les adaptateurs de données font partie intégrante des fournisseurs ADO.NET managés. Essentiellement, les adaptateurs sont
utilisés pour échanger des données entre une source de données et un ensemble de données. Cela veut dire lire les données
depuis une base de données dans un ensemble de données, et écrire dans la base de données les données modifiées dans
l'ensemble de données. Un adaptateur de données peut déplacer les données entre toute source et un ensemble de données.
Affichez la boîte de dialogue de configuration de l'adaptateur de données en faisant glisser un composant
TAdoDbxDataAdapter de la palette d'outils vers la fiche, puis en cliquant sur le verbe du concepteur de composants dans le
bas de l'inspecteur d'objets.

Explorateur de données
L'explorateur de données est un navigateur de base de données hiérarchique et un outil d'édition. L'explorateur de données
est intégré dans l'EDI et peut également être exécuté comme un exécutable autonome. Pour accéder à l'explorateur de
données de l'EDI, choisissez Voir Explorateur de données. Utilisez les menus contextuels de l'explorateur de données
pour effectuer les tâches suivantes :

• Gérer les connexions de base de données — ajouter une nouvelle connexion, modifier, supprimer ou renommer vos
connexions existantes
• Parcourir la structure de la base de données et les données, étendre et ouvrir les noeuds des fournisseurs pour parcourir les
objets de schémas propres aux serveurs de bases de données, notamment les tables, les vues, les définitions de procédures
stockées et les index
• Ajouter et modifier des tables — spécifier la structure des données pour une nouvelle table, ajouter ou supprimer des
colonnes et modifier les informations de colonnes pour une table existante
• Visualiser et tester les paramètres de procédures stockées — spécifier les valeurs pour les paramètres Input ou InputOutput
et exécuter la procédure stockée sélectionnée

32
1.2 Développement d'applications de RAD Studio Déploiement d'applications de bases de

• Migrer des données — migrer le schéma des tables et les données d'une ou plusieurs tables d'un fournisseur vers un autre
• Glisser et déplacer des objets de schémas sur des fiches pour simplifier le développement des applications, glisser des tables
ou des procédures stockées sur la fiche de votre application pour le .NET Framework afin d'ajouter des composants de
connexion et de générer automatiquement des chaînes de connexion
L'explorateur de données fournit une connectivité à plusieurs bases de données standard et peut être étendu pour se
connecter à d'autres bases de données courantes. L'explorateur de données utilise l'interface ISQLDataSource pour obtenir
la liste des fournisseurs disponibles, des connexions de bases de données et des objets schéma qui sont pris en charge par
les divers fournisseurs. La liste des fournisseurs disponibles est persistante dans le fichier TAdoDbxDataSources.xml et
les connexions disponibles sont persistantes dans le fichier TAdoDbxConnections.xml. Lorsque vous avez choisi un 1
fournisseur, l'interface ISQLMetadata est utilisée pour récupérer les métadonnées et afficher une vue arborescente en lecture
seule des objets de bases de données. L'implémentation en cours fournit une liste des tables, vues et procédures stockées
pour toutes les bases de données prises en charge par AdoDbx Client.
L'explorateur de données vous permet de créer de nouvelles tables, de modifier ou déplacer des tables existantes, de migrer
des données à partir de plusieurs tables d'un fournisseur vers un autre et de copier et coller des tables individuelles dans les
bases de données ADO prises en charge. Pour toutes ces opérations, l'explorateur de données appelle l'implémentation
ISQLSchemaCreate du fournisseur.
De plus, l'explorateur de données peut être utilisé pour faire glisser des données depuis une source de données vers n'importe
quel projet RAD Studio pour le .NET Framework. Faire glisser une table sur une fiche ajoute les composants
TAdoDbxConnection et TAdoDbxDataAdapter à votre application et configure automatiquement le TAdoDbxDataAdapter pour
la table donnée. Faire glisser une procédure stockée sur une fiche ajoute les composants TAdoDbxConnection et
TAdoDbxCommand à votre application, et affecte la valeur StoredProcedure à la propriété CommandType de l'objet
TAdoDbxCommand.
Voir aussi
Présentation de ADO.NET

Types de données AdoDbx.NET

Utilisation du concepteur de texte de commande

Utilisation du concepteur éditeur de connexion

Utilisation du concepteur adaptateur de données

Utilisation de la prévisualisation d'adaptateur de données

Utilisation du concepteur d'ensemble de données

Migration de données entre des bases de données

Création de mappages de tables

1.2.8 Déploiement d'applications de bases de données pour


le .NET Framework
Pour déployer des applications de bases de données avec RAD Studio, copiez les assemblages d'exécution et les DLL de
pilotes pour le déploiement à un emplacement spécifié. Les sections suivantes indiquent le nom des assemblages et des DLL et
l'emplacement où chacun doit être placé.

Déploiement des applications ADO.NET 2.0


Pour de plus amples informations, voir le fichier source Borland.Data.AdoDbxClientProvider.pas.

Déploiement d'applications BDP.NET


Copiez les assemblages d'exécution de bases de données spécifiques à l'emplacement suivant :

33
Déploiement d'applications de bases de RAD Studio 1.2 Développement d'applications de

Assemblages managés Fournisseur de données Emplacement


Borland.Data.Common.dll Tous GAC
Borland.Data.Provider.dll Tous GAC
Borland.Data.DB2.dll DB2 GAC
Borland.Data.Interbase.dll Interbase GAC

1 Borland.Data.Mssql.dll MS SQL/MSDE GAC


Borland.Data.Oracle.dll Oracle GAC
Borland.Data.Msacc.dll MS Access GAC
Borland.Data.Sybase.dll Sybase GAC

Remarque: Si vous déployez une application de base de données distribuée utilisant les composants distants BDP.NET, tels
que DataHub, DataSync, RemoteConnection et RemoteServer, vous devez installer Borland.Data.DataSync.dll

dans le GAC. Copiez les DLL des pilotes de bases de données non managées à l'emplacement suivant :

DLL Fournisseur de données Emplacement


bdpint20.dll Interbase chemin de recherche
bdpdb220.dll DB2 chemin de recherche
bdpmss20.dll MS SQL/MSDE chemin de recherche
bdpora20.dll Oracle chemin de recherche
bdpmsa20.dll MS Access chemin de recherche
bdpsyb20.dll Sybase chemin de recherche

Déploiement d'applications dbExpress pour .NET


Copiez les assemblages d'exécution de bases de données spécifiques à l'emplacement suivant :

Assemblages managés Fournisseur de données Emplacement


Borland.VclDbExpress.dll Tous GAC
Borland.VclDbCtrls.dll Tous GAC
Borland.VclDbxCds.dll Requis par les applications de bases de données qui GAC
utilisent des ensembles de données client
Borland.Common.Driver.dll Tous GAC

Vous pouvez déployer les pilotes dbExpress.NET et les DLL associés avec votre exécutable. Copiez les DLL des pilotes de
bases de données non managées à l'emplacement suivant :

DLL Fournisseur de données Emplacement


dbxINT30.dll InterBase 2007, 7.5.1, 7.1*, 7.0*, 6.5* chemin de recherche
dbxASA30.dll Adaptive Sybase Anywhere 9, 8* chemin de recherche
dbxDB230.dll DB2 UDB 8.x, 7.x* chemin de recherche
dbxINF30.dll Informix 9.x chemin de recherche
dbxMSS30.dll MSSQL 2005, 2000 chemin de recherche
dbxMYSA30.dll MySQL 4.0.24 chemin de recherche
dbxMYS30.dll MySQL 5.0.27, 4.1.22* chemin de recherche

34
1.2 Développement d'applications de RAD Studio Framework dbExpress

dbxora30.dll Oracle 10g, 9.2.0*, 9.1.0* chemin de recherche


dbxASE30.dll Sybase 12.5 chemin de recherche
Midas.dll Requis par les applications de bases de données qui chemin de recherche
utilisent des ensembles de données client

Remarque: * Le pilote n'est pas totalement certifié pour cette version de la base de données.

Déploiement d'applications dbGo pour .NET 1


Il n'est pas nécessaire de déployer des assemblages d'exécution ou des pilotes de base de données pour les composants dbGo
utilisés dans des applications VCL.NET. Microsoft Data Access Components (MDAC) version 2.1 ou une version ultérieure est
nécessaire pour exécuter des applications avec des composants dbGo en dehors de l'EDI. Cela s'applique aux applications VCL
Win32, ainsi qu'aux applications VCL.NET. RAD Studio prend en charge MDAC 2.8.

Déploiement d'applications BDE pour .NET


Durant son déploiement, vous devez inclure le BDE avec votre application. Bien que cela augmente la taille de l'application et la
complexité du déploiement, le BDE peut être partagé avec d'autres applications BDE et assurer un support plus large pour la
manipulation des bases de données. Même s'il est possible d'utiliser directement l'API du BDE dans votre application, les
composants de la section BDE de la palette d'outils regroupent la plupart de ces fonctionnalités.

Voir aussi
Présentation Borland du déploiement d'applications

Présentation Microsoft du déploiement d'applications

1.2.9 Framework dbExpress


Le framework dbExpress (framework DBX) est un ensemble de classes abstraites fournies dans l'unité DBXCommon. Les
applications peuvent s'interfacer avec le framework de différentes façons : en utilisant le framework directement pour les
applications natives et managées, et en utilisant les composants dbExpress VCL disposés en couches au sommet du framework
pour les applications natives et managées.

Bien que de nombreuses applications s'interfacent avec les pilotes dbExpress via les composants dbExpress VCL, le framework
DBX offre une option utile et légère pour communiquer avec un pilote de base de données. Vous pouvez également créer un
pilote de base de données pour dbExpress en étendant les classes de base abstraites DBXCommon du framework. Le
framework DBX fournit les fonctionnalités de pilote de base de données les plus courantes pour une application de base de
données orientée "ensemble", ainsi qu'une interface simple.

Voici quelques fonctionnalités clés du framework DBX :

• Le framework de pilote est écrit entièrement en langage Delphi et permet aux pilotes d'être écrits en Delphi.
• Il utilise l'accès aux données fortement typées au lieu des pointeurs. Par exemple, il utilise les types chaîne à la place des
pointeurs vers des chaînes.
• Le framework de pilote est à source unique. Cela signifie qu'une copie unique du source peut être compilée avec les
compilateurs DCC32 natif et DCCIL managés.
• Le framework a seulement des classes de base abstraites qui sont utilisées pour les pilotes, les connexions, les commandes,
les lecteurs, et ainsi de suite.
• Le framework utilise la gestion des erreurs basée sur les exceptions, plutôt que le renvoi de codes d'erreur.
Capacités
IL existe deux catégories de pilotes qui étendent les classes dans DBXCommon : DBXDynaLink et DBXDirect. Ces pilotes

35
Framework dbExpress RAD Studio 1.2 Développement d'applications de

diffèrent les uns des autres dans la façon dont ils sont chargés et par les capacités qu'ils fournissent à une application. Ces
capacités sont détaillées par la suite.

Vous pouvez également étendre le framework DBX pour écrire des pilotes de délégation qui fournissent une couche
supplémentaire entre l'application et le pilote réel. Les pilotes délégués sont utiles pour le pooling de connexion, le profilage de
pilote, le traçage et l'audit. Une autre application possible de délégation de pilote est la création d'un délégué de pilote adapté
aux threads. Un tel délégué peut fournir un accès synchronisé de thread à toutes les méthodes publiques.

La sécurité de thread absolue est laissée aux applications utilisant dbExpress. Toutefois, certains problèmes de sécurité de
1 thread sont mieux gérés par le framework dbExpress. Les opérations de sécurité de thread dbExpress incluent le chargement et
le déchargement des pilotes, ainsi que la création de connexions. Comme mentionné plus tôt, un pilote délégué peut être créé
pour rendre l'interface publique entière de dbExpress adaptée aux threads si nécessaire.

Un pilote dbExpress 4 peut lier statiquement ou dynamiquement des pilotes construits en tant que packages Delphi. La meilleure
façon de lier un package de pilote est simplement de l'inclure la clause "uses". Le chargeur de pilote charge également les
packages spécifiés dans un fichier config ou ini à l'aide de la méthode LoadPackage. Cela permet un chargement dynamique
des pilotes qui ne sont jamais spécifiés dans une clause uses d'une des unités de l'application. Notez que l'approche
LoadPackage peut seulement être employée pour les applications construites pour utiliser des packages.

Les auteurs de pilotes dbExpress 4 doivent examiner les sections d'initialisation des unités DBXDynalink et DBXTrace dans le
code source fourni avec dbExpress. Ces sections se recensent elles-mêmes avec une unité singleton appelée le ClassRegistry.
Le ClassRegistry est utilisé par le chargeur de pilote dbExpress 4 pour instancier les classes chargeur de pilote par le nom (une
chaîne). Le ClassRegistry est un mécanisme léger et simple pour le recensement et l'instanciation d'une classe par le nom.

Pilotes DBXDynalink
DBXDynalink est utilisé pour les pilotes dbExpress 3 existants, ainsi que pour les nouveaux pilotes. Il est compilé comme un
package Delphi natif ou un assemblage .NET managé. DBXDynalink charge les pilotes dbExpress natifs qui implémentent une
interface "native" plus primitive appelée DBXExports. L'interface DBXExports est une petite collection de méthodes d'exportation
simples. Le source de DBXExports est inclus avec dbExpress. DBXExports fournit une API plus fortement typée que l'interface
COM de dbExpress 3. Cela permet l'ajout des méthodes dans les générations de produits futures sans casser la compatibilité
avec les anciennes implémentations de l'interface DBXExports.

DBXAdapter est un pilote compatible dbExpress 4 qui adapte l'interface DBXExports à l'ancienne interface COM dbExpress 3.
Les nouveaux pilotes natifs peuvent être écrits en implémentant directement DBXExports.

Puisque l'interface DBXExports a été conçue pour être implémentée au moyen d'un langage natif (Delphi ou C++), elle utilise
une gestion d'erreurs basée sur les exceptions plus primitive. DBXDynalink mappe les codes d'erreur en exception
DBXCommon.

L'unité DBXDynalink contient un pilote dbExpress 4. Ce pilote délègue les pilotes non-Delphi qui implémentent l'interface
d'exportation simple DBXDynalinkExport. DBXTrace est un pilote délégué utilisé pour le traçage. La bibliothèque VCL
DbExpress utilise DBXCommon, DBXDynalink et DbxTrace comme pilotes "par défaut". Toutefois, cela peut être changé pour
les applications liées statiquement sans modifier le code source dbExpress VCL (SQLExpr.pas). SQLExpr.pas utilise l'unité
DBXDefaultDrivers. L'unité DBXDefaultDrivers contient seulement une clause uses. La clause uses de DBXDefaultDrivers
contient DBXCommon, DBXDynalink et DBXTrace. DBXCommon doit toujours être utilisé. Toutefois, une application liée
statiquement peut retirer DBXTrace et remplacer DBXDynalink par un pilote différent.

Pilotes DBXDirect
Un pilote DBXDirect est un pilote implémenté en étendant les classes de base abstraites DBXCommon. Ces classes sont écrites
en Delphi pour les implémentations natives. Pour les implémentations managées, elles peuvent être écrites au moyen d'un
langage compatible CLR tel que Delphi, C# ou Visual Basic.NET.

Strictement parlant, tous les pilotes de framework DBX sont une forme de pilote DBXDirect. Toutefois, DBXDynalink et
DBXRemote fournissent une liaison plus "indirecte" aux implémentations de pilotes.

36
1.2 Développement d'applications de RAD Studio Compatibilité du framework dbExpress

Voir aussi
Compatibilité du framework de pilote de base de données dbExpress ( see page 37)

Déploiement d'applications de bases de données dbExpress ( see page 2007)

1.2.10 Compatibilité du framework dbExpress 1

Certains logiciels dbExpress développés avant le framework de pilote dbExpress (framework de pilote DBX) ont été modifiés
pour fonctionner avec le framework de pilote DBX. A cause de ces modifications, certains problèmes de compatibilité se
produisent.

Général
Les pilotes dbExpress 2.5 ne peuvent pas être utilisés avec le framework DBX.

Le framework dbExpress n'offre pas une compatibilité à 100% avec dbExpress 3.

Les pilotes dbExpress 3 peuvent être utilisés avec le framework DBX. Le chargeur du framework de pilote DBX détecte
automatiquement les pilotes dbExpress 3 et utilise le pilote DBXAdapter (dbxadapter30.dll) afin qu'un pilote dbExpress 3
ressemble à un pilote dbExpress 4.

Voici la liste des problèmes de compatibilité connus :

• Liaison de pilotes statique. Vous ne pouvez pas lier de façon statique des pilotes dbExpress dans un exécutable.
• SqlExpr.TSQLConnection fournissait un accès protégé au membre Connection qui était de type TISQLConnection seulement
dans la version native de SqlExpr.pas. Cela a été omis dans la version managée en raison de la complexité de l'utilisation de
PInvoke dans la version managée de la VCL dbExpress. SqlExpr.TSQLConnection fournit maintenant à la place un accès
protégé à un TDBXConnection. Cette connexion protégée est accessible aux applications natives et managées.
• L'événement du contrôle des traces est légèrement différent car il est basé sur le framework de pilote DBX.
• Le pilote DBXadapter peut adapter les pilotes dbExpress 3 à dbExpress 4, mais pas les pilotes dbExpress 2.5.
Problèmes VCL
La plupart des applications utilisant des composants VCL dbExpress devraient fonctionner sans modification. Toutefois, des
modifications localisées sont apportées aux composants VCL en raison de la VCL s'interfaçant maintenant sur le framework de
pilote DBX orienté objet au lieu de l'interface de pilote dbExpress 3 basée sur COM C-like.

En outre, l'API a été légèrement modifiée pour les deux composants VCL suivants : TSQLConnection et TSQLDataSet.
Certaines structures de données ont également été modifiées. Vous trouverez ci-après un résumé des changements de l'API.

Remarque: A cause des modifications apportées à l'API, vous devez recompiler SqlExpr.pas qui est livré avec le produit.
L'unité DBXpress a été dépréciée.

• TSQLConnection. La méthode Commit a été dépréciée en faveur de la nouvelle méthode CommitFreeAndNil. La méthode
Rollback a été dépréciée en faveur des nouvelles méthodes RollbackFreeAndNil et RollbackIncompleteFreeAndNil. La
méthode SetTraceCallbackEvent a été remplacée par SetTraceEvent. La méthode StartTransaction a été dépréciée en faveur
de la nouvelle méthode BeginTransaction. La propriété MetaData contient une instance de la nouvelle classe
TDBXDatabaseMetaData au lieu de TISQLMetaData. La propriété SQLConnection a été remplacée par DBXConnection, qui
contient une instance de la nouvelle classe TDBXConnection. La propriété TraceCallbackEvent contient maintenant un
TDBXTraceEvent.
• TSQLDataSet. La nouvelle propriété DbxCommandType a été ajoutée. Elle contient une des chaînes constante de la classe
TDBXCommandTypes.
• Structures de données. TTransactionItem a été dépréciée et remplacée par la nouvelle classe TDBXTransaction.
TSQLDriverOption, TSQLConnectionOption, TSQLCommandOption, TSQLCursorOption, TSQLMetaDataOption et
TSQLObjectType sont obsolètes. TSTMTParamType a été remplacée par la classe TDBXParameterDirections.

37
Compatibilité du framework dbExpress RAD Studio 1.2 Développement d'applications de

TSQLTraceFlag a été remplacée par TDBXTraceFlags. SQLTRACEDesc a été remplacée par TDBXTraceInfo.
Voir aussi
Framework dbExpress

Déploiement du framework dbExpress

38
1.3 Développement des applications RAD Studio Développement d'applications COM

1.3 Développement des applications


interopérables
RAD Studio fournit des experts et des classes qui facilitent l'implémentation d'applications basées sur le modèle COM
1
(Component Object Model) de Microsoft. Grâce à ces experts, vous pouvez créer des classes et des composants basés sur
COM que vous utiliserez dans des applications, ou vous pouvez créer des clients ou des serveurs COM complètement
fonctionnels qui implémentent des objets COM sophistiqués, des serveurs Automation (y compris, des objets Active Server), des
contrôles ActiveX ou des fiches ActiveForms.

Rubriques
Nom Description
Développement d'applications COM ( see page 39) Delphi fournit des experts et des classes qui facilitent l'implémentation
d'applications basées sur COM (Component Object Model) de Microsoft. Grâce à
ces experts, vous pouvez créer des classes et des composants basés sur COM
que vous utiliserez dans des applications, ou vous pouvez créer des clients et
des serveurs COM complètement fonctionnels qui implémentent des objets COM
sophistiqués, des serveurs Automation (y compris, des objets Active Server), des
contrôles ActiveX ou des fiches ActiveForms.
Cette rubrique aborde les thèmes suivants :

• Présentation des technologies COM


• Interfaces COM
• Serveurs COM
• Clients COM

1.3.1 Développement d'applications COM


Delphi fournit des experts et des classes qui facilitent l'implémentation d'applications basées sur COM (Component Object
Model) de Microsoft. Grâce à ces experts, vous pouvez créer des classes et des composants basés sur COM que vous utiliserez
dans des applications, ou vous pouvez créer des clients et des serveurs COM complètement fonctionnels qui implémentent des
objets COM sophistiqués, des serveurs Automation (y compris, des objets Active Server), des contrôles ActiveX ou des fiches
ActiveForms.

Cette rubrique aborde les thèmes suivants :

• Présentation des technologies COM


• Interfaces COM
• Serveurs COM
• Clients COM
Présentation des technologies COM
COM est un modèle de composant logiciel indépendant du langage qui permet l'interaction entre des composants logiciels et
des applications s'exécutant sous Windows. L'aspect le plus important de COM est de permettre la communication entre
composants, entre applications et entre clients et serveurs, par le biais d'interfaces clairement définies. Les interfaces offrent aux
clients un moyen de demander à un composant COM quelles fonctionnalités il supporte à l'exécution. Pour fournir d'autres
fonctionnalités à votre composant, il suffit d'ajouter une autre interface pour ces fonctionnalités.

39
Développement d'applications COM RAD Studio 1.3 Développement des applications

Les applications peuvent accéder aux interfaces des composants COM se trouvant sur le même ordinateur que l'application ou
sur un autre ordinateur du réseau, en utilisant un mécanisme nommé DCOM (Distributed COM).

COM est à la fois une spécification et une implémentation. La spécification COM définit comment des objets sont créés et
comment ils communiquent entre eux. Selon cette spécification, les objets COM peuvent être écrits dans différents langages,
exécutés dans différents espaces de processus et sur différentes plates-formes. Tant que les objets se conforment à la
spécification, ils peuvent communiquer. Cela vous permet d'intégrer le code de composants existants à de nouveaux
composants implémentés dans des langages orientés objet.
1 L'implémentation COM est construite dans le sous-système Win32, qui fournit de nombreux services intégrés supportant la
spécification. La bibliothèque COM contient un ensemble d'interfaces standard définissant la fonctionnalité interne d'un objet
COM et un petit ensemble de fonctions API pour la création et la gestion des objets COM.

Lorsque vous utilisez dans votre application les experts de Delphi et les objets de la VCL, vous utilisez l'implémentation Delphi
de la spécification COM. En outre, Delphi fournit quelques enveloppes pour les services COM dont les fonctionnalités ne sont
pas implémentées directement, comme les documents Active. Ces enveloppes sont définies dans l'unité ComObj, et les
définitions d'API se trouvent dans l'unité AxCtrls.

Remarque: Les objets et les langages des interfaces Delphi sont conformes à la spécification COM. L'implémentation Delphi de
la spécification COM utilise un ensemble de classes appelé cadre de travail Delphi ActiveX (DAX). Ces classes se trouvent dans
les unités AxCtrls, OleCtrls et OleServer. En outre, l'interface Delphi avec l'API COM se trouve dans ActiveX.pas et
ComSvcs.pas.

Interfaces COM
Les clients COM communiquent avec des objets par le biais d'interfaces COM. Les interfaces sont des groupes de routines,
liées par la logique ou par la sémantique, qui assurent la communication entre le fournisseur d'un service (objet serveur) et ses
clients.

Par exemple, tout objet COM doit implémenter l'interface de base, IUnknown. Via une routine appelée QueryInterface de
IUnknown, les clients peut demander les autres interfaces implémentées par le serveur.

Les objets peuvent avoir plusieurs interfaces, où chacune implémente une fonctionnalité. L'interface est le moyen d'indiquer au
client le service fourni par l'objet, sans lui donner les détails de l'implémentation sur la façon dont ce service est fourni.

Les aspects majeurs des interfaces COM sont les suivants :

• Une fois publiées, les interfaces ne changent pas. Une interface permet d'accéder à un ensemble précis de fonctions. Les
fonctionnalités supplémentaires sont fournies par le biais d'interfaces supplémentaires.
• Par convention, les identificateurs d'interfaces COM commencent par un I majuscule suivi d'un nom symbolique définissant
l'interface, comme IMalloc ou IPersist.
• L'identification unique des interfaces est garantie par un GUID (Globally Unique Identifier), qui est un nombre aléatoire de
128 bits. Les GUID utilisés pour identifier les interfaces sont appelés IID (Identificateurs d'interfaces). Ils permettent d'éliminer
les conflits de noms entre différentes versions d'un produit ou différents produits.
• Les interfaces sont indépendantes du langage. Vous pouvez utiliser n'importe quel langage pour implémenter une interface
COM, à condition que ce langage supporte les structures de pointeurs et puisse appeler une fonction via un pointeur, de
façon explicite ou implicite.
• Les interfaces ne sont pas elles-mêmes des objets ; elles fournissent l'accès à un objet. Donc, les clients n'ont pas accès
directement aux données ; ils accèdent aux données par le biais d'un pointeur d'interface. Windows 2000 ajoute une autre
couche d'indirection, connue sous le nom d'intercepteur, à partir duquel il fournit des fonctionnalités COM+ telles que
l'activation just-in-time et le regroupement d'objets.
• Les interfaces sont toujours héritées de l'interface de base, IUnknown.
• Les interfaces peuvent être redirigées par COM via des proxy pour permettre aux appels de méthodes de l'interface de
s'effectuer entre différents threads, processus et machines en réseau, sans que les objets client ou serveur ne soient jamais
informés de la redirection.

40
1.3 Développement des applications RAD Studio Développement d'applications COM

L'interface IUnknown
Les objets COM doivent tous supporter l'interface fondamentale, appelée IUnknown qui représente un typedef sur le type
d'interface de base IInterface. IUnknown contient les routines suivantes :

• QueryInterface : Fournit des pointeurs sur d'autres interfaces supportées par l'objet.
• AddRef et Release : Méthodes simples de décompte de références qui permettent à un objet de contrôler sa durée de vie et
de se supprimer lui-même lorsque le client n'a plus besoin de son service.
1
Les clients obtiennent des pointeurs sur d'autres interfaces via la méthode QueryInterface de IUnknown. QueryInterface
connaît chaque interface de l'objet serveur et peut donner au client un pointeur vers l'interface demandée. Lorsqu'il reçoit un
pointeur vers une interface, le client est assuré de pouvoir appeler n'importe quelle méthode de l'interface.
Les objets contrôlent leur propre durée de vie grâce aux méthodes AddRef et Release de IUnknown, qui sont de simples
méthodes de décompte de références. Tant que le décompte de références d'un objet est différent de zéro, l'objet reste en
mémoire. Dès qu'il atteint zéro, l'implémentation de l'interface peut en toute sécurité disposer des objets sous-jacents.

Pointeurs d'interface COM


Un pointeur d'interface est un pointeur vers une instance d'objet qui pointe, à son tour, vers l'implémentation de chaque méthode
de l'interface. L'implémentation est accédée via un tableau de pointeurs vers ces méthodes, appelé vtable. Les vtables sont
similaires au mécanisme utilisé pour gérer les fonctions virtuelles sous Delphi. A cause de cette similitude, le compilateur peut
résoudre les appels de méthode de l'interface de la même manière qu'il résout les appels des méthodes de classes Delphi.

La vtable est partagée par toutes les instances d'une classe objet, et pour chaque instance de l'objet, le code de l'objet alloue
une deuxième structure contenant ses données privées. Le pointeur d'interface du client est alors un pointeur sur le pointeur sur
la vtable.

Dans Windows 2000 et toutes les versions ultérieures de Windows, quand un objet s'exécute sous COM+, un autre niveau
d'indirection est fourni entre le pointeur d'interface et le pointeur vtable. Le pointeur d'interface disponible sur le client pointe sur
un intercepteur, qui à son tour pointe sur la vtable. Cela permet à COM+ de fournir des services comme l'activation just-in-time,
par lequel le serveur peut être désactivé et réactivé dynamiquement d'une façon opaque pour le client. COM+ garantit que
l'intercepteur se comporte comme s'il était un pointeur vtable ordinaire.

Serveurs COM
Un serveur COM est une application ou une bibliothèque qui fournit des services à une application ou bibliothèque client. Un
serveur COM est constitué d'un ou de plusieurs objets COM, un objet COM étant un ensemble de propriétés (données membre
ou contenu) et de méthodes (fonctions membre).

Les clients ne savent pas comment l'objet COM effectue son service ; l'implémentation de l'objet reste cachée. Un objet met ses
services à disposition par le biais de ses interfaces comme décrit précédemment.

En outre, les clients n'ont pas besoin de savoir où réside l'objet COM. COM offre un accès transparent, quel que soit
l'emplacement de l'objet.

Quand il demande un service à un objet COM, le client transmet un identificateur de classe (CLSID) à COM. Un CLSID est juste
un GUID qui référence un objet COM. COM utilise ce CLSID, recensé dans le registre système, pour localiser l'implémentation
appropriée du serveur. Une fois le serveur localisé, COM amène le code en mémoire, et fait créer par le serveur une instance de
l'objet pour le client. Ce processus est géré indirectement par un objet spécial appelé une factory (basé sur les interfaces) qui
crée sur demande des instances d'objet.

Au minimum, un serveur COM doit effectuer ceci :

• Recenser des entrées dans le registre système pour associer le module serveur à l'identificateur de classe (CLSID).
• Implémenter un objet factory de classe, qui crée un autre objet à partir d'un CLSID particulier.
• Exposer la factory d'objet à COM.
• Fournir un mécanisme de déchargement grâce auquel un serveur qui ne sert pas de client pourra être supprimé de la

41
Développement d'applications COM RAD Studio 1.3 Développement des applications

mémoire.
Clients COM
Les clients COM sont des applications qui utilisent un objet COM implémenté par une autre application ou bibliothèque. Les
types les plus courants sont les contrôleurs Automation, qui contrôlent un serveur Automation et les conteneurs ActiveX, qui
accueillent un contrôle ActiveX.

Il y a deux types de clients COM : les contrôleurs et les conteneurs. Un contrôleur lance le serveur et interagit avec lui via son
interface. Il demande des services de l'objet COM ou il le pilote comme processus distinct. Les conteneurs accueillent des
1
contrôles visuels ou des objets qui apparaissent dans l'interface utilisateur du conteneur. Ils utilisent des interfaces prédéfinies
pour négocier les problèmes d'affichage avec les objets serveur. Il est impossible d'avoir une relation conteneur sur DCOM ; par
exemple, les contrôles visuels qui apparaissent dans l'interface utilisateur du conteneur doivent être localisés localement. En
effet, les contrôles sont supposés se dessiner eux-mêmes, ce qui nécessite qu'ils puissent accéder aux ressources GDI locales.

La réalisation de ces deux types de clients COM est étonnamment similaire : l'application client obtient une interface pour l'objet
serveur et en utilise les propriétés et méthodes. Delphi facilite le développement d'un contrôleur Automation en permettant
d'importer la bibliothèque de types ou un contrôle ActiveX dans un composant enveloppe de telle manière que les objets serveur
apparaissent comme les autres composants VCL. Delphi vous permet d'envelopper la CoClasse serveur dans un composant
du client que vous pouvez même installer sur la palette des composants. Vous trouverez des exemples de ces enveloppes de
composants sur deux pages de la palette des composants, des exemples d'enveloppes ActiveX sur la page ActiveX et des
exemples d'objets Automation sur la page Serveurs.

Même si vous ne choisissez pas d'envelopper un objet serveur et de l'installer dans la palette des composants, vous devez
rendre sa définition d'interface accessible à votre application. Pour ce faire, vous pouvez importer les informations de la
bibliothèque de types du serveur.

Les clients peuvent toujours interroger les interfaces d'un objet COM pour déterminer ce qu'il est capable de faire. Tous les
objets COM permettent aux clients de demander les interfaces connues. De plus, si le serveur gère l'interface IDispatch, les
clients peuvent demander au serveur des informations sur les méthodes gérées par le serveur. Les objets serveurs n'ont pas
d'attentes concernant l'utilisation de ses objets par le client. De même, les clients n'ont pas besoin de savoir comment un objet
fournit les services ; ils s'en remettent simplement sur les objets serveurs pour fournir les services qu'ils décrivent dans leurs
interfaces.

Extensions de COM
COM a évolué et a été étendu au-delà des services COM de base. COM sert de fondement à d'autres technologies, comme
l'Automation, les contrôles ActiveX, les documents Active et les annuaires Active. En outre, si vous travaillez dans un
environnement distribué important, vous pouvez créer des objets COM transactionnels. Avant Windows 2000, ces objets ne
faisaient pas partie de COM, mais s'exécutaient dans l'environnement Microsoft Transaction Server (MTS). Avec l'arrivée de
Windows 2000, cette gestion est intégrée dans COM+. Delphi fournit des experts permettant d'implémenter facilement des
applications qui utilisent toutes ces technologies dans l'environnement Delphi.

Serveurs Automation
L'Automation désigne la capacité d'une application à contrôler par programme les objets d'une autre application, comme une
macro qui peut manipuler plusieurs applications à la fois. Le client d'un objet Automation est appelé contrôleur Automation, et
l'objet serveur manipulé est appelé objet Automation. L'Automation peut être utilisée sur des serveurs en processus, locaux ou
distants.

L'Automation présente deux caractéristiques principales :

• L'objet Automation définit un ensemble de propriétés et de commandes, et décrit ses capacités via les descriptions de type.
Pour ce faire, il doit disposer d'un moyen de fournir des informations sur les interfaces de l'objet, les méthodes des interfaces
et les arguments de ces méthodes. Généralement, ces informations se trouvent dans des bibliothèques de types. Le serveur
Automation peut aussi générer dynamiquement des informations de types lorsqu'elles lui sont demandées via son interface
IDispatch.
• Les objets Automation rendent ces méthodes accessibles pour que d'autres applications puissent les utiliser. Pour cela, ils

42
1.3 Développement des applications RAD Studio Développement d'applications COM

implémentent l'interface IDispatch. C'est par le biais de cette interface qu'un objet peut exposer toutes ses méthodes et
propriétés. Et c'est par le biais de la méthode primaire de cette interface que les méthodes de l'objet peuvent être appelées,
une fois qu'elles ont été identifiées grâce aux informations de type.
Les développeurs utilisent souvent l'Automation pour créer et utiliser des objets OLE non visuels qui s'exécutent dans n'importe
quel espace processus, car l'interface Automation IDispatch automatise le processus de marshaling. En revanche,
l'Automation limite les types que vous pouvez utiliser.

Contrôles Active X
Les experts de Delphi facilitent la création des contrôles ActiveX. ActiveX est une technologie qui permet aux composants COM, 1
particulièrement aux contrôles, d'être plus compacts et efficaces. Cela est particulièrement important pour les contrôles conçus
pour des applications Intranet qui nécessitent leur téléchargement par le client avant de les utiliser.

Les contrôles ActiveX sont des contrôles visuels qui s'exécutent uniquement comme des serveurs en processus et qui peuvent
s'intégrer dans une application conteneur ActiveX. Ce ne sont pas des applications complètes par eux-mêmes, vous pouvez les
voir comme des contrôles OLE déjà écrits qui sont réutilisables dans diverses applications. Les contrôles ActiveX ont une
interface utilisateur apparente et reposent sur l'utilisation d'interfaces prédéfinies pour négocier les entrées/sorties et les
questions d'affichage avec le conteneur hôte.

Les contrôles ActiveX utilisent l'Automation pour exposer leurs propriétés, méthodes et événements. Leurs fonctionnalités
incluent la capacité à déclencher des événements, la liaison aux sources de données et la gestion de licence.

Les contrôles ActiveX s'utilisent parfois dans un site Web comme objets interactifs placés dans une page Web. Ainsi, ActiveX est
devenu un standard particulièrement destiné à des contenus interactifs pour le Web, y compris l'utilisation de documents ActiveX
employés pour visualiser des documents non HTML via un navigateur Web. Pour plus d'informations sur la technologie ActiveX,
voir le site Web de Microsoft.

Documents Active
Les Documents Active (préalablement appelés documents OLE) constituent un ensemble de services COM prenant en charge la
liaison et l'incorporation, le glisser-déplacer, ainsi que l'édition visuelle. Les documents Active intègrent de façon transparente
des données ou des objets de différents formats, par exemple des clips sonores, des feuilles de calcul, du texte et des images.

Au contraire des contrôles ActiveX, les Documents Active ne sont pas limités aux serveurs en processus; ils peuvent être utilisés
dans des applications inter-processus.

Au contraire des objets Automation, qui ne sont presque jamais visuels, les objets Document Active peuvent être visuellement
actifs dans une autre application. De ce fait, les objets Document Active sont associés à deux types de données : les données
de présentation, utilisées pour afficher visuellement l'objet sur un écran ou un autre périphérique de sortie, et les données
natives, utilisées pour modifier un objet.

Les objets document Active peuvent être des conteneurs ou des serveurs de documents. Bien que Delphi ne fournisse pas
d'expert pour créer automatiquement des documents Active, vous pouvez utiliser la classe TOleContainer de la VCL pour
supporter la liaison et l'incorporation dans les documents Active existants.

Vous pouvez aussi utiliser TOleContainer comme base d'un conteneur de document Active. Pour créer des objets pour les
serveurs de documents Active, utilisez une des classes de base COM de la VCL et implémentez les interfaces appropriées à ce
type d'objet, en fonction des services que l'objet doit gérer. Pour plus d'informations sur la création et l'utilisation de serveurs de
documents Active, voir le site Web Microsoft.

Remarque: Bien que la spécification des documents Active contienne une gestion intégrée du marshaling des applications à
processus croisé, les documents Active ne s'exécutent pas sur des serveurs distants car les types qu'ils utilisent (handles de
fenêtre, de menu, etc.) sont spécifiques à un système sur une machine donnée.

Objets transactionnels
Delphi utilise le terme "objets transactionnels" pour désigner des objets qui exploitent les services de transaction, la sécurité et la
gestion des ressources proposées par MTS (pour les versions de Windows antérieures à Windows 2000) ou COM+ (pour

43
Développement d'applications COM RAD Studio 1.3 Développement des applications

Windows 2000 et plus). Ces objets sont conçus pour travailler dans des environnements distribués importants.

Les services de transaction garantissent la fiabilité assurant que des activités sont toujours achevées ou annulées. Le serveur
ne s'arrête jamais en ayant fait la moitié d'une activité. Les services de sécurité vous permettent d'exposer différents niveaux de
services à différentes classes de clients. La gestion des ressources permet à un objet de répondre à davantage de clients en
regroupant les ressources et en ne gardant des objets actifs que s'ils sont utilisés. Pour permettre au système de proposer ces
services, l'objet doit implémenter l'interface IObjectControl. Pour accéder aux services, les objets transactionnels utilisent
une interface appelée IObjectContext qui est créée pour eux par MTS ou COM+.
1 Avec MTS, l'objet serveur doit être conçu dans une bibliothèque DLL qui est installée dans l'environnement d'exécution MTS.
C'est-à-dire que l'objet serveur est un serveur en processus qui s'exécute dans l'espace de processus d'exécution MTS. Avec
COM+, cette restriction ne s'applique plus car tous les appels COM sont redirigés par un intercepteur. Pour les clients, les
différences entre MTS et COM+ sont transparentes.

Les serveurs MTS ou COM+ rassemblent les objets transactionnels dans le même espace de processus. Dans MTS, ce groupe
est appelé un package MTS, alors que dans COM+ il est appelé application COM+. Une même machine peut exécuter plusieurs
packages MTS (ou applications COM+), chacun s'exécutant dans son propre espace de processus.

Pour les clients, les objets transactionnels apparaissent semblables aux autres objets serveur COM. Le client n'a pas besoin de
savoir quoi que ce soit sur les transactions, la sécurité ou l'activation just-in-time, sauf s'il démarre lui-même une transaction.

MTS et COM+ proposent un outil distinct pour administrer les objets transactionnels. Cet outil vous permet de configurer les
objets des packages ou des applications COM+, de visualiser les packages ou les applications COM+ installés dans une
machine ou de modifier les attributs des objets, surveiller et gérer les transactions, mettre des objets à la disposition des clients,
etc. Dans MTS, cet outil s'appelle explorateur MTS. Dans COM+ c'est le gestionnaire de composants COM+.

Bibliothèques de types
Les bibliothèques de types offrent un moyen d'obtenir davantage d'informations de type sur un objet que les interfaces de l'objet.
Les bibliothèques de types contiennent les informations nécessaires sur les objets et leurs interfaces, comme les interfaces
associées à tels objets (étant donné le CLSID), les fonctions membre de chaque interface et les arguments requis par ces
fonctions.

Vous pouvez obtenir les informations de type en interrogeant une instance d'un objet pendant qu'elle s'exécute ou, en chargeant
et en lisant les bibliothèques de types. Grâce à ces informations, vous pouvez implémenter un client qui utilise un objet souhaité,
en sachant exactement les fonctions membre dont vous avez besoin, et ce qu'il faut passer à ces fonctions.

Les clients des serveurs Automation, les contrôles ActiveX et les objets transactionnels ont besoin des informations de type.
Tous les experts Delphi génèrent automatiquement une bibliothèque de types (même si c'est facultatif avec l'expert objet COM).
Vous pouvez visualiser et modifier ces informations de types en utilisant l'éditeur de bibliothèque de types.

Voir aussi
Utilisation des experts COM ( see page 86)

44
1.4 Développement d'états pour vos RAD Studio Utilisation de Rave Reports dans RAD

1.4 Développement d'états pour vos applications


Win32
RAD Studio est livré avec Rave Reports de Nevrona. A l'aide des composants d'états, vous pouvez construire des états
1
complets pour vos applications. Vous pouvez construire des solutions incluant des fonctionnalités de génération d'états, qui
pourront être utilisées et personnalisées par vos clients. De plus, les outils ComponentOne livrés avec RAD Studio incluent des
composants permettant de créer et de générer des états.

Rubriques
Nom Description
Utilisation de Rave Reports dans RAD Studio ( see page 45) L'environnement RAD Studio gère l'intégration d'objets états dans vos
applications. Cette intégration vous permet de créer un état en utilisant le
concepteur Rave Reports directement dans l'EDI de RAD Studio. Les utilisateurs
de votre application peuvent créer et afficher leurs propres états ou afficher des
états existants.

1.4.1 Utilisation de Rave Reports dans RAD Studio


L'environnement RAD Studio gère l'intégration d'objets états dans vos applications. Cette intégration vous permet de créer un
état en utilisant le concepteur Rave Reports directement dans l'EDI de RAD Studio. Les utilisateurs de votre application peuvent
créer et afficher leurs propres états ou afficher des états existants.

Création de nouveaux états dans RAD Studio


Vous pouvez inclure des états dans RAD Studio comme vous le feriez avec d'autres composants tiers. L'état est stocké comme
objet Rave Report distinct. Vous pouvez référencer l'état dans d'autres applications ayant besoin d'appeler ou de générer cet
état. Lorsque vous créez une nouvelle application, vous pouvez inclure l'objet état en y ajoutant une référence dans le
gestionnaire de projet. Rave Reports offre aussi la capacité de connecter votre objet état à une source de données, ce qui
permet à votre application de construire l'état dynamiquement sur la base d'informations de base de données actuelles.

Voir aussi
Ajout de Rave Reports à RAD Studio ( see page 88)

45
Présentation de la VCL RAD Studio 1.5 Développement d'applications avec

1.5 Développement d'applications avec des


composants VCL
1 La VCL (Visual Component Library) est un ensemble de composants visuels permettant le développement rapide d'applications
Windows dans le langage Delphi.

La VCL contient une gamme étendue de classes utilitaires visuelles ou non visuelles pour des tâches telles que la construction
d'applications Windows, d'applications web, d'applications de bases de données et d'applications de consoles.

Rubriques
Nom Description
Présentation de la VCL ( see page 46) Cette section présente :

• Architecture de la VCL
• VCL et VCL.NET
• Composants VCL
• Utilisation des composants
Utilisation de TEncoding pour les fichiers Unicode ( see page 48)

1.5.1 Présentation de la VCL


Cette section présente :

• Architecture de la VCL
• VCL et VCL.NET
• Composants VCL
• Utilisation des composants
Architecture de la VCL
VCL est l'abréviation de Visual Component Library, un ensemble de composants visuels pour le développement rapide
d'applications Windows en langage Delphi. La VCL contient une gamme étendue de classes utilitaires visuelles ou non visuelles
pour des tâches comme la construction d'applications Windows, d'applications web, d'applications de bases de données et
d'applications de consoles. Toutes les classes dérivent de System::TObject. System::TObject introduit des méthodes qui
implémentent un comportement fondamental comme la construction, la destruction et la gestion des messages.

VCL et VCL.NET
VCL.Net contient uniquement un sous-ensemble des fonctionnalités complètes disponibles dans la VCL pour Win32. Le .NET
Framework a été architecturé pour s'adapter à n'importe quel langage compatible .NET. Dans de nombreux cas, le code source
Delphi qui fonctionne sur des classes et des fonctions VCL Win32 se recompile avec un minimum de modifications sur .NET. Il
peut même arriver qu'il se recompile sans aucune modification. Puisque VCL.NET est un sous-ensemble étendu de la VCL, il
prend en charge de nombreuses classes VCL existantes. Toutefois, le code source qui appelle directement l'API Win32
nécessite des modifications.

Composants VCL
Les composants forment un sous-ensemble de la bibliothèque de composants qui dérive de la classe TComponent. Vous

46
1.5 Développement d'applications avec RAD Studio Présentation de la VCL

pouvez placer les composants dans une fiche ou un module de données et les manipuler pendant la conception. En utilisant
l'inspecteur d'objets, vous pouvez affecter les valeurs de propriétés sans écrire de code. La plupart des composants sont
visuels ou non, selon qu'ils apparaissent ou non à l'exécution. Certains des composants apparaissent sur la palette des
composants.

Composants visuels
Les composants visuels, comme TForm ou TSpeedButton, sont appelés des contrôles et dérivent de TControl. Les contrôles
sont utilisés dans des applications à interface utilisateur graphique et ils apparaissent à l'utilisateur lors de l'exécution. TControl 1
fournit des propriétés qui spécifient les attributs visuels des contrôles, comme leur hauteur et leur largeur.

Composants non visuels


Les composants non visuels sont utilisés pour diverses tâches. Si, par exemple, vous écrivez une application qui se connecte à
une base de données, vous pouvez placer un composant TDataSource sur une fiche pour connecter un contrôle et un ensemble
de données utilisé par ce contrôle. Cette connexion étant invisible pour l'utilisateur, TDataSource est donc non visuel. A la
conception, les composants non visuels sont représentés par une icône. Cela vous permet de manipuler leurs propriétés et
événements comme un contrôle visuel.

Autres classes VCL


Les classes qui ne sont pas des composants (c'est-à-dire les classes qui dérivent de System::TObject mais pas de
TComponent) sont également utilisées pour plusieurs tâches. Généralement, ces classes sont utilisées pour l'accès aux objets
système (tels qu'un fichier ou le Presse-papiers) ou pour les tâches transitoires (telles que le stockage des données dans une
liste). Vous ne pouvez pas créer d'instances de ces classes lors de la conception, bien qu'elles soient quelquefois créées par les
composants que vous ajoutez dans le concepteur de fiche.

Utilisation des composants


De nombreux composants sont fournis par l'EDI dans la palette de composants. Vous sélectionnez des composants dans la
palette de composants et les placez sur une fiche ou un module de données. Vous concevez l'interface utilisateur d'une
application en disposant des composants visuels, boutons ou listes, sur une fiche. Vous pouvez également placer des
composants non visuels, comme les composants d'accès aux données, dans une fiche ou un module de données. A première
vue, les composants de Delphi ressemblent aux autres classes. Mais, il existe des différences entre les composants de Delphi et
les hiérarchies de classes standard avec lesquelles travaillent de nombreux programmeurs. Voici certaines de ces différences :

• Tous les composants Delphi dérivent de TComponent.


• Les composants sont la plupart du temps utilisés tels quels. Ils sont modifiés par le biais de leurs propriétés, au lieu de servir
de classes de base à sous-classer pour ajouter des fonctionnalités ou modifier celles qui existent. Quand un composant est
dérivé, on ajoute généralement du code spécifique aux fonctions membres de gestion des événements existants.
• Les composants sont alloués uniquement sur le tas et non sur la pile.
• Les propriétés des composants contiennent des informations de type à l'exécution.
• Des composants peuvent être ajoutés à la palette de composants de l'EDI et manipulés sur une fiche.
Les composants offrent souvent un meilleur degré d'encapsulation que les classes standard. Considérez, par exemple, une
boîte de dialogue contenant un bouton. Dans un programme Windows développé en utilisant les composants de la VCL,
lorsqu'un utilisateur clique sur le bouton, le système génère un message WM_LBUTTONDOWN. Le programme doit intercepter
ce message (généralement dans une instruction switch, une carte de messages ou une table de réponses) et l'envoyer à une
routine qui s'exécutera en réponse au message. La plupart des messages Windows (applications VCL) sont gérés par les
composants Delphi. Quand vous voulez répondre à un message ou événement système, il vous suffit de fournir un
gestionnaire d'événement.

Utilisation des événements


L'essentiel du code que vous écrivez est exécuté, directement ou indirectement, en réponse à des événements. Un événement
est un type particulier de propriété qui représente une situation à l'exécution, généralement une action de l'utilisateur. Le code

47
Utilisation de TEncoding pour les fichiers RAD Studio 1.5 Développement d'applications avec

qui répond directement à un événement, que l'on appelle un gestionnaire d'événement, est une procédure Delphi.

La page Evénements de l'inspecteur d'objets affiche tous les événements définis pour un composant donné. Un double-clic
sur un événement dans l'inspecteur d'objets génère un squelette de la procédure de gestion de l'événement, que vous pouvez
remplir de code pour répondre à cet événement. Certains composants n'ont pas d'événements définis.

Certains composants ont un événement par défaut, celui que le composant a le plus souvent besoin de gérer. Par exemple,
l'événement par défaut d'un bouton est OnClick. Un double-clic sur un composant avec un événement par défaut dans le
concepteur de fiches générera un squelette de la procédure de gestion de l'événement pour l'événement par défaut.
1
Vous pouvez réutiliser le code en écrivant des gestionnaires d'événements qui gèrent plusieurs événements de composants. Par
exemple, de nombreuses applications proposent des turboboutons qui sont l'équivalent de commandes de la barre des menus.
Lorsqu'un bouton effectue la même action qu'une commande de menu, vous pouvez écrire un seul gestionnaire d'événement et
l'affecter ensuite à l'événement OnClick du bouton et de l'élément de menu, en définissant dans l'inspecteur d'objets le
gestionnaire pour les événements auxquels vous voulez répondre.

Il s'agit de la méthode la plus simple pour réutiliser les gestionnaires d'événements. Toutefois, les listes d'actions et, dans la
VCL, les bandes d'actions, sont des outils puissants pour centraliser l'organisation du code répondant à des commandes
utilisateur. Les listes d'actions peuvent être utilisées dans les applications multiplates-formes ; les bandes d'actions ne le
peuvent pas.

Initialisation des propriétés d'un composant


Les propriétés publiées peuvent être initialisées à la conception avec l'inspecteur d'objets ou, dans certains cas, avec des
éditeurs de propriétés. Pour spécifier des propriétés à l'exécution, il suffit d'initialiser leur valeur dans le code source de votre
application.

A la conception, quand vous sélectionnez un composant d'une fiche, l'inspecteur d'objets affiche ses propriétés publiées et
vous permet, si c'est approprié, de les modifier.

Si plusieurs composants sont sélectionnés, l'inspecteur d'objets affiche toutes les propriétés, sauf Name, communes aux
composants sélectionnés. Si la valeur d'une propriété partagée n'est pas la même pour tous les composants sélectionnés,
l'inspecteur d'objets affiche soit la valeur par défaut, soit la valeur de la propriété pour le premier composant sélectionné.
Quand vous modifiez une propriété partagée, la modification s'applique à tous les composants sélectionnés.

La modification de propriétés liées au code dans l'inspecteur d'objets, comme le nom d'un gestionnaire d'événement, modifie
automatiquement le code source correspondant. De plus, les modifications du code source, comme le changement de nom
d'une méthode de gestionnaire d'événement dans la déclaration de classe d'une fiche, se reflètent immédiatement dans
l'inspecteur d'objets.

Voir aussi
Construction d'une application Fiches VCL ( see page 108)

Construction d'une application Fiches VCL "Hello world" ( see page 109)

Organisation des actions pour les barres d'outils et les menus ( see page 2060)

1.5.2 Utilisation de TEncoding pour les fichiers Unicode


Lecture et écriture à l'ancien format
De nombreuses applications Delphi auront toujours besoin d'interagir avec d'autres applications ou sources de données,
beaucoup d'entre elles peuvent seulement gérer les données au format ANSI ou ASCII. Pour cette raison, les valeurs par défaut
des méthodes TStrings écriront les fichiers codés ANSI selon la page de code active et liront les fichiers selon que le fichier

48
1.5 Développement d'applications avec RAD Studio Utilisation de TEncoding pour les fichiers

contient ou ne contient pas un BOM (Byte Order Mark).

Si un BOM est trouvé, les données seront lues comme l'indique le BOM. Si aucun BOM n'est trouvé, les données seront lues en
ANSI et converties selon la page de code active.

Tous les fichiers écrits avec les versions de Delphi antérieures à Tiburon pourront toujours être lus sans problème, avec la
garantie que vous lirez avec la page de code active exactement ce qui a été écrit. De même, tout fichier écrit avec Tiburón avec
un codage ASCII devrait être lisible avec une version antérieure à Tiburón.

Tout fichier écrit avec Tiburón avec un autre codage génèrera un BOM et ne sera pas lisible avec une version antérieure à 1
Tiburón. A ce stade, seuls sont détectés les formats BOM les plus courants (UTF16 Little-Endian, UTF16 Big-Endian et UTF8).

Utilisation des nouveaux codages


Beaucoup d'entre vous voudront lire/écrire les données texte à l'aide de la classe TStrings, un format Unicode à moindre perte,
comme Little-Endian UTF16, Big-Endian UTF16, UTF8, UTF7, etc… La classe TEncoding est très similaire dans les méthodes
et les fonctionnalités à la classe System.Text.Encoding de .NET Framework.
var
S:Stringlist
begin
S: Tstringlist.Create;
-
S.SaveFile('config.txt', TEncoding UTF8);
Sans paramètre supplémentaire, 'config.txt' serait simplement converti et écrit en ANSI codé selon la page de code active. La
chose intéressante à noter ici est que vous n'avez pas besoin de changer le code de lecture puisque TStrings détectera
automatiquement le codage basé sur le BOM et prendra la bonne décision.

Si vous voulez forcer la lecture et l'écriture du fichier en utilisant une page de code spécifique, vous pouvez créer une instance
de TMBCSEncoding et passer la page de code à utiliser dans le constructeur. Utilisez ensuite cette instance pour lire et écrire le
fichier puisque la page de code spécifique peut ne pas correspondre à la page de code active de l'utilisateur.

La même chose tient pour ces classes dans le fait que les données seront lues et écrites comme des données ANSI. Puisque
les fichiers INI ont toujours été traditionnellement codés en ANSI (ASCII), cela peut n'avoir aucun sens de les convertir. Cela
dépendra des besoins de votre application. Si vous préférez utiliser un format Unicode, nous vous offriront des façons d'utiliser
les classes TEncoding pour ce faire.

Dans tous les cas ci-dessus, le stockage interne sera Unicode et toute manipulation de données effectuée avec les chaînes
continuera à fonctionner comme prévu. Les conversions se produiront automatiquement lors de la lecture et de l'écriture des
données. Ceux qui sont familiers avec VCL pour .NET savent déjà comment tout ce qui est au-dessus fonctionne puisque les
nouvelles surcharges ajoutées à TStrings ont été introduites avec VCL pour .NET et utilisent la classe System.Text.Encoding
pour toutes ces opérations.

Voici la liste des identificateurs de page de code (MSDN).

Voici la liste des méthodes de surcharge qui acceptent un paramètre TEncoding :

ComCtrls.TOutlineNode.WriteNode

Outline.TOutlineNode.LoadFromFile

Outline.TOutlineNode.LoadFromStream

Outline.TOutlineNode.SaveToFile

Outline.TOutlineNode.SaveToStream

ComCtrls.TOutlineNode.WriteNode

Classes.TStrings.LoadFromFile

Classes.TStrings.LoadFromStream

49
Utilisation de TEncoding pour les fichiers RAD Studio 1.5 Développement d'applications avec

Classes.TStrings.SaveToFile

Classes.TStrings.SaveToStream

Classes.TStringStream.Create

Classes.TStreamReader.Create

Classes.TStreamWriter.Create

50
1.6 Développement d'applications Web RAD Studio Présentation des applications Web Win32

1.6 Développement d'applications Web avec


WebSnap
Cette section fournit l'arrière-plan conceptuel de construction des applications WebSnap avec RAD Studio. WebSnap facilite la
1
construction d'applications serveur Web fournissant des pages Web complexes orientées données. La prise en charge par
WebSnap des modules multiples et des scripts côté serveur facilite le développement et la maintenance pour les équipes de
développeurs et de concepteurs Web.

Veuillez noter que WebSnap est en cours de dépréciation dans RAD Studio. Bien que WebSnap soit toujours documenté dans
l'aide en ligne, le produit WebSnap n'est plus entièrement supporté. En alternative, commencez à utiliser IntraWeb (VCL pour le
Web). IntraWeb ( see page 2330) est documenté dans cette aide en ligne. Pour obtenir davantage de documentation sur la
VCL pour le Web, visitez http://www.atozed.com/intraweb/docs/.

Rubriques
Nom Description
Présentation des applications Web Win32 ( see page 51) Cette section couvre :

• Prise en charge des applications Web


• Présentation de Web Broker
• Présentation de Web Snap
• Débogage à l'aide du débogueur d'applications Web
Pour des informations plus détaillées sur les applications
web, consultez le guide du développeur Win32, à la
section Référence de ce système d'aide.

1.6.1 Présentation des applications Web Win32


Cette section couvre :

• Prise en charge des applications Web


• Présentation de Web Broker
• Présentation de Web Snap
• Débogage à l'aide du débogueur d'applications Web
Pour des informations plus détaillées sur les applications web, consultez le guide du développeur Win32, à la section Référence
de ce système d'aide.
Prise en charge des applications Web Win32
Les types d'applications web pris en charge dans RAD Studio sont les suivants.

• ISAPI
• CGI
• Débogueur d'applications Web
Les applications web Apache ne sont pas prises en charge pour cette version.

51
Présentation des applications Web Win32 RAD Studio 1.6 Développement d'applications Web

ISAPI
La sélection de ce type d'application configure votre projet comme une DLL proposant les méthodes exportées attendues par le
serveur Web. Il ajoute l'en-tête de bibliothèque au fichier projet et les entrées nécessaires à la liste uses et à la clause exports
du fichier projet.

CGI
1 La sélection de ce type d'application configure votre projet comme application console et ajoute les entrées nécessaires à la
clause uses du fichier projet.

Débogueur d'applications Web


La sélection de ce type d'application configure un environnement pour développer et tester des applications serveur Web. Ce
type d'application n'est pas destiné au déploiement.

Présentation de Web Broker


Les composants WebBroker (situés sur l'onglet Internet de la palette de composants) vous permettent de créer des
gestionnaires d'événements associés à un identificateur de ressource uniforme (URI) spécifique. Lorsque le traitement est
terminé, vous pouvez construire des documents HTML ou XML dans votre programme et les transférer au client. Vous pouvez
utiliser les composants WebBroker pour le développement d'applications multiplates-formes.

En règle générale, le contenu des pages Web est issu de bases de données. Vous pouvez utiliser les composants Internet pour
gérer automatiquement les connexions aux bases de données, ce qui permet à une seule DLL de gérer plusieurs connexions
simultanées aux bases de données sans problèmes de thread.

Présentation de Web Snap


Remarque: WebSnap est en cours de dépréciation dans RAD Studio. Bien que WebSnap soit toujours documenté dans l'aide
en ligne, le produit WebSnap n'est plus entièrement supporté. En alternative, commencez à utiliser IntraWeb (VCL pour le Web).
IntraWeb ( see page 2330) est documenté dans cette aide en ligne. Pour obtenir davantage de documentation sur la VCL pour
le Web, visitez http://www.atozed.com/intraweb/docs/.

WebSnap ajoute à WebBroker des composants, des experts et des vues, ce qui facilite la construction d'applications de serveur
Web présentant des pages Web complexes orientées données. La prise en charge par WebSnap des modules multiples et des
scripts côté serveur facilite le développement et la maintenance pour les équipes de développeurs et de concepteurs Web.
WebSnap permet aux experts en conception HTML de votre équipe d'apporter une contribution plus efficace au développement
et à la maintenance des serveurs Web.

Le produit final du processus de développement WebSnap inclut une série de templates de page HTML à scripts. Ces pages
peuvent être modifiées au moyen d'éditeurs HTML prenant en charge les balises de script incorporées, comme Microsoft
FrontPage, ou même un éditeur de texte. Des modifications peuvent être apportées aux templates selon les besoins, même
après le déploiement de l'application. Il n'est pas nécessaire de modifier le code source du projet, ce qui économise du temps de
développement précieux. La prise en charge de modules multiples par WebSnap peut être utilisée pour diviser votre application
en plus petites parties pendant les phases de codage de votre projet, de sorte que les développeurs puissent travailler de façon
plus indépendante.

Débogage à l'aide du débogueur d'applications Web


Le débogueur d'application Web est un moyen facile de contrôler les demandes et les réponses http, comme de surveiller les
temps de réponse. Le débogueur d'application Web remplace le serveur Web. Une fois l'application déboguée, vous pouvez la
convertir en l'un des types d'applications Web supportés et l'installer sur un serveur Web du commerce.

Pour utiliser le débogueur d'application Web, vous devez commencer par créer votre application Web comme exécutable
débogueur d'application Web. Que vous utilisiez WebBroker ou WebSnap, l'expert qui crée votre application serveur Web le
propose comme option au début de l'application. Cette opération crée une application serveur Web qui est également un serveur
COM. A sa première exécution, votre application recense votre serveur COM afin que le débogueur d'application Web puisse y

52
1.6 Développement d'applications Web RAD Studio Présentation des applications Web Win32

accéder. Avant de pouvoir exécuter le débogueur d'application Web, vous devez exécuter une fois bin\serverinfo.exe afin
de recenser l'application ServerInfo.

Démarrage de l'application avec le débogueur d'application Web


Une fois votre application serveur Web développée, vous pouvez l'exécuter et la déboguer en utilisant le débogueur d'application
Web. Vous pouvez définir des points d'arrêt comme pour déboguer n'importe quel autre exécutable. Lorsque vous exécutez
votre application, elle affiche la fenêtre de console du serveur COM qui constitue votre application serveur Web. Après le
démarrage de votre application et l'exécution du débogueur d'application Web, la page ServerInfo s'affiche dans votre navigateur 1
par défaut et vous pouvez sélectionner votre application à partir d'une liste déroulante. Lorsque vous avez sélectionné votre
application, cliquez sur le bouton de démarrage. Cela démarre votre application dans le débogueur d'application Web, qui vous
donne des détails sur les messages de requête et de réponse échangés entre votre application et le débogueur d'application
Web.

Conversion de votre application en un autre type d'application de serveur Web après le débogage
Une fois la mise au point de votre application serveur Web avec le débogueur d'application Web achevée, vous devez la
convertir en un autre type d'application Web susceptible d'être installé sur un serveur Web commercial.

Voir aussi
Construction d'une application WebSnap ( see page 157)

Construction d'une application "Hello world" WebSnap ( see page 158)

Débogage d'une application WebSnap à l'aide du débogueur d'application Web ( see page 160)

Conversion de votre application en un autre type d'application de serveur Web ( see page 2321)

Utilisation d'IntraWeb ( see page 2330)

53
Présentation des services Web RAD Studio 1.7 Développement de services Web avec

1.7 Développement de services Web avec des


applications Win32
1 Les services Web sont des applications modulaires indépendantes qui peuvent être publiées ou invoquées sur Internet. Les
services Web fournissent des interfaces bien définies qui décrivent les services fournis. A la différence des applications de
serveur Web qui génèrent des pages Web pour les navigateurs client, les services Web ne sont pas conçus pour une interaction
humaine directe. Ils sont plutôt destinés à être appelés par programme de la part d'applications client. Cette section contient une
présentation des services web et de leur prise en charge.

Rubriques
Nom Description
Présentation des services Web ( see page 54) Les applications de services Web sont des implémentations de serveur
n'imposent pas au client l'utilisation d'une plate-forme ou d'un langage de
programmation spécifique. Ces applications définissent des interfaces dans un
document indépendant du langage et elles autorisent de nombreux mécanismes
de communication.
Les services web sont conçus pour fonctionner avec SOAP (Simple Object
Access Protocol). SOAP est un protocole standard allégé définissant l'échange
d'informations dans un environnement décentralisé et distribué. SOAP utilise
XML pour coder les appels de procédures distantes et, habituellement, HTTP
comme protocole de communication.
Les applications de services web publient des informations sur les interfaces
disponibles et... suite ( see page 54)

1.7.1 Présentation des services Web


Les applications de services Web sont des implémentations de serveur n'imposent pas au client l'utilisation d'une plate-forme ou
d'un langage de programmation spécifique. Ces applications définissent des interfaces dans un document indépendant du
langage et elles autorisent de nombreux mécanismes de communication.

Les services web sont conçus pour fonctionner avec SOAP (Simple Object Access Protocol). SOAP est un protocole standard
allégé définissant l'échange d'informations dans un environnement décentralisé et distribué. SOAP utilise XML pour coder les
appels de procédures distantes et, habituellement, HTTP comme protocole de communication.

Les applications de services web publient des informations sur les interfaces disponibles et sur la manière de les appeler à l'aide
d'un document WSDL (Web Service Definition Language). Côté serveur, votre application peut publier un document WSDL
décrivant votre service Web. Côté client, un expert ou un utilitaire en ligne de commande peut importer un document WSDL
publié afin de vous proposer les définitions d'interfaces et les informations de connexion dont vous avez besoin. Si vous
possédez déjà un document WSDL qui décrit le service Web que vous voulez implémenter, vous pouvez aussi générer le code
côté serveur lors de l'importation du document WSDL.

Voir aussi
Utilisation de services Web ( see page 2388)

54
1.8 Développement d'applications Windows RAD Studio Présentation de Windows

1.8 Développement d'applications Windows


Windows propose une approche traditionnelle du développement d'interfaces utilisateur, d'applications client/serveur, de
contrôles et de la logique applicative. Cette section propose une présentation du développement d'applications Windows utilisant
RAD Studio pour Win32 et décrit les étapes de construction d'un projet Windows simple. 1
Rubriques
Nom Description
Présentation de Windows ( see page 55) La plate-forme Windows vous aide à créer et construire des applications de
différentes manières. Les types d'applications Windows les plus courants sont
les suivants :

• Applications GUI
• Applications console
• Applications de service
• Packages et DLL

1.8.1 Présentation de Windows


La plate-forme Windows vous aide à créer et construire des applications de différentes manières. Les types d'applications
Windows les plus courants sont les suivants :

• Applications GUI
• Applications console
• Applications de service
• Packages et DLL
Applications GUI
Une application à interface utilisateur graphique (GUI) utilise des fonctionnalités graphiques telles que les fenêtres, les menus et
les boîtes de dialogue, ainsi que des fonctionnalités qui facilitent l'utilisation de l'application. Quand vous compilez une
application GUI, un fichier exécutable contenant du code de démarrage est créé à partir de vos fichiers source. Généralement,
l'exécutable fournit les fonctionnalités de base de votre programme. Les programmes simples se composent souvent d'un seul
fichier exécutable. Vous pouvez aussi étendre une application en appelant des DLL, des packages ou d'autres bibliothèques
complétant un exécutable.

L'EDI de RAD Studio offre deux modèles d'interface utilisateur d'application :

• L'interface de document unique (Single Document Interface, SDI)


• L'interface de document multiple (Multiple Document Interface, MDI)

L'interface de document unique


Une application SDI ne contient normalement qu'une seule vue de document.

L'interface de document multiple


Dans une application MDI, plusieurs documents ou fenêtres enfant peuvent être ouverts dans une seule fenêtre parent. Cela est

55
Présentation de Windows RAD Studio 1.8 Développement d'applications Windows

courant dans les applications comme les tableurs ou les traitements de texte.

Les applications MDI nécessitent plus de réflexion et sont plus complexes à concevoir que les applications SDI. Les applications
MDI contiennent des fenêtres enfant qui se trouvent dans la fenêtre client ; la fiche principale contient des fiches enfant. Par
exemple, définissez la propriété FormStyle de l'objet TForm pour spécifier si la fiche est un enfant (fsMDIChild) ou la fiche
principale (fsMDIForm). Il est recommandé de définir une classe de base pour les fiches enfant et de dériver chaque fiche enfant
de cette classe. Sinon, vous risqueriez d'avoir à réinitialiser les propriétés de fiche de l'enfant. Les applications MDI proposent
souvent des options du menu principal comme Cascade et Mosaïque pour afficher plusieurs fenêtres de diverses manières.
1 Quand une fenêtre enfant est réduite, son icône est placée dans la fenêtre parent MDI.

Applications console
Les applications console sont des programmes 32-bits exécutés sans interface graphique, dans une fenêtre console.
Habituellement, ces applications ne nécessitent pas une saisie utilisateur importante et accomplissent un jeu limité de fonctions.
Toute application contenant {$APPTYPE CONSOLE} dans son code ouvre une fenêtre console qui lui est propre.

Applications de service
Les applications de service reçoivent les requêtes des applications client, traitent ces requêtes et renvoient les informations aux
applications client. Habituellement, les applications de service s'exécutent en arrière-plan, sans nécessiter de saisie utilisateur
importante. Un serveur Web, FTP ou de messagerie électronique est un exemple d'application de service.

Création de packages et de DLL


Les bibliothèques de liaison dynamique (DLL) sont des modules de code compilés qui fonctionnent en conjonction avec un
exécutable pour proposer des fonctionnalités à une application. Vous pouvez créer des DLL dans des programmes
multiplates-formes.

Les packages sont des DLL spéciales utilisées par les applications Delphi, par l'EDI ou les deux à la fois. Il existe deux types de
packages, d'exécution et de conception. Les packages d'exécution fournissent des fonctionnalités à un programme lors de son
exécution. Les packages de conception permettent d'étendre les fonctionnalités de l'EDI.

Pour la plupart des applications, les packages offrent une plus grande flexibilité et sont plus simples à créer que les DLL.
Cependant, dans quelques cas, les DLL fonctionnent mieux que les packages :

• Votre module de code est appelé par une application qui n'a pas été conçue avec Delphi.
• Vous étendez les fonctionnalités d'un serveur Web.
• Vous créez un module de code qui doit être utilisé par des développeurs extérieurs.
• Votre projet est un conteneur OLE.
Vous ne pouvez pas transmettre des informations de type à l'exécution (RTTI) Delphi entre DLL ou d'une DLL à un exécutable.
Si vous transmettez un objet d'une DLL vers une autre ou vers un exécutable, vous ne pouvez pas utiliser les opérateurs is
ou as avec l'objet transmis. En effet, les opérateurs is et as doivent comparer les informations RTTI. Si vous devez
transmettre des objets à partir d'une bibliothèque, utilisez des packages de préférence aux DLL, car ils peuvent partager les
informations RTTI. De même, vous devez utiliser des packages au lieu de DLL dans les services Web car ils reposent sur des
informations RTTI Delphi.
Voir aussi
Construction d'une application Windows ( see page 97)

56
2 RAD Studio

2 Procédures
Cette section présente les procédures relatives aux diverses zones de développement de RAD Studio.

Rubriques
Nom Description
Procédures CodeGuard ( see page 58) Utilisez ces procédures pour déboguer vos applications C++ avec CodeGuard.
Procédures de bases de données ( see page 60) Cette rubrique décrit la manière d'utiliser les composants de base de données de
la palette d'outils, tels que les composants dbGo, dbExpress, BDE et
DataSnap.
Procédures d'applications interopérables ( see page 86) Delphi fournit des experts et des classes qui facilitent l'implémentation
2
d'applications basées sur COM (Component Object Model) de Microsoft. Les
objets COM les plus simples sont des serveurs qui exposent des propriétés et
des méthodes (et éventuellement des événements) via une interface par défaut
que leurs clients peuvent appeler. L'expert d'objet COM construit un objet COM
léger dont l'interface par défaut descend de IUnknown ou qui implémente une
interface déjà recensée dans votre système. Cet expert offre la plus grande
flexibilité dans les types d'objets COM qu'il est possible de créer.
Procédures de génération d'états ( see page 88) Cette rubrique propose des informations relatives à l'utilisation de solutions de
génération d'états.
Procédures VCL ( see page 89) Cette section propose des informations relatives au développement
d'applications VCL pour Win32.
Procédures WebSnap ( see page 157) Cette section propose des informations relatives au développement
d'applications WebSnap.
Veuillez noter que WebSnap est en cours de dépréciation dans RAD Studio.
Bien que WebSnap soit toujours documenté dans l'aide en ligne, le produit
WebSnap n'est plus entièrement supporté. En alternative, commencez à utiliser
IntraWeb (VCL pour le Web). IntraWeb ( see page 2330) est documenté dans
cette aide en ligne. Pour obtenir davantage de documentation sur la VCL pour le
Web, visitez http://www.atozed.com/intraweb/docs/.
Procédures de services Web ( see page 162) Cette section propose des informations relatives au développement et à
l'utilisation de services web.

57
Utilisation de CodeGuard RAD Studio 2.1 Procédures CodeGuard

2.1 Procédures CodeGuard


Utilisez ces procédures pour déboguer vos applications C++ avec CodeGuard.

Rubriques
Nom Description
Utilisation de CodeGuard ( see page 58) Cette procédure décrit comment utiliser CodeGuard lors du débogage d'une
application C++.

2.1.1 Utilisation de CodeGuard


Cette procédure décrit comment utiliser CodeGuard lors du débogage d'une application C++.

Pour exécuter une application C++ en profitant du signalement des erreurs effectué par CodeGuard
1. Activez l'outil de reporting CodeGuard.
2. Activez les options CodeGuard du compilateur pour votre projet.
3. Choisissez Exécuter Exécuter pour lancer l'application.
Au cours de l'exécution de votre application, les erreurs d'exécution détectées par CodeGuard apparaissent dans la vue
Message.
2
CodeGuard génère également un journal d'erreurs nommé <nom_projet>.cgl qui liste toutes les erreurs qu'il trouve. Le
journal d'erreurs est situé dans le même répertoire que votre exécutable.
Remarque: Si vous pensez que votre programme accède à un bloc mémoire libéré mais que CodeGuard ne signale pas
d'erreur, essayez d'augmenter la valeur de Taille de bloc mémoire maximum
ou de Longueur de queue de retard sur la page Options de ressources de la boîte de dialogue de configuration de
CodeGuard.

Activez l'outil de reporting CodeGuard.


1. Choisissez Outils Configuration CodeGuard pour afficher la boîte de dialogue Configuration CodeGuard.
2. Vérifiez que CodeGuard est activé.
3. Cliquez sur OK.
Remarque: Si vous modifiez un des paramètres CodeGuard dans la boîte de dialogue Configuration CodeGuard
, CodeGuard génère un fichier de configuration .cgi portant le même nom et situé dans le même répertoire que le fichier de
votre projet.

Pour activer les options CodeGuard du compilateur pour votre projet


1. Choisissez Projet Options Compilateur C++ Débogage pour afficher les options CodeGuard du compilateur.
2. Cochez Activer toutes les options Codeguard pour activer une couverture CodeGuard complète.
3. Cliquez sur OK.
4. Reconstruisez votre projet.
Remarque: Si vous effectuez la compilation et la liaison séparément, n'oubliez pas d'inclure la bibliothèque CodeGuard
(cg32.lib

58
2.1 Procédures CodeGuard RAD Studio Utilisation de CodeGuard

) avant toutes les autres bibliothèques.


Voir aussi
Présentation de CodeGuard ( see page 9)

Boîte de dialogue Configuration CodeGuard

59
RAD Studio 2.2 Procédures de bases de données

2.2 Procédures de bases de données


Cette rubrique décrit la manière d'utiliser les composants de base de données de la palette d'outils, tels que les composants
dbGo, dbExpress, BDE et DataSnap.

Rubriques
Nom Description
Accès aux informations de schéma ( see page 61) Ces informations de schéma ou métadonnées indiquent quelles tables et quelles
procédures stockées sont accessibles sur le serveur et donnent des précisions
sur ces tables et ces procédures stockées (comme les champs d'une table, les
index définis et les paramètres utilisés par une procédure stockée).
Configuration d'une connexion TSQL ( see page 62) La première étape du travail avec un ensemble de données unidirectionnel est
de se connecter à un serveur de base de données. A la conception, une fois
qu'un ensemble de données dispose d'une connexion active à un serveur de
base de données, l'inspecteur d'objets peut fournir des listes déroulantes de
valeurs pour les autres propriétés. Par exemple, s'il s'agit d'une procédure
stockée, il faut qu'une connexion soit active pour que l'inspecteur d'objets
puisse indiquer les procédures stockées disponibles sur le serveur. La connexion
à un serveur de base de données est représentée par un composant
TSQLConnection distinct. Vous utilisez TSQLConnection... suite ( see page
62)
Connexion au serveur d'applications à l'aide de composants DataSnap ( see Une application client utilise un ou plusieurs composants connexion appartenant
page 64) à la catégorie DataSnap de la palette d'outils pour établir et maintenir une
connexion à un serveur d'applications.
Débogage d'applications dbExpress à l'aide de TSQLMonitor ( see page 65) Lors du débogage de votre application de base de données, vous pouvez
contrôler les messages SQL envoyés à la base de données et reçus de celle-ci
par le biais de votre composant connexion, y compris ceux automatiquement
générés (par exemple, par un composant fournisseur ou par le pilote dbExpress).
2 Exécution des commandes à l'aide de TSQLDataSet ( see page 65) Vous pouvez utiliser un ensemble de données unidirectionnel même si la requête
ou la procédure stockée qu'il représente ne renvoie pas d'enregistrement. Parmi
ces commandes, on trouve des instructions utilisant le langage de définition de
données (DDL) ou le langage de manipulation de données (DML), mais pas des
instructions SELECT. Le langage utilisé dans les commandes est spécifique au
serveur mais généralement conforme au standard SQL-92 du langage SQL. La
commande SQL que vous exécutez doit être acceptable pour le serveur que
vous utilisez. Les ensembles de données unidirectionnels n'évaluent pas la
commande SQL et ne l'exécutent pas : ils transmettent... suite ( see page 65)
Récupération des données à l'aide de TSQLDataSet ( see page 67)
Spécification des données à afficher à l'aide de TSQLDataSet ( see page 68)
Spécification du fournisseur à l'aide d'un composant TLocalConnection ou Les ensembles de données client sont des ensembles de données spécialisés
TConnectionBroker ( see page 69) qui stockent toutes les données en mémoire. Ils utilisent un fournisseur pour
obtenir les données et appliquer les mises à jour lorsqu'ils stockent en mémoire
cache des mises à jour d'un serveur de base de données ou d'un autre ensemble
de données, représentent les données dans un document XML et les stockent
dans la partie client d'une application multiniveau.
Utilisation du BDE ( see page 70)
Utilisation de DataSnap ( see page 70) Une application client/serveur multiniveau est partitionnée en unités logiques,
appelées niveaux, dont les différentes unités fonctionnent en coordination les
unes avec les autres sur des machines séparées. Les applications multiniveaux
partagent des données et communiquent par un réseau local voire même par
Internet. Elles offrent de nombreux avantages, comme les applications clients
simples et la logique d'entreprise centralisée.
Les applications multiniveaux utilisent les composants de la catégorie DataSnap
de la palette d'outils. DataSnap fournit des fonctionnalités de bases de données
multiniveaux aux applications Delphi en permettant aux applications client de se
connecter aux fournisseurs d'un serveur d'applications.
Utilisation de TBatchMove ( see page 71) TBatchMove copie une structure de table et ses données. Il peut être utilisé pour
transformer des tables entières d'un format de base de données dans un autre.

60
2.2 Procédures de bases de données RAD Studio Accès aux informations de schéma

Connexion aux bases de données avec TDatabase ( see page 72) TDatabase met en place une connexion persistante à une base de données, en
particulier à une base de données distante nécessitant un nom de connexion
utilisateur et un mot de passe. TDatabase est particulièrement utile car il permet
de contrôler le traitement des transactions par le BDE lors d'une connexion à un
serveur SQL distant. Utilisez TDatabase quand une application de base de
données basée sur le BDE nécessite les opérations suivantes :

• Connexions persistantes avec la base de données


• Accès personnalisés à un serveur de bases de données
• Contrôle des transactions
• Alias BDE spécifiques à l'application
Utilisation de TQuery ( see page 73) TQuery est un ensemble de données de type requête qui encapsule une
instruction SQL et permet aux applications d'accéder aux enregistrements
éventuellement obtenus.
Utilisation de TSQLQuery ( see page 75) TSQLQuery représente une requête exécutée en utilisant dbExpress.
TSQLQuery peut représenter les résultats d'une instruction SELECT ou réaliser
des actions sur le serveur de bases de données en utilisant des instructions
telles que INSERT, DELETE, UPDATE, ALTER TABLE, etc. Vous pouvez
ajouter un composant TSQLQuery à une fiche lors de la conception, ou en créer
un dynamiquement à l'exécution.
Utilisation de TSQLStoredProc ( see page 76) TSQLStoredProc représente une procédure stockée exécutée en utilisant
dbExpress. TSQLStoredProc peut représenter l'ensemble de résultats si la
procédure stockée renvoie un curseur. Vous pouvez ajouter un composant
TSQLStoredProc à une fiche lors de la conception, ou en créer un
dynamiquement à l'exécution.
Utilisation de TSQLTable ( see page 77) TSQLTable représente une table de base de données à laquelle on accède en
utilisant dbExpress. TSQLTable génère une requête permettant de récupérer
toutes les lignes et colonnes d'une table spécifiée. Vous pouvez ajouter un
composant TSQLTable à une fiche lors de la conception, ou en créer un
dynamiquement à l'exécution.
Gestion des sessions de bases de données avec TSession ( see page 78) Une session fournit une connexion globale sur un groupe de composants base
de données. Un composant TSession par défaut est créé automatiquement pour
chaque application base de données. Vous ne devez utiliser le composant 2
TSession que si vous créez une application de base de données multithread.
Chaque thread de la base de données doit avoir ses propres composants
Session.
Utilisation de TSimpleDataSet ( see page 78) TSimpleDataSet est un type spécial d'ensemble de données client conçu pour
les applications à deux niveaux simples. A l'image d'un ensemble de données
unidirectionnel, il peut utiliser un composant connexion SQL pour se connecter à
un serveur de bases de données et spécifier une instruction SQL à exécuter sur
ce serveur. Comme les autres ensembles de données client, il place les données
en mémoire tampon afin d'offrir une totale liberté de navigation et d'édition.
Utilisation de TSimpleObjectBroker ( see page 79) Si votre application client peut choisir parmi plusieurs serveurs basés sur COM,
vous pouvez utiliser un courtier d'objets pour localiser un système serveur
disponible.
Utilisation de TStoredProc ( see page 80) TStoredProc est un ensemble de données de type procédure stockée qui
exécute une procédure stockée définie sur un serveur de base de données.
Utilisation de TTable ( see page 81) TTable est un ensemble de données de type table qui représente toutes les
lignes et colonnes d'une seule table de base de données.
Utilisation de TUpdateSQL pour mettre à jour un ensemble de données ( see Quand l'ensemble de données BDE représente une procédure stockée ou une
page 83) requête non "dynamique", il n'est pas possible d'appliquer les mises à jour
directement depuis l'ensemble de données. De tels ensembles de données
peuvent aussi provoquer un problème quand vous utilisez un ensemble de
données client pour placer les mises à jour en mémoire cache.
Utilisation de dbExpress ( see page 83)
Utilisation de l'explorateur de données pour obtenir des informations de Avant d'avoir une connexion, vous pouvez utiliser l'explorateur de données
connexion ( see page 84) pour assembler les chaînes de connexion.

2.2.1 Accès aux informations de schéma


Ces informations de schéma ou métadonnées indiquent quelles tables et quelles procédures stockées sont accessibles sur le
serveur et donnent des précisions sur ces tables et ces procédures stockées (comme les champs d'une table, les index définis

61
Configuration d'une connexion TSQL RAD Studio 2.2 Procédures de bases de données

et les paramètres utilisés par une procédure stockée).

Pour accéder aux informations de schéma


1. Pour remplir un ensemble de données unidirectionnel avec des métadonnées du serveur de base de données, appelez la
méthode SetSchemaInfo pour indiquer quelles sont les données que vous souhaitez voir.
2. Définissez le type d'informations de schéma de la méthode SetSchemaInfo.
3. Définissez le nom du paramètre de la table ou de la procédure stockée de la méthode SetSchemaInfo.
4. Pour récupérer les données après l'utilisation de l'ensemble des données pour les métadonnées, effectuez l'une des
opérations suivantes :
• Définissez la propriété CommandText pour spécifier la requête, la table ou la procédure stockée à partir de laquelle vous
souhaitez lire des données.
• Définissez le type d'informations de schéma par stNoSchema et appelez la méthode SetSchemaInfo.
Remarque: Si vous choisissez la deuxième option, l'ensemble de données récupère les données spécifiées par la propriété
CommandText.

Voir aussi
Composants dbExpress ( see page 16)

Configuration de TSQLConnection ( see page 62)

Spécification des données à afficher ( see page 68)

Récupération des données ( see page 67)

Exécution des commandes ( see page 65)


2
Débogage d'applications dbExpress ( see page 65)

Utilisation de TSQLTable ( see page 77)

Utilisation de TSQLStoredProc ( see page 76)

Utilisation de TSQLQuery ( see page 75)

Utilisation de TSimpleDataSet ( see page 78)

Utilisation d'ensembles de données unidirectionnels ( see page 1879)

2.2.2 Configuration d'une connexion TSQL


La première étape du travail avec un ensemble de données unidirectionnel est de se connecter à un serveur de base de
données. A la conception, une fois qu'un ensemble de données dispose d'une connexion active à un serveur de base de
données, l'inspecteur d'objets peut fournir des listes déroulantes de valeurs pour les autres propriétés. Par exemple, s'il s'agit
d'une procédure stockée, il faut qu'une connexion soit active pour que l'inspecteur d'objets puisse indiquer les procédures
stockées disponibles sur le serveur. La connexion à un serveur de base de données est représentée par un composant
TSQLConnection distinct. Vous utilisez TSQLConnection comme tout autre composant connexion de base de données.

Pour configurer une connexion TSQL


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.

62
2.2 Procédures de bases de données RAD Studio Configuration d'une connexion TSQL

3. A partir de la catégorie dbExpress de la palette d'outils, faites glisser un composant TSQLConnection sur la fiche.
4. Identifiez le pilote.
5. Spécifiez les paramètres de connexion.
6. Identifiez une connexion de base de données.
7. Affichez et utilisez l'éditeur de connexion dbExpress.

Pour identifier le pilote


1. Sélectionnez le composant TSQLConnection.
2. Dans l'inspecteur d'objets, définissez la propriété DriverName sur un pilote dbExpress installé.
3. Identifiez les fichiers associés au nom du pilote. Sélectionnez un des éléments suivants :
• Le pilote dbExpress
• La bibliothèque de liaison dynamique
Remarque: La relation entre le pilote dbExpress ou la bibliothèque de liaison dynamique et le nom de la base de données
est stockée dans un fichier appelé dbxdrivers.ini
, qui est mis à jour lorsque vous installez un pilote dbExpress. Le composant connexion SQL recherche le pilote dbExpress et
la bibliothèque de liaison dynamique dans dbxdrivers.ini lorsqu'il reçoit la valeur de DriverName. Lorsque vous
définissez la propriété DriverName, TSQLConnection attribue automatiquement aux propriétés LibraryName et VendorLib
les noms des dll associées. Une fois LibraryName et VendorLib définies, votre application n'est plus dépendante de
dbxdrivers.ini.

Pour spécifier un paramètre de connexion


1. Double-cliquez sur la propriété Params dans l'inspecteur d'objets pour modifier les paramètres en utilisant l'éditeur de liste
de valeurs au moment de la conception.
2
2. Utilisez la propriété Params.Values pour affecter des valeurs à des paramètres individuels au moment de l'exécution.

Pour identifier une connexion de base de données


1. Initialisez la propriété ConnectionName avec un nom de connexion valide. Cela initialise automatiquement les propriétés
DriverName et Params.
2. Modifiez la propriété Params pour modifier l'ensemble de valeurs de paramètres enregistré.
3. Initialisez la propriété LoadParamsOnConnect à True pour développer votre application en utilisant une base de données et
la déployer en utilisant une autre. Cela provoque l'initialisation automatique par TSQLConnection de DriverName et Params
aux valeurs associées à ConnectionName dans dbxconnections.ini lorsque la connexion est ouverte.
4. Appelez la méthode LoadParamsFromIniFile. Cette méthode initialise DriverName et Params aux valeurs associées à
ConnectionName dans dbxconnections.ini (ou dans un autre fichier que vous spécifiez). Vous pouvez opter pour cette
méthode si vous souhaitez remplacer certaines valeurs de paramètres avant d'ouvrir la connexion.

Pour afficher l'éditeur de connexion


1. Double-cliquez sur le composant TSQLConnection. L'éditeur de connexion dbExpress apparaît, avec une liste déroulante
des pilotes, une liste de noms de connexion pour le pilote sélectionné et un tableau des paramètres de connexion pour le
nom de connexion sélectionné.
2. Dans la liste déroulante Nom du pilote, sélectionnez un pilote pour indiquer la connexion à utiliser.
3. Dans la liste Nom de connexion, sélectionnez nom de connexion.
4. Choisissez la configuration voulue.
5. Cliquez sur le bouton Tester la connexion pour vérifier si la configuration est valide.

Pour définir et modifier des connexions en utilisant l'éditeur de connexion


1. Pour modifier les connexions nommées actuellement sélectionnées dans dbxconnections.ini, modifiez les valeurs des

63
Débogage d'applications dbExpress à RAD Studio 2.2 Procédures de bases de données

paramètres dans la table des paramètres.


2. Cliquez sur OK. Les nouvelles valeurs de paramètres sont enregistrées dans dbxconnections.ini.
3. Cliquez sur le bouton Ajouter une connexion pour définir une nouvelle connexion. La boîte de dialogue Nouvelle
connexion apparaît.
4. Dans la boîte de dialogue Nouvelle connexion, définissez Nom de pilote et Nom de connexion.
5. Cliquez sur OK.
6. Cliquez sur le bouton Supprimer la connexion pour supprimer la connexion nommée actuellement sélectionnée de
dbxconnections.ini.
7. Cliquez sur le bouton Renommer la connexion pour modifier le nom de la connexion nommée sélectionnée.
Voir aussi
Composants dbExpress ( see page 16)

Spécification des données à afficher ( see page 68)

Récupération des données ( see page 67)

Exécution des commandes ( see page 65)

Accès aux informations de schéma ( see page 61)

Débogage d'applications dbExpress ( see page 65)

Utilisation de TSQLTable ( see page 77)

Utilisation de TSQLStoredProc ( see page 76)

Utilisation de TSQLQuery ( see page 75)


2 Utilisation de TSimpleDataSet ( see page 78)

Utilisation d'ensembles de données unidirectionnels ( see page 1879)

2.2.3 Connexion au serveur d'applications à l'aide de


composants DataSnap
Une application client utilise un ou plusieurs composants connexion appartenant à la catégorie DataSnap de la palette d'outils
pour établir et maintenir une connexion à un serveur d'applications.

Pour se connecter au serveur d'applications à l'aide de composants DataSnap


1. Identifiez le protocole utilisé pour communiquer avec le serveur d'applications.
2. Localisez la machine serveur.
3. Identifiez le serveur d'applications sur la machine serveur.
4. Si vous n'utilisez pas SOAP, identifiez le serveur à l'aide de la propriété ServerName ou ServerGUID.
5. Gérez les connexions serveur.
Voir aussi
Connexion au serveur d'applications ( see page 1547)

Utilisation de TLocalConnection ou de TConnectionBroker ( see page 69)

Utilisation de TSimpleObjectBroker ( see page 79)

64
2.2 Procédures de bases de données RAD Studio Exécution des commandes à l'aide de

2.2.4 Débogage d'applications dbExpress à l'aide de


TSQLMonitor
Lors du débogage de votre application de base de données, vous pouvez contrôler les messages SQL envoyés à la base de
données et reçus de celle-ci par le biais de votre composant connexion, y compris ceux automatiquement générés (par exemple,
par un composant fournisseur ou par le pilote dbExpress).

Pour déboguer des applications dbExpress


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. Pour surveiller les commandes SQL, à partir de la catégorie dbExpress de la palette d'outils, faites glisser un composant
TSQLMonitor sur la fiche.
4. Définissez la propriété SQLConnection du TSQLMonitor sur le composant TSQLConnection.
5. Définissez la propriété Active du TSQLMonitor sur True.

Pour utiliser un callback afin de surveiller les commandes SQL


1. Utilisez la méthode SetTraceEvent du composant TSQLConnection.
2. Définissez le paramètre d'événement TDBXTraceEvent.
Le pilote dbExpress déclenche l'événement chaque fois que le composant connexion SQL transmet une commande au serveur
ou que celui-ci renvoie un message d'erreur.
2
Avertissement: N'appelez pas SetTraceEvent si l'objet TSQLConnection
a un composant associé TSQLMonitor. TSQLMonitor utilise le mécanisme de callback pour fonctionner et
TSQLConnection ne peut prendre en charge qu'un callback à la fois.
Voir aussi
Composants dbExpress ( see page 16)

Configuration de TSQLConnection ( see page 62)

Spécification des données à afficher ( see page 68)

Récupération des données ( see page 67)

Exécution des commandes ( see page 65)

Accès aux informations de schéma ( see page 61)

Utilisation d'ensembles de données unidirectionnels ( see page 1879)

2.2.5 Exécution des commandes à l'aide de TSQLDataSet


Vous pouvez utiliser un ensemble de données unidirectionnel même si la requête ou la procédure stockée qu'il représente ne
renvoie pas d'enregistrement. Parmi ces commandes, on trouve des instructions utilisant le langage de définition de données
(DDL) ou le langage de manipulation de données (DML), mais pas des instructions SELECT. Le langage utilisé dans les
commandes est spécifique au serveur mais généralement conforme au standard SQL-92 du langage SQL. La commande SQL

65
Exécution des commandes à l'aide de RAD Studio 2.2 Procédures de bases de données

que vous exécutez doit être acceptable pour le serveur que vous utilisez. Les ensembles de données unidirectionnels n'évaluent
pas la commande SQL et ne l'exécutent pas : ils transmettent la commande au serveur pour exécution.

Pour exécuter des commandes


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. A partir de la catégorie dbExpress de la palette d'outils, faites glisser un composant TSQLDataSet sur la fiche.
4. Spécifiez la commande à exécuter.
5. Exécutez la commande.
6. Créez et modifiez les métadonnées du serveur.

Pour spécifier la commande à exécuter


1. Définissez les propriétés CommandType et CommandText dans l'inspecteur d'objets pour spécifier la commande pour un
TSQLDataSet.
2. Définissez la propriété SQL dans l'inspecteur d'objets pour spécifier l'instruction SQL à transmettre au serveur pour un
TSQLQuery.
3. Définissez la propriété StoredProcName dans l'inspecteur d'objets pour spécifier le nom de la procédure stockée à exécuter
pour un TSQLStoredProc.

Pour exécuter la commande


1. Si l'ensemble de données est une instance d'un TSQLDataSet ou d'un TSQLQuery, appelez la méthode ExecSQL.
2. Si l'ensemble de données est une instance d'un TSQLStoredProc, appelez la méthode ExecProc.
2
Conseil: Si vous exécutez la requête ou la procédure stockée plusieurs fois, il est souhaitable de définir la propriété
Prepared par True.

Pour créer et modifier des métadonnées de serveur


1. Pour créer des tables dans une base de données, utilisez l'instruction CREATE TABLE.
2. Pour créer de nouveaux index pour ces tables, utilisez l'instruction CREATE INDEX.
3. Pour ajouter différents objets de métadonnées, utilisez les instructions CREATE DOMAIN, CREATE VIEW, CREATE
SCHEMA et CREATE PROCEDURE.
4. Pour supprimer l'un des objets de métadonnées ci-dessus, utilisez DROP TABLE, DROP VIEW, DROP DOMAIN, DROP
SCHEMA et DROP PROCEDURE.
5. Pour modifier la structure d'une table, utilisez une instruction ALTER TABLE.
Voir aussi
Composants dbExpress ( see page 16)

Configuration de TSQLConnection ( see page 62)

Spécification des données à afficher ( see page 68)

Récupération des données ( see page 67)

Accès aux informations de schéma ( see page 61)

Débogage d'applications dbExpress ( see page 65)

Utilisation de TSQLTable ( see page 77)

Utilisation de TSQLStoredProc ( see page 76)

66
2.2 Procédures de bases de données RAD Studio Spécification des données à afficher à

Utilisation de TSQLQuery ( see page 75)

Utilisation d'ensembles de données unidirectionnels ( see page 1879)

2.2.6 Récupération des données à l'aide de TSQLDataSet


Pour récupérer les données
1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. A partir de la catégorie dbExpress de la palette d'outils, faites glisser un composant TSQLDataSet sur la fiche.
4. Pour récupérer les données d'un ensemble de données unidirectionnel, effectuez l'une des opérations suivantes :
• Dans l'inspecteur d'objets, définissez la propriété Active sur la valeur True.
• Appelez la méthode Open lors de l'exécution.
Conseil: Utilisez la propriété GetMetadata pour récupérer, de façon sélective, les métadonnées sur un objet base de
données. Affectez la valeur False à GetMetadata si vous récupérez un ensemble de données à des fins de lecture seule.

5. Définissez sa propriété Prepared sur True pour préparer l'ensemble de données explicitement.
6. Appelez la méthode NextRecordSet pour récupérer plusieurs ensembles ou enregistrements.
Remarque: NextRecordSet renvoie un composant TCustomSQLDataSet récemment créé qui permet d'accéder à l'ensemble
d'enregistrements suivant. Ainsi, la première fois que vous appelez NextRecordSet, elle renvoie un ensemble de données 2
pour le second ensemble d'enregistrements. Appeler NextRecordSet renvoie un troisième ensemble de données, et ainsi de
suite jusqu'à ce qu'il n'y ait plus d'ensemble d'enregistrements. Lorsque qu'il n'y a pas d'ensemble de données
supplémentaire, NextRecordSet ne renvoie rien.
Voir aussi
Composants dbExpress ( see page 16)

Spécification des données à afficher ( see page 68)

Récupération des données

Exécution des commandes ( see page 65)

Accès aux informations de schéma ( see page 61)

Débogage d'applications dbExpress ( see page 65)

Utilisation de TSQLTable ( see page 77)

Utilisation de TSQLStoredProc ( see page 76)

Utilisation de TSQLQuery ( see page 75)

Utilisation d'ensembles de données unidirectionnels ( see page 1879)

67
Spécification des données à afficher à RAD Studio 2.2 Procédures de bases de données

2.2.7 Spécification des données à afficher à l'aide de


TSQLDataSet
Pour spécifier les données à afficher
1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. A partir de la catégorie dbExpress de la palette d'outils, faites glisser un composant TSQLDataSet sur la fiche.
4. Pour TSQLDataSet, spécifiez le type d'ensemble de données unidirectionnel en définissant la propriété CommandType dans
l'inspecteur d'objets.
5. Spécifiez si les informations proviennent des résultats d'une requête, d'une table de base de données ou d'une procédure
stockée.

Pour afficher les résultats d'une requête


1. Initialisez la propriété CommandType à ctQuery pour un TSQLDataSet.
2. Pour TSQLQuery, déposez un composant TSQLQuery sur la fiche depuis la palette d'outils.
3. Affectez à la propriété SQL la requête que vous souhaitez affecter.
4. Sélectionnez TSQLDataSet.
5. Cliquez sur la propriété CommandText. L'éditeur CommandText s'ouvre.
2
6. Dans l'éditeur CommandText, définissez la propriété SQL sur le texte de l'instruction de requête.
Remarque: Lorsque vous spécifiez la requête, elle peut inclure des paramètres, ou variables, dont les valeurs peuvent être
modifiées pendant la conception ou pendant l'exécution. Les paramètres peuvent remplacer les valeurs des données qui
apparaissent dans l'instruction SQL. SQL définit des requêtes comme UPDATE qui exécutent des actions sur le serveur mais
ne renvoient pas un ensemble d'enregistrements.

Pour afficher les enregistrements d'une table


1. Dans l'inspecteur d'objets, initialisez la propriété CommandType à la valeur ctTable. TSQLDataSet génère une requête à
partir des valeurs de deux propriétés : CommandText qui spécifie le nom de la table de base de données que l'objet
TSQLDataSet devrait représenter et SortFieldNames qui énumère les noms des champs à utiliser pour trier les données,
dans l'ordre de leur prépondérance.
2. Déposez un composant TSQLTable sur la fiche.
3. Dans l'inspecteur d'objets, définissez la propriété TableName sur la table souhaitée.
4. Affectez à la propriété IndexName le nom d'un index défini sur le serveur ou affectez à la propriété IndexFieldNames une liste
de noms de champs séparés par des points-virgules pour spécifier l'ordre des champs dans l'ensemble de données.

Pour afficher les résultats d'une procédure stockée


1. Dans l'inspecteur d'objets, initialisez la propriété CommandType à la valeur ctStoredProc.
2. Spécifiez le nom de la procédure stockée comme valeur de la propriété CommandText.
3. Initialisez la propriété StoredProcName au nom de la procédure stockée pour TSQLStoredProc.
Remarque: Une fois que vous avez identifié une procédure stockée, il se peut que votre application ait besoin de fournir les
valeurs des paramètres d'entrée de la procédure stockée ou d'extraire les valeurs des paramètres de sortie à la fin de
l'exécution de la procédure stockée.

68
2.2 Procédures de bases de données RAD Studio Utilisation du BDE

Voir aussi
Composants dbExpress ( see page 16)

Configuration de TSQLConnection ( see page 62)

Récupération des données ( see page 67)

Exécution des commandes ( see page 65)

Accès aux informations de schéma ( see page 61)

Débogage d'applications dbExpress ( see page 65)

Utilisation de TSQLTable ( see page 77)

Utilisation de TSQLStoredProc ( see page 76)

Utilisation de TSQLQuery ( see page 75)

Utilisation de TSimpleDataSet ( see page 78)

Utilisation d'ensembles de données unidirectionnels ( see page 1879)

2.2.8 Spécification du fournisseur à l'aide d'un composant


TLocalConnection ou TConnectionBroker
Les ensembles de données client sont des ensembles de données spécialisés qui stockent toutes les données en mémoire. Ils
2
utilisent un fournisseur pour obtenir les données et appliquer les mises à jour lorsqu'ils stockent en mémoire cache des mises à
jour d'un serveur de base de données ou d'un autre ensemble de données, représentent les données dans un document XML et
les stockent dans la partie client d'une application multiniveau.

Pour spécifier le fournisseur


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. A partir de la catégorie DataSnap de la palette d'outils, faites glisser un composant TConnectionBroker sur la fiche si le
fournisseur se trouve sur un serveur d'applications distant.
4. Dans l'inspecteur d'objets, affectez à la propriété ConnectionBroker de votre ensemble de données client le composant
TConnectionBroker sur la fiche.
5. Dans la catégorie DataSnap de la palette d'outils, faites glisser un composant TLocalConnection sur la fiche si le
fournisseur est dans la même application que l'ensemble de données client.
6. Affectez à la propriété RemoteServer de votre ensemble de données client le composant TLocalConnection sur la fiche.
Voir aussi
Utilisation de DataSnap ( see page 70)

Connexion au serveur d'applications ( see page 64)

Utilisation de TSimpleObjectBroker ( see page 79)

69
Utilisation de DataSnap RAD Studio 2.2 Procédures de bases de données

2.2.9 Utilisation du BDE


Pour utiliser le BDE
1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments s'ouvre.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TTable sur la fiche. Cela encapsulera toute la
structure des données dans une table de base de données sous-jacente.
4. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TQuery sur la fiche. Cela encapsulera une
instruction SQL et permettra aux applications d'accéder aux enregistrements résultants.
5. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TStoredProc sur la fiche. Cela exécutera une
procédure stockée définie sur un serveur de base de données.
6. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TBatchMove sur la fiche. Cela copiera une
structure de table ou ses données.
7. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TUpdateSQL sur la fiche. Cela fournira une
façon de mettre à jour les ensembles de données sous-jacents.
Voir aussi
Vue globale BDE ( see page 15)

Utilisation de TDatabase ( see page 72)

2 Utilisation de TSession ( see page 78)

Utilisation de TTable ( see page 81)

Utilisation de TQuery ( see page 73)

Utilisation de TStoredProc ( see page 80)

Utilisation de TBatchMove ( see page 71)

Utilisation de TupdateSQL ( see page 83)

2.2.10 Utilisation de DataSnap


Une application client/serveur multiniveau est partitionnée en unités logiques, appelées niveaux, dont les différentes unités
fonctionnent en coordination les unes avec les autres sur des machines séparées. Les applications multiniveaux partagent des
données et communiquent par un réseau local voire même par Internet. Elles offrent de nombreux avantages, comme les
applications clients simples et la logique d'entreprise centralisée.

Les applications multiniveaux utilisent les composants de la catégorie DataSnap de la palette d'outils. DataSnap fournit des
fonctionnalités de bases de données multiniveaux aux applications Delphi en permettant aux applications client de se connecter
aux fournisseurs d'un serveur d'applications.

Pour construire des applications de bases de données multiniveaux à l'aide de DataSnap


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches

70
2.2 Procédures de bases de données RAD Studio Utilisation de TBatchMove

VCL. Le concepteur Windows s'affiche.


3. A partir de la catégorie DataSnap de la palette d'outils, faites glisser un composant TDCOMConnection sur la fiche. Cela
établira une connexion DCOM avec un serveur distant dans une application de base de données multiniveau.
4. A partir de la catégorie DataSnap de la palette d'outils, faites glisser un composant TSocketConnection sur la fiche. Cela
établira une connexion TCP/IP à un serveur distant dans une application de base de données multiniveau.
5. A partir de la catégorie DataSnap de la palette d'outils, faites glisser un composant TSimpleObjectBroker sur la fiche. Cela
localisera un serveur pour un composant connexion à partir d'une liste des serveurs d'applications disponibles.
6. A partir de la catégorie DataSnap de la palette d'outils, faites glisser un composant TWebConnection sur la fiche. Cela
établira une connexion HTTP à un serveur distant dans une application de base de données multiniveau.
7. A partir de la catégorie DataSnap de la palette d'outils, faites glisser un composant TConnectionBroker sur la fiche. Cela
centralisera toutes les connexions au serveur d'applications afin que les applications ne nécessitent pas de réécriture majeure
lors de la modification du protocole de connexion.
8. A partir de la catégorie DataSnap de la palette d'outils, faites glisser un composant TSharedConnection sur la fiche. Cela
provoquera une connexion à un module de données distant enfant lors de la construction du serveur d'applications au moyen
de plusieurs modules de données distants.
9. A partir de la catégorie DataSnap de la palette d'outils, faites glisser un composant TLocalConnection sur la fiche. Cela
fournira un accès aux méthodes IAppServer qui seraient sinon inaccessibles, et facilitera l'évolution ultérieure vers une
application multiniveau. Il agit comme un composant connexion pour les fournisseurs résidant dans la même application.
Voir aussi
Connexion au serveur d'applications ( see page 64)

Déploiement d'applications de bases de données multiniveaux (DataSnap). ( see page 2017)

Utilisation de TLocalConnection ou de TConnectionBroker ( see page 69)

Utilisation de TSimpleObjectBroker ( see page 79) 2

2.2.11 Utilisation de TBatchMove


TBatchMove copie une structure de table et ses données. Il peut être utilisé pour transformer des tables entières d'un format de
base de données dans un autre.

Pour utiliser TBatchMove


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. Créez un composant action groupée.
4. Spécifiez un mode d'action groupée.
5. Etablissez un mappage des types de données.
6. Exécutez une action groupée.
7. Gérez les erreurs relatives aux actions groupées.
Voir aussi
Utilisation de TBatchMove ( see page 1724)

Utilisation de TTable ( see page 81)

Utilisation de TQuery ( see page 73)

71
Connexion aux bases de données avec RAD Studio 2.2 Procédures de bases de données

Utilisation de TStoredProc ( see page 80)

Utilisation d'objets mise à jour pour mettre à jour un ensemble de données ( see page 1735)

Utilisation de TSession ( see page 78)

2.2.12 Connexion aux bases de données avec TDatabase


TDatabase met en place une connexion persistante à une base de données, en particulier à une base de données distante
nécessitant un nom de connexion utilisateur et un mot de passe. TDatabase est particulièrement utile car il permet de contrôler
le traitement des transactions par le BDE lors d'une connexion à un serveur SQL distant. Utilisez TDatabase quand une
application de base de données basée sur le BDE nécessite les opérations suivantes :

• Connexions persistantes avec la base de données


• Accès personnalisés à un serveur de bases de données
• Contrôle des transactions
• Alias BDE spécifiques à l'application

Pour se connecter aux bases de données avec TDatabase


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. Associez un composant base de données à une session.
2
4. Identifiez la base de données.
5. Ouvrez une connexion avec TDatabase.

Pour associer un composant base de données à une session


1. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TDatabase sur la fiche.
2. Déposez un composant TSession sur la fiche.
3. Dans l'inspecteur d'objets, définissez la propriété SessionName du composant TSession. SessionName a la valeur
"Default", ce qui signifie qu'elle est associée au composant session par défaut qui est référencé par la variable globale
Session.
4. Si vous utilisez plusieurs sessions, ajoutez un composant TSession pour chaque session.
5. Définissez la propriété SessionName du composant TDatabase sur la propriété SessionName du composant TSession pour
associer votre ensemble de données à un composant session.
6. Lisez la propriété Session pour accéder au composant session avec lequel la base de données est associée pendant
l'exécution. Si SessionName est vide ou a pour valeur "Default", la propriété Session référence la même instance de
TSession référencée par la variable globale Session.
Session permet aux applications d'accéder aux propriétés, méthodes et événements d'un composant session parent d'un
composant de base de données sans connaître le nom réel de la session. Si vous utilisez un composant base de données
implicite, la session de ce composant base de données est celle spécifiée par la propriété SessionName de l'ensemble de
données.

Pour identifier la base de données


1. Dans les listes déroulantes des composants ensembles de données, spécifiez le nom de l'alias ou le nom d'un alias BDE
existant pour un composant base de données.
Remarque: Cette action efface toutes les valeurs déjà affectées à DriverName. Quand vous créez un alias BDE local pour

72
2.2 Procédures de bases de données RAD Studio Utilisation de TQuery

un composant base de données, vous pouvez aussi spécifier un nom de pilote à la place d'un alias en utilisant la propriété
DatabaseName. Si vous spécifiez un nom de pilote, toutes les valeurs déjà affectées à AliasName sont effacées. Pour fournir
votre propre nom pour une connexion de base de données, définissez la propriété DatabaseName. Pour spécifier un alias
BDE au moment de la conception, affectez un pilote BDE.

2. Créez un alias BDE local.


3. Double-cliquez sur un composant base de données. L'éditeur de base de données s'ouvre.
4. Dans la zone de saisie Nom de l'éditeur de propriétés, entrez le même nom que celui spécifié par la propriété
DatabaseName.
5. Dans la boîte à options Nom d'alias entrez un nom d'alias BDE existant ou choisissez un alias existant dans la liste
déroulante.
6. Pour créer ou modifier des paramètres de connexion au moment de la conception, effectuez l'une des opérations suivantes :
• Utilisez l'explorateur de base de données ou l'utilitaire d'administration BDE.
• Double-cliquez sur la propriété Params dans l'inspecteur d'objets pour appeler l'éditeur de liste de valeurs.
• Double-cliquez sur un composant base de données dans un module de données ou une fiche pour appeler l'éditeur de base
de données.
Remarque: Toutes ces méthodes éditent la propriété Params du composant base de données. Quand vous appelez l'éditeur
de propriétés de bases de données
pour la première fois, les paramètres de l'alias BDE ne sont pas visibles. Pour afficher les paramètres en cours, cliquez sur
Défaut. Les paramètres en cours s'affichent dans la zone mémo Paramètres de connexion. Vous pouvez éditer les entrées
existantes ou en ajouter de nouvelles. Pour effacer les paramètres existants, cliquez sur Effacer. Les modifications ne
prennent effet que lorsque vous cliquez sur OK.

Pour ouvrir une connexion avec TDatabase 2


1. Dans la propriété Params d'un composant TDatabase, configurez le pilote ODBC de votre application.
2. Pour vous connecter à une base de données à l'aide de TDatabase, définissez la propriété Connected à True ou appelez la
méthode Open.
Remarque: Le fait d'appeler TDatabase.Rollback n'appelle pas TDataSet.Cancel pour les ensembles de données associés à
la base de données.
Voir aussi
Vue globale BDE ( see page 15)

Utilisation de TSession ( see page 78)

Utilisation de TTable ( see page 81)

Utilisation de TQuery ( see page 73)

Utilisation de TStoredProc ( see page 80)

Utilisation de TBatchMove ( see page 71)

Utilisation de TUpdateSQL ( see page 83)

2.2.13 Utilisation de TQuery


TQuery est un ensemble de données de type requête qui encapsule une instruction SQL et permet aux applications d'accéder
aux enregistrements éventuellement obtenus.

73
Utilisation de TQuery RAD Studio 2.2 Procédures de bases de données

Pour utiliser TQuery


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. Associez l'ensemble de données avec les connexions de bases de données et de session.
4. Créez des requêtes hétérogènes.
5. Obtenez un ensemble de résultats modifiable.
6. Mettez à jour les ensembles de résultats en lecture seule.

Pour associer un ensemble de données aux connexions de bases de données et de sessions


1. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TDatabase sur la fiche.
2. Déposez un composant TSession sur la fiche.
3. Définissez la propriété DatabaseName du composant TDatabase pour associer un ensemble de données orienté BDE à une
base de données. Pour le composant TDatabase, le nom de la base de données est la valeur de la propriété DatabaseName
du composant base de données.
4. Spécifiez un alias BDE comme valeur de DatabaseName si vous désirez utiliser un composant base de données implicite et
si la base de données possède un alias BDE.
Remarque: Un alias BDE représente une base de données et ses informations de configuration. Les informations de
configuration associées avec les alias diffèrent avec le type de la base de données (Oracle, Sybase, InterBase, Paradox,
dBASE, etc.).

2 5. Dans l'inspecteur d'objets, définissez la propriété DatabaseName pour spécifier simplement le répertoire contenant les
tables de la base de données si vous souhaitez utiliser un composant base de données implicite pour une base de données
Paradox ou dBASE.
6. Utilisez la session par défaut pour contrôler toutes les connexions aux bases de données de votre application.
7. Définissez la propriété SessionName du composant TSession pour associer votre ensemble de données à un composant
session créé de manière explicite.
Remarque: Que vous ayez utilisé la session par défaut ou spécifié une session explicite avec la propriété SessionName,
vous pouvez accéder à la session associée à un ensemble de données en lisant la propriété DBSession. Si vous utilisez un
composant session, la propriété SessionName d'un ensemble de données doit concorder avec la propriété SessionName du
composant base de données auquel l'ensemble de données est associé.

Pour créer des requêtes hétérogènes


1. Définissez des alias BDE distincts pour chaque base de données concernée dans la requête, en utilisant l'outil
d'administration BDE ou l'explorateur SQL.
2. Laissez vide la propriété DatabaseName du composant TQuery. Les noms des bases de données utilisées sont spécifiés
dans l'instruction SQL.
3. Affectez à la propriété SQL l'instruction SQL que vous souhaitez exécuter.
4. Faites-y précéder le nom de chaque table par l'alias BDE de la base de données de cette table, encadré par des caractères
deux-points. La référence entière est elle-même encadrée de guillemets.
5. Affectez à la propriété Params tout paramètre de la requête.
6. Ecrivez une méthode Prepare pour préparer la requête avant sa première exécution.
7. Ecrivez une méthode Open ou ExecSQL selon le type de requête que vous exécutez.
8. Utilisez un composant TDatabase au lieu d'utiliser un alias BDE pour spécifier la base de données dans une requête
hétérogène.

74
2.2 Procédures de bases de données RAD Studio Utilisation de TSQLQuery

9. Configurez le TDatabase pour la base de données, affectez à la propriété TDatabase. DatabaseName une valeur unique et
utilisez cette valeur dans l'instruction SQL à la place d'un nom d'alias BDE.

Pour obtenir un ensemble de résultats modifiable


1. Initialisez la valeur True à la propriété RequestLive du composant TQuery.
2. Si la requête contient des champs liés, vous devez considérer l'ensemble de résultats comme étant en lecture seule, et le
mettre à jour.
Si une application demande un ensemble de résultats dynamique mais que la syntaxe de l'instruction SELECT ne le permet pas,
le BDE renvoie un ensemble de résultats en lecture seule pour les requêtes effectuées sur Paradox ou dBASE, ou un code
d'erreur pour les requêtes SQL effectuées sur un serveur distant.

Pour mettre à jour des ensembles de résultats en lecture seule


1. Si toutes les mises à jour sont appliquées à une table de base de données unique, indiquez la table sous-jacente à mettre à
jour dans un gestionnaire d'événement OnGetTableName.
2. Affectez à la propriété UpdateObject de la requête l'objet TUpdateSQL que vous utilisez pour mieux contrôler l'application
des mises à jour.
3. Affectez aux propriétés DeleteSQL, InsertSQL et ModifySQL de l'objet de mise à jour les instructions SQL qui effectuent les
mises à jour adaptées aux données de votre requête.
Si vous utilisez le BDE pour mettre en mémoire cache les mises à jour, vous devez utiliser un objet de mise à jour.
Voir aussi
Vue globale BDE ( see page 15)

Utilisation de TDatabase ( see page 72)

Utilisation de TSession ( see page 78)


2
Utilisation de TTable ( see page 81)

Utilisation de TStoredProc ( see page 80)

Utilisation de TBatchMove ( see page 71)

Utilisation de TUpdateSQL ( see page 83)

2.2.14 Utilisation de TSQLQuery


TSQLQuery représente une requête exécutée en utilisant dbExpress. TSQLQuery peut représenter les résultats d'une
instruction SELECT ou réaliser des actions sur le serveur de bases de données en utilisant des instructions telles que INSERT,
DELETE, UPDATE, ALTER TABLE, etc. Vous pouvez ajouter un composant TSQLQuery à une fiche lors de la conception, ou
en créer un dynamiquement à l'exécution.

Pour utiliser TSQLQuery


1. A partir de la catégorie dbExpress de la palette d'outils, faites glisser un composant TSQLQuery sur la fiche.
2. Dans l'inspecteur d'objets, attribuez à sa propriété Name une valeur unique appropriée à votre application.
3. Initialisez la propriété SQLConnection.
4. Cliquez sur le bouton points de suspension à côté de la propriété SQL du composant TSQLQuery. L'éditeur de liste de
chaînes s'ouvre.
5. Dans l'éditeur de liste de chaînes, tapez l'instruction de requête à exécuter.
6. Si les données de la requête doivent être utilisées avec des contrôles de données visuels, ajoutez un composant source de

75
Utilisation de TSQLStoredProc RAD Studio 2.2 Procédures de bases de données

données à la fiche.
7. Affectez l'ensemble de données de type requête à la propriété DataSet du composant source de données.
8. Pour activer le composant requête, attribuez la valeur True à la propriété Active ou appelez la méthode Open à l'exécution.
Voir aussi
Composants dbExpress ( see page 16)

Configuration de TSQLConnection ( see page 62)

Spécification des données à afficher ( see page 68)

Récupération des données ( see page 67)

Exécution des commandes ( see page 65)

Accès aux informations de schéma ( see page 61)

Utilisation de TSQLTable ( see page 77)

Utilisation de TSQLStoredProc ( see page 76)

Utilisation de TSimpleDataSet ( see page 78)

Utilisation d'ensembles de données unidirectionnels ( see page 1879)

2.2.15 Utilisation de TSQLStoredProc


2 TSQLStoredProc représente une procédure stockée exécutée en utilisant dbExpress. TSQLStoredProc peut représenter
l'ensemble de résultats si la procédure stockée renvoie un curseur. Vous pouvez ajouter un composant TSQLStoredProc à une
fiche lors de la conception, ou en créer un dynamiquement à l'exécution.

Pour utiliser TSQLStoredProc


1. A partir de la catégorie dbExpress de la palette d'outils, faites glisser un composant TSQLStoredProc sur la fiche.
2. Dans l'inspecteur d'objets, attribuez à sa propriété Name une valeur unique appropriée à votre application.
3. Initialisez la propriété SQLConnection.
4. Définissez la propriété StoredProcName pour spécifier la procédure stockée à exécuter.
5. Si la procédure stockée renvoie un curseur à utiliser avec des contrôles de données visuels, ajoutez un composant source de
données à la fiche.
6. Affectez l'ensemble de données de type procédure stockée à la propriété DataSet du composant source de données.
7. Fournissez les valeurs des éventuels paramètres de la procédure stockée.
8. Pour exécuter la procédure stockée qui renvoie un curseur, utilisez la propriété Active ou appelez la méthode Open.
9. Traitez les éventuels résultats.
Voir aussi
Composants dbExpress ( see page 16)

Configuration de TSQLConnection ( see page 62)

Spécification des données à afficher ( see page 68)

Récupération des données ( see page 67)

Exécution des commandes ( see page 65)

76
2.2 Procédures de bases de données RAD Studio Gestion des sessions de bases de

Accès aux informations de schéma ( see page 61)

Utilisation de TSQLTable ( see page 77)

Utilisation de TSQLQuery ( see page 75)

Utilisation de TSimpleDataSet ( see page 78)

Utilisation d'ensembles de données unidirectionnels ( see page 1879)

2.2.16 Utilisation de TSQLTable


TSQLTable représente une table de base de données à laquelle on accède en utilisant dbExpress. TSQLTable génère une
requête permettant de récupérer toutes les lignes et colonnes d'une table spécifiée. Vous pouvez ajouter un composant
TSQLTable à une fiche lors de la conception, ou en créer un dynamiquement à l'exécution.

Pour utiliser TSQLTable


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. A partir de la catégorie dbExpress de la palette d'outils, faites glisser un composant TSQLTable sur la fiche.
4. Dans l'inspecteur d'objets, attribuez à sa propriété Name une valeur unique appropriée à votre application.
5. Initialisez la propriété SQLConnection.
6. Définissez la propriété TableName par le nom de la table de la base de données. 2
7. Ajoutez un composant source de données à la fiche.
8. Affectez le nom de l'ensemble de données à la propriété DataSet du composant source de données.
Voir aussi
Composants dbExpress ( see page 16)

Configuration de TSQLConnection ( see page 62)

Spécification des données à afficher ( see page 68)

Récupération des données ( see page 67)

Exécution des commandes ( see page 65)

Accès aux informations de schéma ( see page 61)

Utilisation de TSQLStoredProc ( see page 76)

Utilisation de TSQLQuery ( see page 75)

Utilisation de TSimpleDataSet ( see page 78)

Utilisation d'ensembles de données unidirectionnels ( see page 1879)

77
Utilisation de TSimpleDataSet RAD Studio 2.2 Procédures de bases de données

2.2.17 Gestion des sessions de bases de données avec


TSession
Une session fournit une connexion globale sur un groupe de composants base de données. Un composant TSession par défaut
est créé automatiquement pour chaque application base de données. Vous ne devez utiliser le composant TSession que si
vous créez une application de base de données multithread. Chaque thread de la base de données doit avoir ses propres
composants Session.

Pour gérer des sessions de bases de données


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. Activez une session.
4. Spécifiez le comportement de la connexion de base de données par défaut.
5. Gérez les connexions aux bases de données.
6. Manipulez les tables Paradox et dBASE protégées par mot de passe.
7. Manipulez les alias BDE.
8. Récupérez les informations d'une session.
9. Créez, nommez et gérez des sessions supplémentaires.
2
Voir aussi
Gestion des sessions de bases de données ( see page 1704)

Utilisation de TTable ( see page 81)

Utilisation de TQuery ( see page 73)

Utilisation de TStoredProc ( see page 80)

Utilisation de TDatabase ( see page 72)

Utilisation de TBatchMove ( see page 71)

Utilisation de TUpdateSQL ( see page 83)

2.2.18 Utilisation de TSimpleDataSet


TSimpleDataSet est un type spécial d'ensemble de données client conçu pour les applications à deux niveaux simples. A
l'image d'un ensemble de données unidirectionnel, il peut utiliser un composant connexion SQL pour se connecter à un serveur
de bases de données et spécifier une instruction SQL à exécuter sur ce serveur. Comme les autres ensembles de données
client, il place les données en mémoire tampon afin d'offrir une totale liberté de navigation et d'édition.

Pour utiliser TSQLStoredProc


1. A partir de la catégorie dbExpress de la palette d'outils, faites glisser un composant TSimpleDataSet sur la fiche.
2. Attribuez à sa propriété Name une valeur unique adaptée à votre application.

78
2.2 Procédures de bases de données RAD Studio Utilisation de TSimpleObjectBroker

3. A partir de la section dbExpress de la palette d'outils, faites glisser un composant TSQLConnection sur la fiche.
4. Sélectionnez le composant TSimpleDataSet. Affectez à la propriété Connection le composant TSQLConnection.
5. Pour récupérer des données du serveur, effectuez l'une des actions suivantes :
• Attribuez à CommandType la valeur ctQuery et à CommandText une instruction SQL à exécuter sur le serveur.
• Attribuez à CommandType la valeur ctStoredProc et à CommandText le nom de la procédure stockée à exécuter.
• Attribuez à CommandType la valeur ctTable et à CommandText le nom des tables de base de données dont vous souhaitez
utiliser les enregistrements.
6. Si la procédure stockée renvoie un curseur à utiliser avec des contrôles de données visuels, ajoutez un composant source de
données à la fiche.
7. Affectez à la propriété DataSet du composant source de données l'objet TSimpleDataSet.
8. Pour activer l'ensemble de données, utilisez la propriété Active ou appelez la méthode Open.
9. Si vous avez exécuté une procédure stockée, utilisez la propriété Params pour extraire les paramètres de sortie.
Voir aussi
Composants dbExpress ( see page 16)

Configuration de TSQLConnection ( see page 62)

Spécification des données à afficher ( see page 68)

Récupération des données ( see page 67)

Exécution des commandes ( see page 65)

Accès aux informations de schéma ( see page 61)

Utilisation de TSQLTable ( see page 77) 2


Utilisation de TSQLStoredProc ( see page 76)

Utilisation de TSQLQuery ( see page 75)

Utilisation d'ensembles de données unidirectionnels ( see page 1879)

2.2.19 Utilisation de TSimpleObjectBroker


Si votre application client peut choisir parmi plusieurs serveurs basés sur COM, vous pouvez utiliser un courtier d'objets pour
localiser un système serveur disponible.

Pour utiliser TSimpleObjectBroker


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. A partir de la catégorie DataSnap de la palette d'outils, choisissez le composant connexion en fonction du type de
connexion souhaité.
4. A partir de la palette d'outils, faites glisser un composant TSimpleObjectBroker sur la fiche.
5. Dans l'inspecteur d'objets, attribuez à la propriété ObjectBroker le composant connexion choisi à l'étape 3 pour utiliser ce
courtier.
Avertissement: N'utilisez pas la propriété ObjectBroker avec des connexions SOAP.

79
Utilisation de TStoredProc RAD Studio 2.2 Procédures de bases de données

Voir aussi
Utilisation de DataSnap ( see page 70)

Connexion au serveur d'applications ( see page 64)

Utilisation de TLocalConnection ou de TConnectionBroker ( see page 69)

2.2.20 Utilisation de TStoredProc


TStoredProc est un ensemble de données de type procédure stockée qui exécute une procédure stockée définie sur un serveur
de base de données.

Pour utiliser TStoredProc


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. Associez un ensemble de données aux connexions de bases de données et de sessions.
4. Liez les paramètres.

Pour associer un ensemble de données aux connexions de bases de données et de sessions


1. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TDatabase sur la fiche.
2. Pour associer un ensemble de données BDE à une base de données, définissez la propriété DatabaseName. Pour le
2 composant TDatabase, le nom de la base de données est la valeur de la propriété DatabaseName du composant base de
données.
3. Déposez un composant TSession sur la fiche.
4. Pour contrôler toutes les connexions de bases de données dans votre application, utilisez la session par défaut.
5. Pour associer votre ensemble de données à un composant session explicitement créé, dans l'inspecteur d'objets,
définissez la propriété SessionName du composant TSession.
Remarque: Si vous utilisez un composant session, la propriété SessionName d'un ensemble de données doit concorder
avec la propriété SessionName du composant base de données auquel l'ensemble de données est associé.

Pour lier les paramètres


1. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TStoredProc sur la fiche.
2. Attribuez à la propriété ParamBindMode la valeur par défaut pbByName pour spécifier comment les paramètres doivent être
liés aux paramètres sur le serveur.
3. Examinez le code source de la procédure stockée d'un serveur dans l'explorateur SQL si vous souhaitez initialiser
ParamBindMode à pbByNumber.
4. Déterminez l'ordre de tri et le type corrects des paramètres.
5. Spécifiez les types de paramètres corrects dans l'ordre correct.
Remarque: Certains serveurs supportent aussi la liaison des paramètres par valeur ordinale, c'est-à-dire l'ordre dans lequel
ils apparaissent dans la procédure stockée. Dans ce cas, l'ordre dans lequel vous spécifiez les paramètres dans l'éditeur de
collection de paramètres est important. Le premier paramètre spécifié correspond au premier paramètre d'entrée sur le
serveur, et ainsi de suite. Si votre serveur supporte la liaison de paramètres par valeur ordinale, vous pouvez initialiser
ParamBindMode à pbByNumber
.

80
2.2 Procédures de bases de données RAD Studio Utilisation de TTable

Voir aussi
Vue globale BDE ( see page 15)

Utilisation de TTable ( see page 81)

Utilisation de TQuery ( see page 73)

Utilisation de TBatchMove ( see page 71)

Utilisation de TUpdateSQL ( see page 83)

2.2.21 Utilisation de TTable


TTable est un ensemble de données de type table qui représente toutes les lignes et colonnes d'une seule table de base de
données.

Pour utiliser TTable


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application Fiches
VCL. Le concepteur Windows s'affiche.
3. Associez l'ensemble de données aux connexions de bases de données et de sessions.
4. Spécifiez le type de table pour les tables locales et contrôlez l'accès en lecture/écriture aux tables locales.
5. Spécifiez un fichier d'index dBASE.
2
6. Renommez les tables locales.
7. Importez les données d'une autre table.

Pour associer un ensemble de données aux connexions de bases de données et de sessions


1. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TDatabase sur la fiche.
2. Déposez un composant TSession sur la fiche.
3. Pour associer un ensemble de données BDE à une base de données, dans l'inspecteur d'objets, définissez la
propriétéDatabaseName du composant TDatabase. Pour un composant TDatabase, le nom de la base de données est la
valeur de la propriété DatabaseName du composant base de données.
4. Utilisez la session par défaut pour contrôler toutes les connexions aux bases de données de votre application.
5. Définissez la propriété SessionName du composant TSession pour associer votre ensemble de données à un composant
session créé de manière explicite.
Si vous utilisez un composant session, la propriété SessionName d'un ensemble de données doit concorder avec la propriété
SessionName du composant base de données auquel l'ensemble de données est associé.

Pour spécifier le TableType et contrôler l'accès en lecture/écriture


1. A partir de la catégorie BDE de la palette d'outils, faites glisser un composant TTable sur la fiche.
2. Si une application accède à une table Paradox, dBASE, FoxPro ou ASCII délimité par des virgules, dans l'inspecteur
d'objets, définissez la propriété TableType. BDE utilise la propriété TableType pour déterminer le type de la table.
3. Affectez la valeur ttDefault à TableType si vos tables locales Paradox, dBASE et texte ASCII utilisent des extensions de
fichiers telles que .DB, .DBF et .TXT.
4. Pour les autres extensions, initialisez respectivement la propriété TableType à ttParadox pour Paradox, à ttDBase pour
dBASE, à ttFoxPro pour FoxPro et à ttASCII pour du texte ASCII délimité par des virgules.

81
Utilisation de TUpdateSQL pour mettre à RAD Studio 2.2 Procédures de bases de données

5. Initialisez la propriété Exclusive du composant table à la valeur True avant d'ouvrir la table pour obtenir l'accès exclusif en
lecture/écriture.
Remarque: Si la table est déjà en cours d'utilisation lorsque vous essayez de l'ouvrir, la requête d'accès exclusif ne peut être
honorée. Vous pouvez essayer d'appliquer Exclusive aux tables SQL, mais certains serveurs ne supportent pas le
verrouillage exclusif au niveau des tables. D'autres peuvent admettre le verrouillage exclusif, mais permettre tout de même à
d'autres applications de lire des données dans la table.

Pour spécifier un fichier d'index dBASE


1. Affectez à la propriété IndexFiles le nom d'un fichier d'index autonome ou listez les fichiers d'extension .NDX.
2. Spécifiez ensuite un index dans la propriété IndexName pour qu'il trie effectivement l'ensemble de données.
3. Au moment de la conception, cliquez sur le bouton Points de suspension dans la propriété IndexFiles. L'éditeur de fichiers
d'index s'ouvre.
4. Pour ajouter un fichier index autonome ou un fichier .NDX, cliquez sur le bouton Ajouter dans la boîte de dialogue Fichiers
index et sélectionnez le fichier dans la boîte de dialogue d'ouverture.
Remarque: Pour chaque fichier d'index autonome ou fichier d'index .NDX., répétez une fois les étapes 3 et 4.

5. Après avoir ajouté tous les index voulus, cliquez sur le bouton OK de l'éditeur de fichiers d'index.
Remarque: Pour effectuer les étapes 3 à 5 lors de l'exécution, accédez à la propriété IndexFiles en utilisant les propriétés et
méthodes des listes de chaînes.

Pour renommer les tables locales


1. Pour renommer une table Paradox ou dBASE au moment de la conception, cliquez avec le bouton droit sur le composant
2 table. Un menu contextuel déroulant apparaît.
2. Dans le menu contextuel, sélectionnez Renommer la table.
3. Pour renommer une table Paradox ou dBASE à l'exécution, appelez la méthode RenameTable de la table.

Pour importer des données d'une autre table


1. Utilisez la méthode BatchMove d'un composant table pour importer des données, copier, mettre à jour, ajouter à cette table
des enregistrements d'une autre table ou supprimer des enregistrements d'une table.
2. Spécifiez le nom de la table depuis laquelle importer les données, ainsi que le mode qui détermine quelle opération
d'importation effectuer.
Voir aussi
Vue globale BDE ( see page 15)

Utilisation de TDatabase ( see page 72)

Utilisation de TSession ( see page 78)

Utilisation de TQuery ( see page 73)

Utilisation de TStoredProc ( see page 80)

Utilisation de TBatchMove ( see page 71)

Utilisation de TUpdateSQL ( see page 83)

82
2.2 Procédures de bases de données RAD Studio Utilisation de dbExpress

2.2.22 Utilisation de TUpdateSQL pour mettre à jour un


ensemble de données
Quand l'ensemble de données BDE représente une procédure stockée ou une requête non "dynamique", il n'est pas possible
d'appliquer les mises à jour directement depuis l'ensemble de données. De tels ensembles de données peuvent aussi provoquer
un problème quand vous utilisez un ensemble de données client pour placer les mises à jour en mémoire cache.

Pour mettre à jour un ensemble de données à l'aide d'un objet mise à jour
1. A partir de la palette d'outils, ajoutez un composant TUpdateSQL à la même fiche de données que celui de l'ensemble de
données BDE.
2. Dans l'inspecteur d'objets, affectez à la propriété UpdateObject du composant ensemble de données BDE le composant
TUpdateSQL dans la fiche.
3. Définissez les propriétés ModifySQL, InsertSQL et DeleteSQL de l'objet de mise à jour pour spécifier les instructions SQL
nécessaires à l'exécution des mises à jour.
4. Fermez l'ensemble de données.
5. Affectez à la propriété CachedUpdates du composant ensemble de données la valeur True ou liez l'ensemble de données à
l'ensemble de données client à l'aide d'un fournisseur d'ensemble de données.
6. Rouvrez l'ensemble de données.
7. Créez les instructions SQL pour les composants de mise à jour.
8. Utilisez plusieurs objets mise à jour.
2
9. Exécutez les instructions SQL.
Voir aussi
Utilisation d'objets mise à jour pour mettre à jour un ensemble de données ( see page 1735)

Utilisation de TTable ( see page 81)

Utilisation de TQuery ( see page 73)

Utilisation de TStoredProc ( see page 80)

Utilisation de TbatchMove ( see page 71)

Utilisation de TSession ( see page 78)

2.2.23 Utilisation de dbExpress


Pour construire une application de base de données à l'aide de dbExpress
1. Connectez-vous au serveur de base de données puis configurez une connexion TSQL.
2. Spécifiez les données à afficher.
3. Récupérez les données.
4. Exécutez les commandes.
5. Accédez aux informations de schéma.
6. Déboguez l'application dbExpress à l'aide de TSQLMonitor.

83
Utilisation de l'explorateur de données pour RAD Studio 2.2 Procédures de bases de données

7. Utilisez TSQLTable pour représenter une table sur un serveur de bases de données accédé via TSQLConnection.
8. Utilisez TSQLQuery pour exécuter une commande SQL sur un serveur de bases de données accédé via TSQLConnection.
9. Utilisez TSQLStoredProc pour exécuter une procédure stockée sur un serveur de bases de données accédé via
TSQLConnection.
Voir aussi
Composants dbExpress ( see page 16)

Configuration de TSQLConnection ( see page 62)

Spécification des données à afficher ( see page 68)

Récupération des données ( see page 67)

Exécution des commandes ( see page 65)

Accès aux informations de schéma ( see page 61)

Débogage d'applications dbExpress ( see page 65)

Utilisation de TSQLTable ( see page 77)

Utilisation de TSQLStoredProc ( see page 76)

Utilisation de TSQLQuery ( see page 75)

Utilisation de TSimpleDataSet ( see page 78)

Utilisation des ensembles de données dbExpress ( see page 1879)

2
2.2.24 Utilisation de l'explorateur de données pour obtenir
des informations de connexion
Avant d'avoir une connexion, vous pouvez utiliser l'explorateur de données pour assembler les chaînes de connexion.

Pour parcourir les fournisseurs de bases de données


1. Choisissez Voir Explorateur de données ou cliquez sur l'onglet Explorateur de données dans le Gestionnaire de
projets.
2. Développez un noeud fournisseur sous dbExpress ou Ado.Net pour exposer la liste des fournisseurs de bases de données
disponibles.
3. Développez le noeud fournisseur de second niveau pour visualiser la liste des connexions potentielles.

Pour obtenir les informations de connexion


1. Dans la liste des fournisseurs de l'explorateur de données, cliquez avec le bouton droit sur un fournisseur de second
niveau.
2. Dans le menu contextuel, cliquez sur Modifier la connexion. Le dialogue Ajouter une connexion s'affiche.
3. Dans le dialogue Ajouter une connexion, cliquez sur Avancées. Le dialogue Propriétés avancées s'affiche, avec une liste
déroulante de propriétés de connexion. La colonne de gauche contient les clés des chaînes de connexion ; la colonne de
droite contient leurs valeurs.

Pour formater une chaîne de connexion


1. Dans le dialogue Propriétés avancées, entrez dans la colonne de droite les valeurs des propriétés de connexion nommées
dans la colonne de gauche. Le champ texte situé en bas du dialogue Propriétés avancées contient le texte de la chaîne de

84
2.2 Procédures de bases de données RAD Studio Utilisation de l'explorateur de données pour

connexion résultante.
2. Déplacez le curseur sur le texte de la chaîne de connexion pour sélectionner ce texte. Copiez le texte. Vous pouvez alors
coller cette chaîne de connexion là où vous le souhaitez.
Voir aussi
Exploration d'une base de données dans l'explorateur de données

Ajout d'une nouvelle connexion

Modification des connexions

85
Utilisation des experts COM RAD Studio 2.3 Procédures d'applications

2.3 Procédures d'applications interopérables


Delphi fournit des experts et des classes qui facilitent l'implémentation d'applications basées sur COM (Component Object
Model) de Microsoft. Les objets COM les plus simples sont des serveurs qui exposent des propriétés et des méthodes (et
éventuellement des événements) via une interface par défaut que leurs clients peuvent appeler. L'expert d'objet COM construit
un objet COM léger dont l'interface par défaut descend de IUnknown ou qui implémente une interface déjà recensée dans votre
système. Cet expert offre la plus grande flexibilité dans les types d'objets COM qu'il est possible de créer.

Rubriques
Nom Description
Utilisation des experts COM ( see page 86) RAD Studio dispose d'experts pour vous aider à créer des projets COM et des
objets COM. Ces experts sont disponibles pour les projets Delphi et C++. Les
experts COM proposés sont les suivants :

• Bibliothèque ActiveX
• Objet COM
• Bibliothèque de types
• ActiveForm
• Objet Active Server
• Objet Automation
• Objet événement COM+
2 • Objet Abonnement COM+
• Page propriétés

2.3.1 Utilisation des experts COM


RAD Studio dispose d'experts pour vous aider à créer des projets COM et des objets COM. Ces experts sont disponibles pour
les projets Delphi et C++. Les experts COM proposés sont les suivants :

• Bibliothèque ActiveX
• Objet COM
• Bibliothèque de types
• ActiveForm
• Objet Active Server
• Objet Automation
• Objet événement COM+
• Objet Abonnement COM+
• Page propriétés

Pour utiliser un expert COM


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments s'affiche.
2. Dans l'arborescence Catégories d'éléments, cliquez sur le dossier ActiveX. Les experts disponibles sont affichés dans le

86
2.3 Procédures d'applications RAD Studio Utilisation des experts COM

volet droit da la boîte de dialogue Nouveaux éléments. Ces experts COM sont disponibles pour les projets Delphi et C++.
3. Double-cliquez sur l'expert que vous souhaitez utiliser.
Remarque: Si votre application implémente plusieurs objets COM, vous devez utiliser la même méthode d'instanciation pour
tous.
Voir aussi
Présentation des technologies COM ( see page 1404)

87
Ajout de Rave Reports à RAD Studio RAD Studio 2.4 Procédures de génération d'états

2.4 Procédures de génération d'états


Cette rubrique propose des informations relatives à l'utilisation de solutions de génération d'états.

Rubriques
Nom Description
Ajout de Rave Reports à RAD Studio ( see page 88) Rave Reports offre un ensemble d'outils puissant pour créer des états et les
intégrer à vos applications. Les outils Rave Reports sont installés dans le
sous-répertoire \RaveReports de votre répertoire d'installation. Pour y accéder
plus facilement, ajoutez l'exécutable de la commande au menu Outils.

2.4.1 Ajout de Rave Reports à RAD Studio


Rave Reports offre un ensemble d'outils puissant pour créer des états et les intégrer à vos applications. Les outils Rave Reports
sont installés dans le sous-répertoire \RaveReports de votre répertoire d'installation. Pour y accéder plus facilement, ajoutez
l'exécutable de la commande au menu Outils.

Pour ajouter une commande Rave Reports au menu Outils


1. Choisissez Outils Configurer les outils. Cette opération affiche la boîte de dialogue Options des outils.
2. Cliquez sur Ajouter. Cette opération affiche la boîte de dialogue Propriétés des outils.
2
3. Tapez Rave Reports dans la zone de saisie Titre.
4. Cliquez sur le bouton Parcourir.
5. Naviguez vers le sous-répertoire \RaveReports de votre répertoire d'installation de RAD Studio.
6. Sélectionnez l'icône Rave.exe.
7. Cliquez sur OK. Cette action ajoute le chemin d'accès au programme et le répertoire de travail à la boîte de dialogue
Propriétés des outils.
8. Cliquez sur OK.
9. Cliquez sur Fermer. Cette action ajoute au menu Outils la commande qui lancera une session Rave Reports. Reportez-vous
à l'aide en ligne de Rave Reports pour de plus amples informations sur la construction et l'intégration d'objets état.
Voir aussi
Présentation de Rave Reports ( see page 45)

88
2.5 Procédures VCL RAD Studio

2.5 Procédures VCL


Cette section propose des informations relatives au développement d'applications VCL pour Win32.

Rubriques
Nom Description
Construction d'une application console "Hello World" Windows ( see page 96) Cette application console "Hello World" Windows illustre les étapes essentielles
de la création d'une application Windows dans Delphi ou C++. L'application
utilise Windows, une fenêtre console et un événement, et affiche une boîte de
dialogue en réponse à une action de l'utilisateur.
Développement d'une application Windows ( see page 97) La procédure suivante illustre les étapes essentielles de la construction d'une
application Windows.
Construction des menus d'applications ( see page 97) Les menus constituent pour les utilisateurs un moyen commode d'exécuter des
commandes regroupées logiquement. Vous pouvez ajouter ou supprimer des
éléments de menu ou les déplacer pour réorganiser les éléments lors de la
conception. Outre les composants TMainMenu et TPopupMenu, la palette
d'outils contient aussi TActionMainMenuBar, TActionManager et
TActionToolBar.
Construction d'une application Fiches VCL avec des composants d'aide à la La création d'une fiche avec des tableaux et des graphes de données
décision ( see page 99) multidimensionnelles se compose des étapes majeures suivantes :

1. Création d'une fiche VCL.


2. Ajout d'une requête de décision et d'un ensemble de
données.
3. Ajout d'un cube de décision.
4. Ajout d'une source de décision. 2
5. Ajout éventuel d'un pivot de décision.
6. Ajout d'un ou plusieurs graphes de décision ou d'une ou
plusieurs grilles de décision.
7. Initialisation de la propriété Active de la requête de
décision (ou d'un autre composant ensemble de données)
à True.
Construction d'applications Fiches VCL avec graphiques ( see page 101) Chacune des procédures ci-dessous permet de construire une application Fiche
VCL qui utilise des graphiques. Construisez un ou plusieurs exemples puis
ajoutez d'autres fonctionnalités graphiques à ces applications Fiches VCL de
base. *

1. Dessin de lignes droites.


2. Dessin de rectangles et d'ellipses.
3. Dessin d'un polygone.
4. Affichage d'une image bitmap.
5. Ajout d'un bitmap dans une boîte à options.
Construction d'une application MDI Fiches VCL à l'aide d'un expert ( see page L'expert Application MDI Fiches VCL crée automatiquement un projet qui inclut
101) les fichiers de base pour une application MDI. En plus du fichier source principal,
l'expert crée des fichiers d'unités pour des fenêtres enfants et de boîte de
dialogue A propos, avec les fichiers de fiches et les ressources.
Construction d'une application MDI Fiches VCL sans utiliser d'expert ( see
page 102)
Construction d'une application SDI Fiches VCL ( see page 104)
Création d'un nouveau composant VCL ( see page 105) Vous pouvez utiliser l'expert Nouveau composant VCL pour créer un nouveau
composant VCL pour votre application. Il détecte la personnalité du produit que
vous utilisez et crée le type de composant approprié.

89
RAD Studio 2.5 Procédures VCL

Conception d'une application Fiches VCL de base de données ADO ( see page La procédure suivante indique comment construire une application de base de
106) données ADO.
La construction d'une application VCL ADO comprend les étapes principales
suivantes :

1. Définition de la connexion à la base de données.


2. Définition de l'ensemble de données.
3. Installation du fournisseur de données, de l'ensemble de
données client et de la source de données.
4. Connexion d'une grille de données aux composants
connexion.
5. Exécution de l'application.
Construction d'une application Fiches VCL ( see page 108) La procédure suivante illustre les étapes essentielles de la construction d'une
application Fiches VCL avec RAD Studio.
Création d'actions dans une application Fiches VCL ( see page 108) Dans RAD Studio, la procédure suivante illustre comment créer des actions avec
l'outil ActionList. Elle configure une application simple et explique comment créer
un élément de menu fichier avec une action d'ouverture de fichier.
La construction d'une application VCL avec ActionList comprend les étapes
principales suivantes :

1. Créez une fenêtre principale et ajoutez des outils pour


créer un menu principal et une action d'ouverture de
fichier.
2. Ajoutez la catégorie Fichier au menu principal.
3. Ajoutez l'action d'ouverture de fichier à la catégorie
Fichier.
4. Construction et exécution de l'application.
2 Construction d'une application Fiches VCL "Hello World" ( see page 109) Cette procédure montre comment construire une simple application Fiches VCL
"Hello world" avec Delphi ou C++. Malgré sa simplicité, l'application Fiches VCL
"Hello world" illustre les étapes essentielles de la création d'une application
Fiches VCL. L'application utilise une fiche VCL, un contrôle et un événement, et
affiche une boîte de dialogue en réponse à une action de l'utilisateur.
La création de l'application "Hello world" comprend les étapes suivantes :

1. Création d'une fiche VCL avec un contrôle bouton.


2. Ecriture du code pour afficher "Hello Word" quand
l'utilisateur clique sur le bouton.
3. Exécution de l'application.
Utilisation de ActionManager pour créer des actions dans une application Fiches Dans RAD Studio, la procédure suivante illustre comment créer des actions avec
VCL ( see page 110) ActionManager. Elle configure une interface utilisateur simple avec une zone de
texte, adaptée à une application d'édition de texte, et explique comment créer un
élément de menu fichier avec une action d'ouverture de fichier.
La construction d'une application VCL avec ActionManager comprend les étapes
principales suivantes :

1. Création d'une fenêtre principale.


2. Ajout d'une action d'ouverture de fichier à ActionManager.
3. Création du menu principal.
4. Ajout de l'action au menu.
5. Construction et exécution de l'application.

90
2.5 Procédures VCL RAD Studio

Conception d'une application Fiches VCL de base de données dbExpress ( La procédure suivante indique comment construire une application de base de
see page 111) données dbExpress.
La construction d'une application Fiches VCL dbExpress comprend les étapes
principales suivantes :

1. Définition de la connexion à la base de données.


2. Installation de l'ensemble de données unidirectionnel.
3. Installation du fournisseur de données, de l'ensemble de
données client et de la source de données.
4. Connexion d'une grille de données aux composants
connexion.
5. Exécution de l'application.
Construction d'une application avec des composants XML ( see page 113) Cet exemple crée une application Fiches VCL qui utilise un composant
XMLDocument pour afficher le contenu d'un fichier XML.
Copie de données d'un flux vers un autre ( see page 115) La création de cette application VCL comprend les étapes suivantes :

1. Création d'un répertoire projet contenant un fichier texte à


copier.
2. Création d'une fiche VCL avec un contrôle bouton.
3. Ecriture du code pour lire la chaîne et l'écrire dans un
fichier.
4. Exécution de l'application.
Copie de la totalité d'une liste de chaînes ( see page 116) La copie d'une liste de chaînes peut avoir l'effet d'ajouter un élément ou
d'écraser une liste de chaînes existante. Cette application VCL ajoute un élément
à une liste de chaînes. Avec une simple modification, elle peut écraser une liste
de chaînes. La création de cette application VCL comprend les étapes suivantes :

1. Création d'une fiche VCL avec des contrôles TButtons,


TComboBox et TMemo.
2
2. Ecriture du code de création d'une liste de chaînes dans
le gestionnaire OnClick de Button1.
3. Ecriture du code de copie de la liste de chaînes dans le
gestionnaire OnClick de Button2.
4. Exécution de l'application.
Création de chaînes ( see page 118) La création de cette application VCL comprend les étapes suivantes :

1. Créer une fiche VCL avec des contrôles TButton et


TComboBox.
2. Ecrire le code de création des chaînes dans le
gestionnaire OnClick de TButton.
3. Exécuter l'application.
Création d'une instance de fiche VCL en utilisant une variable locale ( see Un moyen fiable de créer une instance unique d'une fiche VCL modale consiste
page 119) à utiliser une variable locale d'un gestionnaire d'événement comme référence à
une nouvelle instance. Si vous utilisez une variable locale, peu importe que la
fiche soit créée automatiquement ou non. Le code du gestionnaire d'événement
ne fait pas référence à la variable fiche globale. En utilisant RAD Studio, la
procédure suivante crée une instance de fiche modale dynamiquement. Elle
retire (facultativement) l'appel de la deuxième fiche au démarrage.
La construction de cette application VCL comprend les étapes suivantes :

1. Créer le répertoire projet.


2. Créer deux fiches pour le... suite ( see page 119)

91
RAD Studio 2.5 Procédures VCL

Suppression de chaînes ( see page 121) La création de cette application VCL comprend les étapes suivantes :

1. Créer une fiche VCL avec des contrôles de boutons et de


boîtes liste.
2. Ecrire du code afin d'ajouter des chaînes à une liste.
3. Ecrire du code pour supprimer une chaîne de la liste.
4. Exécuter l'application.
Affichage d'une fiche VCL créée automatiquement ( see page 122) Avec RAD Studio, la procédure suivante crée au moment de la conception une
fiche modale qui est affichée ultérieurement au moment de l'exécution du
programme.
La construction de cette application VCL comprend les étapes suivantes :

1. Créer le répertoire projet.


2. Créer deux fiches pour le projet.
3. Lier les fiches.
4. Créer un contrôle sur la fiche principale pour afficher la
fiche modale, puis écrire le gestionnaire d'événement.
5. Construire et exécuter l'application.
Affichage d'une image bitmap dans une application Fiches VCL ( see page 124) Cette procédure charge une image bitmap à partir d'un fichier et l'affiche sur une
fiche VCL.

1. Créer une fiche VCL avec un contrôle bouton.


2. Fournir une image bitmap.
3. Coder le gestionnaire d'événement onClick du bouton
pour charger et afficher une image bitmap.

2 4. Construire et exécuter l'application.


Affichage d'une image bitmap plein écran dans une application Fiches VCL ( Cette procédure charge une image bitmap à partir d'un fichier et l'affiche dans
see page 125) son intégralité sur une fiche VCL. Elle utilise les propriétés Height et Width de
l'objet Bitmap pour afficher une vue complète de l'image.

1. Créer une fiche VCL avec un contrôle bouton.


2. Fournir une image bitmap.
3. Coder le gestionnaire d'événement onClick du bouton
pour charger et afficher une image bitmap.
4. Construire et exécuter l'application.
Dessin d'un polygone dans une application Fiches VCL ( see page 126) Cette procédure dessine un polygone dans une fiche VCL.

1. Créer une fiche VCL.


2. Coder le gestionnaire d'événement OnPaint de la fiche
pour dessiner un polygone.
3. Construire et exécuter l'application.
Dessin de rectangles et d'ellipses dans une application Fiches VCL ( see page Cette procédure dessine un rectangle et une ellipse dans une fiche VCL.
127)
1. Créer une fiche VCL.
2. Coder le gestionnaire d'événement OnPaint de la fiche
pour dessiner un rectangle et une ellipse.
3. Construire et exécuter l'application.

92
2.5 Procédures VCL RAD Studio

Dessin d'un rectangle arrondi dans une application Fiches VCL ( see page 128) Cette procédure dessine un rectangle arrondi dans une fiche VCL.

1. Créer une fiche VCL et coder le gestionnaire d'événement


OnPaint de la fiche.
2. Construire et exécuter l'application.
Dessin de lignes droites dans une application Fiches VCL ( see page 128) Cette procédure dessine deux diagonales droites sur une image dans une fiche
VCL.

1. Créer une fiche VCL.


2. Coder le gestionnaire d'événement OnPaint de la fiche
pour dessiner les lignes droites.
3. Construire et exécuter l'application.
Création dynamique d'une fiche VCL modale ( see page 129) Toutes les fiches de votre application n'ont pas besoin d'être en mémoire
simultanément. Pour réduire la quantité de mémoire requise au moment du
chargement, votre application peut créer des fiches uniquement lorsqu'elles
doivent être disponibles pour être utilisées. Une boîte de dialogue, par exemple,
n'a besoin d'être en mémoire que pendant le temps où l'utilisateur interagit avec
elle. En utilisant RAD Studio, la procédure suivante crée une instance de fiche
modale dynamiquement. La principale différence entre la création dynamique
d'une fiche et l'affichage d'une fiche VCL créée automatiquement réside dans le
fait que vous supprimez l'appel de la deuxième fiche... suite ( see page 129)
Création dynamique d'une fiche VCL non modale ( see page 131) Une fiche non modale est une fenêtre qui s'affiche jusqu'à ce qu'elle soit
masquée par une autre fenêtre ou jusqu'à sa fermeture ou sa réduction par
l'utilisateur. Avec RAD Studio, la procédure suivante crée une fiche non modale
dynamiquement.
La construction de cette application VCL comprend les étapes suivantes :

1. Créer le répertoire projet.


2. Créer deux fiches pour le projet.
3. Retirer l'appel de la deuxième fiche au démarrage.
2
4. Lier les fiches.
5. Créer un contrôle sur la fiche principale pour créer et
afficher la fiche modale, puis écrire le gestionnaire
d'événement.
6. Construire et exécuter l'application.
Parcours des chaînes d'une liste ( see page 132) Cette application VCL crée d'abord une liste de chaînes. Elle parcourt ensuite les
chaînes, en transformant tous les caractères de chaînes en majuscule. Elle est
constituée des étapes suivantes :

1. Créer une fiche VCL avec des boutons et des contrôles


TListBox.
2. Ecrire du code pour créer une liste de chaînes et ajouter
des chaînes à cette liste.
3. Ecrire du code pour parcourir la liste de chaînes afin de
traiter les caractères des chaînes.
4. Exécuter l'application.
Construction d'une application multithread ( see page 134) Voici les étapes essentielles de construction d'une application Fiches VCL
multithread avec un objet thread en utilisant RAD Studio.
Ecriture du code de nettoyage ( see page 134)
Eviter les accès de threads simultanés dans la même mémoire ( see page 134) Utilisez ces techniques de base pour empêcher les autres threads d'accéder à la
même mémoire que votre thread :

1. Verrouiller les objets.


2. Utiliser les sections critiques.
3. Utiliser le synchronisateur à écriture exclusive et lecture
multiple.

93
RAD Studio 2.5 Procédures VCL

Définition de l'objet thread ( see page 136)


Gestion des exceptions ( see page 139)
Initialisation d'un thread ( see page 139)
Utilisation du thread VCL principal ( see page 140) L'utilisation du thread VCL principal comprend les étapes suivantes :

1. Créer une routine distincte pour gérer les messages


Windows reçus par les composants de votre application.
2. Appeler régulièrement CheckSynchronize.
3. Déclarer, si nécessaire, des variables locales aux threads
pour une utilisation exclusive par votre thread.
Attente des threads ( see page 142) Voici les procédures qui peuvent être utilisées pour attendre les threads.

• Attendre la fin d'exécution d'un thread


• Attendre l'achèvement d'une tâche
• Vérifier si un autre thread attend la fin de votre thread
Ecriture de la fonction Thread ( see page 144) La méthode Execute constitue la fonction thread. Vous pouvez la concevoir
comme un programme qui est exécuté par l'application, à cette différence près
qu'il partage le même espace de processus. L'écriture d'une fonction thread est
plus délicate que celle d'un programme distinct car il faut prendre garde à ne pas
écraser la mémoire utilisée par d'autres processus de l'application. D'un autre
côté, comme le thread partage le même espace de processus que les autres
threads, il est possible d'utiliser la mémoire partagée pour faire communiquer les
threads.
Insertion d'une image bitmap dans un contrôle d'une application Fiches VCL ( Cette procédure ajoute une image bitmap à une boîte à options d'une application
see page 144) Fiches VCL.

1. Créer une fiche VCL.


2. Ajouter des composants à la fiche.
2 3. Définir des propriétés des composants dans l'inspecteur
d'objets.
4. Ecrire des gestionnaires d'événements pour l'action de
dessin des composants.
5. Construire et exécuter l'application.
Lecture d'une chaîne et écriture de cette chaîne dans un fichier ( see page 145) La création de cette application VCL comprend les étapes suivantes :

1. Création d'une fiche VCL avec un contrôle bouton.


2. Ecriture du code pour lire la chaîne et l'écrire dans un
fichier.
3. Exécuter l'application.
Renommage de fichiers ( see page 146) La création de cette application VCL comprend les étapes suivantes :

1. Créer un répertoire projet contenant un fichier à


renommer.
2. Créer une fiche VCL avec des contrôles de boutons et de
libellés.
3. Ecrire du code pour renommer le fichier.
4. Exécuter l'application.
Ajout et tri de chaînes ( see page 147) La création de cette application VCL comprend les étapes suivantes :

1. Créer une fiche VCL avec des contrôles Button, Label et


TListBox.
2. Ecrire du code pour ajouter et trier des chaînes.
3. Exécuter l'application.

94
2.5 Procédures VCL RAD Studio Construction d'une application console

Création d'un bouton ActiveX Fiches VCL ( see page 148) Comme un contrôle Delphi, un contrôle ActiveX génère du code de programme
lorsque vous placez le composant sur une fiche ou un autre conteneur logique
dans l'EDI. La principale différence entre un contrôle ActiveX et un contrôle
Delphi réside dans le fait qu'un contrôle ActiveX est indépendant du langage.
Vous pouvez créer des contrôles ActiveX pour le déploiement vers plusieurs
environnements de programmation sous Windows, pas seulement Delphi ou
C++Builder.
Cette procédure utilise l'expert ActiveX Fiches VCL pour créer un contrôle
ActiveX. Pour tester le contrôle, vous pouvez l'installer sur votre machine comme
un composant VCL dans l'EDI. Pour installer... suite ( see page 148)
Création d'une fiche active VCL ActiveX ( see page 150) Comme un contrôle Delphi, un contrôle ActiveX génère du code de programme
lorsque vous placez le composant sur une fiche ou un autre conteneur logique
dans l'EDI. La principale différence entre un contrôle ActiveX et un contrôle
Delphi réside dans le fait qu'un contrôle ActiveX est indépendant du langage.
Vous pouvez créer des contrôles ActiveX pour le déploiement vers plusieurs
environnements de programmation sous Windows, pas seulement Delphi ou
C++Builder, par exemple.
Cette procédure utilise l'expert de fiche active ActiveX Fiches VCL pour créer
une fiche active contenant deux composants. Pour tester le contrôle, vous
pouvez le déployer sur le... suite ( see page 150)
Construction d'une application de navigateur Web Fiches VCL ( see page 151) La création de l'application de navigateur Web comprend les étapes suivantes :

1. Créer une fiche VCL avec un contrôle bouton.


2. Ajouter un composant TWebBrowser à la fiche.
3. Ajouter des contrôles pour entrer une URL et lancer le
navigateur.
4. Ecrire du code pour lancer le navigateur lorsque
l'utilisateur clique sur un bouton.
5. Exécuter l'application.
Création d'une application qui utilise les contrôles ruban ( see page 152) Cette procédure décrit la création d'une application qui utilise les contrôles ruban.
La fonctionnalité ruban est dérivée du composant TRibbon. Lorsque le ruban
utilise d'autres composants, aucun composant fondamental n'est recensé sur la
palette d'outils.
2
Composants :

1. TRibbon : Composant visuel principal qui fournit le plus


de fonctionnalités.
2. TRibbonApplicationMenuBar : Composant qui fournit la
fonctionnalité du menu d'application.
3. TRibbonQuickAccessToolbar : Composant qui fournit la
fonctionnalité de la barre d'outils d'accès rapide.
4. TRibbonPage : Composant qui représente la page du
ruban actuellement visible
5. TRibbonGroup : Composant dans lequel sont affichées
toutes les commandes de pages. Les commandes doivent
être placées dans un groupe.
Ajout de commandes au ruban ( see page 153) Cette rubrique suit en séquence la création d'une application ruban à l'aide de
l'expert Application Ruban ou des étapes manuelles décrites dans Création d'une
application qui utilise les contrôles ruban ( see page 152).
Cette rubrique suppose que vous êtes familier avec le composant
TActionManager et les composants associés à son utilisation. De nombreuses
nouvelles propriétés ont été ajoutées afin de prendre en charge les exigences de
ruban. La plupart des propriétés existantes sont sans effet quand elles sont
modifiées sur une commande qui est affichée sur le ruban.
Par exemple :

• Les petits boutons affichent toujours leur glyphe sur la


gauche du... suite ( see page 153)

95
Développement d'une application Windows RAD Studio 2.5 Procédures VCL

2.5.1 Construction d'une application console "Hello World"


Windows
Cette application console "Hello World" Windows illustre les étapes essentielles de la création d'une application Windows dans
Delphi ou C++. L'application utilise Windows, une fenêtre console et un événement, et affiche une boîte de dialogue en réponse
à une action de l'utilisateur.

Pour créer l'application console "Hello world"


1. Créez une application console Windows.
2. Créez la logique.
3. Exécutez l'application.

Pour créer une application console Windows


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi ou Projets C++Builder et double-cliquez sur
Application console.
3. Pour C++, dans la boîte de dialogue Nouvelle application console, assurez-vous que les cases Utiliser la VCL et
Multi-Thread ne sont pas cochées, et que la case Application console est cochée. Cliquez ensuite sur OK.

Pour associer du code à la fenêtre console


2 1. Dans le template de code affiché dans l'éditeur de code : Pour Delphi, entrez les instructions suivantes après le mot clé try
et devant le mot clé except :
Writeln('Bonjour!');

ReadLn;
Pour C++, entrez l'instruction suivante après #pragma hdrstop :
#include <iostream>
2. Pour C++, entrez le code suivant après l'accolade d'ouverture ({) :
std::cout<<"Bonjour!"<<std::endl;
std::cin.ignore();
3. Enregistrez l'application.

Pour exécuter l'application "Hello World"


1. Choisissez Exécuter Exécuter. L'application se compile et affiche une fenêtre console comportant le message "Bonjour!".
2. Appuyez sur la touche Entrée. La fenêtre console se ferme quand le programme se termine.
Voir aussi
Vue globale de Windows ( see page 55)

Construction d'une application Windows ( see page 97)

Construction des menus d'applications ( see page 97)

96
2.5 Procédures VCL RAD Studio Construction des menus d'applications

2.5.2 Développement d'une application Windows


La procédure suivante illustre les étapes essentielles de la construction d'une application Windows.

Pour créer un projet Windows


1. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi, puis double-cliquez sur Application. Le
concepteur Windows s'affiche.
2. Au besoin, sélectionnez la vue Conception.
3. A partir de la palette d'outils, faites glisser des composants dans le concepteur pour créer l'interface utilisateur.
4. Associez de la logique aux contrôles.

Pour associer du code à un contrôle


1. Dans le concepteur, double-cliquez sur le composant auquel vous souhaitez appliquer la logique. L'éditeur de code apparaît,
avec le curseur placé entre les mots réservés begin et end dans le gestionnaire d'événement.
2. Codez la logique de votre application.
3. Enregistrez et compilez l'application.
Voir aussi
Vue globale de Windows ( see page 55)

Construction d'une application "Hello world" Windows ( see page 96)

Construction de menus d'application Windows ( see page 97) 2

2.5.3 Construction des menus d'applications


Les menus constituent pour les utilisateurs un moyen commode d'exécuter des commandes regroupées logiquement. Vous
pouvez ajouter ou supprimer des éléments de menu ou les déplacer pour réorganiser les éléments lors de la conception. Outre
les composants TMainMenu et TPopupMenu, la palette d'outils contient aussi TActionMainMenuBar, TActionManager et
TActionToolBar.

Pour créer des menus d'applications


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Application Fiches VCl. Le concepteur Windows s'affiche.
3. Construisez les menus d'applications.
4. Utilisez le concepteur de menus.
5. Créez un gestionnaire d'événement pour chaque élément de menu.
6. Déplacez les éléments de menus.
7. Ajoutez des images aux éléments de menus.

Pour construire des menus d'applications


1. Dans la catégorie Standard de la palette d'outils, ajoutez un composant TMainMenu ou TPopupMenu à votre fiche. Une
représentation visuelle du menu apparaît sur le concepteur.

97
Construction des menus d'applications RAD Studio 2.5 Procédures VCL

Remarque: Un composant TMainMenu


crée un menu attaché à la barre de titre de la fiche. Un composant TPopupMenu crée un menu qui apparaît lorsque
l'utilisateur clique avec le bouton droit de la souris sur la fiche.
2. Pour voir le menu, si la fiche est visible, cliquez sur la fiche. Le menu apparaît dans la fiche exactement tel qu'il apparaîtra à
l'exécution du programme.
3. Pour supprimer un élément de menu, sélectionnez l'élément de menu que vous voulez supprimer. Appuyez sur Suppr.
4. Pour modifier des éléments de menus, sélectionnez la fiche VCL, sélectionnez l'élément du menu que vous voulez modifier et
modifiez ses propriétés.
5. Pour que l'élément de menu soit une ligne de séparation, placez le curseur sur le menu où vous voulez voir apparaître un
séparateur et entrez un signe moins (-) comme libellé ou appuyez sur la touche moins (-).
6. Pour spécifier un raccourci clavier pour un élément de menu, dans l'inspecteur d'objets, définissez la propriété ShortCut.

Pour utiliser le concepteur de menus


1. Sélectionnez un composant menu sur la fiche.
2. Double-cliquez sur le composant menu. La fenêtre du concepteur de menus s'ouvre.
Remarque: Vous pouvez également ouvrir le concepteur de menus
en cliquant sur le bouton points de suspension (...) à côté de la propriété Items dans l'inspecteur d'objets.
3. Pour nommer un composant menu, dans l'inspecteur d'objets, définissez la propriété Caption.
Conseil: Delphi dérive la propriété Name du libellé, par exemple si vous affectez à la propriété Caption d'un élément de
menu la valeur File, Delphi affectera à la propriété Name de cet élément la valeur File1. Par contre, si vous renseignez
d'abord la propriété Name, avant de renseigner la propriété Caption, Delphi laissera la propriété Caption vide jusqu'à ce que
vous saisissiez une valeur.

2
4. Cliquez avec le bouton droit de la souris n'importe où dans le concepteur de menus pour utiliser le menu contextuel du
concepteur de menus. Une liste déroulante s'ouvre. Il s'agit du menu contextuel du concepteur de menus.
5. Pour insérer un emplacement en dessous ou à la droite du curseur, choisissez Insérer dans le menu contextuel.
6. Pour supprimer l'élément de menu sélectionné (et tous ses sous-éléments, s'il y a lieu), cliquez sur Supprimer dans le menu
contextuel.
7. Pour parcourir les menus d'une fiche, choisissez Sélectionner un menu dans le menu contextuel. La boîte de dialogue
Sélection de menu s'affiche. Elle énumère tous les menus associés à la fiche dont le menu est actuellement ouvert dans le
concepteur de menus.
8. Dans la liste de la boîte de dialogue Sélection de menu, choisissez le menu que vous souhaitez consulter ou modifier.

Pour créer un gestionnaire d'événement pour un élément de menu


1. Dans le concepteur, double-cliquez sur l'élément de menu auquel vous souhaitez ajouter un gestionnaire d'événement. Le
concepteur de code apparaît, avec le curseur placé entre des crochets de gestionnaire d'événement.
2. Codez la logique de l'élément de menu.
3. Enregistrez et compilez l'application.

Pour déplacer des éléments de menus


1. Pour déplacer un élément de menu dans la barre de menu souhaitée, déplacez l'élément jusqu'à ce que la pointe du curseur
de déplacement désigne la nouvelle position.
2. Relâchez le bouton de la souris.
3. Pour déplacer un élément de menu dans une liste de menus, déplacez l'élément jusqu'à ce que la pointe du curseur de
déplacement désigne le nouveau menu.
4. Relâchez le bouton de la souris.

98
2.5 Procédures VCL RAD Studio Construction d'une application Fiches VCL

Pour ajouter des images à des éléments de menus


1. Dans la palette d'outils, déposez un composant TMainMenu ou TPopupMenu sur la fiche.
2. A partir de la palette d'outils, déposez un composant TImageList sur la fiche.
3. Double-cliquez sur le composant TImageList. L'éditeur ImageList s'affiche.
4. Cliquez sur Ajouter pour sélectionner le bitmap ou le groupe de bitmaps que vous souhaitez utiliser dans le menu.
5. Sélectionnez le bitmap voulu et cliquez sur OK.
6. Dans l'inspecteur d'objets, affectez à la propriété Images du composant TMainMenu ou TPopupMenu l'image que vous
avez sélectionnée dans l'éditeur ImageList.
Voir aussi
Vue globale de Windows ( see page 55)

Construction d'une application Windows ( see page 97)

TActionMainMenuBar

TActionManager

TActionToolBar

2.5.4 Construction d'une application Fiches VCL avec des


composants d'aide à la décision
2
La création d'une fiche avec des tableaux et des graphes de données multidimensionnelles se compose des étapes majeures
suivantes :

1. Création d'une fiche VCL.


2. Ajout d'une requête de décision et d'un ensemble de données.
3. Ajout d'un cube de décision.
4. Ajout d'une source de décision.
5. Ajout éventuel d'un pivot de décision.
6. Ajout d'un ou plusieurs graphes de décision ou d'une ou plusieurs grilles de décision.
7. Initialisation de la propriété Active de la requête de décision (ou d'un autre composant ensemble de données) à True.

Pour créer une fiche VCL


1. Choisissez Fichier Nouveau Autre Projets Delphi, puis double-cliquez sur l'icône Application Fiches VCL. Le
concepteur de fiches VCL apparaît.
2. Si nécessaire, cliquez sur Form1 pour rendre la fenêtre active.

Pour ajouter un ensemble de données de décision


1. Sur la page Cube de décision de la palette d'outils, ajoutez un composant DecisionQuery en haut de la fiche.
Conseil: Placez les composants non visuels comme celui-ci dans le coin supérieur gauche de la fiche de manière à les
séparer des composants visuels que vous allez ajouter.

2. Cliquez avec le bouton droit de la souris sur le composant DecisionQuery, et sélectionnez Editeur de requête de décision....

99
Construction d'une application Fiches VCL RAD Studio 2.5 Procédures VCL

La boîte de dialogue Editeur de requête de décision apparaît.


3. Sur l'onglet Dimensions/récapitulatifs, sélectionnez la base de données BCDEMOS dans la liste déroulante Base de
données : .
4. Dans la liste déroulante Table :, sélectionnez la table parts.db. La boîte liste Liste des champs disponibles : affiche les
champs de la table parts.db.
5. Utilisez CTRL+clic pour sélectionner les champs PartNo, OnOrder et Cost. Cliquez ensuite sur le bouton flèche droite à côté
de la boîte liste Dimensions : . PartNo, OnOrder et Cost s'affichent dans la boîte liste.
6. Sélectionnez le champ OnOrder ; cliquez ensuite sur le bouton flèche droite à côté de la boîte liste Récapitulatifs : et
sélectionnez nombre dans le menu déroulant qui s'affiche. COUNT(OnOrder) s'affiche dans la boîte liste Récapitulatifs : .
7. Sélectionnez le champ Cost dans la boîte liste Liste des champs disponibles :, puis cliquez sur le bouton flèche droite à
côté de la boîte liste Récapitulatifs : et sélectionnez somme dans le menu déroulant qui s'affiche. SUM(Cost) s'affiche dans
la boîte liste Récapitulatifs : .
8. Cliquez sur OK pour fermer l'éditeur de requête de décision.
Remarque: Lorsque vous utilisez l'éditeur de requête de décision, la requête est initialement gérée en utilisant la syntaxe
SQL ANSI-92 puis traduite (si nécessaire) dans le dialecte utilisé par le serveur. L'éditeur ne lit et n'affiche que du SQL ANSI
standard. La traduction dans le dialecte approprié est affectée automatiquement à la propriété SQL du TDecisionQuery. Pour
modifier une requête, éditez la version ANSI-92 dans l'éditeur de requête de décision et non celle de la propriété SQL.

Pour ajouter un cube de décision


1. Sur la page Cube de décision de la palette d'outils, ajoutez un composant cube de décision dans le coin supérieur gauche
de la fiche.
2. Dans l'inspecteur d'objets, sélectionnez DecisionQuery1 dans la liste déroulante à côté de la propriété DataSet du cube de
décision.

2 Pour ajouter une source de décision


1. Sur la page Cube de décision de la palette d'outils, ajoutez un composant source de décision dans le coin supérieur
gauche de la fiche.
2. Dans l'inspecteur d'objets, sélectionnez DecisionCube1 dans la liste déroulante à côté de la propriété DecisionCube de la
source de décision.

Pour ajouter un pivot de décision


1. Sur la page Cube de décision de la palette d'outils, ajoutez un composant DecisionPivot facultatif en haut de la fiche.
Conseil: Le pivot de décision s'affiche dans la fenêtre de l'application finale. Placez-le à droite des composants non visuels.

2. Dans l'inspecteur d'objets, sélectionnez DecisionSource1 dans la liste déroulante à côté de la propriété DecisionSource du
pivot de décision.

Pour créer une grille de décision


1. Sur la page Cube de décision de la palette d'outils, ajoutez un composant grille de décision à la fiche juste à côté du pivot
de décision.
2. Dans l'inspecteur d'objets, sélectionnez DecisionSource1 dans la liste déroulante à côté de la propriété DecisionSource de
la grille de décision.

Pour créer un graphe de décision


1. Sur la page Cube de décision de la palette d'outils, ajoutez un composant graphe de décision à la fiche juste à côté de la
grille de décision.
2. Dans l'inspecteur d'objets, sélectionnez DecisionSource1 dans la liste déroulante à côté de la propriété DecisionSource du
graphe de décision.

100
2.5 Procédures VCL RAD Studio Construction d'une application MDI Fiches

Pour exécuter l'application


1. Dans l'inspecteur d'objets, sélectionnez True dans le menu déroulant de la propriété Active. Les composants visuels
graphe, grille et pivot de décision affichent des données.
2. Choisissez Exécuter Exécuter pour lancer l'application. L'application exécute et affiche les composants d'aide à la
décision.
3. Utilisez le pivot de décision pour mettre à jour, comme vous le souhaitez, les données affichées dans la grille et dans le
graphe.
Voir aussi
Présentation de la VCL ( see page 46)

2.5.5 Construction d'applications Fiches VCL avec


graphiques
Chacune des procédures ci-dessous permet de construire une application Fiche VCL qui utilise des graphiques. Construisez un
ou plusieurs exemples puis ajoutez d'autres fonctionnalités graphiques à ces applications Fiches VCL de base. *

1. Dessin de lignes droites.


2. Dessin de rectangles et d'ellipses.
3. Dessin d'un polygone.
4. Affichage d'une image bitmap.
2
5. Ajout d'un bitmap dans une boîte à options.
Voir aussi
Présentation de la programmation relative aux graphiques ( see page 2248)

Dessin de lignes droites dans une application VCL ( see page 128)

Dessin de rectangles et d'ellipses dans une application VCL ( see page 127)

Affichage d'une image bitmap dans une application VCL ( see page 124)

Insertion d'une image bitmap dans une boîte à options d'une application VCL ( see page 144)

2.5.6 Construction d'une application MDI Fiches VCL à l'aide


d'un expert
L'expert Application MDI Fiches VCL crée automatiquement un projet qui inclut les fichiers de base pour une application MDI. En
plus du fichier source principal, l'expert crée des fichiers d'unités pour des fenêtres enfants et de boîte de dialogue A propos,
avec les fichiers de fiches et les ressources.

Pour créer une nouvelle application MDI à l'aide d'un expert


1. Choisissez Fichier Nouveau Autre Projets Delphi, puis double-cliquez sur l'icône Application MDI. La boîte de
dialogue de recherche d'un dossier s'affiche.
2. Naviguez dans le dossier dans lequel vous souhaitez stocker les fichiers du projet.

101
Construction d'une application MDI Fiches RAD Studio 2.5 Procédures VCL

3. Cliquez sur OK.


4. Choisissez Exécuter Exécuter pour compiler et lancer l'application.
5. Essayez les commandes configurées automatiquement par l'expert Application MDI.
Voir aussi
Présentation de la VCL ( see page 46)

2.5.7 Construction d'une application MDI Fiches VCL sans


utiliser d'expert
Les étapes de base pour créer une nouvelle application MDI avec une fenêtre enfant sans utiliser d'expert sont les
suivantes :
1. Créez une fiche de fenêtre principale (fenêtre parent MDI).
2. Créez une fiche de fenêtre enfant.
3. La fenêtre principale crée la fenêtre enfant sous le contrôle de l'utilisateur.
4. Ecrivez le code du gestionnaire d'événement pour fermer la fenêtre enfant.
5. Créez le menu principal et les commandes.
6. Ajoutez les gestionnaires d'événements pour les commandes.
7. Compilez l'application et exécutez-la.

2 Pour créer la fiche de fenêtre principale


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Dans l'inspecteur d'objets, initialisez la propriété FormStyle à la valeur fsMDIForm.
3. Entrez un nom plus descriptif, tel que frMain, pour la propriété Name.
4. Enregistrez le fichier d'unité avec un nom plus descriptif, par exemple uMain.pas (Delphi) ou uMain.cpp (C++).

Pour créer une fenêtre enfant


1. Choisissez Fichier Nouveau Fiche.
2. Dans l'inspecteur d'objets, initialisez la propriété FormStyle à la valeur fsMDIChild.
3. Entrez un nom plus descriptif, tels que frChild, pour la propriété Name.
4. Enregistrez le fichier d'unité sous le nom uChild.pas (Delphi) ou uChild.cpp (C++).

Pour avoir la fenêtre principale, créez la fenêtre enfant


1. Choisissez Projet Options Fiches. La boîte de dialogue Options du projet s'affiche.
2. Sélectionnez la fiche frChild dans la liste Fiches créées automatiquement et cliquez sur [>] pour la placer dans la liste
Fiches disponibles, puis cliquez sur OK.
3. Sélectionnez la fiche frMain pour l'activer ; accédez ensuite à la vue Code.
4. Pour Delphi, faites défiler jusqu'à la section uses et ajoutez uChild à la liste. Pour C++, ajoutez #include "uChild.h" à
uMain.h.
5. Pour Delphi, faites défiler jusqu'à la section des déclarations private et entrez la déclaration de procédure suivante :
procedure CreateChildForm(const childName: string);

102
2.5 Procédures VCL RAD Studio Construction d'une application MDI Fiches

Pour C++, ajoutez la déclaration de fonction suivante aux déclarations private: de TfrMain.
void __fastcall CreateChildForm( const AnsiString childName );
6. Pour Delphi, faites défiler jusqu'à la section implementation et entrez le code suivant :
procedure TfrMain.CreateChildForm (const childName: string);
var Child: TfrChild;
begin
Child := TfrChild.Create(Application);
Child.Caption := childName;
end;
Pour C++, ajoutez la déclaration de fonction suivante à uMain.cpp :
void __fastcall TfrMain::CreateChildForm( const AnsiString childName )
{
TfrChild *Child = new TfrChild( Application );
Child->Caption = childName;
}

Pour écrire le code du gestionnaire d'événement pour la fermeture de la fenêtre enfant


1. Si nécessaire, activez la fiche frMain, puis sélectionnez l'onglet Evénements dans l'inspecteur d'objets.
2. Double-cliquez sur l'événement OnClose. L'éditeur de code s'affiche, avec le curseur placé dans le bloc du gestionnaire de
l'événement TfrMain.FormClose (Delphi) ou TfrMain::FormClose (C++).
3. Pour Delphi, entrez le code suivant :
Action := caFree;
Pour C++, entrez le code suivant :
Action = caFree;
2
Pour créer le menu principal et les commandes
1. A partir de la page Standard de la palette d'outils, placez un composant TMainMenu sur la fiche principale.
2. Double-cliquez sur le composant TMainMenu. Le concepteur de menus (frMain.MainMenu1) s'affiche avec le premier élément
de menu vide en surbrillance.
3. Dans l'inspecteur d'objets sur l'onglet Propriétés, entrez mnFile pour la propriété Name et &Fichier pour la propriété
Caption. Appuyez ensuite sur ENTREE. Dans le concepteur de menus, le nom affiché pour le premier élément du menu est
Fichier.
4. Dans le concepteur de menus, sélectionnez Fichier. Un champ de commande vide s'affiche dans le groupe Fichier.
Sélectionnez la commande vide.
5. Dans l'inspecteur d'objets, entrez mnNewChild pour la propriété Name et &Nouvel enfant pour la propriété Caption ;
appuyez ensuite sur ENTREE. Dans le concepteur de menus, le nom de la première commande de fichier affiché est Nouvel
enfant et un champ de commande vide s'affiche juste à côté de Nouvel enfant.
6. Sélectionnez la commande vide.
7. Dans l'inspecteur d'objets, entrez mnCloseAll pour la propriété Name et &Tout fermer pour la propriété Caption ; appuyez
ensuite sur ENTREE. Dans le concepteur de menus, le nom affiché pour la deuxième commande de fichier est Tout fermer.

Pour ajouter des gestionnaires d'événements pour les commandes Nouvel enfant et Tout fermer
1. Si nécessaire, ouvrez le concepteur de menus et sélectionnez Nouvel enfant.
2. Dans l'inspecteur d'objets, double-cliquez sur l'événement OnClick de l'onglet Evénements. L'éditeur de code s'affiche,
avec le curseur placé dans le bloc du gestionnaire de l'événement TfrMain.mnNewChildClick (Delphi) ou
TfrMain::mnNewChildClick (C++).
3. Pour Delphi, entrez le code suivant :
CreateChildForm('Enfant '+IntToStr(MDIChildCount+1));

103
Construction d'une application SDI Fiches RAD Studio 2.5 Procédures VCL

Pour C++, entrez le code suivant :


CreateChildForm( "Enfant " + IntToStr( MDIChildCount + 1 ) );
4. Dans le concepteur de menus, sélectionnez Tout fermer.
5. Dans l'inspecteur d'objets, double-cliquez sur l'événement OnClick de l'onglet Evénements. L'éditeur de code s'affiche,
avec le curseur placé dans le bloc du gestionnaire de l'événement TfrMain.mnCloseAllClick (Delphi) ou
TfrMain::mnCloseAllClick (C++).
6. Pour Delphi, entrez le code suivant :
for i:=0 to MDIChildCount - 1 do
MDIChildren[i].Close;
Pour C++, entrez le code suivant :
for( int i = 0; i < MDIChildCount; i++ ) {
MDIChildren[i]->Close();
}
7. Pour Delphi, déclarez la variable locale i. Les deux premières lignes du code du gestionnaire d'événement doivent apparaître
comme affiché ici lorsque vous avez terminé :
procedure TfrMain.mnCloseAllClick(Sender: TObject);
var i : integer;
Remarque: Le gestionnaire d'événement minimise la fenêtre enfant dans la fenêtre principale. Pour fermer la fenêtre enfant,
vous devez ajouter une procédure OnClose à la fiche enfant (ci-dessous).

Pour fermer la fenêtre enfant


1. Activez la fiche enfant.
2. Dans l'inspecteur d'objets, double-cliquez sur l'événement OnClose de l'onglet Evénements. L'éditeur de code s'affiche,
2 avec le curseur placé dans le bloc du gestionnaire de l'événement TfrChild.FormClose (Delphi) ou
TfrChild::FormClose (C++).
3. Pour Delphi, entrez l'instruction suivante :
Action := caFree;
Pour C++, entrez l'instruction suivante :
Action = caFree;

Pour compiler et exécuter l'application MDI


1. Choisissez Exécuter Exécuter.
2. L'application s'exécute, en affichant la commande Fichier.
3. Choisissez Fichier Nouvel enfant une ou plusieurs fois. Une fenêtre enfant apparaît avec chaque commande Nouvel
enfant.
4. Choisissez Fichier Tout fermer. Les fenêtres enfants se ferment.
Voir aussi
Présentation de la VCL ( see page 46)

2.5.8 Construction d'une application SDI Fiches VCL


Pour créer une nouvelle application SDI
1. Choisissez Fichier Nouveau Autre Projets Delphi, puis double-cliquez sur l'icône Application SDI.

104
2.5 Procédures VCL RAD Studio Création d'un nouveau composant VCL

2. Choisissez un dossier dans lequel enregistrer les fichiers et cliquez sur OK.
3. Choisissez Exécuter Exécuter pour compiler et lancer l'application.
Voir aussi
Présentation de la VCL ( see page 46)

2.5.9 Création d'un nouveau composant VCL


Vous pouvez utiliser l'expert Nouveau composant VCL pour créer un nouveau composant VCL pour votre application. Il détecte
la personnalité du produit que vous utilisez et crée le type de composant approprié.

Métaprocédure : Création d'un nouveau composant VCL


1. Spécifiez un composant ancêtre sur la page Composant ancêtre.
2. Spécifiez le nom de la classe et d'autres propriétés sur la page Composant.
3. Choisissez une des trois méthodes suivantes pour la création d'une unité :
• Créer une unité, sur la page Créer une unité
• Installer l'unité dans un package existant, sur la page Package existant
• Installer l'unité dans un nouveau package, sur la page Nouveau package

Pour spécifier un composant ancêtre


1. Créez un nouveau package pour le nouveau composant en choisissant Fichier Nouveau Autre Projets Delphi et en
double-cliquant sur l'icône Package. Cette étape ajoute un nouveau package au Gestionnaire de projets et active l'option 2
Ajouter l'unité au projet <mon_nouveau_package> sur la page Créer une unité.
2. Dans l'EDI, choisissez Composant Nouveau composant VCL. Cette étape affiche la première page de l'expert Nouveau
composant VCL (la page Composant ancêtre) et charge la page avec des noms de composant, ainsi que l'unité qui définit
chaque composant.
3. Sur la page Composant ancêtre, sélectionnez un composant ancêtre dans la liste.
4. Cliquez sur Suivant. Cela affiche la page Composant de l'expert Nouveau composant VCL.

Pour spécifier le nom de la classe et d'autres propriétés


1. Sur la page Composant, les champs Nom de classe, Page de palette, Nom d'unité et Chemin de recherche sont
préremplis. Vous pouvez accepter les valeurs par défaut de ces champs ou modifier les valeurs en suivant les étapes
ci-après. Si vous souhaitez accepter les valeurs par défaut, passez directement à l'étape 6.
2. Pour modifier le nom de classe par défaut, entrez un autre nom de classe dans la zone de saisie Nom de classe.
3. Pour changer la page de palette par défaut pour le composant, entrez dans la zone de saisie Page de palette le nom de la
zone de la palette d'outils choisie ou cliquez sur la flèche vers le bas pour faire une sélection parmi les zones de la palette
d'outils.
4. Dans la zone de saisie Nom d'unité, vous pouvez entrer ou modifier le chemin complet du nom de l'unité. Cliquez sur [...]
pour naviguer et sélectionner l'unité voulue.
5. Entrez ou modifiez le chemin de recherche dans la zone de saisie Chemin de recherche.
6. Cliquez sur Suivant. Cela ouvre la page Créer une unité de l'expert. Les choix de la page Créer une unité sont les suivants :
• Créer l'unité
• Installer dans un package existant
• Installer dans un nouveau package

105
Conception d'une application Fiches VCL RAD Studio 2.5 Procédures VCL

• Ajouter l'unité au projet <mon_nouveau_package> (cette sélection est présente uniquement si vous avez créé un
nouveau package à la première étape ci-dessus)

Pour créer une unité


1. Sur la page Créer une unité, sélectionnez le bouton radio Créer l'unité.
2. Cliquez sur Terminer. La nouvelle unité s'ouvre dans l'éditeur de code.

Pour installer une unité dans un package existant


1. Sur la page Créer une unité, sélectionnez le bouton radio Installer dans un package existant.
2. Cliquez sur Suivant. Cela génère une liste des packages existants.
3. Sur la page Package existant, sélectionnez le package dans lequel vous souhaitez installer l'unité.
4. Cliquez sur Terminer. La nouvelle unité s'ouvre dans l'éditeur de code.

Pour installer une unité dans un nouveau package


1. Sur la page Créer une unité, sélectionnez le bouton radio Installer dans un nouveau package.
2. Cliquez sur Suivant.
3. Sur la page Nouveau package, entrez le nom du package dans la zone de saisie Nom du package.
4. Dans la zone de saisie Description, entrez la description de votre nouveau package.
5. Cliquez sur Terminer. La nouvelle unité s'ouvre dans l'éditeur de code.

Pour installer une unité dans le package créé avant de lancer l'expert
1. Sur la page Créer une unité, sélectionnez Ajouter l'unité au projet <mon_nouveau_package>.
2 2. Cliquez sur Terminer. La nouvelle unité s'ouvre dans l'éditeur de code.
Voir aussi
Présentation de la VCL ( see page 46)

2.5.10 Conception d'une application Fiches VCL de base de


données ADO
La procédure suivante indique comment construire une application de base de données ADO.

La construction d'une application VCL ADO comprend les étapes principales suivantes :

1. Définition de la connexion à la base de données.


2. Définition de l'ensemble de données.
3. Installation du fournisseur de données, de l'ensemble de données client et de la source de données.
4. Connexion d'une grille de données aux composants connexion.
5. Exécution de l'application.

Pour ajouter un composant connexion ADO


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. A partir de la page ADO de la palette d'outils, placez un composant ADOConnection sur la fiche.

106
2.5 Procédures VCL RAD Studio Conception d'une application Fiches VCL

3. Double-cliquez sur le composant ADOConnection pour afficher la boîte de dialogue ConnectionString.


4. Si nécessaire, sélectionnez Utiliser la chaîne de connexion puis cliquez sur le bouton Construire pour afficher la boîte de
dialogue Propriétés de liaison.
5. Sur la page Fournisseur de la boîte de dialogue, sélectionnez Fournisseur Microsoft Jet 4.0 OLE DB puis cliquez sur le
bouton Suivant pour afficher la page Connexion.
6. Sur la page Connexions, cliquez sur le bouton points de suspension pour parcourir la base de données dbdemos.mdb. Le
chemin par défaut de cette base de données est C:\Program Files\Fichiers communs\Borland Shared\Data.
7. Cliquez sur Tester la connexion pour confirmer la connexion. L'état de la connexion s'affiche dans une boîte de dialogue.
8. Cliquez sur OK pour fermer la boîte de dialogue des propriétés de liaison de données. Cliquez sur OK pour fermer la boîte
de dialogue ConnectionString.

Pour configurer l'ensemble de données


1. Sur la page ADO, placez un composant ADODataSet en haut de la fiche.
2. Dans l'inspecteur d'objets, sélectionnez la liste déroulante de la propriété Connection. Attribuez-lui la valeur
ADOConnection1.
3. Affectez une commande SQL à la propriété CommandText ; par exemple, Select * from orders. Vous pouvez soit taper
l'instruction Select dans l'inspecteur d'objets, soit cliquer sur les points de suspension à droite de CommandText pour
afficher l'éditeur de CommandText, dans lequel vous pouvez construire votre propre requête.
Conseil: Si vous avez besoin d'une assistance particulière lorsque vous utilisez l'éditeur de CommandText
, cliquez sur le bouton Aide.
4. Initialisez la propriété Active à True pour ouvrir l'ensemble de données. Vous êtes invité à vous connecter. Utilisez admin
comme nom d'utilisateur et ne saisissez pas de mot de passe.

Pour ajouter le fournisseur 2


1. Sur l'onglet Accès aux données, placez un composant DataSetProvider en haut de la fiche.
2. Dans l'inspecteur d'objets, sélectionnez la liste déroulante de la propriété DataSet. Attribuez-lui la valeur ADODataSet1.

Pour ajouter l'ensemble de données client


1. Sur la page Accès aux données, placez un composant ClientDataSet à droite du composant DataSetProvider sur la fiche.
2. Dans l'inspecteur d'objets, sélectionnez la liste déroulante de la propriété ProviderName. Attribuez-lui la valeur
DataSetProvider1.
3. Définissez la propriété Active par True pour permettre la transmission des données à votre application. Une source de
données se connecte à l'ensemble de données client par des contrôles orientés données. Chaque contrôle orienté données
doit être associé à un composant source de données afin de pouvoir afficher et manipuler des données. De même, tous les
ensembles de données doivent être associés à un composant source de données afin que leurs données puissent être
affichées et manipulées dans les contrôles orientés données de la fiche.

Pour ajouter la source de données


1. Sur la page Accès aux données de la palette d'outils, placez un composant DataSource à droite du composant
ClientDataSet sur la fiche.
2. Dans l'inspecteur d'objets, sélectionnez la liste déroulante de la propriété DataSet. Attribuez-lui la valeur ClientDataSet1.

Pour connecter un DataGrid au DataSet


1. Sur la page Contrôles de données de la palette d'outils, placez un composant DBGrid sur la fiche.
2. Dans l'inspecteur d'objets, sélectionnez la liste déroulante de la propriété DataSource. Attribuez la valeur DataSource1 à la
source de données.
3. Choisissez Exécuter Exécuter.

107
Création d'actions dans une application RAD Studio 2.5 Procédures VCL

4. Vous êtes invité à vous connecter. Entrez admin comme nom d'utilisateur et n'entrez pas de mot de passe. L'application se
compile et affiche une fiche VCL comportant un composant DBGrid.
Voir aussi
Présentation de la VCL ( see page 46)

2.5.11 Construction d'une application Fiches VCL


La procédure suivante illustre les étapes essentielles de la construction d'une application Fiches VCL avec RAD Studio.

Pour créer une fiche VCL


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. A partir de la palette d'outils, placez des composants sur la fiche pour créer l'interface utilisateur.
3. Ecrivez le code des contrôles.

Pour associer du code à un contrôle


1. Double-cliquez sur le composant auquel vous souhaitez appliquer la logique. L'éditeur de code apparaît, avec le curseur
dans le bloc de code du gestionnaire d'événement.
2. Codez la logique de votre application.
3. Enregistrez et compilez l'application.
Voir aussi
2
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL "Hello World" ( see page 109)

Construction d'une application MDI Fiches VCL sans utiliser d'expert ( see page 102)

Utilisation de ActionManager pour créer des actions dans une application Fiches VCL ( see page 110)

2.5.12 Création d'actions dans une application Fiches VCL


Dans RAD Studio, la procédure suivante illustre comment créer des actions avec l'outil ActionList. Elle configure une application
simple et explique comment créer un élément de menu fichier avec une action d'ouverture de fichier.

La construction d'une application VCL avec ActionList comprend les étapes principales suivantes :

1. Créez une fenêtre principale et ajoutez des outils pour créer un menu principal et une action d'ouverture de fichier.
2. Ajoutez la catégorie Fichier au menu principal.
3. Ajoutez l'action d'ouverture de fichier à la catégorie Fichier.
4. Construction et exécution de l'application.

Pour créer une fenêtre principale


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Dans la catégorie Standard de la palette d'outils, ajoutez un composant TMainMenu et TActionList à la fiche.

108
2.5 Procédures VCL RAD Studio Construction d'une application Fiches VCL

Conseil: Pour afficher des icônes pour les composants non visuels tels que ActionList1, choisissez
Outils->Options->Options d'environnement
, sélectionnez Concepteur VCL dans les options Delphi, cliquez sur Afficher libellés des composants puis sur OK.

Pour ajouter la catégorie Fichier au menu principal


1. Double-cliquez sur MainMenu1 dans la fiche. L'éditeur MainMenu1 s'affiche avec la première catégorie de commande vide
sélectionnée.
2. Dans l'inspecteur d'objets, entrez &Fichier pour la propriété Caption et appuyez sur la touche ENTREE. Fichier apparaît
dans le menu principal.
3. Cliquez sur Fichier dans l'éditeur MainMenu1. La première action vide sous la commande Fichier s'affiche. Sélectionnez
l'action vide.
4. Double-cliquez sur ActionList1 dans la fiche. L'éditeur ActionList s'affiche.
5. Dans l'éditeur, sélectionnez Nouvelle action standard dans la liste déroulante pour afficher la boîte de dialogue Classes
d'actions standard.
6. Faites défiler jusqu'à la catégorie Fichier et cliquez sur l'action TFileOpen.
7. Cliquez sur OK pour fermer la boîte de dialogue. Fichier s'affiche dans la boîte liste Catégories dans l'éditeur ActionList.
8. Cliquez sur Fichier dans l'éditeur. L'action FileOpen1 s'affiche dans la boîte liste Action.

Pour ajouter l'action d'ouverture de fichier à la catégorie Fichier


1. Double-cliquez sur MainMenu1, si nécessaire, pour afficher l'éditeur MainMenu1. Sélectionnez l'action vide sous la catégorie
Fichier.
2. Dans l'inspecteur d'objets, entrez &Ouvrir pour la propriété Caption et sélectionnez FileOpen1 dans la liste déroulante de la
propriété Action. Appuyez ensuite sur ENTREE. Ouvrir... s'affiche dans l'action vide de l'éditeur MainMenu1.
2
Pour construire et exécuter l'application
1. Choisissez Exécuter Exécuter. L'application s'exécute et affiche une fiche avec la barre de menus principale et le menu
Fichier.
2. Choisissez Fichier Ouvrir dans l'application. La boîte de dialogue d'ouverture de fichier standard apparaît.
Voir aussi
Présentation de la VCL ( see page 46)

2.5.13 Construction d'une application Fiches VCL "Hello


World"
Cette procédure montre comment construire une simple application Fiches VCL "Hello world" avec Delphi ou C++. Malgré sa
simplicité, l'application Fiches VCL "Hello world" illustre les étapes essentielles de la création d'une application Fiches VCL.
L'application utilise une fiche VCL, un contrôle et un événement, et affiche une boîte de dialogue en réponse à une action de
l'utilisateur.

La création de l'application "Hello world" comprend les étapes suivantes :

1. Création d'une fiche VCL avec un contrôle bouton.


2. Ecriture du code pour afficher "Hello Word" quand l'utilisateur clique sur le bouton.
3. Exécution de l'application.

109
Utilisation de ActionManager pour créer RAD Studio 2.5 Procédures VCL

Pour créer une fiche VCL


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Cliquez sur la fiche VCL pour afficher la vue de la fiche.
3. Sur la page Standard de la palette d'outils, placez un composant TButton sur la fiche.

Pour afficher la chaîne "Hello world"


1. Sélectionnez Button1 sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur le champ d'action OnClick de l'onglet Evénements. L'éditeur de code
s'affiche, avec le curseur placé dans le bloc du gestionnaire d'événement Button1Click.
3. Pour Delphi, déplacez le curseur avant le mot réservé begin, puis appuyez sur la touche Entrée. Cette action crée une
nouvelle ligne au-dessus du bloc de code. Pour C++, placez le curseur après l'accolade ouvrante ({), puis appuyez sur la
touche Entrée.
4. Pour Delphi, placez le curseur sur la nouvelle ligne créée, puis tapez la déclaration de variable suivante :
var s: string;
Pour C++, entrez le code suivant :
AnsiString s;
5. Pour Delphi, placez le curseur dans le bloc de code, puis tapez le code suivant :
s:= 'Hello world!';
ShowMessage( s );
Pour C++, entrez le code suivant :
2 s = "Hello world!";
ShowMessage( s );

Pour exécuter l'application "Hello world"


1. Choisissez Exécuter Exécuter pour construire et exécuter l'application. La fiche apparaît avec un bouton appelé Button1.
2. Cliquez sur Button1. Une boîte de dialogue affiche le message "Hello World!"
3. Fermez la fiche VCL pour revenir à l'EDI.
Voir aussi
Présentation de la VCL ( see page 46)

2.5.14 Utilisation de ActionManager pour créer des actions


dans une application Fiches VCL
Dans RAD Studio, la procédure suivante illustre comment créer des actions avec ActionManager. Elle configure une interface
utilisateur simple avec une zone de texte, adaptée à une application d'édition de texte, et explique comment créer un élément de
menu fichier avec une action d'ouverture de fichier.

La construction d'une application VCL avec ActionManager comprend les étapes principales suivantes :

1. Création d'une fenêtre principale.


2. Ajout d'une action d'ouverture de fichier à ActionManager.
3. Création du menu principal.

110
2.5 Procédures VCL RAD Studio Conception d'une application Fiches VCL

4. Ajout de l'action au menu.


5. Construction et exécution de l'application.

Pour créer une fenêtre principale et ajouter une action d'ouverture de fichier
1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Sur la page Supplément de la palette d'outils, ajoutez un composant TActionManager sur la fiche.
3. Double-cliquez sur TActionManager pour afficher l'éditeur de gestionnaire d'actions.
Conseil: Pour afficher les libellés des composants non visuels comme ActionManager, choisissez Outils->Options
d'environnement
. Sur l'onglet Concepteur, cochez Afficher les libellés des composants et cliquez sur OK.
4. Au besoin, cliquez sur l'onglet Actions.
5. Sélectionnez Nouvelle action standard dans la liste déroulante pour afficher la boîte de dialogue Classes d'actions
standard.
6. Faites défiler jusqu'à la catégorie Fichier et cliquez sur l'action TFileOpen.
7. Cliquez sur OK pour fermer la boîte de dialogue.
8. Dans l'éditeur de gestionnaire d'actions, sélectionnez la catégorie Fichier. Ouvrir... s'affiche dans la boîte liste Actions : .
9. Cliquez sur Fermer pour fermer l'éditeur.

Pour créer le menu principal


1. Sur la page Supplément de la palette d'outils, placez un composant TActionMainMenuBar sur la fiche.
2. Ouvrez l'éditeur du gestionnaire d'actions, puis sélectionnez la catégorie Fichier dans la boîte de liste Catégories : .
2
3. Faites glisser la catégorie Fichier sur la barre de menus vide. Fichier apparaît dans la barre de menus.

Pour construire et exécuter l'application


1. Choisissez Exécuter Exécuter. L'application s'exécute et affiche une fiche avec la barre de menus principale et le menu
Fichier.
2. Choisissez Fichier Ouvrir. La boîte de dialogue d'ouverture de fichier s'affiche.
Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

Construction d'une application MDI Fiches VCL sans utiliser d'expert ( see page 102)

2.5.15 Conception d'une application Fiches VCL de base de


données dbExpress
La procédure suivante indique comment construire une application de base de données dbExpress.

La construction d'une application Fiches VCL dbExpress comprend les étapes principales suivantes :

1. Définition de la connexion à la base de données.


2. Installation de l'ensemble de données unidirectionnel.
3. Installation du fournisseur de données, de l'ensemble de données client et de la source de données.

111
Conception d'une application Fiches VCL RAD Studio 2.5 Procédures VCL

4. Connexion d'une grille de données aux composants connexion.


5. Exécution de l'application.

Pour ajouter un composant de connexion dbExpress


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. A partir de la page dbExpress de la palette d'outils, placez un composant TSQLConnection sur la fiche.
3. Double-cliquez sur le composant TSQLConnection pour afficher l'éditeur de connexion.
4. Dans l'éditeur de connexion, affectez au champ Nom de connexion la valeur IBConnection.
5. Dans la zone Paramètres de connexion, indiquez dans le champ Database le chemin d'accès au fichier de base de
données InterBase appelé employee.gdb. Par défaut, le fichier se trouve dans C:\Program Files\Fichiers
communs\Borland Shared\Data.
6. Acceptez la valeur des champs Nom d'utilisateur (sysdba) et Mot de passe (masterkey).
7. Cliquez sur OK pour fermer l'éditeur de connexions et enregistrer les modifications.

Pour configurer l'ensemble de données unidirectionnel


1. Sur la page dbExpress de la palette d'outils, placez un composant TSQLDataSet en haut de la fiche.
2. Dans l'inspecteur d'objets, sélectionnez la liste déroulante de la propriété SQLConnection. Attribuez-lui la valeur
TSQLConnection1.
3. Affectez une commande SQL à la propriété CommandText ; par exemple, Select * from SALES. Vous êtes invité à vous
connecter. Utilisez le mot de passe masterkey. Pour la commande SQL, vous pouvez soit taper une instruction Select dans
l'inspecteur d'objets, soit cliquer sur les points de suspension à droite de CommandText pour afficher l'éditeur de
CommandText, dans lequel vous pouvez construire votre propre instruction de requête.
2 Conseil: Si vous avez besoin d'une assistance particulière lorsque vous utilisez l'éditeur de CommandText
, cliquez sur le bouton Aide.
4. Dans l'inspecteur d'objets, initialisez la propriété Active à la valeur True pour ouvrir l'ensemble de données

Pour ajouter le fournisseur


1. Sur la page Accès aux données de la palette d'outils, placez un composant TDataSetProvider en haut de la fiche.
2. Dans l'inspecteur d'objets, sélectionnez la liste déroulante de la propriété DataSet. Attribuez-lui la valeur SQLDataSet1.

Pour ajouter l'ensemble de données client


1. Sur la page Accès aux données de la palette d'outils, placez un composant TClientDataSet à droite du composant
TDataSetProvider sur la fiche.
2. Dans l'inspecteur d'objets, sélectionnez la liste déroulante de la propriété ProviderName. Attribuez-lui la valeur
DataSetProvider1.
3. Définissez la propriété Active par True pour permettre la transmission des données à votre application. Une source de
données se connecte à l'ensemble de données client par des contrôles orientés données. Chaque contrôle orienté données
doit être associé à un composant source de données afin de pouvoir afficher et manipuler des données. De même, tous les
ensembles de données doivent être associés à un composant source de données afin que leurs données puissent être
affichées et manipulées dans les contrôles orientés données de la fiche.

Pour ajouter la source de données


1. Sur la page Accès aux données de la palette d'outils, placez un composant TDataSource à droite du composant
TClientDataSet sur la fiche.
2. Dans l'inspecteur d'objets, sélectionnez la liste déroulante de la propriété DataSet. Attribuez-lui la valeur ClientDataSet1.

112
2.5 Procédures VCL RAD Studio Construction d'une application avec des

Pour connecter un DataGrid au DataSet


1. Sur la page Contrôles de données de la palette d'outils, placez un composant TDBGrid sur la fiche.
2. Dans l'inspecteur d'objets, sélectionnez la liste déroulante de la propriété DataSource. Attribuez la valeur DataSource1 à la
source de données.
3. Choisissez Exécuter Exécuter. Vous êtes invité à saisir un mot de passe. Entrez masterkey. Si vous entrez un mot de
passe incorrect ou si vous n'entrez aucun mot de passe, le débogueur déclenche une exception. L'application se compile et
affiche une fiche VCL comportant un composant DBGrid.
Voir aussi
Présentation de la VCL ( see page 46)

2.5.16 Construction d'une application avec des composants


XML
Cet exemple crée une application Fiches VCL qui utilise un composant XMLDocument pour afficher le contenu d'un fichier XML.

Les étapes de base sont les suivantes :


1. Création d'un document XML.
2. Création d'une fiche VCL.
3. Positionnement d'un composant XMLDocument sur la fiche et association au fichier XML.
4. Création de composants VCL pour permettre l'affichage du contenu du fichier XML. 2
5. Ecriture de gestionnaires d'événements pour afficher le contenu des noeuds enfants XML.
6. Compilation et exécution de l'application.

Pour créer le document XML


1. Copiez le texte ci-dessous dans un fichier dans un éditeur de texte.
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE StockHoldings [
<!ELEMENT StockHoldings (Stock+)>
<!ELEMENT Stock (name)>
<!ELEMENT Stock (price)>
<!ELEMENT Stock (symbol)>
<!ELEMENT Stock (shares)>
]>

<StockHoldings>
<Stock exchange="NASDAQ">
<name>CodeGear</name>
<price>10.375</price>
<symbol>BORL</symbol>
<shares>100</shares>
</Stock>

<Stock exchange="NYSE">
<name>MyCompany</name>
<price>8.75</price>
<symbol>MYCO</symbol>
<shares type="preferred">25</shares>
</Stock>
</StockHoldings>

113
Construction d'une application avec des RAD Studio 2.5 Procédures VCL

2. Enregistrez le fichier sur votre disque local en tant que document XML. Donnez-lui un nom semblable à stock.xml.
3. Ouvrez le document dans votre navigateur. Le contenu devrait s'afficher sans erreur.
Remarque: Dans le navigateur, vous pouvez choisir Voir->Source
pour consulter le fichier source dans l'éditeur de texte.

Pour créer une fiche avec un composant XMLDocument


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Sur la page Internet de la palette d'outils, placez un composant TXMLDocument sur la fiche.
3. Dans l'inspecteur d'objets, cliquez sur les points de suspension à côté de la propriété FileName, naviguez jusqu'à
l'emplacement du fichier XML que vous avez créé et ouvrez-le. Le fichier XML est associé au composant TXMLDocument.
4. Dans l'inspecteur d'objets, initialisez la propriété Active à la valeur true.

Pour configurer les composants VCL


1. Sur la page Standard de la palette d'outils, placez un composant TMemo sur la fiche.
2. Sur la page Standard de la palette d'outils, placez deux composants TButton sur la fiche juste au-dessus de Memo1.
3. Dans l'inspecteur d'objets, avec Button1 sélectionné, entrez CodeGear pour la propriété Caption.
4. Dans l'inspecteur d'objets, avec Button2 sélectionné, entrez MyCompany pour la propriété Caption.

Pour afficher le contenu des noeuds enfants dans le fichier XML


1. Dans l'inspecteur d'objets avec Button1 sélectionné, double-cliquez sur l'événement OnClick sur l'onglet Evénements. Le
code s'affiche, avec le curseur placé dans le bloc du gestionnaire d'événement TForm1.Button1Click.
2 2. Entrez le code suivant pour afficher le cours de l'action pour le premier noeud enfant lorsque l'utilisateur clique sur le bouton
CodeGear :
BorlandStock:=XMLDocument1.DocumentElement.ChildNodes[0];
Price:= BorlandStock.ChildNodes['price'].Text;
Memo1.Text := Price;
IXMLNode *BorlandStock = XMLDocument1->DocumentElement->
ChildNodes->GetNode(0);
WideString Price = BorlandStock->ChildNodes->
FindNode( "price" )->Text;
Memo1->Text = Price;
3. Pour Delphi, ajoutez une section var juste au-dessus du bloc de code dans le gestionnaire d'événement et entrez les
déclarations de variables locales suivantes :
var
BorlandStock: IXMLNode;
Price: string;
4. Dans l'inspecteur d'objets avec Button2 sélectionné, double-cliquez sur l'événement OnClick sur l'onglet Evénements. Le
code s'affiche, avec le curseur placé dans le bloc du gestionnaire d'événement TForm1.Button2Click.
5. Entrez le code suivant pour afficher le cours de l'action pour le deuxième noeud enfant lorsque l'utilisateur clique sur le bouton
MyCompany :
MyCompany:=XMLDocument1.DocumentElement.ChildNodes[1];
Price:= MyCompany.ChildNodes['price'].Text;
Memo1.Text := Price;
IXMLNode *MyCompany = XMLDocument1–>DocumentElement
->ChildNodes->GetNode(1);
WideString Price = BorlandStock->ChildNodes
->FindNode( "price" )->Text;
Memo1–>Text = Price;
6. Pour Delphi, ajoutez une section var juste au-dessus du bloc de code dans le gestionnaire d'événement et entrez les

114
2.5 Procédures VCL RAD Studio Copie de données d'un flux vers un autre

déclarations de variables locales suivantes :


var
MyCompany: IXMLNode;
Price: string;

Pour compiler et exécuter l'application


1. Choisissez Exécuter Exécuter pour compiler et exécuter l'application. La fiche de l'application affiche deux boutons et un
mémo.
2. Cliquez sur le bouton CodeGear. Le cours de l'action s'affiche.
3. Cliquez sur le bouton MyCompany. Le cours de l'action s'affiche.
Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

2.5.17 Copie de données d'un flux vers un autre


La création de cette application VCL comprend les étapes suivantes :

1. Création d'un répertoire projet contenant un fichier texte à copier.


2. Création d'une fiche VCL avec un contrôle bouton.
3. Ecriture du code pour lire la chaîne et l'écrire dans un fichier.
4. Exécution de l'application. 2
Pour configurer votre répertoire projet et un fichier texte à copier
1. Créez un répertoire dans lequel stocker les fichiers de votre projet.
2. En utilisant un éditeur de texte, créez un fichier texte simple et enregistrez-le sous from.txt dans votre répertoire projet.

Pour créer une fiche VCL avec un contrôle bouton


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Sur la page Standard de la palette d'outils, placez un composant TButton sur la fiche.
3. Dans l'inspecteur d'objets, entrez CopyFile pour les propriétés Caption et Name.

Pour écrire la procédure de copie de flux


1. Sélectionnez Button1 sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, avec le
curseur placé dans le bloc du gestionnaire de l'événement TForm1.CopyFileClick (Delphi) ou
TForm1::CopyFileClick (C++).
3. Pour Delphi, placez le curseur avant le mot réservé begin, puis appuyez sur la touche Entrée. Cette action crée une nouvelle
ligne au-dessus du bloc de code.
4. Pour Delphi, placez le curseur sur la nouvelle ligne créée, puis tapez la déclaration de variable suivante :
var stream1, stream2: TStream;
Pour C++, entrez les déclarations de variables suivantes :
TStream *stream1, *stream2;

115
Copie de la totalité d'une liste de chaînes RAD Studio 2.5 Procédures VCL

5. Placez le curseur dans le bloc de code, puis tapez le code suivant :


stream1 := TFileStream.Create('from.txt', fmOpenRead);
try
stream2:= TFileStream.Create('to.txt', fmCreate);
try
stream2.CopyFrom(stream1, stream1.Size);
finally
stream2.Free;
end;
finally
stream1.Free;
end;
stream1 = new TFileStream( “from.txt”, fmOpenRead );
try {
stream2 = new TFileStream( “to.txt”, fmCreate );
try {
stream2–>CopyFrom( stream1, stream1–>Size );
} __finally {
stream2–>Free();
}
} finally {
stream1–>Free();
}

Pour exécuter l'application


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter pour construire et exécuter l'application. La fiche
apparaît avec un bouton appelé CopyFile.
2. Cliquez sur CopyFile.
3. Utilisez un éditeur de texte pour ouvrir le fichier nouvellement créé to.txt, qui est localisé dans votre répertoire projet. Le
2 contenu de from.txt est copié dans to.txt.
Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

2.5.18 Copie de la totalité d'une liste de chaînes


La copie d'une liste de chaînes peut avoir l'effet d'ajouter un élément ou d'écraser une liste de chaînes existante. Cette
application VCL ajoute un élément à une liste de chaînes. Avec une simple modification, elle peut écraser une liste de chaînes.
La création de cette application VCL comprend les étapes suivantes :

1. Création d'une fiche VCL avec des contrôles TButtons, TComboBox et TMemo.
2. Ecriture du code de création d'une liste de chaînes dans le gestionnaire OnClick de Button1.
3. Ecriture du code de copie de la liste de chaînes dans le gestionnaire OnClick de Button2.
4. Exécution de l'application.

Pour créer une fiche VCL avec des contrôles de boutons, boîtes à options et mémo
1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. A partir de la page Standard de la palette d'outils, placez deux composants TButtons, un composant TComboBox et un
composant TMemo sur la fiche.

116
2.5 Procédures VCL RAD Studio Copie de la totalité d'une liste de chaînes

Pour créer la liste de chaînes


1. Sélectionnez Button1 sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, le
curseur placé dans le bloc du gestionnaire de l'événement TForm1.Button1Click (Delphi) ou TForm1::Button1Click
(C++).
3. Pour Delphi, placez le curseur avant le mot réservé begin, puis appuyez sur la touche Entrée. Cette action crée une
nouvelle ligne au-dessus du bloc de code.
4. Pour Delphi, placez le curseur sur la nouvelle ligne créée, puis tapez les déclarations de variables suivantes :
var
StringList: TStrings;
Pour C++, entrez les déclarations de variables suivantes :
TStrings *StringList;
5. Placez le curseur dans le bloc de code, puis tapez le code suivant :
StringList := TStringList.Create;
try
with StringList do begin
Add('Cet exemple utilise une liste de chaînes.');
Add('C'est le moyen le plus facile d'ajouter des chaînes');
Add('à la liste des chaînes d'une boîte à options.');
Add('N'oubliez pas que : la méthode TStrings.Create');
Add('est abstraite; utilisez plutôt la');
Add('méthode TStringList.Create.');
end;

with ComboBox1 do begin


Width := 210; 2
Items.Assign(StringList);
ItemIndex := 0;
end;
finally
StringList.free;
end;
StringList = new TStringList();
try {
StringList->Add( "Cet exemple utilise une liste de chaînes" );
StringList->Add( "C'est le moyen le plus facile d'ajouter des chaînes" );
StringList->Add( "à la liste des chaînes d'une boîte à options." );
StringList->Add( "Pensez à appeler le constructeur TstringList!" );
ComboBox1->Width = 210;
ComboBox1->Items->Assign( StringList );
ComboBox1->ItemIndex = 0;
} __finally {
StringList->Free();
}

Pour copier la liste de chaînes


1. Sélectionnez Button2 sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, le
curseur placé dans le bloc du gestionnaire de l'événement TForm1.Button2Click (Delphi) ou TForm1::Button2Click
(C++). Au niveau du curseur, entrez le code suivant :
Memo1.Lines.AddStrings(ComboBox1.Items);
Memo1–>Lines->AddStrings( ComboBox1–>Items

Pour exécuter l'application


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter pour construire et exécuter l'application. La fiche

117
Création de chaînes RAD Studio 2.5 Procédures VCL

apparaît avec les contrôles.


2. Cliquez sur Button1.
3. Dans ComboBox1, cliquez sur la flèche pour étendre la liste déroulante. Les chaînes s'affichent dans TComboBox suivant
l'ordre dans lequel elles apparaissent dans le code du gestionnaire d'événement pour Button1.
4. Cliquez sur Button2. Dans la fenêtre Memo1, les chaînes de ComboBox1 sont ajoutées à la chaîne 'Memo1'.
Remarque: Essayez de remplacer le code dans le gestionnaire d'événement Button2 par le code suivant, puis compilez et
exécutez de nouveau l'application.

Memo1.Lines.Assign(ComboBox1.Items);
Memo1–>Lines->Assign( ComboBox1–>Items );
Les chaînes de ComboBox1 écrasent la chaîne 'Memo1'.

Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

2.5.19 Création de chaînes


La création de cette application VCL comprend les étapes suivantes :

1. Créer une fiche VCL avec des contrôles TButton et TComboBox.


2 2. Ecrire le code de création des chaînes dans le gestionnaire OnClick de TButton.
3. Exécuter l'application.

Pour créer une fiche VCL avec des contrôles TButton et TComboBox
1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Sur la page Standard de la palette d'outils, placez un composant TButton, un TLabel et un TComboBox sur la fiche.

Pour écrire la procédure de création de chaîne


1. Sélectionnez Button1 sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, le
curseur placé dans le bloc du gestionnaire de l'événement TForm1.Button1Click (Delphi) ou TForm1::Button1Click
(C++).
3. Pour Delphi, placez le curseur avant le mot réservé begin, puis appuyez sur la touche Entrée. Cette action crée une
nouvelle ligne au-dessus du bloc de code.
4. Pour Delphi, placez le curseur sur la nouvelle ligne créée, puis tapez les déclarations de variables suivantes :
var
StringList: TStrings;
Pour C++, entrez les déclarations de variables suivantes :
TStrings *StringList;
5. Placez le curseur dans le bloc de code, puis tapez le code suivant :
StringList := TStringList.Create;
try
with StringList do begin

118
2.5 Procédures VCL RAD Studio Création d'une instance de fiche VCL en

Add('Animaux');
Add('Chats');
Add('Fleurs');
end;

with ComboBox1 do begin


Width := 210;
Items.Assign(StringList);
ItemIndex := 0;
end;

Label1.Caption := 'Fleurs a un indice de ' +


IntToStr( StringList->IndexOf( 'Fleurs' ) );
finally
StringList.free;
end;
StringList = new TStringList();
try {
StringList->Add( "Animaux" );
StringList->Add( "Chats" );
StringList->Add( "Fleurs" );
ComboBox1–>Width = 210;
ComboBox1–>Items->Assign( StringList );
ComboBox1–>ItemIndex = 0;
Label1–>Caption = "Fleurs a un indice de " +
IntToStr( StringList->IndexOf( "Fleurs" ) );
} __finally {
StringList->Free();
}

Pour exécuter l'application


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter pour construire et exécuter l'application. La fiche
apparaît avec les contrôles. 2
2. Cliquez sur le composant Button. Les chaînes 'Animaux', 'Voitures' et 'Fleurs' s'affichent dans l'ordre alphabétique dans une
liste de la boîte liste. Le libellé affiche le message : 'Les fleurs ont l'indice 2.'
3. Dans la boîte à options, cliquez sur la flèche pour développer la liste déroulante. Les chaînes ajoutées au gestionnaire
d'événement TButton s'affichent.
Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

2.5.20 Création d'une instance de fiche VCL en utilisant une


variable locale
Un moyen fiable de créer une instance unique d'une fiche VCL modale consiste à utiliser une variable locale d'un gestionnaire
d'événement comme référence à une nouvelle instance. Si vous utilisez une variable locale, peu importe que la fiche soit créée
automatiquement ou non. Le code du gestionnaire d'événement ne fait pas référence à la variable fiche globale. En utilisant
RAD Studio, la procédure suivante crée une instance de fiche modale dynamiquement. Elle retire (facultativement) l'appel de la
deuxième fiche au démarrage.

La construction de cette application VCL comprend les étapes suivantes :

1. Créer le répertoire projet.


2. Créer deux fiches pour le projet.

119
Création d'une instance de fiche VCL en RAD Studio 2.5 Procédures VCL

3. Retirer l'appel de la deuxième fiche au démarrage (facultatif).


4. Lier les fiches.
5. Créer un contrôle sur la fiche principale pour créer et afficher la fiche modale, puis écrire le gestionnaire d'événement.
6. Construire et exécuter l'application.

Pour créer les deux fiches


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL affiche Form1.
2. Choisissez Fichier Nouveau Autre Projets Delphi Fichiers Delphi ou Projets C++Builder, puis double-cliquez sur
l'icône Fiches. Le concepteur de fiches VCL affiche Form2.

Pour retirer facultativement l'appel de Form2 au démarrage


1. Choisissez Projet Options Fiches. La boîte de dialogue Options du projet s'affiche.
2. Sélectionnez Form2 dans la liste Fiches créées automatiquement et cliquez sur [>]. Form2 est déplacée dans la liste
Fiches disponibles.
3. Cliquez sur OK pour fermer la boîte de dialogue.

Pour lier Form1 à Form2


1. Sélectionnez Form1 et choisissez Fichier Utiliser l'unité (Delphi) or Inclure l'en-tête d'unité (C++). La boîte de dialogue
Utiliser l'unité s'affiche.
2. Sélectionnez Form2 (la fiche nécessaire à Form1 comme référence) dans la boîte de dialogue.
3. Cliquez sur OK.
Pour Delphi, une clause uses contenant le nom de l'unité Unit2 est placée dans la section implementation de Unit1.
2
Pour C++, la directive #include "Unit2.h" est ajoutée à Unit1.h.

Pour afficher Form2 à partir de Form1


1. Sélectionnez Form1, si nécessaire, puis, dans la page Standard de la palette d'outils, placez un TButton sur la fiche.
2. Dans l'inspecteur d'objets avec Button1 sélectionné, double-cliquez sur l'événement OnClick de l'onglet Evénements.
L'éditeur de code s'affiche, le curseur placé dans le bloc du gestionnaire de l'événement TForm1.Button1Click (Delphi)
ou TForm1::Button1Click (C++).
3. Pour Delphi, placez le curseur juste au-dessus du bloc gestionnaire d'événement et entrez l'instruction suivante définissant
une variable locale :
var FM: TForm2;
Pour C++, entrez la déclaration de variable suivante :
TForm2 *FM;
4. Insérez le curseur dans le bloc du gestionnaire d'événement et entrez le code suivant :
FM := TForm2.Create(self);
FM.ShowModal;
FM.Free;
FM = new TForm2( this );
FM->ShowModal();
FM->Free();

Pour construire et exécuter l'application


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter. L'application s'exécute, en affichant Form1.
2. Cliquez sur le bouton. Form2 s'affiche.
3. Avec Form2 affichée, essayez de cliquer sur Form1 pour l'activer. Rien ne se passe. Cliquez sur le X dans le coin supérieur

120
2.5 Procédures VCL RAD Studio Suppression de chaînes

droit de Form2. Form2 se ferme et Form1 devient la fiche active.


Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

Création dynamique d'une fiche VCL non modale ( see page 131)

Affichage d'une fiche VCL créée automatiquement ( see page 122)

2.5.21 Suppression de chaînes


La création de cette application VCL comprend les étapes suivantes :

1. Créer une fiche VCL avec des contrôles de boutons et de boîtes liste.
2. Ecrire du code afin d'ajouter des chaînes à une liste.
3. Ecrire du code pour supprimer une chaîne de la liste.
4. Exécuter l'application.

Pour créer une fiche VCL avec des contrôles TButton et ListBox
1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. A partir de la page Standard de la palette d'outils, placez deux composants TButtons et un composant TListBox sur la fiche.
3. Sélectionnez Button1 sur la fiche. 2
4. Dans l'inspecteur d'objets, entrez Ajouter pour les propriétés Caption et Name.
5. Sélectionnez Button2 sur la fiche.
6. Dans l'inspecteur d'objets, entrez Supprimer pour les propriétés Caption et Name.

Pour ajouter des chaînes à une liste


1. Sélectionnez le bouton Ajouter sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, le
curseur placé dans le bloc du gestionnaire de l'événement TForm1.AddClick (Delphi) ou TForm1::AddClick (C++).
3. Pour Delphi, placez le curseur avant le mot réservé begin, puis appuyez sur la touche Entrée. Cette action crée une nouvelle
ligne au-dessus du bloc de code.
4. Pour Delphi, placez le curseur sur la nouvelle ligne créée, puis tapez la déclaration de variable suivante :
var
MyList: TStringList;
Pour C++, entrez la déclaration de variable suivante :
TStringList *MyList;
5. Placez le curseur dans le bloc de code, puis tapez le code suivant :
MyList := TStringList.Create;
try
with MyList do
begin
Add('Souris');
Add('Chèvres');
Add('Eléphants');

121
Affichage d'une fiche VCL créée RAD Studio 2.5 Procédures VCL

Add('Oiseaux');
ListBox1.Items.AddStrings(MyList);
end;
finally
MyList.Free;
end;
MyList = new TStringList();
try {
MyList->Add( "Souris" );
MyList->Add( "Chèvres" );
MyList->Add( "Eléphants" );
MyList->Add( "Oiseaux" );
ListBox1–>Items->AddStrings( MyList );
} __finally {
MyList->Free();
}

Pour supprimer une chaîne de la liste


1. Sélectionnez le bouton Supprimer sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, avec le
curseur placé dans le bloc du gestionnaire de l'événement TForm1.DeleteClick (Delphi) ou TForm1::DeleteClick
(C++).
3. Pour Delphi, placez le curseur avant le mot réservé begin, puis appuyez sur la touche Entrée. Cette action crée une
nouvelle ligne au-dessus du bloc de code.
4. Pour Delphi, placez le curseur sur la nouvelle ligne créée, puis tapez la déclaration de variable suivante :
var
BIndex: Integer;
Pour C++, entrez la déclaration de variable suivante :
2
int BIndex;
5. Pour Delphi, placez le curseur dans le bloc de code, puis tapez le code suivant :
with ListBox1.Items do
begin
BIndex := IndexOf('Eléphants');
Delete (BIndex);
end;
BIndex = ListBox1–>Items->IndexOf( "Eléphants" );
ListBox1–>Items->Delete( BIndex );

Pour exécuter l'application


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter pour construire et exécuter l'application. La fiche
apparaît avec les contrôles.
2. Cliquez sur le bouton Ajouter. Les chaînes 'Souris', 'Chèvres', 'Eléphants' et 'Oiseaux' s'affichent dans l'ordre indiqué.
3. Cliquez sur le bouton Supprimer. La chaîne 'Eléphants' est supprimée de la liste.
Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

2.5.22 Affichage d'une fiche VCL créée automatiquement


Avec RAD Studio, la procédure suivante crée au moment de la conception une fiche modale qui est affichée ultérieurement au

122
2.5 Procédures VCL RAD Studio Affichage d'une image bitmap dans une

moment de l'exécution du programme.

La construction de cette application VCL comprend les étapes suivantes :

1. Créer le répertoire projet.


2. Créer deux fiches pour le projet.
3. Lier les fiches.
4. Créer un contrôle sur la fiche principale pour afficher la fiche modale, puis écrire le gestionnaire d'événement.
5. Construire et exécuter l'application.

Pour créer les deux fiches


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL affiche Form1.
2. Choisissez Fichier Nouveau Autre Projets Delphi Fichiers Delphi ou Fichier Nouveau Autre Fichiers
C++Builder, puis double-cliquez sur l'icône Fiche. Le concepteur de fiches VCL affiche Form2.

Pour lier Form1 à Form2


1. Pour Delphi, sélectionnez Form1 et choisissez Fichier Utiliser l'unité. Pour C++, sélectionnez Form1 et choisissez
Fichier Inclure l'en-tête d'unité. La boîte de dialogue Utiliser l'unité s'affiche.
2. Sélectionnez Form2 (la fiche nécessaire à Form1 comme référence) dans la boîte de dialogue.
3. Cliquez sur OK.
Pour Delphi, une clause uses contenant le nom de l'unité Unit2 est placée dans la section implementation de Unit1.
Pour C++, la directive #include "Unit2.h" est ajoutée à Unit1.h.

Pour afficher Form2 à partir de Form1 2


1. Sélectionnez Form1, si nécessaire, puis, dans la page Standard de la palette d'outils, placez un bouton sur la fiche.
2. Dans l'inspecteur d'objets avec Button1 sélectionné, double-cliquez sur l'événement OnClick de l'onglet Evénements.
L'éditeur de code s'affiche, le curseur placé dans le bloc du gestionnaire de l'événement TForm1.Button1Click (Delphi)
ou TForm1::Button1Click (C++).
3. Entrez le code de gestion d'événement suivant :
Form2.ShowModal;
Form2–>ShowModal();

Pour construire et exécuter l'application


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter. L'application s'exécute, en affichant Form1.
2. Cliquez sur le bouton. Form2 s'affiche.
3. Cliquez sur le X dans le coin supérieur droit de Form2. Form2 se ferme et Form1 devient la fiche active.
Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

Création dynamique d'une fiche VCL modale ( see page 129)

123
Affichage d'une image bitmap dans une RAD Studio 2.5 Procédures VCL

2.5.23 Affichage d'une image bitmap dans une application


Fiches VCL
Cette procédure charge une image bitmap à partir d'un fichier et l'affiche sur une fiche VCL.

1. Créer une fiche VCL avec un contrôle bouton.


2. Fournir une image bitmap.
3. Coder le gestionnaire d'événement onClick du bouton pour charger et afficher une image bitmap.
4. Construire et exécuter l'application.

Pour créer une fiche VCL et un bouton


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Sur la page Standard de la palette d'outils, placez un composant TButton sur la fiche.

Pour fournir une image bitmap


1. Créez un répertoire dans lequel stocker les fichiers de votre projet.
2. Localisez une image bitmap sur votre disque local, puis copiez-la dans le répertoire de votre projet.
3. Enregistrez tous les fichiers du projet dans le répertoire de votre projet.

2 Pour écrire le gestionnaire d'événement OnClick


1. Dans l'inspecteur d'objets, double-cliquez sur l'événement Button1 OnClick de l'onglet Evénements. L'éditeur de code
s'affiche, le curseur placé dans le bloc du gestionnaire de l'événement TForm1.Button1Click (Delphi) ou
TForm1::Button1Click (C++).
2. Entrez le code de gestion d'événement suivant, en remplaçant MyFile.bmp par le chemin d'accès à l'image bitmap du
répertoire de votre projet :
Bitmap := TBitmap.Create;
try
Bitmap.LoadFromFile('MyFile.bmp');
Form1.Canvas.Brush.Bitmap := Bitmap;
Form1.Canvas.FillRect(Rect(0,0,100,100));
finally
Form1.Canvas.Brush.Bitmap := nil;
Bitmap.Free;
end;
Graphics::TBitmap *Bitmap = new Graphics::TBitmap();
try {
Bitmap->LoadFromFile( "..\\MyFile.bmp" );
Form1->Canvas->Brush->Bitmap = Bitmap;
Form1->Canvas->FillRect( Rect(0,0,100,100) );
} __finally {
Form1->Canvas->Brush->Bitmap = NULL;
Bitmap->Free();
}
Remarque: Pour les projets C++, le code suppose que le répertoire de sortie cible est situé dans le répertoire du projet.

Conseil: Vous pouvez modifier la taille du rectangle à afficher en ajustant les valeurs du paramètre Rect.

3. Pour Delphi, ajoutez la déclaration de variable suivante dans le bloc var :


Bitmap : TBitmap;

124
2.5 Procédures VCL RAD Studio Affichage d'une image bitmap plein écran

Pour exécuter le programme


1. Sélectionnez Exécuter Exécuter.
2. Cliquez sur le bouton pour afficher l'image bitmap dans un rectangle de 100 x 100 pixels dans le coin supérieur gauche de la
fiche.
Voir aussi
Présentation de la VCL ( see page 46)

Dessin de lignes droites dans une application VCL ( see page 128)

Dessin de rectangles et d'ellipses dans une application VCL ( see page 127)

Dessin d'un polygone dans une application VCL ( see page 126)

Insertion d'une image bitmap dans une boîte à options d'une application VCL ( see page 144)

2.5.24 Affichage d'une image bitmap plein écran dans une


application Fiches VCL
Cette procédure charge une image bitmap à partir d'un fichier et l'affiche dans son intégralité sur une fiche VCL. Elle utilise les
propriétés Height et Width de l'objet Bitmap pour afficher une vue complète de l'image.

1. Créer une fiche VCL avec un contrôle bouton.


2. Fournir une image bitmap. 2
3. Coder le gestionnaire d'événement onClick du bouton pour charger et afficher une image bitmap.
4. Construire et exécuter l'application.

Pour créer une fiche VCL et un bouton


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Sur la page Standard de la palette d'outils, placez un composant bouton sur la fiche.
3. Dans l'inspecteur d'objets, entrez "Vue complète" pour la propriété Caption et FullView pour la propriété Name.

Pour fournir une image bitmap


1. Créez un répertoire dans lequel stocker les fichiers de votre projet.
2. Localisez une image bitmap sur votre disque local, puis copiez-la dans le répertoire de votre projet.
3. Enregistrez tous les fichiers du projet dans le répertoire de votre projet.

Pour écrire le gestionnaire d'événement OnClick


1. Dans l'inspecteur d'objets, double-cliquez sur l'événement Button1 OnClick de l'onglet Evénements. L'éditeur de code
s'affiche, avec le curseur placé dans le bloc du gestionnaire de l'événement TForm1.FullViewClick (Delphi) ou
TForm1::FullViewClick (C++).
2. Entrez le code de gestion d'événement suivant, en remplaçant MyFile.bmp par le nom de l'image bitmap du répertoire de
votre projet :
Bitmap := TBitmap.Create;
try
Bitmap.LoadFromFile('MyFile.bmp');
Form1.Canvas.Brush.Bitmap := Bitmap;

125
Dessin d'un polygone dans une application RAD Studio 2.5 Procédures VCL

Form1.Canvas.FillRect(Rect(0,0,Bitmap.Width,Bitmap.Height));
finally
Form1.Canvas.Brush.Bitmap := nil;
Bitmap.Free;
end;
Graphics::TBitmap Bitmap = new Graphics::TBitmap();
try {
Bitmap->LoadFromFile( "..\\MyFile.bmp" );
Form1–>Canvas->Brush->Bitmap = Bitmap;
Form1–>Canvas->FillRect(
Rect( 0, 0, Bitmap->Width, Bitmap->Height ) );
} __finally {
Form1–>Canvas->Brush->Bitmap = NULL;
Bitmap->Free();
}
Remarque: Pour les projets C++, le code suppose que le répertoire de sortie cible est situé dans le répertoire du projet.

3. Pour Delphi, ajoutez la déclaration de variable suivante dans le bloc var :


Bitmap : TBitmap;s

Pour exécuter le programme


1. Choisissez Exécuter Exécuter.
2. Cliquez sur le bouton pour afficher l'image bitmap dans un rectangle dans le coin supérieur gauche de la fiche.
Voir aussi
Présentation de la VCL ( see page 46)

Dessin de lignes droites dans une application Fiches VCL ( see page 128)

Affichage d'une image bitmap dans une application Fiches VCL ( see page 124)
2
Dessin de rectangles et d'ellipses dans une application Fiches VCL ( see page 127)

Dessin d'un polygone dans une application Fiches VCL ( see page 126)

Insertion d'une image bitmap dans une boîte à options d'une application Fiches VCL ( see page 144)

2.5.25 Dessin d'un polygone dans une application Fiches


VCL
Cette procédure dessine un polygone dans une fiche VCL.

1. Créer une fiche VCL.


2. Coder le gestionnaire d'événement OnPaint de la fiche pour dessiner un polygone.
3. Construire et exécuter l'application.

Pour créer une fiche VCL


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Dans la vue fiche, cliquez sur la fiche, si nécessaire, pour afficher Form1 dans l'inspecteur d'objets.

Pour écrire le gestionnaire d'événement OnPaint


1. Dans l'inspecteur d'objets, cliquez sur l'onglet Evénements.

126
2.5 Procédures VCL RAD Studio Dessin de rectangles et d'ellipses dans une

2. Double-cliquez sur l'événement OnPaint. L'éditeur de code s'affiche, avec le curseur placé dans le bloc du gestionnaire de
l'événement TForm1.FormPaint (Delphi) ou TForm1::FormPaint (C++).
3. Entrez le code de gestion d'événement suivant :
Canvas.Polygon ([Point(0,0), Point(0, ClientHeight),
Point(ClientWidth, ClientHeight)]);
TPoint points[] = { Point(0,0),
Point(0, ClientHeight),
Point(ClientWidth, ClientHeight) };
Canvas->Polygon( points, 3 );

Pour exécuter le programme


1. Sélectionnez Exécuter Exécuter.
2. L'application s'exécute, en affichant un triangle droit dans la moitié inférieure gauche de la fiche.
Voir aussi
Présentation de la VCL ( see page 46)

Dessin de lignes droites dans une application Fiches VCL ( see page 128)

Dessin de rectangles et d'ellipses dans une application Fiches VCL ( see page 127)

Affichage d'une image bitmap dans une application Fiches VCL ( see page 124)

2.5.26 Dessin de rectangles et d'ellipses dans une


application Fiches VCL 2
Cette procédure dessine un rectangle et une ellipse dans une fiche VCL.

1. Créer une fiche VCL.


2. Coder le gestionnaire d'événement OnPaint de la fiche pour dessiner un rectangle et une ellipse.
3. Construire et exécuter l'application.

Pour créer une fiche VCL et y placer une image


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Dans la vue fiche, cliquez sur la fiche, si nécessaire, pour afficher Form1 dans l'inspecteur d'objets.

Pour écrire le gestionnaire d'événement OnPaint


1. Dans l'inspecteur d'objets, double-cliquez sur l'événement Form1 OnPaint de l'onglet Evénements. L'éditeur de code
s'affiche, avec le curseur placé dans le bloc du gestionnaire de l'événement TForm1.FormPaint (Delphi) ou
TForm1::FormPaint (C++).
2. Entrez le code de gestion d'événement suivant :
Canvas.Rectangle (0, 0, ClientWidth div 2, ClientHeight div 2);
Canvas.Ellipse (0, 0, ClientWidth div 2, ClientHeight div 2);
Canvas->Rectangle( 0, 0, ClientWidth / 2, ClientHeight / 2 );
Canvas->Ellipse( 0, 0, ClientWidth / 2, ClientHeight / 2 );

Pour exécuter le programme


1. Choisissez Exécuter Exécuter.
2. L'application s'exécute et affiche un rectangle et une ellipse dans le quart supérieur gauche de la fiche.

127
Dessin de lignes droites dans une RAD Studio 2.5 Procédures VCL

Voir aussi
Présentation de la VCL ( see page 46)

Dessin d'un polygone dans une application Fiches VCL ( see page 126)

Affichage d'une image bitmap dans une application Fiches VCL ( see page 124)

2.5.27 Dessin d'un rectangle arrondi dans une application


Fiches VCL
Cette procédure dessine un rectangle arrondi dans une fiche VCL.

1. Créer une fiche VCL et coder le gestionnaire d'événement OnPaint de la fiche.


2. Construire et exécuter l'application.

Pour créer une fiche VCL


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Dans l'inspecteur d'objets, cliquez sur l'onglet Evénements.
3. Double-cliquez sur l'événement OnPaint. L'éditeur de code s'affiche, avec le curseur placé dans le bloc du gestionnaire de
l'événement TForm1.FormPaint (Delphi) ou TForm1::FormPaint (C++).
4. Entrez le code de gestion d'événement suivant :
2
Canvas.RoundRect(0, 0, ClientWidth div 2,
ClientHeight div 2, 10, 10);
Canvas->RoundRect( 0, 0, ClientWidth / 2, ClientHeight / 2, 10, 10 );

Pour exécuter le programme


1. Enregistrez tous les fichiers de votre projet, puis choisissez Exécuter Exécuter.
2. L'application s'exécute et affiche un rectangle arrondi dans le quart supérieur gauche de la fiche.
Voir aussi
Présentation de la VCL ( see page 46)

Dessin de rectangles et d'ellipses dans une application Fiches VCL ( see page 127)

2.5.28 Dessin de lignes droites dans une application Fiches


VCL
Cette procédure dessine deux diagonales droites sur une image dans une fiche VCL.

1. Créer une fiche VCL.


2. Coder le gestionnaire d'événement OnPaint de la fiche pour dessiner les lignes droites.
3. Construire et exécuter l'application.

128
2.5 Procédures VCL RAD Studio Création dynamique d'une fiche VCL

Pour créer une fiche VCL et y placer une image


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Dans la vue fiche, cliquez sur la fiche, si nécessaire, pour afficher Form1 dans l'inspecteur d'objets.

Pour écrire le gestionnaire d'événement OnPaint


1. Dans l'inspecteur d'objets, double-cliquez sur l'événement Form1 OnPaint de l'onglet Evénements. L'éditeur de code
s'affiche, avec le curseur placé dans le bloc du gestionnaire d'événement TForm1.FormPaint.
2. Entrez le code de gestion d'événement suivant :
with Canvas do
begin
MoveTo(0,0);
LineTo(ClientWidth, ClientHeight);
MoveTo(0, ClientHeight);
LineTo(ClientWidth, 0);
end;
Canvas->MoveTo( 0, 0 );
Canvas->LineTo( ClientWidth, ClientHeight );
Canvas->MoveTo( 0, ClientHeight );
Canvas->LineTo( ClientWidth, 0 );

Pour exécuter le programme


1. Choisissez Exécuter Exécuter.
2. L'application s'exécute et affiche une fiche avec deux diagonales.
Conseil: Pour que le crayon devienne vert, insérez l'instruction suivante après la première instruction MoveTo() dans le
code du gestionnaire d'événement : Pen.Color := clGreen; (Delphi) Canvas->Pen->Color = clGreen; (C++). 2
Essayez d'utiliser d'autres propriétés des objets canevas et crayon. Voir "Utilisation des propriétés de l'objet canevas" dans le
guide du développeur de Delphi 7.

Voir aussi
Présentation de la VCL ( see page 46)

Construction d'applications Fiches VCL avec graphiques ( see page 101)

Dessin de rectangles et d'ellipses dans une application Fiches VCL ( see page 127)

Dessin d'un polygone dans une application Fiches VCL ( see page 126)

Affichage d'une image bitmap dans une application Fiches VCL ( see page 124)

2.5.29 Création dynamique d'une fiche VCL modale


Toutes les fiches de votre application n'ont pas besoin d'être en mémoire simultanément. Pour réduire la quantité de mémoire
requise au moment du chargement, votre application peut créer des fiches uniquement lorsqu'elles doivent être disponibles pour
être utilisées. Une boîte de dialogue, par exemple, n'a besoin d'être en mémoire que pendant le temps où l'utilisateur interagit
avec elle. En utilisant RAD Studio, la procédure suivante crée une instance de fiche modale dynamiquement. La principale
différence entre la création dynamique d'une fiche et l'affichage d'une fiche VCL créée automatiquement réside dans le fait que
vous supprimez l'appel de la deuxième fiche au démarrage et écrivez du code pour créer dynamiquement la fiche.

La construction de cette application VCL comprend les étapes suivantes :

129
Création dynamique d'une fiche VCL RAD Studio 2.5 Procédures VCL

1. Créer le répertoire projet.


2. Créer deux fiches pour le projet.
3. Retirer l'appel de la deuxième fiche au démarrage.
4. Lier les fiches.
5. Créer un contrôle sur la fiche principale pour créer et afficher la fiche modale, puis écrire le gestionnaire d'événement.
6. Construire et exécuter l'application.

Pour créer les deux fiches


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL affiche Form1.
2. Choisissez Fichier Nouveau Autre Projets Delphi Fichiers Delphi ou Fichier Nouveau Autre Fichiers
C++Builder, puis double-cliquez sur l'icône Fiche. Le concepteur de fiches VCL affiche Form2.

Pour retirer l'appel de Form2 au démarrage


1. Choisissez Projet Options Fiches. La boîte de dialogue Options du projet s'affiche.
2. Sélectionnez Form2 dans la liste Fiches créées automatiquement et cliquez sur [>]. Form2 est déplacée dans la liste
Fiches disponibles.
3. Cliquez sur OK pour fermer la boîte de dialogue.

Pour lier Form1 à Form2


1. Pour Delphi, sélectionnez Form1 et choisissez Fichier Utiliser l'unité. Pour C++, sélectionnez Form1 et choisissez
Fichier Inclure l'en-tête d'unité. La boîte de dialogue Utiliser l'unité s'affiche.
2. Sélectionnez Form2 (la fiche nécessaire à Form1 comme référence) dans la boîte de dialogue.
2
3. Cliquez sur OK. Pour Delphi, une clause uses contenant le nom de l'unité Unit2 est placée dans la section implementation de
Unit1. Pour C++, la directive #include "Unit2.h" est ajoutée à Unit1.h.

Pour afficher Form2 à partir de Form1


1. Sélectionnez Form1, si nécessaire, puis, dans la page Standard de la palette d'outils, placez un TButton sur la fiche.
2. Dans l'inspecteur d'objets avec Button1 sélectionné, double-cliquez sur l'événement OnClick de l'onglet Evénements.
L'éditeur de code s'affiche, le curseur placé dans le bloc du gestionnaire de l'événement TForm1.Button1Click (Delphi)
ou TForm1::Button1Click (C++).
3. Entrez le code de gestion d'événement suivant :
Form2 := TForm2.Create(self);
try
Form2.ShowModal;
finally
Form2.Free;
end;
Form2 = new TForm2( this );
try {
Form2–>ShowModal();
} __finally {
Form2–>Free();
}

Pour construire et exécuter l'application


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter. L'application s'exécute, en affichant Form1.
2. Cliquez sur le bouton. Form2 s'affiche.
3. Cliquez sur le X dans le coin supérieur droit de la fiche. Form2 se ferme et Form1 devient la fiche active.

130
2.5 Procédures VCL RAD Studio Création dynamique d'une fiche VCL non

Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

Création dynamique d'une fiche VCL non modale ( see page 131)

Affichage d'une fiche VCL créée automatiquement ( see page 122)

2.5.30 Création dynamique d'une fiche VCL non modale


Une fiche non modale est une fenêtre qui s'affiche jusqu'à ce qu'elle soit masquée par une autre fenêtre ou jusqu'à sa fermeture
ou sa réduction par l'utilisateur. Avec RAD Studio, la procédure suivante crée une fiche non modale dynamiquement.

La construction de cette application VCL comprend les étapes suivantes :

1. Créer le répertoire projet.


2. Créer deux fiches pour le projet.
3. Retirer l'appel de la deuxième fiche au démarrage.
4. Lier les fiches.
5. Créer un contrôle sur la fiche principale pour créer et afficher la fiche modale, puis écrire le gestionnaire d'événement.
6. Construire et exécuter l'application.

Pour créer les deux fiches 2


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL affiche Form1.
2. Choisissez Fichier Nouveau Autre Projets Delphi Fichiers Delphi ou Fichier Nouveau Autre Fichiers
C++Builder, puis double-cliquez sur l'icône Fiche. Le concepteur de fiches VCL affiche Form2.

Pour retirer l'appel de Form2 au démarrage


1. Choisissez Projet Options. La boîte de dialogue Options du projet s'affiche.
2. Sélectionnez Form2 dans la liste Fiches créées automatiquement et cliquez sur [>]. Form2 est déplacée dans la liste
Fiches disponibles.
3. Cliquez sur OK pour fermer la boîte de dialogue.

Pour lier Form1 à Form2


1. Pour Delphi, sélectionnez Form1 et choisissez Fichier Utiliser l'unité. Pour C++, sélectionnez Form1 et choisissez
Fichier Inclure l'en-tête d'unité. La boîte de dialogue Utiliser l'unité s'affiche.
2. Sélectionnez Form2 (la fiche nécessaire à Form1 comme référence) dans la boîte de dialogue.
3. Cliquez sur OK. Pour Delphi, une clause uses contenant le nom de l'unité Unit2 est placée dans la section implementation de
Unit1. Pour C++, la directive #include "Unit2.h" est ajoutée à Unit1.h.

Pour afficher Form2 à partir de Form1


1. Sélectionnez Form1, si nécessaire, puis, dans la page Standard de la palette d'outils, placez un bouton sur la fiche.
2. Dans l'inspecteur d'objets avec Button1 sélectionné, double-cliquez sur l'événement OnClick de l'onglet Evénements.
L'éditeur de code s'affiche, le curseur placé dans le bloc du gestionnaire de l'événement TForm1.Button1Click (Delphi)
ou TForm1::Button1Click (C++).

131
Parcours des chaînes d'une liste RAD Studio 2.5 Procédures VCL

3. Entrez le code de gestion d'événement suivant :


Form2 := TForm2.Create(self);
Form2.Show;
Form2 = new TForm2( this );
Form2–>Show();
Remarque: Si votre application a besoin d'autres instances de la fiche non modale, déclarez une variable globale distincte pour
chaque instance. Le plus souvent, vous utiliserez la référence globale qui a été créée lorsque vous avez réalisé la fiche (le nom
de variable qui correspond à la valeur de la propriété Name de la fiche).

Pour construire et exécuter l'application


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter. L'application s'exécute, en affichant Form1.
2. Cliquez sur le bouton. Form2 s'affiche.
3. Cliquez sur Form1. Form1 devient la fiche active. Form2 est affichée jusqu'à sa réduction ou sa fermeture.
Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

Affichage d'une fiche VCL créée automatiquement ( see page 122)

Création dynamique d'une fiche VCL modale ( see page 129)

2.5.31 Parcours des chaînes d'une liste


2
Cette application VCL crée d'abord une liste de chaînes. Elle parcourt ensuite les chaînes, en transformant tous les caractères
de chaînes en majuscule. Elle est constituée des étapes suivantes :

1. Créer une fiche VCL avec des boutons et des contrôles TListBox.
2. Ecrire du code pour créer une liste de chaînes et ajouter des chaînes à cette liste.
3. Ecrire du code pour parcourir la liste de chaînes afin de traiter les caractères des chaînes.
4. Exécuter l'application.

Pour créer une fiche VCL avec des contrôles TButton et TListBox
1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. A partir de la page Standard de la palette d'outils, placez deux composants TButtons et un composant TListBox sur la fiche.
3. Sélectionnez Button1 sur la fiche.
4. Dans l'inspecteur d'objets, entrez Ajouter pour les propriétés Caption et Name.
5. Sélectionnez Button2 sur la fiche.
6. Dans l'inspecteur d'objets, entrez ToUpper pour les propriétés Caption et Name.

Pour créer une liste de chaînes et ajouter des chaînes à cette liste
1. Sélectionnez le bouton Ajouter sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, le
curseur placé dans le bloc du gestionnaire de l'événement TForm1.AddClick (Delphi) ou TForm1::AddClick (C++).
3. Pour Delphi, placez le curseur avant le mot réservé begin, puis appuyez sur la touche Entrée. Cette action crée une

132
2.5 Procédures VCL RAD Studio Parcours des chaînes d'une liste

nouvelle ligne au-dessus du bloc de code.


4. Pour Delphi, placez le curseur sur la nouvelle ligne créée, puis tapez la déclaration de variable suivante :
var
MyList: TStringList;
5. Placez le curseur dans le bloc de code, puis tapez le code suivant :
MyList := TStringList.Create;
try
with MyList do
begin
Add('Souris');
Add('Chèvres');
Add('Eléphants');
Add('Oiseaux');
ListBox1.Items.AddStrings(MyList);
end;
finally
MyList.Free;
end;
TStringList *MyList = new TStringList();
try {
MyList->Add( "Souris" );
MyList->Add( "Chèvres" );
MyList->Add( "Eléphants" );
MyList->Add( "Oiseaux" );
ListBox1–>Items->AddStrings( MyList );
} __finally {
MyList->Free();
}

Pour transformer tous les caractères en majuscules


2
1. Sélectionnez le bouton ToUpper sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, le
curseur placé dans le bloc du gestionnaire de l'événement TForm1.ToUpperClick (Delphi) ou TForm1::ToUpperClick
(C++).
3. Pour Delphi, placez le curseur avant le mot réservé begin, puis appuyez sur la touche Entrée. Cette action crée une nouvelle
ligne au-dessus du bloc de code.
4. Pour Delphi, placez le curseur sur la nouvelle ligne créée, puis tapez la déclaration de variable suivante :
var
Index: Integer;
5. Placez le curseur dans le bloc de code, puis tapez le code suivant :
for Index := 0 to ListBox1.Items.Count - 1 do
ListBox1.Items[Index] := UpperCase(ListBox1.Items[Index]);
for( int i = 0; i < ListBox1–>Items->Count; i++ ) {
ListBox1–>Items[i] = UpperCase( ListBox1–>Items[i] );
}

Pour exécuter l'application


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter pour construire et exécuter l'application. La fiche
apparaît avec les contrôles.
2. Cliquez sur le bouton Ajouter. Les chaînes 'Souris', 'Chèvres', 'Eléphants' et 'Oiseaux' s'affichent dans l'ordre indiqué.
3. Cliquez sur le bouton ToUpper. Les caractères de la chaîne sont affichés en majuscules.
Voir aussi
Présentation de la VCL ( see page 46)

133
Eviter les accès de threads simultanés RAD Studio 2.5 Procédures VCL

Construction d'une application Fiches VCL ( see page 108)

2.5.32 Construction d'une application multithread


Voici les étapes essentielles de construction d'une application Fiches VCL multithread avec un objet thread en utilisant RAD
Studio.

Pour placer un composant sur une fiche


1. Créer une fiche VCL avec un objet thread défini.
2. Initialiser le thread (facultatif).
3. Ecrire la fonction thread.
4. Ecrire le code de nettoyage (facultatif).
Voir aussi
Présentation de la VCL ( see page 46)

Définition d'un objet thread ( see page 136)

Initialisation d'un thread ( see page 139)

Ecriture de la fonction Thread ( see page 144)

Ecriture du code de nettoyage ( see page 134)

2.5.33 Ecriture du code de nettoyage


Pour nettoyer un thread quand son exécution est terminée
1. Centralisez le code de nettoyage en le plaçant dans le gestionnaire d'événement OnTerminate. Vous êtes ainsi certain que le
code s'exécutera.
2. N'utilisez pas de variables locales de thread, car OnTerminate ne s'exécute pas dans le cadre de votre thread.
3. Vous pouvez accéder en toute sécurité à tous les objets du gestionnaire OnTerminate.
Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application multithread ( see page 134)

2.5.34 Eviter les accès de threads simultanés dans la même


mémoire
Utilisez ces techniques de base pour empêcher les autres threads d'accéder à la même mémoire que votre thread :

1. Verrouiller les objets.


2. Utiliser les sections critiques.

134
2.5 Procédures VCL RAD Studio Définition de l'objet thread

3. Utiliser le synchronisateur à écriture exclusive et lecture multiple.

Pour verrouiller des objets


1. Pour les objets tels que les canevas qui possèdent une méthode Lock, appelez la méthode Lock, si nécessaire, pour
empêcher d'autres objets d'accéder à cet objet, et appelez Unlock quand le verrouillage n'est plus nécessaire.
2. Appelez TThreadList.LockList (Delphi) ou TThreadList::LockList() (C++) pour empêcher des threads d'utiliser
l'objet liste TThreadList, et appelez TThreadList.UnlockList quand le verrouillage n'est plus nécessaire.
Remarque: Vous pouvez appeler en toute sécurité TCanvas.Lock et TThreadList.LockList.

Pour utiliser une section critique


1. Créez une instance globale de TCriticalSection.
2. Appelez la méthode Acquire pour verrouiller les autres threads pendant l'accès à la mémoire globale.
3. Appelez la méthode Release pour que les autres threads puissent accéder à la mémoire en appelant Acquire. Le code
suivant a une section critique des variables globales, LockXY, qui bloque l'accès aux variables globales X et Y. Tout thread
utilisant X ou Y doit encadrer cette utilisation d'appels à la section critique comme ci-dessous :
LockXY.Acquire;
try
X := X + 1;
Y := sin(X);
finally
LockXY.Release
end;
LockXY->Acquire();
try {
x++;
y = sin( x ); 2
} __finally {
LockXY->Release();
}
Avertissement: Les sections critiques ne peuvent fonctionner que si tous les threads les utilisent pour accéder à la mémoire
globale. Sinon, des problèmes d'accès simultané peuvent se produire.

Pour utiliser le synchronisateur à écriture exclusive et lecture multiple


1. Créez une instance globale de TMultiReadExclusiveWriteSynchronizer associée à la mémoire globale que vous
souhaitez protéger.
2. Pour qu'un thread puisse lire la mémoire, il doit appeler BeginRead.
3. Une fois l'opération de lecture de la mémoire achevée, le thread doit appeler EndRead.
4. Pour qu'un thread puisse écrire dans la mémoire, il doit appeler BeginWrite.
5. Une fois l'opération d'écriture achevée, le thread doit appeler EndWrite.
Avertissement: Le synchronisateur à écriture exclusive et à lecture multiple ne fonctionne que si chaque thread l'utilise pour
accéder à la mémoire globale associée. Sinon, des problèmes d'accès simultané peuvent se produire.
Voir aussi
Présentation de la VCL ( see page 46)

Ecriture de la fonction Thread ( see page 144)

Utilisation du thread VCL principal ( see page 140)

Attente des threads ( see page 142)

Gestion des exceptions ( see page 139)

135
Définition de l'objet thread RAD Studio 2.5 Procédures VCL

2.5.35 Définition de l'objet thread


Pour définir l'objet thread
1. Choisissez Fichier Nouveau Autre Projets Delphi Fichiers Delphi ou Fichier Nouveau Autre Fichiers
C++Builder, puis double-cliquez sur l'icône Objet Thread. La boîte de dialogue Nouvel objet Thread apparaît.
2. Entrez un nom de classe, par exemple TMyThread.
3. Vous pouvez éventuellement cocher la case Thread nommé et spécifier un nom de thread, par exemple MyThreadName.
Conseil: Le fait d'entrer un nom pour Thread nommé facilite le suivi du thread pendant le débogage.

4. Cliquez sur OK.


L'éditeur de code affiche le squelette du code pour l'objet thread.
Le code généré pour la nouvelle unité ressemblera à cela si vous avez nommé votre classe thread TMyThread.
unit Unit1;

interface

uses
Classes;

type
TMyThread = class(TThread)
private
2 { Déclarations privées }
protected
procedure Execute; override;
end;

implementation

{ Important : Les méthodes et les propriétés des objets dans les composants visuels peuvent
uniquement être
utilisées dans une méthode appelée en utilisant Synchronize, par exemple,

Synchronize(UpdateCaption);

et UpdateCaption pourra ressembler à

procedure TMyThread.UpdateCaption;
begin
Form1.Caption := 'Mis à jour dans un thread';
end; }

{ TMyThread }

procedure TMyThread.Execute;
begin
{ placer le code du thread ici }
end;

end.
L'ajout d'un nom pour le thread génère du code supplémentaire pour l'unité. Il inclut l'unité Windows, ajoute la procédure (Delphi)
ou la fonction (C++) SetName et ajoute l'enregistrement TThreadNameInfo (Delphi) ou la structure THREADNAME_INFO (C++).
Le nom est affecté au champ FName comme ci-dessous :

136
2.5 Procédures VCL RAD Studio Définition de l'objet thread

unit Unit1;

interface

uses
Classes {$IFDEF MSWINDOWS} , Windows {$ENDIF};

type
TMyThread = class(TThread)
private
procedure SetName;
protected
procedure Execute; override;
end;

implementation

{ Important : Les méthodes et les propriétés des objets dans les composants visuels peuvent
uniquement être
utilisées dans une méthode appelée en utilisant Synchronize, par exemple,

Synchronize(UpdateCaption);

et UpdateCaption pourra ressembler à

procedure TMyThread.UpdateCaption;
begin
Form1.Caption := 'Mis à jour dans un thread';
end; }

{$IFDEF MSWINDOWS}
type
TThreadNameInfo = record
FType: LongWord; // doit avoir la valeur 0x1000 2
FName: PChar; // pointeur sur le nom (dans l'espace adresse de l'utilisateur)
FThreadID: LongWord; // ID de thread (-1 indique le thread appelant)
FFlags: LongWord; // réservé à un usage ultérieur, doit être à zéro
end;
{$ENDIF}

{ TMyThread }

procedure TMyThread.SetName;
{$IFDEF MSWINDOWS}
var
ThreadNameInfo: TThreadNameInfo;
{$ENDIF}
begin
{$IFDEF MSWINDOWS}
ThreadNameInfo.FType := $1000;
ThreadNameInfo.FName := 'MyThreadName';
ThreadNameInfo.FThreadID := $FFFFFFFF;
ThreadNameInfo.FFlags := 0;

try
RaiseException( $406D1388, 0, sizeof(ThreadNameInfo) div sizeof(LongWord), @ThreadNameInfo
);
except
end;
{$ENDIF}
end;

procedure TMyThread.Execute;
begin
SetName;
{ placer le code du thread ici }

137
Gestion des exceptions RAD Studio 2.5 Procédures VCL

end;

end.
// Unit1.h

#ifndef Unit1H
#define Unit1H
#include <Classes.hpp>
class TMyThread : public TThread
{
typedef struct tagTHREADNAME_INFO
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
} THREADNAME_INFO;
private:
void SetName();
protected:
void __fastcall Execute();
public:
__fastcall TMyThread(bool CreateSuspended);
};

#endif
// Unit1.cpp
#include "Unit3.h"
#pragma package(smart_init)

__fastcall TMyThread::TMyThread(bool CreateSuspended)


: TThread(CreateSuspended)
{
2 }

void TMyThread::SetName()
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = "TMyThreadName";
info.dwThreadID = -1;
info.dwFlags = 0;

__try
{
RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD),(DWORD*)&info; );
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
}
}

void __fastcall TMyThread::Execute()


{
SetName();
// ---- Placez le code du thread ici ----
}
Voir aussi
Présentation de la VCL ( see page 46)

Initialisation du thread ( see page 139)

Ecriture de la fonction Thread ( see page 144)

Ecriture du code de nettoyage ( see page 134)

138
2.5 Procédures VCL RAD Studio Initialisation d'un thread

2.5.36 Gestion des exceptions


Pour gérer les exceptions dans la fonction thread
1. Ajoutez un bloc try...except à l'implémentation de votre méthode Execute.
2. Codez la logique comme suit :
procedure TMyThreadExecute;
begin
try
while not Terminated do
PerformSomeTask;
except
{ faire quelque chose avec les exceptions }
end;
end;
void __fastcall TMyThread::Execute() {
try {
while( !Terminated() ) {
// exécuter des tâches
}
} catch(...) { // catch des exceptions spécifiques d'abord
// code de gestion d'exception
}
}
Voir aussi
Présentation de la VCL ( see page 46)
2
Ecriture de la fonction Thread ( see page 144)

Utilisation du thread VCL principal ( see page 140)

Eviter les accès de threads simultanés dans la même mémoire ( see page 134)

Attente des threads ( see page 142)

2.5.37 Initialisation d'un thread


Pour initialiser un objet thread
1. Affectez une priorité par défaut.
2. Indiquez le moment auquel le thread est libéré.

Pour affecter une priorité par défaut


1. Affectez une priorité par défaut au thread à partir des valeurs du tableau ci-dessous. Utilisez une priorité élevée pour gérer les
tâches critiques et une priorité basse pour les autres tâches.

Valeur Priorité
tpIdle Le thread s'exécute seulement quand le système est en attente. Windows n'interrompt pas les autres
threads pour exécuter un thread de priorité tpIdle.
tpLowest La priorité du thread est deux points en dessous de la normale.
tpLower La priorité du thread est un point en dessous de la normale.

139
Utilisation du thread VCL principal RAD Studio 2.5 Procédures VCL

tpNormal La priorité du thread est normale.


tpHigher La priorité du thread est un point au dessus de la normale
tpHighest La priorité du thread est deux points au dessus de la normale.
tpTimeCritical Le thread a la priorité la plus élevée.

2. Redéfinissez la méthode Create (Delphi) ou le constructeur par défaut (C++) de la classe thread en ajoutant un nouveau
constructeur à la déclaration.
3. Codez le constructeur. Voici l'exemple d'un thread à basse priorité :
constructor TMyThread.Create(CreateSuspended: Boolean);
begin
inherited Create(CreateSuspended);
Priority := tpIdle;
end;
TMyThread::TMyThread( bool CreateSuspended ) : TThread( CreateSuspended ) {
Priority = tpIdle;
}
4. Indiquez si le thread doit être automatiquement libéré quand son exécution est terminée.
Avertissement: "Gonfler" la priorité du thread pour une opération utilisant intensivement la CPU peut "sous-alimenter" les
autres threads de l'application. Il ne faut accorder une priorité élevée qu'à des threads qui passent l'essentiel du temps à
attendre des événements extérieurs.

Pour indiquer le moment auquel un thread est libéré


1. Attribuez la valeur true à la propriété FreeOnTerminate, sauf si le thread doit être coordonné avec d'autres threads.
2. Si le thread doit être coordonné avec un autre thread, initialisez FreeOnTerminate à false, puis libérez explicitement le
2 premier thread du second.
Voir aussi
Présentation de la VCL ( see page 46)

Définition d'un objet thread ( see page 136)

Ecriture de la fonction Thread ( see page 144)

Ecriture du code de nettoyage ( see page 134)

2.5.38 Utilisation du thread VCL principal


L'utilisation du thread VCL principal comprend les étapes suivantes :

1. Créer une routine distincte pour gérer les messages Windows reçus par les composants de votre application.
2. Appeler régulièrement CheckSynchronize.
3. Déclarer, si nécessaire, des variables locales aux threads pour une utilisation exclusive par votre thread.

Pour créer une routine distincte


1. Ecrivez une routine de thread principal qui gère l'accès aux propriétés des objets et l'exécution des méthodes de tous les
objets de votre application.
2. Appelez la routine en utilisant la méthode TThread.Synchronize (Delphi) ou TThread::Synchronize. Le code suivant
illustre un exemple de l'appel d'une méthode en utilisant Synchronize :
procedure TMyThread.PushTheButton

140
2.5 Procédures VCL RAD Studio Attente des threads

begin
Button1.Click;
end;
procedure TMyThread.Execute;
begin
...
Synchronize(PushThebutton);
...
end;
void TMyThread::PushTheButton() { Form1–>Button1–>Click(); }
void __fastcall TMyThread::Execute() {
...
Synchronize( (TThreadMethod)&PushTheButton );
...
}
Synchronize attend le thread principal pour entrer dans la boucle des messages puis exécute la méthode qui lui est transmise.

Remarque: Comme Synchronize utilise une boucle de messages, elle ne fonctionne pas dans les applications console. Pour
les applications consoles, utilisez d'autres mécanismes, comme les sections critiques, pour protéger l'accès aux objets VCL.

Pour appeler CheckSynchronize


1. Appelez régulièrement CheckSynchronize depuis le thread principal pour que les threads d'arrière-plan synchronisent leur
exécution avec le thread principal.
2. Pour garantir la sécurité des appels aux threads d'arrière-plan, appelez CheckSynchronize lorsque l'application est inactive
(par exemple, dans le gestionnaire de l'événement OnIdle).

Pour utiliser une variable locale au thread


1. Identifiez les variables que vous voulez rendre globales pour toutes les routines exécutées dans votre thread sans qu'elles ne
soient partagées par les autres instances de la même classe de thread.
2
2. Pour Delphi, déclarez ces variables dans une section threadvar, par exemple,
threadvar
x: integer;
Dans C++, déclarez ces variables avec le modificateur __thread :
int __thread x;
Remarque: La section threadvar

ne peut être utilisée que pour des variables globales. Ne l'utilisez pas pour les variables Pointer et Function ou les types qui
utilisent une sémantique de copie-sur-écriture, comme les chaînes longues.

Remarque: Pour C++, si vous initialisez une variable __thread

, vous devez l'initialiser par une expression constante. Par exemple, int __thread foo = 3; est une instruction correcte
mais int __thread foo = get_value(); est interdit car l'initialisation se produit au moment de l'exécution.

Voir aussi
Présentation de la VCL ( see page 46)

Ecriture de la fonction Thread ( see page 144)

Eviter les accès de threads simultanés dans la même mémoire ( see page 134)

Attente des threads ( see page 142)

Gestion des exceptions ( see page 139)

141
Attente des threads RAD Studio 2.5 Procédures VCL

2.5.39 Attente des threads


Voici les procédures qui peuvent être utilisées pour attendre les threads.

• Attendre la fin d'exécution d'un thread


• Attendre l'achèvement d'une tâche
• Vérifier si un autre thread attend la fin de votre thread

Pour attendre la fin d'exécution d'un thread


1. Utilisez la méthode WaitFor de l'autre thread.
2. Codez votre logique. Par exemple, le code suivant attend qu'un autre thread remplisse un objet liste de threads avant
d'accéder aux objets de la liste :
if ListFillingThread.WaitFor then
begin
with ThreadList1.LockList do
begin
for I := 0 to Count - 1 do
ProcessItem(Items[I];
end;
ThreadList1.UnlockList;
end;
if( ListFillingThread->WaitFor() ) {
TList* list = ThreadList1–>LockList();
for( int i = 0; i < list->Count; i++ ) {
DoSomething( list->Items[i] );
2 }
ThreadList1–>UnlockList();
}

Pour attendre l'achèvement d'une tâche


1. Créez un objet TEvent de portée globale.
2. Quand un thread termine une opération que d'autres threads attendent, il appelle TEvent.SetEvent.
3. Pour désactiver le signal, appelez TEvent.ResetEvent.
L'exemple suivant est un gestionnaire d'événement OnTerminate qui utilise un compteur global dans une section critique pour
mémoriser le nombre de threads terminés. Quand Counter atteint 0, le gestionnaire appelle la méthode SetEvent pour
signaler que tous les processus sont terminés :
procedure TDataModule.TaskTerminateThread(Sender: TObject);
begin
...
CounterGuard.Acquire; {obtient un verrou sur le compteur}
Dec(Counter); { décrémente la variable globale du compteur }
if Counter = 0 then
Event1.SetEvent; { signale s'il s'agit du dernier thread }
Counter.Release; {déverrouiller le compteur}
...
end;
void __fastcall TDataModule::TaskThreadTerminate( TObject *Sender ) {
...
CounterGuard->Acquire(); // verrouille le compteur
if( ––Counter == 0 ) // décrémente le compteur
Event1->SetEvent(); // signale si c'est le dernier thread
CounterGuard->Release(); // libère le verrouillage
}

142
2.5 Procédures VCL RAD Studio Ecriture de la fonction Thread

Le thread principal initialise la variable Counter, lance les threads de tâches et attend le signal indiquant l'achèvement de
l'exécution de tous les threads en appelant la méthode TEvent::WaitFor. WaitFor attend l'activation du signal pendant une
durée spécifiée et renvoie l'une des valeurs du tableau ci-dessous.

L'exemple de code suivant montre comment le thread principal lance les threads de tâches et reprend la main lorsque leur
exécution est achevée.
Event1.ResetEvent; {efface l'événement avant de lancer les threads}
for i := 1 to Counter do
TaskThread.Create(False); {crée et lance les threads de tâches}
if Event1.WaitFor(20000) <> wrSignaled then
raise Exception;
{poursuite avec le thread principal}
Event1–>ResetEvent(); // efface l'événement avant de lancer les threads
for( int i = 0; i < Counter; i++ ) {
new TaskThread( false );
if( Event1–>WaitFor(20000) != wrSignaled )
throw Exception;
// poursuite maintenant avec le thread principal
Remarque: Si vous ne voulez pas cesser d'attendre un gestionnaire d'événement après un délai spécifié, transmettez à la
méthode WaitFor une valeur de paramètre INFINITE. Faites attention en utilisant INFINITE, car cela peut provoquer le blocage
du thread si le signal attendu n'arrive pas.

Pour vérifier si un autre thread attend la fin de votre thread


1. Dans votre procédure Execute, implémentez la méthode Terminate en testant la valeur de la propriété Terminated.
2. Voici un moyen de coder la logique :
procedure TMyThread.Execute;
begin
while not Terminated do 2
PerformSomeTask;
end;
void __fastcall TMyThread::Execute() {
while( !Terminated )
DoSomething();
}
Valeurs renvoyées par WaitFor

Valeur Signification
wrSignaled Le signal de l'objet événement a été activé.
wrTimeout La durée spécifiée s'est écoulée sans que le signal soit défini.
wrAbandoned L'objet événement a été détruit avant l'écoulement de la période d'attente.
wrError Une erreur a eu lieu pendant l'attente.

Voir aussi
Présentation de la VCL ( see page 46)

Ecriture de la fonction Thread ( see page 144)

Utilisation du thread VCL principal ( see page 140)

Eviter les accès de threads simultanés dans la même mémoire ( see page 134)

Gestion des exceptions ( see page 139)

143
Insertion d'une image bitmap dans un RAD Studio 2.5 Procédures VCL

2.5.40 Ecriture de la fonction Thread


La méthode Execute constitue la fonction thread. Vous pouvez la concevoir comme un programme qui est exécuté par
l'application, à cette différence près qu'il partage le même espace de processus. L'écriture d'une fonction thread est plus délicate
que celle d'un programme distinct car il faut prendre garde à ne pas écraser la mémoire utilisée par d'autres processus de
l'application. D'un autre côté, comme le thread partage le même espace de processus que les autres threads, il est possible
d'utiliser la mémoire partagée pour faire communiquer les threads.

Pour implémenter la méthode Execute, coordonnez l'exécution des threads en


1. Les synchronisant avec un thread VCL principal.
2. Evitant les accès simultanés à la même mémoire.
3. Attendant des threads.
4. Gérant les exceptions.
Voir aussi
Présentation de la VCL ( see page 46)

Utilisation du thread VCL principal ( see page 140)

Eviter les accès de threads simultanés dans la même mémoire ( see page 134)

Attente des threads ( see page 142)

Gestion des exceptions ( see page 139)


2

2.5.41 Insertion d'une image bitmap dans un contrôle d'une


application Fiches VCL
Cette procédure ajoute une image bitmap à une boîte à options d'une application Fiches VCL.

1. Créer une fiche VCL.


2. Ajouter des composants à la fiche.
3. Définir des propriétés des composants dans l'inspecteur d'objets.
4. Ecrire des gestionnaires d'événements pour l'action de dessin des composants.
5. Construire et exécuter l'application.

Pour créer une fiche VCL avec un composant TComboBox


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Sur la page Win32 de la palette d'outils, placez un composant TImageList sur la fiche.
3. Sur la page Standard de la palette d'outils, placez un composant TComboBox sur la fiche.

Pour définir les propriétés d'un composant


1. Sélectionnez ComboBox1 sur la fiche.

144
2.5 Procédures VCL RAD Studio Lecture d'une chaîne et écriture de cette

2. Dans l'inspecteur d'objets, définissez la liste déroulante de la propriété Style à csOwnerDrawFixed.


3. Dans l'inspecteur d'objets, cliquez sur le bouton points de suspension à côté de la propriété Items. L'éditeur de liste de
chaînes s'affiche.
4. Entrez une chaîne à associer à l'image bitmap, par exemple MyImage, puis cliquez sur OK.
5. Double-cliquez sur ImageList1 dans la fiche. L'éditeur ImageList s'affiche.
6. Cliquez sur le bouton Ajouter pour afficher la boîte de dialogue d'ajout d'images.
7. Localisez une image bitmap à afficher dans la boîte à options. Pour localiser une image, vous pouvez rechercher les images
*.bmp sur votre disque local. Sélectionnez une très petite image comme une icône. Copiez-la dans le répertoire de votre
projet et cliquez sur Ouvrir. L'image s'affiche dans l'éditeur ImageList.
8. Cliquez sur OK pour fermer l'éditeur.

Pour ajouter le code du gestionnaire d'événement


1. Dans la vue Fiche VCL, sélectionnez ComboBox1.
2. Dans l'inspecteur d'objets, cliquez sur la page Evénements et double-cliquez sur l'événement OnDrawItem. L'éditeur de
code s'affiche, avec le curseur placé dans le bloc du gestionnaire de l'événement ComboBox1DrawItem (Delphi) ou
ComboBox1::DrawItem (C++).
3. Entrez le code suivant pour ce gestionnaire d'événement :
Combobox1.Canvas.FillRect(Rect);
ImageList1.Draw(ComboBox1.Canvas, Rect.Left, Rect.Top, Index);
Combobox1.Canvas.TextOut(Rect.Left+ImageList1.Width+2,
Rect.Top, ComboBox1.Items[Index]);
ComboBox1–>Canvas->FillRect( Rect );
ImageList1–>Draw( ComboBox1–>Canvas, Rect.Left, Rect.Top, Index );
ComboBox1–>Canvas->TextOut( Rect.Left + ImageList1–>Width + 2,
Rect.Top,
ComboBox1–>Items[Index] ); 2

Pour exécuter le programme


1. Choisissez Exécuter Exécuter. L'application s'exécute et affiche une fiche avec une boîte à options.
2. Cliquez sur la liste déroulante de la boîte à options. L'image bitmap et la chaîne de texte apparaissent en tant qu'élément de
la liste.
Voir aussi
Présentation de la VCL ( see page 46)

Construction d'applications Fiches VCL avec graphiques ( see page 101)

2.5.42 Lecture d'une chaîne et écriture de cette chaîne dans


un fichier
La création de cette application VCL comprend les étapes suivantes :

1. Création d'une fiche VCL avec un contrôle bouton.


2. Ecriture du code pour lire la chaîne et l'écrire dans un fichier.
3. Exécuter l'application.

Pour créer une fiche VCL


1. Créez un répertoire dans lequel stocker les fichiers de votre projet.

145
Renommage de fichiers RAD Studio 2.5 Procédures VCL

2. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
3. Sur la page Standard de la palette d'outils, placez un composant TButton sur la fiche.

Pour lire et écrire une chaîne


1. Sélectionnez Button1 sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, le
curseur placé dans le bloc du gestionnaire de l'événement TForm1.Button1Click (Delphi) ou TForm1::Button1Click
(C++).
3. Pour Delphi, placez le curseur avant le mot réservé begin, puis appuyez sur la touche Entrée. Cette action crée une nouvelle
ligne au-dessus du bloc de code.
4. Tapez les déclarations de variables suivantes :
TFileStream *fs const AnsiString str = "Bonjour";
5. Placez le curseur dans le bloc de code, puis tapez le code suivant :
fs = new TFileStream( "temp.txt", fmCreate );
fs->Write ((void*)str.c_str(), str.fmCreate);

Pour exécuter l'application "Hello world"


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter pour construire et exécuter l'application. La fiche
apparaît avec un bouton appelé Button1.
2. Cliquez sur Button1.
3. Utilisez un éditeur de texte pour ouvrir le fichier nouvellement créé temp.txt, qui est localisé dans votre répertoire projet. La
chaîne 'Hello' apparaît dans le fichier.
2 Voir aussi
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

2.5.43 Renommage de fichiers


La création de cette application VCL comprend les étapes suivantes :

1. Créer un répertoire projet contenant un fichier à renommer.


2. Créer une fiche VCL avec des contrôles de boutons et de libellés.
3. Ecrire du code pour renommer le fichier.
4. Exécuter l'application.

Pour configurer votre répertoire projet et un fichier texte à copier


1. Créez un répertoire dans lequel stocker les fichiers de votre projet.
2. Créez ou copiez un fichier texte dans votre répertoire projet puis enregistrez-le sous le nom MyFile.txt.

Pour créer une fiche VCL avec un bouton et un libellé


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Sur la page Standard de la palette d'outils, placez un composant TButton sur la fiche.

146
2.5 Procédures VCL RAD Studio Ajout et tri de chaînes

3. A partir de la page Standard de la palette d'outils, placez un composant TLabel sur la fiche.

Pour écrire la procédure de renommage de fichier


1. Sélectionnez Button1 sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, le
curseur placé dans le bloc du gestionnaire de l'événement TForm1.Button1Click (Delphi) ou TForm1::Button1Click
(C++).
3. Au niveau du curseur, tapez le code suivant :
if not RenameFile('MyFile.txt', 'YourFile.txt') then
Label1.Caption := 'Erreur de renommage du fichier!';
if( !RenameFile( "..\\MyFile.txt", "..\\YourFile.txt" )
Label1–>Caption = "Erreur de renommage du fichier";
// les paramètres fichier supposent que le répertoire de sortie cible est situé dans le
répertoire du projet
Remarque: Il n'est pas possible de renommer (déplacer) un fichier d'un lecteur vers un autre en utilisant RenameFile. Pour ce
faire, vous devez commencer par copier le fichier, puis supprimer le fichier original. Dans la bibliothèque d'exécution,
RenameFile est une enveloppe pour la fonction MoveFile de l'API Windows, et MoveFile ne fonctionne donc pas non plus d'un
lecteur à l'autre.

Pour exécuter l'application


1. Enregistrez le fichier projet, puis choisissez Exécuter Exécuter pour construire et exécuter l'application. La fiche apparaît.
2. Cliquez sur le bouton. Si aucun message ne s'affiche dans le libellé, vérifiez le nom du fichier dans votre répertoire projet.
MyFile.txt devrait être renommé en YourFile.txt.
3. Si le libellé affiche le message d'erreur, revérifiez le code de votre gestionnaire d'événement.
Voir aussi 2
Présentation de la VCL ( see page 46)

Construction d'une application Fiches VCL ( see page 108)

2.5.44 Ajout et tri de chaînes


La création de cette application VCL comprend les étapes suivantes :

1. Créer une fiche VCL avec des contrôles Button, Label et TListBox.
2. Ecrire du code pour ajouter et trier des chaînes.
3. Exécuter l'application.

Pour créer une fiche VCL avec des contrôles de boutons, de libellés et de boîtes liste
1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Dans la catégorie Standard de la palette d'outils, placez un composant TButton, TLabel et TListBox sur la fiche.

Pour écrire la procédure de copie de flux


1. Sélectionnez Button1 sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, avec le
curseur placé dans le bloc du gestionnaire d'événement TForm1.Button1Click.
3. Pour Delphi, placez le curseur avant le mot réservé begin, puis appuyez sur la touche Entrée. Cette action crée une

147
Création d'un bouton ActiveX Fiches VCL RAD Studio 2.5 Procédures VCL

nouvelle ligne au-dessus du bloc de code.


4. Tapez les déclarations de variables suivantes :
var
MyList: TStringList;
Index: Integer;
TStringList *MyList;
int Index;
5. Placez le curseur dans le bloc de code, puis tapez le code suivant :
MyList := TStringList.Create;
try
MyList.Add('Animaux');
MyList.Add('Fleurs');

MyList.Add('Voitures');

MyList.Sort;
if MyList.Find('Fleurs', Index) then
begin
ListBox1.Items.AddStrings(MyList);
Label1.Caption := 'Fleurs a une valeur d''indice de ' + IntToStr(Index);
end;
finally
MyList.Free;
end;
MyList = new TStringList();
try {
MyList->Add("Animaux");
MyList->Add("Fleurs");
MyList->Add( "Voitures" );
MyList->Sort();
2 if( MyList->Find( "Fleurs", Index ) {
ListBox1–>Items->AddStrings( MyList );
Label1–>Caption = "Fleurs a un indice de " +
IntToStr( Index );
}
} __finally {
MyList->Free();
}
Remarque: Find ne fonctionne que sur des listes triées. Utilisez IndexOf sur les listes non triées.

Pour exécuter l'application


1. Enregistrez tous les fichiers du projet, puis choisissez Exécuter Exécuter pour construire et exécuter l'application. La fiche
apparaît avec les contrôles.
2. Cliquez sur le composant Button. Les chaînes 'Animaux', 'Voitures' et 'Fleurs' s'affichent dans l'ordre alphabétique dans une
liste de la boîte liste. Le libellé affiche le message : 'Les fleurs ont l'indice 2.'
Voir aussi
Présentation de la VCL ( see page 46)

2.5.45 Création d'un bouton ActiveX Fiches VCL


Comme un contrôle Delphi, un contrôle ActiveX génère du code de programme lorsque vous placez le composant sur une fiche
ou un autre conteneur logique dans l'EDI. La principale différence entre un contrôle ActiveX et un contrôle Delphi réside dans le
fait qu'un contrôle ActiveX est indépendant du langage. Vous pouvez créer des contrôles ActiveX pour le déploiement vers
plusieurs environnements de programmation sous Windows, pas seulement Delphi ou C++Builder.

148
2.5 Procédures VCL RAD Studio Création d'un bouton ActiveX Fiches VCL

Cette procédure utilise l'expert ActiveX Fiches VCL pour créer un contrôle ActiveX. Pour tester le contrôle, vous pouvez l'installer
sur votre machine comme un composant VCL dans l'EDI. Pour installer le contrôle, vous devez d'abord lui créer un package.
Cette procédure est constituée des étapes majeures suivantes :

1. Créez un projet de bibliothèque ActiveX pour un contrôle de bouton ActiveX.


2. Recensez le bouton ActiveX pour que son icône puisse être affichée dans la barre d'outils.
3. Créez un package pour le bouton ActiveX.
4. Installez le package.
5. Testez le bouton ActiveX.

Pour créer un projet de bibliothèque ActiveX pour un contrôle de bouton ActiveX


1. Créez un répertoire sur votre disque local pour le projet ActiveX. Attribuez-lui un nom facile à trouver, par exemple ActiveX.
2. Choisissez Fichier Nouveau Autre et sélectionnez la page ActiveX dans la boîte de dialogue Nouveaux éléments.
3. Dans la page ActiveX, double-cliquez sur Contrôle ActiveX. L'expert Contrôle ActiveX apparaît.
4. Dans la liste déroulanteClasse VCL, sélectionnez TButton.
5. Par défaut, ButtonX s'affiche comme ActiveX. Renommez ButtonX en attribuant le nom que vous souhaitez afficher pour
votre bouton ActiveX, par exemple, MyActiveXButton.
Remarque: Les modifications apportées au nom mettent à jour l'unité d'implémentation et le nom du projet. Laissez les
autres champs aux valeurs par défaut.

6. Cliquez sur OK. L'expert génère le code nécessaire à l'implémentation du contrôle ActiveX et ajoute le code au projet. Si le
projet est déjà une bibliothèque ActiveX, l'expert ajoute le contrôle au projet en cours.
Remarque: Si le projet n'est pas encore une bibliothèque ActiveX, une boîte de dialogue Avertissement 2
s'affiche et vous demande si vous souhaitez démarrer un nouveau projet de bibliothèque ActiveX.
7. Cliquez sur OK pour démarrer le nouveau projet de bibliothèque ActiveX.

Pour recenser le bouton ActiveX


1. Construisez le projet et enregistrez tous les fichiers dans votre répertoire projet ActiveX. Faites disparaître l'avertissement sur
le débogage. Le projet construit et crée un fichier OCX dans votre répertoire projet.
2. Choisissez Exécuter Recenser le serveur ActiveX pour recenser le bouton ActiveX. Une boîte de dialogue affiche un
message indiquant que ce recensement a réussi et elle affiche le chemin du fichier OCX résultant.
3. Cliquez sur OK.

Pour créer un nouveau package pour le bouton ActiveX


1. Choisissez Fichier Nouveau Autre afin de créer un nouveau package. La boîte de dialogue Nouveaux éléments
apparaît.
2. Double-cliquez sur Package dans la page Nouveau pour afficher la boîte de dialogue Package - package.dpk et cliquez sur
Ajouter.
3. Sur l'onglet d'ajout d'unité de la boîte de dialogue d'ajout, naviguez jusqu'au répertoire projet.
4. Sélectionnez le fichier ButtonXControl1_TLB.pas et cliquez sur Ouvrir.
5. Cliquez sur OK pour ajouter le fichier au package et revenez à la boîte de dialogue Package - package.dpk. La boîte de
dialogue Package - package.dpk apparaît, en montrant les fichiers du package et deux fichiers nécessaires : rtl.dcp et
vcl.dcp.

Pour ajouter les fichiers nécessaires et installer le package


1. Dans la boîte de dialogue Package - package.dpk, sélectionnez rtl.dcp et cliquez sur Ajouter.

149
Création d'une fiche active VCL ActiveX RAD Studio 2.5 Procédures VCL

2. Sur l'onglet d'ajout d'unité de la boîte de dialogue d'ajout, naviguez jusqu'au répertoire Lib dans Delphi, sélectionnez le
fichier rtl.dcp et cliquez sur Ouvrir, puis cliquez sur OK dans la boîte de dialogue d'ajout.
3. Dans la boîte de dialogue Package - package.dpk, sélectionnez vcl.dcp et cliquez sur Ajouter.
4. Sur l'onglet d'ajout d'unité de la boîte de dialogue d'ajout, naviguez jusqu'au répertoire Lib dans Delphi, sélectionnez le
fichier vcl.dcp et cliquez sur Ouvrir, puis cliquez sur OK dans la boîte de dialogue d'ajout.
5. Dans la boîte de dialogue Package - package.dpk, cliquez sur Compiler pour compiler le package. Une boîte de dialogue
apparaît, en indiquant que le package a été installé. Cliquez sur OK.
6. Cliquez sur le X dans le coin supérieur droit de la boîte de dialogue Package - package.dpk pour la fermer. Vous êtes invité
à enregistrer le package.
7. Enregistrez le package dans le répertoire de vos projets.

Pour tester le bouton


1. Choisissez Fichier Nouvelle application.
2. Sur la page ActiveX de la palette d'outils, localisez votre bouton et placez-le sur la fiche. Le bouton s'affiche sur la fiche.
Voir aussi
Présentation de VCL.NET

Création d'une fiche active ActiveX Fiches VCL ( see page 150)

2.5.46 Création d'une fiche active VCL ActiveX


2 Comme un contrôle Delphi, un contrôle ActiveX génère du code de programme lorsque vous placez le composant sur une fiche
ou un autre conteneur logique dans l'EDI. La principale différence entre un contrôle ActiveX et un contrôle Delphi réside dans le
fait qu'un contrôle ActiveX est indépendant du langage. Vous pouvez créer des contrôles ActiveX pour le déploiement vers
plusieurs environnements de programmation sous Windows, pas seulement Delphi ou C++Builder, par exemple.

Cette procédure utilise l'expert de fiche active ActiveX Fiches VCL pour créer une fiche active contenant deux composants. Pour
tester le contrôle, vous pouvez le déployer sur le Web. Cette procédure est constituée des étapes majeures suivantes :

1. Créer un projet de bibliothèque ActiveX pour une fiche active ActiveX.


2. Ajouter des contrôles à la fiche active.
3. Ajouter du code de gestion des événements pour les contrôles.
4. Déployer le projet sur le Web.
5. Afficher la fiche et tester les contrôles dans votre navigateur Web.

Pour créer un projet de bibliothèque ActiveX pour une fiche active ActiveX
1. Créez un répertoire sur votre disque local pour le projet ActiveX. Attribuez-lui un nom facile à trouver, par exemple ActiveX.
2. Créez un deuxième répertoire destiné à contenir le composant ActiveX et un fichier HTML pour déployer la fiche active dans
votre navigateur Web Microsoft Internet Explorer. Nommez ce répertoire ActiveX_Deploy.
3. Choisissez Fichier Nouveau Autre et sélectionnez la page ActiveX dans la boîte de dialogue Nouveaux éléments.
4. Dans la page ActiveX, double-cliquez sur la fiche active. L'expert Fiche active s'affiche.
5. Acceptez les paramètres par défaut et cliquez sur OK. L'expert génère le code nécessaire à l'implémentation du contrôle
ActiveX et ajoute le code au projet. Si le projet est déjà une bibliothèque ActiveX, l'expert ajoute le contrôle au projet en cours.
Remarque: Si le projet n'est pas encore une bibliothèque ActiveX, une boîte de dialogue Avertissement
s'affiche et vous demande si vous souhaitez démarrer un nouveau projet de bibliothèque ActiveX.

150
2.5 Procédures VCL RAD Studio Construction d'une application de

6. Cliquez sur OK pour démarrer un nouveau projet de bibliothèque ActiveX. Une fiche active ActiveX apparaît.

Pour ajouter certaines fonctionnalités à la fiche active


1. A partir de la page Standard de la palette d'outils, ajoutez des composants TEdit et TButton sur la fiche.
2. Sélectionnez le bouton.
3. Sur l'onglet Evénements, double-cliquez sur l'événement OnClick de l'inspecteur d'objets. L'éditeur de code s'affiche, le
curseur placé dans le bloc du gestionnaire de l'événement TActiveFormX.Button1Click (Delphi) ou
TActiveFormX::Button1Click() (C++). Entrez le code suivant au niveau du curseur :
ShowMessage(Edit1.text);
ShowMessage( Edit1–>Text )
4. Enregistrez les fichiers du projet pour votre répertoire ActiveX.
Remarque: Pour déployer la fiche active sur votre Web, utilisez le Gestionnaire de déploiement
. Cliquez sur Fichier Nouveau Autre Déploiement.

Pour tester la fiche active


1. Lancez votre navigateur.
2. Choisissez Fichier Ouvrir et naviguez jusqu'au répertoire ActiveX_Deploy.
3. Double-cliquez sur le fichier HTML pour le lancer dans la fenêtre du navigateur. La fiche active s'affiche dans la fenêtre du
navigateur.
4. Cliquez sur le bouton. Une boîte de dialogue déroulante affiche le texte dans la zone de saisie.
5. Modifiez le texte et cliquez à nouveau sur le bouton. Le nouveau texte que vous avez saisi s'affiche dans la boîte de dialogue
déroulante.
Voir aussi
2
Présentation de VCL.NET

Utilisation du gestionnaire de déploiement

2.5.47 Construction d'une application de navigateur Web


Fiches VCL
La création de l'application de navigateur Web comprend les étapes suivantes :

1. Créer une fiche VCL avec un contrôle bouton.


2. Ajouter un composant TWebBrowser à la fiche.
3. Ajouter des contrôles pour entrer une URL et lancer le navigateur.
4. Ecrire du code pour lancer le navigateur lorsque l'utilisateur clique sur un bouton.
5. Exécuter l'application.

Pour créer une fiche VCL


1. Choisissez Fichier Nouveau Autre Projets Delphi ou Projets C++Builder et double-cliquez sur l'icône Application
Fiches VCL. Le concepteur de fiches VCL apparaît.
2. Sur la page Internet de la palette d'outils, placez un composant TWebBrowser sur la fiche.
3. Avec le composant TWebBrowser sélectionné sur la fiche, déplacez les poignées pour ajuster la taille de la fenêtre du
navigateur. Laissez un espace sur la fiche sous le composant TWebBrowser pour ajouter une fenêtre de saisie d'URL. Si la

151
Création d'une application qui utilise les RAD Studio 2.5 Procédures VCL

fenêtre n'est pas assez grande pour afficher une page entière du navigateur, le composant TWebBrowser ajoute des barres
de défilement lorsque vous exécutez l'application et lancez la fenêtre du navigateur.
4. Sur la page Standard de la palette d'outils, placez un composant TMemo sur la fiche. Avec le composant TMemo
sélectionné sur la fiche, déplacez les poignées afin d'ajuster la taille pour une URL saisie par l'utilisateur.
5. Sur la page Standard de la palette d'outils, placez un composant Label sur la fiche.
6. Sélectionnez le libellé, puis dans l'inspecteur d'objets, entrez l'URL : comme légende du libellé.
7. Sur la page Standard de la palette d'outils, placez un composant TButton sur la fiche.
8. Sélectionnez le bouton et dans l'inspecteur d'objets, entrez OK comme libellé de TButton.

Pour coder un bouton, cliquez sur l'événement qui lance le navigateur


1. Sélectionnez Button1 sur la fiche.
2. Dans l'inspecteur d'objets, double-cliquez sur l'action OnClick de l'onglet Evénements. L'éditeur de code s'affiche, avec le
curseur placé dans le bloc du gestionnaire d'événement Button1Click.
3. Tapez le code suivant :
WebBrowser1.Navigate(WideString(Memo1.Text));
WebBrowser1–>Navigate( WideString( Memo1–>Text ) );

Pour exécuter l'application


1. Choisissez Exécuter Exécuter pour construire et exécuter l'application.
2. Entrez une URL vers une page Web dans la fenêtre mémo, puis cliquez sur le bouton. Le navigateur démarre dans la fenêtre
TWebBrowser.
Voir aussi
Présentation de la VCL ( see page 46)
2
Construction d'une application Fiches VCL ( see page 108)

2.5.48 Création d'une application qui utilise les contrôles


ruban
Cette procédure décrit la création d'une application qui utilise les contrôles ruban. La fonctionnalité ruban est dérivée du
composant TRibbon. Lorsque le ruban utilise d'autres composants, aucun composant fondamental n'est recensé sur la palette
d'outils.

Composants :

1. TRibbon : Composant visuel principal qui fournit le plus de fonctionnalités.


2. TRibbonApplicationMenuBar : Composant qui fournit la fonctionnalité du menu d'application.
3. TRibbonQuickAccessToolbar : Composant qui fournit la fonctionnalité de la barre d'outils d'accès rapide.
4. TRibbonPage : Composant qui représente la page du ruban actuellement visible
5. TRibbonGroup : Composant dans lequel sont affichées toutes les commandes de pages. Les commandes doivent être
placées dans un groupe.

Pour créer une application à l'aide de l'expert Application Ruban


1. Sélectionnez Nouveau Autre... Projets Delphi.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez l'icône Nouvelle application Ruban.

152
2.5 Procédures VCL RAD Studio Ajout de commandes au ruban

3. Cliquez sur OK pour créer la nouvelle application. Vous serez invité à spécifier un dossier pour l'enregistrement de
l'application. Les fichiers générés seront placés dans ce dossier. Après la génération des fichiers et l'ouverture du projet dans
l'EDI, passez à la section Ajout de commandes au ruban de ce document.

Pour créer une nouvelle application sans l'expert


1. Créez une nouvelle application Delphi Win32 VCL (sélectionnez Nouveau Application Fiches VCL — Delphi pour
Win32).
2. Déposez un composant TActionManager sur la fiche.
3. Déposez un composant TRibbon sur la fiche.
4. Cliquez avec le bouton droit sur le composant TRibbon et sélectionnez l'élément Ajouter Menu Application.
5. Cliquez avec le bouton droit de nouveau sur le composant TRibbon et sélectionnez l'élément Ajouter Barre d'outils Accès
rapide.
Remarque: Durant la configuration initiale du ruban, vous pourrez voir un dialogue vous indiquant que le style actuellement
sélectionné dans le TActionManager.Style n'est pas un style de ruban valide. Définissez la propriété TRibbonManager.Style
sur Ribbon – Luna. Les styles applicables au ruban ont le préfixe Ribbon. Par défaut, trois styles de ruban sont implémentés.
Ces styles de ruban fonctionnent également avec la barre d'outils ActionManager par défaut et les contrôles de la barre de
menus. Les styles de ruban disponibles sont les suivants :
• Luna
• Obsidian
• Silver
Voir aussi
Présentation de la VCL ( see page 46)

Construction d'applications Fiches VCL avec graphiques ( see page 101)


2
win32_ribboncontrols2.xml ( see page 153)

2.5.49 Ajout de commandes au ruban


Cette rubrique suit en séquence la création d'une application ruban à l'aide de l'expert Application Ruban ou des étapes
manuelles décrites dans Création d'une application qui utilise les contrôles ruban ( see page 152).

Cette rubrique suppose que vous êtes familier avec le composant TActionManager et les composants associés à son utilisation.
De nombreuses nouvelles propriétés ont été ajoutées afin de prendre en charge les exigences de ruban. La plupart des
propriétés existantes sont sans effet quand elles sont modifiées sur une commande qui est affichée sur le ruban.

Par exemple :

• Les petits boutons affichent toujours leur glyphe sur la gauche du libellé.
• Les grands boutons affichent toujours leur glyphe en haut.
• Un grand bouton doit avoir un libellé. Le libellé doit être au maximum de deux lignes et la largeur du bouton est
redimensionnée en conséquence. La hauteur d'un grand bouton est fixée pour couvrir la hauteur du groupe où la commande
est affichée.
• Seuls les petits boutons sans libellé peuvent être affichés dans les groupes.
Nouvelles propriétés
CommandStyle : La propriété CommandStyle détermine le type de contrôle qui est utilisé pour représenter cette commande sur
le ruban. Le style par défaut est csButton. CommandStyle est beaucoup utilisée pour déterminer le type de contrôle utilisé pour
la commande, sauf sous une exception.

153
Ajout de commandes au ruban RAD Studio 2.5 Procédures VCL

type TCommandStyle = (csButton, csMenu, csSeparator, csText, csGallery, csComboBox, csControl,


csCustom);

Style de la commande sur le groupe de ruban

csButton La commande est un bouton.


csMenu La commande est un élément de menu.
csSeparator La commande est un séparateur avec une description texte.
csText La commande affiche seulement du texte et n'a pas de contrôle associé.
csGallery La commande est une galerie, ou elle affiche une galerie quand elle est sélectionnée.
csComboBox La commande affiche une boîte à options de style Office 2007. Voir la remarque suivante.
csControl La commande a un descendant de TControl qui lui est associé. Un exemple est l'action de déposer un
composant TEdit sur un groupe de ruban.
csCustom Défini par l'utilisateur.

Remarque: Vous pouvez seulement utiliser le style de commande csComboBox si vous avez d'abord placé un composant
TRibbonComboBox de la palette d'outils sur votre groupe de ruban.

CommandProperties : CommandProperties est une classe de propriété dynamique. Les propriétés publiées de cette propriété
(c'est un descendant de TPersistent) varient selon le style de commande sélectionné. Si vous sélectionnez le style de
commande csButton, la classe CommandProperties utilisée est appelée TButtonProperties. Cette classe de propriété publie les
propriétés qui sont spécifiques au style de commande csButton.

L'exemple ButtonSize vous permet d'indiquer si le bouton est un petit ou un grand bouton. Il n'est pas nécessaire pour une
commande csMenu d'avoir une propriété ButtonSize car le menu ne réagit pas à une variation de taille.
2
Toutes les classes CommandProperties dérivent de TCommandProperties. Si vous utilisez le style de commande csCustom,
vous devez dériver de la classe TCommandProperties.

Les propriétés disponibles dans la propriété CommandProperties dépendent du style de commande sélectionné.

csButton ButtonSize
Taille du bouton :
TButtonSize = (bsSmall, bsLarge);

ButtonType
Types spéciaux des boutons autorisés :
TButtonType = (btNone, btDropDown, btSplit, btGallery); // btNone - bouton
normal // btDropdown - bouton affichant un menu déroulant // btSplit - bouton
ayant un menu déroulant et une action par défaut // btGallery - bouton affichant
une galerie
GroupPosition
Position de cette commande dans un groupe de commandes :
TGroupPosition = (gpNone, gpStart, gpMiddle, gpEnd, gpSingle); // Détermine si
une bordure est dessinée autour d'un bouton // gpNone - pas de bordure dessinée
// gpStart - le côté droit d'une bordure n'est pas dessiné // gpMiddle - le haut
et le bas de la bordure sont dessinés // gpEnd - le côté gauche n'est pas
dessiné // gpSingle - la bordure complète est dessinée
csMenu ShowRichContent Définissez cette propriété sur true pour afficher le contenu enrichi d'un élément de menu.
Content Le contenu à afficher sous forme de contenu enrichi. Font Permet d'utiliser une fonte personnalisée
lors de l'affichage du contenu enrichi. Les éléments de menu du contenu enrichi sont limités à deux lignes.
Selon le contenu, les éléments de menu peuvent être plus larges et ne sont pas changés afin d'être plus
hauts, et par conséquent certains éléments de menu affichent des lignes supplémentaires (au-delà des deux
permises.)

154
2.5 Procédures VCL RAD Studio Ajout de commandes au ruban

csSeparator csText et csSeparator partagent la même classe CommandProps, les propriétés disponibles sont ainsi les
mêmes.
Alignment : L'alignement du texte du libellé.
EllipsisPosition : Place des points de suspension si le texte du libellé est trop large pour la largeur du
menu. Il est seulement possible pour les éléments de menu d'être affichés dans le menu Application.
Font : Fonte à utiliser lors du dessin du texte du libellé.
Width : Impose une taille spécifique à la largeur du contrôle créé. Laissez -1 pour csSeparator
CommandStyle et modifiez à votre guise csText CommandStyle.
csText csText et csSeparator partagent la même classe CommandProps, les propriétés disponibles sont ainsi les
mêmes.
csGallery La classe CommandProperties csGallery dérive de la classe CommandProperties csButton. Cela
signifie que toutes les propriétés csButton sont également disponibles pour les commandes csGallery,
ainsi que les propriétés de galerie suivantes.
GalleryType
Type de galerie à afficher :
TGalleryType = (gtDropDown, gtGrid, gtRibbon); // gtDropDown - La galerie a la
forme d'un menu déroulant // gtGrid - La galerie est une disposition grille.
ItemsPerRow contrôle le nombre d'éléments par ligne // gtRibbon - la galerie est
dans le ruban
ItemsPerRow
Nombre d'éléments à afficher sur une ligne.
ShowRichContent
Définissez cette propriété sur true pour afficher le contenu enrichi des éléments de la galerie.
csComboBox AllowResize Contrôle si le menu déroulant associé à la boîte à options peut être redimensionné :
TGalleryResize = (grNone, grVertical, grBoth); // grNone – ne permet pas le
redimensionnement // grVertical – autorise seulement le redimensionnement 2
vertical // grBoth – autorise les redimensionnements vertical et horizontal
Items
Eléments à afficher quand l'utilisateur sélectionne le bouton déroulant. Ces éléments s'affichent dans une
fenêtre comme une boîte à options habituelle.
Text
Le texte à afficher dans la boîte à options.
Width
La largeur du contrôle incrémenteur, à l'exclusion de toute largeur de libellé.
csControl ContainedControl Référence au contrôle auquel elle est associée sur le ruban.
csCustom Défini par l'utilisateur.

KeyTip : La touche qui est enfoncée pour activer la commande lors de l'utilisation du clavier. Pour activer KeyTips, appuyez
sur la touche Alt ou F10.
NewCol : La définition de NewCol pour une commande force l'affichage du contrôle dans une nouvelle colonne du groupe de
ruban. Cette propriété est seulement effective quand l'alignement du groupe de ruban est gaVertical.
NewRow : La définition de NewRow pour une commande force l'affichage du contrôle dans une nouvelle ligne du groupe de
ruban. Cette propriété est seulement effective quand l'alignement du groupe de ruban est gaHorizontal.
Default : Définissez cette propriété sur true pour afficher en gras le libellé des éléments de de menu. Seulement effective pour
les éléments de menu.

Voir aussi
Présentation de la VCL ( see page 46)

Construction d'applications Fiches VCL avec graphiques ( see page 101)

155
Ajout de commandes au ruban RAD Studio 2.5 Procédures VCL

Création d'une application qui utilise les contrôles ruban ( see page 152)

156
2.6 Procédures WebSnap RAD Studio Construction d'une application WebSnap

2.6 Procédures WebSnap


Cette section propose des informations relatives au développement d'applications WebSnap.

Veuillez noter que WebSnap est en cours de dépréciation dans RAD Studio. Bien que WebSnap soit toujours documenté dans
l'aide en ligne, le produit WebSnap n'est plus entièrement supporté. En alternative, commencez à utiliser IntraWeb (VCL pour le
Web). IntraWeb ( see page 2330) est documenté dans cette aide en ligne. Pour obtenir davantage de documentation sur la
VCL pour le Web, visitez http://www.atozed.com/intraweb/docs/.

Rubriques
Nom Description
Construction d'une application WebSnap ( see page 157) La procédure suivante décrit les étapes génériques requises pour construire un
projet WebSnap simple. Pour des rubriques plus avancées, voir les informations
connexes après la procédure.
La construction d'une application WebSnap comprend cinq étapes principales :

1. Créer un projet WebSnap


2. Modifier les composants inclus (facultatif)
3. Définir les options de page (facultatif)
4. Créer des pages WebSnap supplémentaires
5. Exécuter l'application.
Construction d'une application "Hello world" WebSnap ( see page 158) Malgré sa simplicité, l'application "Hello world" WebSnap illustre les étapes
essentielles de la création d'une application WebSnap.
La construction de l'application "Hello world" comprend cinq étapes principales : 2
1. Créer un projet WebSnap.
2. Accepter les composants inclus par défaut.
3. Définir le titre de la page dans les options de page.
4. Modifier le modèle HTML.
5. Exécuter l'application.
Débogage d'une application WebSnap à l'aide du débogueur d'application Web Cette rubrique décrit les tâches essentielles du débogage d'une application
( see page 160) WebSnap au moyen du débogueur d'application Web.

2.6.1 Construction d'une application WebSnap


La procédure suivante décrit les étapes génériques requises pour construire un projet WebSnap simple. Pour des rubriques plus
avancées, voir les informations connexes après la procédure.

La construction d'une application WebSnap comprend cinq étapes principales :

1. Créer un projet WebSnap


2. Modifier les composants inclus (facultatif)
3. Définir les options de page (facultatif)
4. Créer des pages WebSnap supplémentaires
5. Exécuter l'application.

157
Construction d'une application "Hello RAD Studio 2.6 Procédures WebSnap

Pour créer un projet WebSnap


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Application WebSnap à partir du dossier Projets
Delphi WebSnap.
3. Cliquez sur OK. La boîte de dialogue Nouvelle application WebSnap apparaît.
4. Sélectionnez le type de l'application créée.
5. Sélectionnez les composants du modèle de votre application.
6. Dans le champ Nom de page, entrez le nom de votre page.
7. Sélectionnez votre type de mise en cache dans la liste déroulante Mise en cache.

Pour modifier les composants inclus (facultatif)


1. Dans la boîte de dialogue Nouvelle application WebSnap, cliquez sur Composants. La boîte de dialogue Composants
d'application Web s'affiche.
2. Sélectionnez les composants que vous souhaitez inclure.
Conseil: Dans la plupart des cas, les paramètres par défaut sont suffisants.

3. Cliquez sur OK.

Pour définir les options de page (facultatif)


1. Dans la boîte de dialogue Nouvelle application WebSnap, cliquez sur Options de page. La boîte de dialogue Options de
page du module d'application s'affiche.
2 2. Définissez les options de page.

Pour créer des pages WebSnap supplémentaires


1. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Module de page WebSnap à partir du répertoire Projets
Delphi WebSnap.
2. Configurez les options de module de page et cliquez sur OK.
3. Ajoutez et configurez les composants.
Remarque: WebSnap est en cours de dépréciation dans RAD Studio. Bien que WebSnap soit toujours documenté dans
l'aide en ligne, le produit WebSnap n'est plus entièrement supporté. En alternative, commencez à utiliser IntraWeb (VCL pour
le Web). IntraWeb ( see page 2330) est documenté dans cette aide en ligne. Pour obtenir davantage de documentation sur
la VCL pour le Web, visitez http://www.atozed.com/intraweb/docs/.
Voir aussi
Présentation des applications Web ( see page 51)

Construction d'une application "Hello world" WebSnap ( see page 158)

2.6.2 Construction d'une application "Hello world" WebSnap


Malgré sa simplicité, l'application "Hello world" WebSnap illustre les étapes essentielles de la création d'une application
WebSnap.

La construction de l'application "Hello world" comprend cinq étapes principales :

1. Créer un projet WebSnap.

158
2.6 Procédures WebSnap RAD Studio Construction d'une application "Hello

2. Accepter les composants inclus par défaut.


3. Définir le titre de la page dans les options de page.
4. Modifier le modèle HTML.
5. Exécuter l'application.

Pour créer un projet WebSnap


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Dans la boîte de dialogue Nouveaux éléments, sélectionnez Application WebSnap à partir du dossier Projets
Delphi WebSnap ou Projets C++Builder WebSnap.
3. Cliquez sur OK. La boîte de dialogue Nouvelle application WebSnap apparaît.
4. Sélectionnez le bouton radio Exécutable débogueur d'application Web.
5. Dans le champ Nom de classe, entrez HelloWorld.
6. Sélectionnez les composants du modèle de votre application.
7. Dans le champ Nom de page, entrez HelloWorld.
8. Sélectionnez votre type de mise en cache dans la liste déroulante Mise en cache.

Pour modifier les composants inclus (facultatif)


1. Dans la boîte de dialogue Nouvelle application WebSnap, cliquez sur Composants. La boîte de dialogue Composants
d'application Web s'affiche.
2. Sélectionnez les composants que vous souhaitez inclure.
Conseil: Dans la plupart des cas, les paramètres par défaut sont suffisants.
2
3. Cliquez sur OK.

Pour définir le titre de la page dans les options de page


1. Dans la boîte de dialogue Nouvelle application WebSnap, cliquez sur Options de page. La boîte de dialogue Options de
page du module d'application s'affiche.
2. Dans le champ Titre, entrez Hello World!.

Pour modifier le modèle HTML


1. Cliquez sur l'onglet HTML dans l'EDI.
2. Sous la ligne <h2><%= Page.Title %></h2>, insérez une ligne indiquant Voici ma première application
WebSnap.
3. Enregistrez l'application.

Pour exécuter l'application "Hello world"


1. Choisissez Exécuter Exécuter. Une fenêtre d'application s'ouvre et le serveur COM enregistre votre application WebSnap
avec le débogueur d'application Web.
2. Fermez la fenêtre de l'application.
3. Choisissez Outils Débogueur d'application Web. Le débogueur d'application Web se lance.
4. Dans le débogueur, cliquez sur le bouton Démarrer.
5. Cliquez sur URL par défaut pour lancer le navigateur.
6. Dans le navigateur, sélectionnez votre application Hello World dans la liste des applications et cliquez sur Aller. Votre
application apparaît dans le navigateur avec le texte Hello World! Voici ma première application WebSnap.

159
Débogage d'une application WebSnap à RAD Studio 2.6 Procédures WebSnap

7. Fermez le navigateur Web pour revenir à l'EDI.


Remarque: WebSnap est en cours de dépréciation dans RAD Studio. Bien que WebSnap soit toujours documenté dans
l'aide en ligne, le produit WebSnap n'est plus entièrement supporté. En alternative, commencez à utiliser IntraWeb (VCL pour
le Web). IntraWeb ( see page 2330) est documenté dans cette aide en ligne. Pour obtenir davantage de documentation sur
la VCL pour le Web, visitez http://www.atozed.com/intraweb/docs/.
Voir aussi
Présentation des applications Web ( see page 51)

Construction d'une application WebSnap ( see page 157)

2.6.3 Débogage d'une application WebSnap à l'aide du


débogueur d'application Web
Cette rubrique décrit les tâches essentielles du débogage d'une application WebSnap au moyen du débogueur d'application
Web.

Pour déboguer une application WebSnap à l'aide du débogueur d'application Web


1. Enregistrez l'application des informations de serveur pour le débogueur d'application Web.
2. Enregistrez votre application WebSnap avec le débogueur d'application Web à sa première exécution.
3. Lancez le débogueur d'application Web.
4. Sélectionnez et lancez votre application web.
2 5. Déboguez votre application web en utilisant des points d'arrêt et le journal du débogueur d'application Web.

Pour enregistrer l'application des informations de serveur pour le débogueur d'application Web
1. Naviguez vers le répertoire bin de votre installation RAD Studio.
2. Exécutez serverinfo.exe.
3. Fermez la fenêtre vide d'application qui s'ouvre.
Cette étape doit uniquement être effectuée lors de la première utilisation du débogueur d'application Web.

Pour enregistrer votre application web avec le débogueur


1. Choisissez Exécuter Exécuter. Cela affiche la fenêtre console du serveur COM qui constitue votre application serveur Web.
2. Fermez la fenêtre vide d'application qui s'ouvre.
Votre serveur COM est maintenant enregistré et accessible au débogueur d'application Web.

Pour lancer le débogueur d'application Web


1. Choisissez Outils Débogueur d'application Web. Le débogueur d'application Web se lance.
2. Dans le débogueur, cliquez sur le bouton Démarrer.
3. Cliquez sur URL par défaut pour lancer le navigateur.

Pour sélectionner et lancer votre application web


1. Dans le navigateur, sélectionnez votre application dans la liste des applications.
2. Cliquez sur Aller. Votre application apparaît dans le navigateur.
Remarque: WebSnap est en cours de dépréciation dans RAD Studio. Bien que WebSnap soit toujours documenté dans

160
2.6 Procédures WebSnap RAD Studio Débogage d'une application WebSnap à

l'aide en ligne, le produit WebSnap n'est plus entièrement supporté. En alternative, commencez à utiliser IntraWeb (VCL pour
le Web). IntraWeb ( see page 2330) est documenté dans cette aide en ligne. Pour obtenir davantage de documentation sur
la VCL pour le Web, visitez http://www.atozed.com/intraweb/docs/.
Voir aussi
Présentation des applications Web ( see page 51)

Construction d'une application WebSnap ( see page 157)

161
Construction d'une application de services RAD Studio 2.7 Procédures de services Web

2.7 Procédures de services Web


Cette section propose des informations relatives au développement et à l'utilisation de services web.

Rubriques
Nom Description
Construction d'une application de services Web "Hello World" ( see page 162) Les services Web sont des applications modulaires indépendantes qui peuvent
être publiées ou invoquées sur un réseau (comme le web). Les services Web
utilisent SOAP, un protocole léger standard permettant d'échanger des
informations dans une environnement distribué. Il utilise HTTP comme protocole
de communication et XML pour coder les appels des procédures distantes.
Accès à une application services Web "Hello World" ( see page 164) Pour exploiter l'application de services Web que vous avez créée, vous devez
créer une application client qui accédera à l'application de services Web
ASP.NET. Ce processus requiert différentes étapes de développement pour
atteindre le résultat recherché.
L'accès à une application "Hello World" simple avec des services Web ASP.NET
comprend quatre étapes principales :

1. Créez une application client.


2. Ajoutez une référence Web pour un service Web XML.
3. Créez la logique de code sous-jacent.
4. Sélectionnez un nom pour votre projet et cliquez sur OK.
Un fichier WinForm1.cs TWinForm1.pas est généré.
Construction d'une application de services Web "Hello World" ASP.NET ( see La construction d'une application avec des services Web ASP.NET vous permet
page 165) d'exposer des fonctionnalités à votre application client sur une connexion Web.
2 Ces étapes vous guident dans la construction d'une application "Hello World"
simple avec des services Web ASP.NET. Une fois construite, l'application
expose tous ses objets et méthodes par le biais d'un WebMethod que vous créez
et atteignez via un navigateur Web.
La création d'une application "Hello World" simple avec des services Web
ASP.NET comprend trois étapes principales :

1. Créer une application de services Web ASP.NET.


2. Créer un WebMethod.
3. Tester et exécuter l'application de services Web
ASP.NET.
Remarque: Actuellement, avec... suite ( see page 165)

2.7.1 Construction d'une application de services Web "Hello


World"
Les services Web sont des applications modulaires indépendantes qui peuvent être publiées ou invoquées sur un réseau
(comme le web). Les services Web utilisent SOAP, un protocole léger standard permettant d'échanger des informations dans
une environnement distribué. Il utilise HTTP comme protocole de communication et XML pour coder les appels des procédures
distantes.

Pour construire une application de services Web "Hello World"


1. Choisissez Fichier Nouveau Autre. La boîte de dialogue Nouveaux éléments apparaît.
2. Sélectionnez le dossier WebServices.

162
2.7 Procédures de services Web RAD Studio Accès à une application services Web

3. Double-cliquez sur l'icône Application serveur SOAP. L'expert Application serveur SOAP s'ouvre.
4. Choisissez le type d'application serveur Web que vous voulez utiliser pour votre service Web. L'expert génère une nouvelle
application serveur Web qui inclut un module Web contenant les trois composants HTTPSoapPascalInvoker,
HTTPSoapDispatcher et WSDLHTMLPublish. Lorsque vous quittez l'expert d'application serveur SOAP, il vous demande de
définir une interface pour votre service Web.
5. Pour créer un service Web à partir de rien, cliquez sur Oui. L'expert d'ajout d'un nouveau service Web s'ouvre.
6. Pour ajouter un nouveau service Web, spécifiez le nom de l'interface invocable que vous souhaitez exposer aux clients.
L'expert d'ajout d'un nouveau service Web vous permet de spécifier le nom de l'interface invocable et génère le code pour
déclarer et recenser l'interface et sa classe d'implémentation.
7. Pour implémenter un service Web ayant déjà été défini dans un document WSDL, utilisez l'importateur WSDL pour générer
les interfaces.

Pour utiliser l'importateur WSDL


1. Choisissez Fichier Nouveau Autre. Une boîte de dialogue Nouveaux éléments apparaît.
2. Sélectionnez le dossier WebServices.
3. Double-cliquez sur l'icône Importateur WSDL. Un expert Importateur WSDL apparaît.
4. Dans cette boîte de dialogue, spécifiez le nom de fichier d'un document WSDL (ou d'un fichier XML) ou spécifiez l'URL où ce
document est publié. Si vous ignorez l'URL du document WSDL à importer, cliquez sur Rechercher UDDI. Cela lance le
navigateur UDDI.
5. Si le document WSDL réside sur un serveur nécessitant l'authentification, cliquez sur Options. Une boîte de dialogue
Options d'importation apparaît.
6. Entrez un nom d'utilisateur et un mot de passe afin que l'expert puisse récupérer le document WSDL.
7. Cliquez sur Suivant. L'importateur WSDL affiche le code qu'il génère pour chaque définition dans le document WSDL
compatible avec l'infrastructure de services Web. 2
8. Cliquez sur Terminer. L'importateur crée de nouvelles unités qui définissent et recensent les interfaces invocables pour les
opérations définies dans le document, et qui définissent et recensent les classes distantes correspondant aux types définis
par le document.

Pour utiliser le navigateur UDDI


1. Dans le Navigateur UDDI, indiquez le registre UDDI.
2. Pour localiser l'entité métier à partir de laquelle vous souhaitez importer un service Web, entrez son nom.
3. Pour une correspondance exacte et une recherche sensible à la casse, cliquez sur les cases à cocher Concordance exacte et
MAJ/min.
4. Dans la zone de texte Lignes, entrez le nombre de correspondances désiré.
5. Pour spécifier l'ordre des résultats, choisissez dans la liste déroulante Tri la valeur pour Nom, Description,
LastUpdatedDescending et LastUpdatedAescending.
6. Cliquez sur Rechercher. Toutes les correspondances apparaissent dans la vue arborescente dans le coin supérieur droit.
Lorsque vous sélectionnez un TModel qui représente un service Web avec un document WSDL, le bouton d'importation est
activé.
7. Cliquez sur le bouton Importer.
Voir aussi
Présentation des services Web ( see page 54)

Utilisation de services Web ( see page 2388)

Accès à une application de services Web "Hello World"

163
Accès à une application services Web RAD Studio 2.7 Procédures de services Web

2.7.2 Accès à une application services Web "Hello World"


Pour exploiter l'application de services Web que vous avez créée, vous devez créer une application client qui accédera à
l'application de services Web ASP.NET. Ce processus requiert différentes étapes de développement pour atteindre le résultat
recherché.

L'accès à une application "Hello World" simple avec des services Web ASP.NET comprend quatre étapes principales :

1. Créez une application client.


2. Ajoutez une référence Web pour un service Web XML.
3. Créez la logique de code sous-jacent.
4. Sélectionnez un nom pour votre projet et cliquez sur OK. Un fichier WinForm1.cs TWinForm1.pas est généré.

Pour créer une application client


1. Choisissez Fichier Nouveau Autre. Une boîte de dialogue Nouveaux éléments apparaît.
2. Sélectionnez n'importe quel type d'application pour créer votre client, comme une application RAD Studio ou une application
Web ASP.NET. Pour cet exemple, nous allons créer une application RAD Studio utilisant un Windows Form.
3. Cliquez sur OK. Une boîte de dialogue Nouveau projet apparaît.

Pour ajouter une référence Web pour une application de services Web ASP.NET
1. Choisissez Projet Ajouter une référence Web.

2 2. Dans la boîte de dialogue web Navigateur UDDI Universel CodeGear C#Builder Navigateur UDDI Universel CodeGear
Delphi pour .NET , entrez l'URL suivante : http://localhost/WebService1/WebService1.asmx dans la zone
d'adresse en haut de la boîte de dialogue.
Remarque: Le nom de votre application peut être différent de WebService1, comme indiqué. Dans ce cas, utilisez le nom de
votre application à la place de WebService1 dans l'exemple précédent.

3. Appuyez sur la touche Entrée.


Remarque: Si vous devez déterminer le chemin correct et que vous utilisez IIS, vous pouvez ouvrir l'administrateur IIS à
partir des outils d'administration dans le panneau de configuration de Windows XP. Trouvez le service Web que vous avez
enregistré et compilé dans la liste des sites Web IIS, puis consultez le nom du site et le nom du fichier .asmx.
Si vous avez entré le chemin correct, les informations concernant les WebMethods doivent s'afficher.
4. Cliquez sur le lien Description du service pour visualiser le document WSDL.
5. Cliquez sur Ajouter une référence pour ajouter le document WSDL à l'application client. Un dossier Références Web est
ajouté au répertoire Projet dans le gestionnaire de projet qui contient le fichier WebService1.wsdl et la boîte de dialogue
disparaît.

Pour créer la logique de code sous-jacent


1. Ajoutez un objet button dans Windows Form.
2. Double-cliquez sur le contrôle button pour visualiser le fichier de code sous-jacent.
3. Créez un événement button en tapant le texte suivant dans l'éditeur de code :
private void button1_Click(object sender, System.EventArgs e)
{
WebService1 ws = new WebService1();
button1.Text = ws.HelloWorld();
}

164
2.7 Procédures de services Web RAD Studio Construction d'une application de services

procedure TWinForm1.Button1_Click(sender: System.Object; e: System.EventArgs);


begin
new ws := WebService1();
button1.Text := ws.HelloWorld();
end;

Pour exécuter l'application client


1. Enregistrez l'application.
2. Compilez le projet et exécutez-le.
3. Cliquez sur le contrôle button. La mention "HelloWorld" apparaît sur le bouton.
Voir aussi
Présentation des services Web ( see page 54)

Support des services Web

Construction d'une application de services Web "Hello World" ( see page 165)

2.7.3 Construction d'une application de services Web "Hello


World" ASP.NET
La construction d'une application avec des services Web ASP.NET vous permet d'exposer des fonctionnalités à votre application
client sur une connexion Web. Ces étapes vous guident dans la construction d'une application "Hello World" simple avec des
services Web ASP.NET. Une fois construite, l'application expose tous ses objets et méthodes par le biais d'un WebMethod que
vous créez et atteignez via un navigateur Web. 2
La création d'une application "Hello World" simple avec des services Web ASP.NET comprend trois étapes principales :

1. Créer une application de services Web ASP.NET.


2. Créer un WebMethod.
3. Tester et exécuter l'application de services Web ASP.NET.
Remarque: Actuellement, avec RAD Studio vous pouvez seulement créer des services web en utilisant la méthode de code
sous-jacent. Vous ne pouvez pas utiliser la méthode de code en ligne, dans laquelle vous codez votre service web dans le
fichier <NomService>.asmx. Actuellement, RAD Studio ne prend pas en charge la méthode de code en ligne de création de
services web.

Pour créer une application de services Web ASP.NET


1. Choisissez Fichier Nouveau Autre. Une boîte de dialogue Nouveaux éléments apparaît.
2. Sélectionnez le dossier pour la langue que vous utilisez.
3. Sélectionnez Application Service Web ASP.NET. Une boîte de dialogue Nom de l'application apparaît.
4. Entrez un nom et un emplacement pour l'application dans les champs et conservez toutes les autres valeurs par défaut.
Remarque: Si vous utilisez le serveur Web Cassini, vous devez modifier les entrées Emplacement et Serveur. Vous devez
également vous assurer de configurer le serveur Web Cassini avant de tenter d'exécuter cette application. Choisissez
Outils->Options
et sélectionnez Options ASP.NET pour définir le Chemin et le Port pour Cassini.
5. Cliquez sur OK. Un fichier WebService1.asmx et un WebService1.asmx.<typefichier> sont automatiquement créés.

165
Construction d'une application de services RAD Studio 2.7 Procédures de services Web

Pour créer un WebMethod


1. Sélectionnez l'onglet WebService.asmx.cs WebService.asmx.pas en bas de l'éditeur de code. Si vous donnez un nom
différent du nom par défaut à votre application de service Web, c'est ce nom qui apparaîtra sur l'onglet. Le code de
l'application "Hello World" est déjà inclus dans le WebMethod qui est créé lorsque vous créez l'application de services Web.
2. Retirez le commentaire du WebMethod exemple "HelloWorld" et du WebMethod exemple "EchoString" fournis dans le fichier
de code sous-jacent. L'un se trouve dans le module Interface et l'autre dans le module Implementation.
3. Choisissez Projet Construire <nom_projet> pour construire votre projet.
4. Exécutez votre projet. Cette opération appelle le navigateur qui héberge le service Web. Les pages que vous verrez incluront
le code exemple SOAP et HTTP que vous pouvez utiliser pour accéder aux WebMethods. Vous pouvez exécuter les
exemples et voir comment les résultats sont transmis à un fichier XML de sortie.

Pour tester et exécuter manuellement le service Web XML


1. A partir d'un navigateur Web, entrez l'emplacement du fichier WebService1.asmx sur votre hôte local :
http://localhost/WebService1/WebService1.asmx. Les pages que vous verrez incluront le code exemple SOAP et
HTTP que vous pouvez utiliser pour accéder aux WebMethods. Vous pouvez exécuter les exemples et voir comment les
résultats sont transmis à un fichier XML de sortie.
Remarque: Vous pourrez utiliser une syntaxe légèrement différente de celle présentée dans cette étape. Par exemple, sur
certaines machines Windows XP, l'identificateur localhost doit être le nom de votre machine. Ainsi, si le nom de votre
machine est MaMachine, la syntaxe serait : http://MaMachine/WebService1/Webservice1.asmx.

2. Testez les deux méthodes à partir d'un navigateur Web.


Voir aussi
Présentation des services Web ASP.NET
2
Gestion des services Web ASP.NET

Accès à une application services Web "Hello World"

166
3 RAD Studio

3 Référence
Rubriques
Nom Description
Référence C++ ( see page 168) Cette section contient les rubriques de référence de la bibliothèque C++ de RAD
Studio.
Guide du développeur Win32 ( see page 1224) Cette section contient les rubriques du Guide du développeur Win32 relatives à
la personnalité Delphi Win32 de RAD Studio.

167
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

3.1 Référence C++


Cette section contient les rubriques de référence de la bibliothèque C++ de RAD Studio.

Rubriques
Nom Description
Utilitaires en ligne de commande ( see page 168) C++Builder fournit un jeu complet d'utilitaires en ligne de commande en plus de
son environnement de développement intégré (EDI). Ces utilitaires vous
permettent d'utiliser la ligne de commande pour effectuer une compilation ciblée
et d'autres fonctions associées, y compris la recherche de fichiers et l'importation
de fichiers de définition.
Liste de tous les avertissements et erreurs du compilateur C++ ( see page 229) Cette section décrit les messages d'erreur et d'avertissement du compilateur C++
RAD Studio.
Exemples C++ ( see page 400) Cette section contient des exemples C++.
Guide du langage C++ ( see page 401) Cette section traite du langage C++.
C Runtime Library Reference ( see page 717) RAD Studio has several hundred functions, macros, and classes that you call
from within your C and C++ programs to perform a wide variety of tasks,
including low- and high-level I/O, string and file manipulation, memory allocation,
process control, data conversion, mathematical calculations, and more.
Note: In the online help, each function, macro, and class in the C Runtime
Library is listed only once . However, some functions, macros, and classes are
defined in more than one header file.
For example, _strerror is defined in both string.h and stdio.h. For functions
that are defined in several header files, the online... suite ( see page 717)

3.1.1 Utilitaires en ligne de commande


C++Builder fournit un jeu complet d'utilitaires en ligne de commande en plus de son environnement de développement intégré
(EDI). Ces utilitaires vous permettent d'utiliser la ligne de commande pour effectuer une compilation ciblée et d'autres fonctions
associées, y compris la recherche de fichiers et l'importation de fichiers de définition.

Rubriques
Nom Description
BCC32, le compilateur C++ en ligne de commande ( see page 171) Le compilateur C++ CodeGear (BCC32.EXE) est un shell de compilateur de
ressources. Il invoque BRCC32 et RLINK32, selon la syntaxe de la ligne de
commande.
BRC32, le Shell de ressources ( see page 176) Le compilateur de ressources Borland (BRC32) est un shell de compilateur de
ressources. Il invoque BRCC32 et RLINK32, selon la syntaxe de la ligne de
commande.
BRCC32.EXE, le compilateur de ressources ( see page 177) BRCC32 est la version en ligne de commande du compilateur de ressources. Il
accepte un fichier script de ressources (.RC) en entrée et produit un fichier objet
ressource (.RES) en sortie.
COFF2OMF.EXE, l'outil de conversion d'une bibliothèque d'importation ( see COFF2OMF convertit un fichier bibliothèque d'importation COFF (FichierEntrée)
page 178) en un fichier bibliothèque d'importation OMF correspondant (FichierSortie).
COFF2OMF.EXE est situé dans le répertoire \bin de C++Builder.
3 CPP32.EXE, le préprocesseur du compilateur C ( see page 179) CPP32.EXE produit un fichier de listage d'un programme C ou C++, dans lequel
tous les #define de macros et tous les #include de fichiers ont été développés.
Bien qu'il ne soit pas nécessaire d'utiliser le préprocesseur pour une compilation
normale, ce fichier de listage peut être utile à des fins de débogage.
Souvent, lorsque le compilateur signale une erreur dans une macro ou un fichier
d'inclusion, vous pouvez obtenir davantage d'informations sur la nature de
l'erreur en consultant les fichiers d'inclusion ou les résultats du développement
des macros. Avec un grand nombre de compilateurs à plusieurs passes, ce
travail est... suite ( see page 179)
DCC32.EXE, le compilateur en ligne de commande Delphi. ( see page 181) DCC32 est le compilateur en ligne de commande Delphi (Pascal Objet).
Pour afficher l'aide de la ligne de commande, entrez :

168
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

DCCIL.EXE, le compilateur en ligne de commande Delphi pour .NET ( see DCCIL est le compilateur en ligne de commande Delphi (Pascal Objet) pour
page 183) l'environnement .NET. Utilisez DCCIL pour compiler des exécutables .NET
managés.
Pour afficher l'aide de la ligne de commande, entrez :
GREP.EXE, l'utilitaire de recherche de texte ( see page 184) GREP (Global Regular Expression Print) est un puissant programme de
recherche de texte dérivé de l'utilitaire UNIX du même nom. GREP recherche un
texte dans un ou plusieurs fichiers ou dans le flux d'entrée standard.
ILINK32.EXE, le lieur incrémentiel ( see page 189) ILINK32 lie des modules objets (fichiers .OBJ), des modules bibliothèques
(fichiers .LIB) et des ressources pour produire des fichiers exécutables (fichiers
.EXE, .DLL et .BPL). ILINK32 crée et gère une série de fichiers d'état contenant
ces informations. Ces fichiers d'état permettent aux liens suivants d'être de type
incrémentiel, ce qui réduit sensiblement la durée totale des liens.
IMPDEF.EXE, le gestionnaire de définition de module ( see page 194) Les bibliothèques d'importation permettent d'accéder aux fonctions d'une DLL
Windows. Les bibliothèques d'importation contiennent des enregistrements.
Chaque enregistrement contient le nom d'une DLL et spécifie l'emplacement
dans la DLL des fonctions importées. Ces enregistrements sont liés à
l'application par le lieur, et ils fournissent à Windows les informations nécessaires
pour résoudre les appels de fonctions de DLL. Vous pouvez substituer une
bibliothèque d'importation à une partie ou à la totalité de la section IMPORTS
d'un fichier de définition de module.
IMPDEF accepte en entrée un nom de DLL et génère en sortie un fichier de
définition de module avec une... suite ( see page 194)
IMPLIB.EXE, l'outil bibliothèque d'importation ( see page 196) IMPLIB accepte en entrée des DLL et/ou des fichiers de définition de module et
génère en sortie une bibliothèque d'importation.
Si vous avez créé une application Windows, vous avez déjà utilisé
IMPORT32.LIB, la bibliothèque d'importation des DLLs Windows standard.
IMPORT32.LIB est liée automatiquement lors de la construction d'une application
Win32 dans l'EDI de C++Builder et lors de l'utilisation de BCC32 au niveau de la
ligne de commande.
Une bibliothèque d'importation liste certaines voire toutes les fonctions exportées
pour une ou plusieurs DLLs. IMPLIB crée directement une bibliothèque
d'importation à partir de DLLs ou de fichiers de définition de module pour... suite
( see page 196)
Utilisation des fichiers d'inclusion ( see page 197) Dans C++, les fichiers d'inclusion ont toujours l'extension de fichier .h.
MAKE ( see page 198) MAKE.EXE est un utilitaire en ligne de commande qui vous aide à gérer les
cycles de compilation et de liaison des projets. MAKE n'est pas uniquement
consacré à la compilation et à la liaison, c'est un outil plus généraliste
d'exécution de commandes basées sur les dépendances des fichiers. MAKE
vous aide à construire rapidement les projets en compilant uniquement les
fichiers modifiés depuis la dernière compilation. De plus, vous pouvez définir les
règles spécifiant comment doit agir MAKE dans certaines circonstances
spéciales au cours de vos constructions.
Directives MAKE ( see page 201) Les directives de MAKE ressemblent aux directives des langages tels que Pascal
et C. Dans MAKE, elles effectuent diverses opérations de contrôle, telles que
l'affichage des commandes avant leur exécution. Les directives de MAKE
commencent par un point ou par un point d'exclamation, et remplacent les
options données sur la ligne de commande. Les directives qui commencent par
un point d'exclamation doivent apparaître au début d'une nouvelle ligne.
Le tableau suivant donne la liste des directives de MAKE et leur options en ligne
de commande correspondantes :

Macros MAKE ( see page 206) Une macro est une variable que MAKE traduit par une chaîne à chaque fois qu'il
rencontre la macro dans un fichier make. Par exemple, vous pouvez définir une
macro appelée LIBNAME qui représente la chaîne "mylib.lib". Pour cela, tapez la
ligne LIBNAME = mylib.lib au début de votre fichier make. Puis, lorsque MAKE
rencontre la macro $(LIBNAME), il substitue la chaîne mylib.lib. Les macros vous
permettent de créer des fichiers make modèle que vous pouvez ensuite ajuster à
vos besoins.
Pour utiliser une macro dans un fichier make, tapez $(NomMacro) où NomMacro
est une macro définie. Vous pouvez utiliser des... suite ( see page 206)
3

169
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

Commandes et règles (explicites et implicites) de MAKE ( see page 208) Vous écrivez des règles explicites et implicites indiquant à MAKE comment
construire les cibles de votre fichier make. En général, ces règles sont les
suivantes :

• Les règles explicites sont des instructions applicables à


certains fichiers.
• Les règles implicites sont des instructions générales
applicables aux fichiers non concernés par les règles
explicites.
Toutes les règles que vous écrivez doivent respecter le
format général suivant :
Options des messages ( see page 212) Utilisez l'option -w pour spécifier les options des messages du compilateur
CodeGear C++ :

• Pour activer un message d'avertissement particulier,


entrez l'option -w avec un code d'option d'une à trois
lettres.
• Pour désactiver le message d'avertissement, entrez
l'option -w- avec un code d'option d'une à trois lettres.
Fichiers de définition de module ( see page 214) Utilisez les fichiers de définition de module avec ILINK32. Un fichier de définition
de module est un fichier texte ASCII qui fournit des informations à ILINK32 sur le
contenu et les exigences système d'une application Windows. Utilisez IMPDEF
pour créer un fichier de définition de module.
Le fichier de définition de module nomme les fichiers .EXE ou .DLL, identifie le
type d'application, énumère les fonctions importées et exportées, décrit les
attributs des segments de données et des sections de code, vous permet de
spécifier les attributs des segments de données et des sections de code
supplémentaires, spécifie la taille de... suite ( see page 214)
Fichiers en-tête précompilés ( see page 219) Les fichiers en-tête précompilés accélèrent de façon significative la vitesse de
compilation en stockant une image de la table des symboles dans un fichier sur
disque. Ce fichier est ensuite rechargé au lieu d'analyser de nouveau tous les
fichiers en-tête. Le chargement direct de la table des symboles depuis le disque
est beaucoup plus rapide que l'analyse du texte des fichiers en-tête, en
particulier si plusieurs fichiers source incluent le même fichier en-tête.
Pour utiliser les fichiers en-tête précompilés, spécifiez les diverses options -H
dans votre commande BCC32.
Options des en-têtes précompilés
RLINK32.DLL, le lieur de ressources (C++) ( see page 220) RLINK32.DLL est le lieur de ressources qui lie des ressources sous la forme de
fichiers .RES pour produire un fichier .EXE et marque le fichier .EXE résultant
comme exécutable Windows. RLINK32.DLL :

• Lie les ressources en combinant les tables de chaînes et


les tables de messages, puis en liant ces ressources liées
à l'exécutable.
• Est appelé par ILINK32 et est utilisé pour les ressources
32 bits.
TDUMP.EXE, l'utilitaire de vidage de fichier ( see page 221) TDUMP.EXE produit un vidage montrant la structure d'un fichier.
TDUMP divise un fichier de manière structurelle et utilise son extension pour
déterminer le format d'affichage de sortie. TDUMP reconnaît de nombreux
formats de fichiers tels qu'.EXE, .OBJ et .LIB. Si TDUMP ne reconnaît pas une
extension, il produit un vidage hexadécimal du fichier. Vous pouvez contrôler le
format de sortie en utilisant les options de la ligne de commande TDUMP au
lancement du programme.
3 La capacité de TDUMP à visualiser la structure interne d'un fichier permet non
seulement de voir le contenu d'un fichier, mais aussi de savoir comment il... suite
( see page 221)

170
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

TLIB.EXE, le gestionnaire de bibliothèques ( see page 224) TLIB est un utilitaire qui gère les bibliothèques de fichiers .OBJ (modules objet).
Une bibliothèque permet de manipuler facilement un collection de modules objet
comme une unité.
Les bibliothèques fournies avec le compilateur CodeGear C++ ont été construites
avec TLIB. Vous pouvez utiliser TLIB pour construire vos propres bibliothèques
ou pour modifier les bibliothèques CodeGear C++, vos bibliothèques, les
bibliothèques fournies par d'autres programmeurs ou des bibliothèques que vous
avez achetées.
Quand TLIB modifie une bibliothèque existante, TLIB crée une copie de la
bibliothèque d'origine et lui attribue l'extension .BAK.
Vous pouvez utiliser TLIB pour :

• Créer une nouvelle bibliothèque à... suite ( see page


224)
Utilisation de TOUCH.EXE ( see page 227) TOUCH.EXE met à jour la date d'un fichier afin qu'elle corresponde à la date et à
l'heure en cours de votre système.
TRIGRAPH ( see page 228) Les trigraphs sont des séquences de trois caractères qui remplacent certains
caractères utilisés dans le langage C et qui ne sont pas disponibles sur tous les
claviers. Comme la conversion des trigraphs dans le compilateur ralentirait
considérablement les compilations, CodeGear C++ fournit un filtre nommé
TRIGRAPH.EXE qui permet de gérer les séquences trigraph.

3.1.1.1 BCC32, le compilateur C++ en ligne de commande


Le compilateur C++ CodeGear (BCC32.EXE) est un shell de compilateur de ressources. Il invoque BRCC32 et RLINK32, selon
la syntaxe de la ligne de commande.

Syntaxe de la ligne de commande


bcc32 [option [option...}] <nomfichier> [<nomfichier>...]

Utilisez des espaces pour séparer le nom du compilateur, chaque option et les noms de fichier sur la ligne de commande.
Placez devant chaque option un tiret (-) ou une barre oblique (/). Par exemple :
BCC32 -Ic:\code\hfiles

Vous pouvez également spécifier les options dans les fichiers de configuration (.CFG), qui sont décrites dans une section
suivante.

Vous pouvez également utiliser BCC32 pour envoyer les fichiers .OBJ à ILINK32 ou les fichiers .ASM à TASM32 (si TASM32 est
installé sur votre machine).

Consultez l'aide de la ligne de commande BCC32 pour obtenir des informations détaillées
Pour afficher l'aide de la ligne de commande BCC32.exe dans la fenêtre cmd, incluez l'option de ligne de commande —h.

Par exemple, pour afficher la liste des options de la ligne de commande du compilateur les plus courantes, tapez :
BCC32 -h

La liste affichée indique les options activées par défaut (*) :


C:\>bcc32 -h CodeGear C++ 5.92 for Win32 Copyright (c) 1993, 2007 CodeGear
Options disponibles (* = paramètre par défaut, xxx = comporte des sous-options : utilisez -h
-X) : 3
(Remarque : -X- ou -w-XXX annulera habituellement tout ce qui a été défini ou restauré par -X)
-3 Générer des instructions compatibles au mode protégé 80386
-4 Générer des instructions compatibles au mode protégé 80386/80486
-5 Générer les instructions Pentium
-6 Générer les instructions Pentium Pro
-Axxx Active la conformité ANSI
-B Compiler en .ASM (-S), puis assembler en .OBJ
-C Activer les commentaires imbriqués
-CP Activer la pagination de code (pour MBCS)
-D -D <nom> définit 'nom' comme une chaîne null, ou utilisez -D<nom>=<valeur>

171
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

-E Spécifier l'assembleur à utiliser


-G Optimiser pour la taille/vitesse ; utilisez à la place -O1 et -O2
-Hxxx Générer et utiliser des en-têtes précompilés
-I Définit le chemin de recherche des fichiers d'inclusion
-Jxxx Options de génération de template
-K Définir le type de caractère par défaut à non signé
-L Chemin d'accès aux fichiers bibliothèque
-M Créer un fichier map du lieur
-O Optimiser les sauts
-P Effectuer la compilation C++ quelle que soit l'extension des sources
-Q Informations erreurs du compilateur étendues
-R Inclure les informations du navigateur dans les fichiers .OBJ générés
-RF Chercher les références au symbole
* -RT Activer les informations de type à l'exécution
-S Compiler en assembleur
-T Spécifier l'option assembleur, ex. -Tx
-U Annuler les définitions de nom précédentes
-Vxxx Options de compatibilité
-Wxxx La cible est une application Windows
-X Désactiver les sorties d'auto-dépendance du compilateur
-axxx Définir la frontière de l'alignement des données. La valeur par défaut est -a8; -a-
signifie -a1
* -b Donner une taille entière aux énumérations (-b- les rend aussi court que possible)
-c Compiler en fichier objet uniquement, ne pas lier
-d Fusionner les chaînes dupliquées
-dc Placer les chaînes dans le segment de données en lecture seule
-dw Placer les chaînes dans le segment de données (en écriture)
-e Spécifier le chemin de l'exécutable cible
* -ff Virgule flottante rapide
-fp Corriger le défaut Pentium FDIV
* -fq Utiliser l'instruction de comparaison en virgule flottante silencieuse (FUCOMP)
-g Arrêter la compilation groupée après n avertissements (255 par défaut)
-h Demande d'aide ('-h -' affiche toute l'aide). Peut être spécifique : -h -V
-i Définir la longueur d'identificateur significative maximale (250 par défaut)
-j Arrêter la compilation groupée après n erreurs (Aucune par défaut)
* -k Générer les cadres de pile standard
-l Passer des options au lieur ; par exemple : -ls -l-x
-m Générer les informations de dépendance du makefile
-md Placer les informations de dépendance dans des fichiers .d, pas dans le fichier
objet
-mm Ignorer les fichiers en-tête système en générant les informations de dépendance
-mo Spécifier le fichier de sortie pour les informations de dépendance
-n Définir le répertoire de sortie pour les fichiers objet
-o Définir le nom du fichier de sortie (-o<nomfichier> ou —o <nomfichier> supporté)
-pxxx Utiliser la convention d'appel Pascal
-q Supprimer la bannière d'identification du compilateur
-r Utiliser les variables registre
-rd Utiliser les variables registre seulement quand le mot clé register est employé
-s Lier en utilisant le lieur non incrémentiel du système
-txxx Un autre nom pour les commutateurs -Wxxx ; pas de différence
* -u Générer des traits de soulignement dans les noms de symbole
-vxxx Activer le débogage du source
-w Afficher tous les avertissements
-w! Renvoyer la valeur non-zéro du compilateur sur les avertissements
-xxxx Activer la gestion des exceptions
-y Numéros de ligne du débogage activés
3 -z Options de redéfinition des noms de segment standard

Affichage de l'aide pour des options spécifiques, des groupes comme -Axxx et -Vxxx
Vous pouvez obtenir des informations plus spécifiques sur les options multilettres, comme -Axxx (compatibilité au langage et
conformité aux standards) et -Vxxx (compatibilité descendante).

Pour ce faire, utilisez l'option de ligne de commande -h avec la lettre initiale du groupe d'options (comme -A pour spécifier les

172
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

options -Axxx). BCC32 affichera seulement les rubriques d'aide pour le jeu d'options spécifié (comme —Axxx, —Vxxx ou
—Wxxx).

Par exemple, pour afficher une description des options -Axxx (compatibilité au langage et conformité aux standards), utilisez les
options de ligne de commande —h et —A :
C:\>bcc32 -h -A
CodeGear C++ 6.10 pour Win32 Copyright (c) 1993-2008 CodeGear
Options disponibles (* = paramètre par défaut, xxx = comporte des sous-options : utilisez -h
-X) :
(Remarque : -X- ou -w-XXX annulera habituellement tout ce qui a été défini ou restauré par -X)
-A Activer la conformité ANSI
-AF Utiliser les extensions et mots clés SUN Forte
-AG Utiliser les extensions et mots clés GNU
-AK Utiliser les extensions et mots clés Kernighan and Ritchie
-AT Utiliser les extensions et mots clés CodeGear C++ (aussi -A-)
-AU Utiliser les extensions et mots clés UNIX System
-An Utiliser les extensions et mots clés C99
-Ax Utiliser les extensions et mots clés C++-0x
Dans l'exemple suivant, l'aide de la ligne de commande BCC32 affiche des détails sur toutes les options -Vxxx (compatibilité
descendante) :
C:\>bcc32 -h -V
CodeGear C++ 6.10 pour Win32 Copyright (c) 1993-2008 CodeGear
Options disponibles (* = paramètre par défaut, xxx = comporte des sous-options : utilisez -h
-X) :
(Remarque : -X- ou -w-XXX annulera habituellement tout ce qui a été défini ou restauré par -X)
-V Options de compatibilité
-V0 Tables virtuelles C++ externes
-V1 Tables virtuelles C++ publiques
* -VA Générer toutes les fonctions globales dans leur propre segment virtuel/faible
-VC Ne pas mélanger les conventions d'appel dans les symboles
-VF Compatibilité MFC
-VF3 Supporter MFC 3.2
-VF4 Supporter MFC 4.0
* -VI Utiliser l'algorithme de recherche Microsoft pour localiser les fichiers d'en-tête
-VM Compatibilité Microsoft Visual C++
-Va Supporter les arguments de classe de style ancien
-Vb Activer la compatibilité descendante avec les versions Bcc 5.8.2 et antérieures.
-Vbc Ne pas réduire la référence ou le pointeur à la référence, ou la référence qualifiée.
-Vbe Permettre la spécialisation de template explicite de style ancien
-Vbn Permettre l'appel d'une fonction membre non-const ou non-volatile pour un objet
const ou volatile
-Vbo Utiliser les anciennes règles de résolution de surcharge Borland
-Vbr Permettre la liaison de références non-const
-Vbs Traiter les littéraux chaîne en tant que non-const
-Vbt Utiliser les anciennes règles de type Borland pour les opérateurs ternaires
-Vbx Permettre la spécialisation de template explicite comme fonction membre
-Vc Supporter les déplacements de constructeurs
-Vd Utiliser les règles de portée d'instruction for C++ anciennes
-Ve Classes de base vides de taille nulle
-Vg Désactiver l'analyseur digraphe lexical
-Vi Utiliser l'algorithme de recherche 8.3 pour localiser les fichiers d'en-tête
-Vl Utiliser les anciennes dispositions de classe Borland
-Vm Options de pointeur membre 3
-Vmd Utiliser la plus petite représentation possible pour les pointeurs membre
-Vmm Supporter l'héritage multiple pour les pointeurs membre
-Vmp Honorer la précision déclarée des pointeurs membre
-Vms Supporter l'héritage unique pour les pointeurs membre
-Vmv Ne pas placer de restrictions sur l'endroit où les pointeurs membre peuvent pointer
-Vn Activer les nouveaux noms d'opérateur : and, or, and_eq, bitand, etc.
-Vo Définir les indicateurs de compatibilité ; utilisé avec le code ancien
-Vp Empiler 'this' en premier, comme en Pascal
-Vr Inverser l'ordre pour les constantes multicaractères
-Vs Utiliser la génération virdef de style ancien

173
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

-Vt Placer le pointeur de table virtuelle au début de la disposition d'objet


-Vv Utiliser les pointeurs de base virtuelle 'slow'
-Vw Emettre le code natif au lieu de l'Unicode pour les caractères multi-octets
-Vx Fonctions de membre de classe vide de longueur zéro

Paramètres par défaut


BCC32.EXE comporte des options spécifiques qui sont activées par défaut. Pour désactiver une option par défaut ou redéfinir
les options d'un fichier de configuration, placez un signe moins (-) après l'option.

Les fichiers d'extension .CPP sont compilés comme des fichiers C++. Les fichiers d'extension .C, sans extension ou avec une
extension différente de .CPP, .OBJ, .LIB ou .ASM sont compilés comme des fichiers C.

Le compilateur essaie de lier avec un fichier de définition de module de même nom que l'exécutable, et l'extension .DEF.

Options générales de sortie du compilateur

Option Description Détails


-c Compile en .OBJ, Compile et assemble les fichiers .C, .CPP et .ASM nommés, mais n'exécute pas un lien sur
pas de liaison les fichiers .OBJ résultants.

-e Spécifie le nom Lie le fichier en utilisant <nomfichier> comme nom du fichier exécutable. Si vous ne
<nomfichier> du fichier spécifiez pas un nom d'exécutable avec cette option, le lieur crée un fichier exécutable basé
exécutable sur le nom du premier fichier source ou fichier objet mentionné dans la commande.

-l <x> Passe l'option au Utilisez cette option de la ligne de commande pour passer les options <x> au lieur à partir
lieur. d'une commande de compilation. Utilisez l'option de la ligne de commande -l-x pour
désactiver une option spécifique du lieur.
-M Crée un fichier Utilisez cette option du compilateur pour demander au lieur de créer un fichier map.
MAP
-o Compile en Compile le fichier source spécifié en <nomfichier>.OBJ
<nomfichier> <nomfichier>.OBJ
-P Compilation C++ Provoque la compilation C++ de tous les fichiers source quelle que soit leur extension.
Utilisez l'option -P- pour compiler tous les fichiers .CPP comme des fichiers source C++ et
tous les autres fichiers comme des fichiers source C.
L'option de la ligne de commande -Pext provoque la compilation de tous les fichiers source
comme des fichiers C++ en indiquant que ext est l'extension par défaut. Cette option est
fournie car certains programmeurs utilisent une autre extension par défaut pour le code
C++.
L'option -P-ext compile les fichiers selon leur extension (.CPP est compilé en C++, toutes
les autres extensions sont compilées en C) et définit l'extension par défaut (autre que
.CPP).
-tWM Génère une cible Crée un .EXE ou .DLL multithread. Cette option n'est pas nécessaire si vous incluez un
multithread fichier de définition de module (fichier .DEF) dans vos commandes de compilation et de
liaison spécifiant le type d'application 32 bits que vous voulez construire.
3

Règles de priorité des options du compilateur


Les compilateurs de la ligne de commande évaluent les options de la gauche vers la droite, et suivent les règles suivantes :

• Si vous dupliquez une option (à l'exception des options -D, -I, -L ou -U), la dernière option tapée redéfinit toute option
antérieure.
• Les options tapées sur la ligne de commande redéfinissent les options des fichiers de réponse et de configuration à

174
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

l'exception des options -D, -I, -L et -U, qui sont cumulatives.

Spécification des répertoires dans les options de la ligne de commande


Le compilateur CodeGear C++ peut rechercher les fichiers de bibliothèque et d'inclusion dans plusieurs répertoires. La syntaxe
de l'option des répertoires de bibliothèque (-L) et des répertoires d'inclusion (-I), (comme l'option #define (-D)), permet plusieurs
listages d'une option donnée. Voici la syntaxe de ces options :
-L <nomrépertoire> [<nomrépertoire>;...]
-I <nomrépertoire> [<nomrépertoire>;...]
Le paramètre <nomrépertoire> utilisé avec -L et -I peut correspondre à tout répertoire ou chemin de répertoire. Vous pouvez
entrer ces répertoires sur la ligne de commande de l'une des façons suivantes

• Vous pouvez empiler plusieurs entrées avec une seule option -L ou -I en les séparant par un point virgule : BCC32.EXE —L
nomrép1;nomrép2;nomrép3 —I include1;include2;include3 monfichier.c
• Vous pouvez placer plusieurs occurrences de chaque option sur la ligne de commande : BCC32.EXE —L nomrép1 —L
nomrép2 —L nomrép3 —I include1 —I include2 —I include3 monfichier.c
• Vous pouvez mélanger les styles : BCC32.EXE —L nomrép1;nomrép2 —Lnomrép3 —I include1;include2 —I
include3 monfichier.c
Si vous listez plusieurs options -L ou -I sur la ligne de commande, le résultat est cumulatif. Le compilateur recherche tous les
répertoires listés, de la gauche vers la droite.

Utilisation des fichiers de configuration du compilateur (fichiers .CFG)


Si vous utilisez de façon répétitive un certain nombre d'options, vous pouvez les énumérer dans un fichier de configuration au
lieu de les taper sans cesse sur la ligne de commande. Un fichier de configuration est un fichier texte ASCII standard qui
contient une ou plusieurs options de ligne de commande. Chaque option doit être séparée par un espace ou un retour chariot.

A chaque émission d'une commande de compilation, BCC32.EXE recherche le fichier de configuration BCC32.CFG. Le
compilateur recherche d'abord le fichier .CFG dans le répertoire d'où provient la commande de compilation, puis dans le
répertoire où se trouve le compilateur.

Vous pouvez créer et utiliser plusieurs fichiers de configuration en supplément du fichier .CFG par défaut.

Pour utiliser un fichier de configuration, utilisez la syntaxe suivante où vous placerez les options du compilateur :
+[chemin]nomfichier

Par exemple, vous pouvez utiliser la ligne de commande suivante pour le fichier de configuration MYCONFIG.CFG :
BCC32 +C:\MYPROJ\MYCONFIG.CFG mycode.cpp

Les options tapées sur la ligne de commande remplacent les paramètres stockés dans les fichiers de configuration, à l'exception
des options cumulatives -D, -I, -L et -U.

Utilisation des fichiers de réponse


Les fichiers de réponse vous permettent d'avoir la liste des options du compilateur et des noms de fichiers dans un seul fichier (à
l'inverse des fichiers de configuration qui ne contiennent que les options du compilateur). Un fichier de réponse est un fichier
texte au format ASCII standard contenant une ou plusieurs options de ligne de commande et/ou des noms de fichiers, les
3
entrées du fichier étant séparées par des espaces ou des retours chariot. En plus de simplifier les commandes du compilateur,
les fichiers de réponse permettent d'avoir une ligne de commande plus longue que ce qui est autorisé par la plupart des
systèmes d'exploitation.

Voici la syntaxe d'utilisation d'un seul fichier de réponse :


BCC32 @[chemin]respfile.txt

175
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

Voici la syntaxe d'utilisation de plusieurs fichiers de réponse :


BCC32 @[chemin]respfile.txt @[chemin]otheresp.txt

Les fichiers de réponse ont généralement l'extension .RSP.

Les options tapées sur la ligne de commande remplacent toute option ou nom de fichier d'un fichier de réponse, à l'exception
des options -D, -I, -L et -U qui sont cumulatives.

Voir aussi
Utilisation des fichiers d'inclusion

Fichiers en-tête précompilés ( see page 219)

Utilisation des fichiers de définition de module ( see page 214)

RLINK32.DLL ( see page 220)

BRCC32.EXE ( see page 177)

3.1.1.2 BRC32, le Shell de ressources


Le compilateur de ressources Borland (BRC32) est un shell de compilateur de ressources. Il invoque BRCC32 et RLINK32,
selon la syntaxe de la ligne de commande.

Syntaxe de la ligne de commande


brc32 [options] <nomfichier>.RC [<nomfichier>.EXE]

Pour afficher l'aide de la ligne de commande, entrez :


brc32

Options de la ligne de commande

Option Description
-d<nom> Définit un symbole que vous pouvez tester avec la directive #IFDEF du préprocesseur.
[=<chaîne>]
-fo<nomfichier> Renomme le fichier .RES.
-fe<nomfichier> Renomme le fichier .EXE.
-i<chemin> Ajoute un ou plusieurs répertoires (séparés par des points-virgules) au chemin de recherche d'inclusion.
-k Désactive le préchargement contigu des segments et des ressources dans le fichier .EXE. Les segments
sont conservés dans l'ordre dans lequel ils apparaissent dans le fichier .DEF. Cette option s'applique
seulement aux ressources 16 bits et elle est désactivée quand l'option -r est effective.
-r Crée un fichier .RES uniquement. Le fichier .RES compilé n'est pas ajouté à l'.EXE.
-v Affiche des messages de progression (mode "bavard").
-x Indique au compilateur d'ignorer la variable d'environnement INCLUDE lors de la recherche de fichiers de
3 ressources ou d'inclusion.
-16 Construit des fichiers .RES 16 bits.
-32 Construit des fichiers .RES 32 bits.
-Vd.d Génère le fichier .EXE pour la version de Windows spécifiée (v3.1 est la version par défaut pour les
ressources 16 bits ; -v4.0 est la version par défaut pour les ressources 32 bits). Les options de version sont
énumérées dans le tableau suivant.

Options de version (utilisées avec l'option —Vd.d)

176
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

Option Bit Aspect résultant


3.1 16 Donne un arrière-plan blanc sans aspect 3-D pour Windows 3.1x, Windows 32s ou WinNT 3.1
4.0 16 Donne un aspect 3-D grisé pour Windows 95 et WinNT 3.51
3.1 32 Donne un arrière-plan blanc sans aspect 3-D pour Windows 32s ou WinNT 3.1
4.0 32 Donne un aspect 3-D grisé pour Windows 95 et WinNT 3.51

Options de compatibilité descendante

Option Description
-t Crée une application ne fonctionnant qu'en mode protégé (mode Windows standard ou 386 étendu).
-31 Génère des fichiers .RES compatibles Windows 3.1
-w32 Génère des fichiers .RES compatibles Win32.

Exemples de Shell de ressources


L'instruction suivante compile le fichier .RC, crée un fichier .RES et ajoute le fichier .RES au fichier exécutable :
brc32 <nomfichier>.RC <nomfichier>.EXE

BRC32 recherche automatiquement un fichier .EXE de même nom que le fichier .RC. Vous devez spécifier le fichier .EXE
seulement si son nom est différent de celui du fichier .RC.

L'instruction suivante crée un fichier .RES, mais pas un fichier .EXE. Si vous nommez un fichier .EXE dans la ligne de
commande, BRC l'ignore :
brc32 -r <nomfichier>.EXE

L'instruction suivante ajoute un fichier .RES existant à un fichier exécutable. Le nom du fichier .EXE est obligatoire seulement s'il
est différent du nom du fichier .RES :
brc32 <nomfichier>.RES <nomfichier>.EXE

Cet exemple utilise BRC32 pour construire un fichier .RES compatible Windows 3.1 16 bits :
brc32 -16 -v3.1 -fo<nomfichier>.RES <nomfichier>.RC

Voir aussi
RLINK32.DLL ( see page 220)

BRCC32.EXE ( see page 177)

3.1.1.3 BRCC32.EXE, le compilateur de ressources


BRCC32 est la version en ligne de commande du compilateur de ressources. Il accepte un fichier script de ressources (.RC) en
entrée et produit un fichier objet ressource (.RES) en sortie.

Syntaxe de la ligne de commande


3
BRCC32 [<options>] <nomfichier>

Pour afficher l'aide de la ligne de commande, entrez :


brcc32

Ou ajoutez l'indicateur d'aide :


brcc32 -h

177
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

Options de la commande BRCC32

Option Description
@<fichrép> Prend les instructions dans le fichier de commande spécifié.
-c <pagecode> Utilise la page de code spécifiée pour la traduction des ressources. Si -c n'est pas utilisé, la page de
code ANSI par défaut est utilisée.
-d<nom>[=<chaîne>] Définit un symbole du préprocesseur.
-fo<nomfichier> Renomme le fichier .RES de sortie. Par défaut, BRCC32 crée le fichier .RES de sortie avec le même
nom que le fichier .RC d'entrée.
-i<chemin> Ajoute un ou plusieurs répertoires (séparés par des points-virgules) au chemin de recherche d'inclusion.
-l<langage> Spécifie le langage par défaut.
-m Indique que la page de code spécifiée à l'aide du commutateur -c contient des caractères du jeu de
caractères à deux octets (DBCS).
-r Ce commutateur est ignoré. Il n'est inclus que par compatibilité avec d'autres compilateurs de
ressources.
-v Affiche des messages de progression (mode "bavard").
-x Supprime le chemin d'inclusion en cours.
-h ou ? Affiche l'aide.
-16 Construit une ressource 16 bits.
-32 Construit une ressource 32 bits.

BRCC32 prédéfinit des constantes Windows liées aux ressources telles que WS_VISIBLE et BS_PUSHBUTTON. En outre,
deux symboles spéciaux liés au compilateur sont définis : RC_INVOKED et WORKSHOP_INVOKED. Ces symboles peuvent
être utilisés dans le texte source avec les instructions conditionnelles du préprocesseur pour contrôler la compilation.

Par exemple, la construction suivante peut accélérer de manière significative la compilation :


#ifndef WORKSHOP_INVOKED#include “windows.h”
#endif
Compatibilité descendante
La syntaxe et les options suivantes sont prises en charge à des fins de compatibilité descendante :

Option Description
-16 Construit des fichiers .RES 16 bits.
-32 Construit des fichiers .RES 32 bits.
-31 Construit des fichiers .RES compatibles Windows 3.1.
-w32 Construit des fichiers .RES compatibles Win32.

Voir aussi
3 BRC32.EXE ( see page 176)

3.1.1.4 COFF2OMF.EXE, l'outil de conversion d'une bibliothèque


d'importation
COFF2OMF convertit un fichier bibliothèque d'importation COFF (FichierEntrée) en un fichier bibliothèque d'importation OMF
correspondant (FichierSortie). COFF2OMF.EXE est situé dans le répertoire \bin de C++Builder.

178
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

Syntaxe de la ligne de commande


Coff2Omf [<options>] FichierEntrée FichierSortie

Pour afficher l'aide de la ligne de commande, entrez :


coff2omf

COFF2OMF convertit les symboles exportés publiquement dans la bibliothèque d'importation COFF en un jeu de symboles
correspondant dans la bibliothèque d'importation OMF. COFF2OMF permet aux utilisateurs de C++Builder d'établir un lien avec
des DLLs Microsoft et tierces qui utilisent le format COFF. COFF2OMF ne convertit pas les fichiers .OBJ.

Exécutez l'outil COFF2OMF sur une bibliothèque d'importation COFF créée pour une DLL spécifique et utilisez la bibliothèque
d'importation obtenue pour lier les fichiers DLL et EXE de format OMF à la DLL COFF.

Option de Description
la ligne de
commande

-q Mode silencieux. Convertit sans écrire les informations de l'outil et de copyright dans la sortie standard)
-v Affiche les symboles sélectionnés. Affiche les symboles convertis dans la sortie standard et pouvant être redirigés
vers un fichier de sortie.
-d Supprime le fichier de sortie s'il est vide. Supprime le fichier de sortie en cas d'erreur et si la conversion résulte en
un fichier vide.
-h ou -? Affiche l'aide.
-r Retire (supprime) le fichier de sortie s'il est vide.
-lib:xx Spécifie les options de la génération de la bibliothèque d'importation OMF. Vous pouvez définir les options xx
suivantes :
• ms — Autorise les entrées présentant un substantypage des noms MS C++. La valeur par défaut est Non.
• st — Normalise les noms au lieu de créer des alias de substantypage MS stdcall.
• ca — Ne crée pas d'alias MS cdecl. La valeur par défaut est la création d'alias.

3.1.1.5 CPP32.EXE, le préprocesseur du compilateur C


CPP32.EXE produit un fichier de listage d'un programme C ou C++, dans lequel tous les #define de macros et tous les #include
de fichiers ont été développés. Bien qu'il ne soit pas nécessaire d'utiliser le préprocesseur pour une compilation normale, ce
fichier de listage peut être utile à des fins de débogage.

Souvent, lorsque le compilateur signale une erreur dans une macro ou un fichier d'inclusion, vous pouvez obtenir davantage
d'informations sur la nature de l'erreur en consultant les fichiers d'inclusion ou les résultats du développement des macros. Avec
un grand nombre de compilateurs à plusieurs passes, ce travail est effectué par une passe séparée dont on peut examiner les
résultats. Puisque le compilateur CodeGear C++ est un compilateur à une seule passe, utilisez CPP32 pour obtenir les résultats
3
procurés par la première passe d'autres compilateurs.

Pour chaque fichier traité par CPP32, la sortie est écrite dans un fichier du répertoire en cours (ou du répertoire de sortie
désigné à l'aide de l'option -n) portant le nom du fichier source mais avec l'extension .I.

Ce fichier de sortie est un fichier texte contenant chaque ligne du fichier source et tous les fichiers d'inclusion. Les lignes
contenant des directives de prétraitement ont été retirées, de même que les lignes de texte conditionnel exclues de la
compilation. Si vous n'avez pas utilisé d'option de ligne de commande pour définir une autre spécification, les lignes de texte
sont préfixées par le nom de fichier et le numéro de ligne du fichier source ou du fichier d'inclusion dont elles proviennent. Dans

179
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

chaque ligne de texte, les macros sont remplacées par leur texte développé. Utilisez l'option -Sr pour produire un fichier sans
numéros de ligne. Vous pouvez alors passer ce fichier au compilateur (utilisez l'option -P du compilateur pour imposer une
compilation C++).

Syntaxe de la ligne de commande


CPP32 [<options>] <nomfichier[s]>

Pour afficher l'aide de la ligne de commande, entrez :


cpp32 -h

CPP32 reconnaît les mêmes options que BCC32, à l'exception des ajouts suivants pour l'option -S (contrôle du format de sortie
prétraité) :

Option Description
-Sc Conserve les commentaires dans le fichier prétraité.
-Sd Conserve les définitions dans le fichier prétraité.
-Sk Conserve les sorties en cas d'erreur.
-Sr Rend les sorties lisibles en préservant les commentaires et les indentations.
-Ss Affiche les statistiques sur les noms de fichiers et les compteurs de lignes.

CPP32 en tant que préprocesseur de macros


CPP32 peut être utilisé comme un préprocesseur de macros ; le fichier .i résultant peut alors être compilé avec BCC32. Le
programme simple suivant illustre le prétraitement d'un fichier par CPP32.

Fichier source : HELLOFB.C


#define NAME “Frank CodeGear”
#define BEGIN {
#define END }
main()
BEGIN
printf(“%s\n”, NAME);p
END

Ligne de commande CPP32


CPP32 HELLOFB.C

Sortie (écrite dans HELLOFB.I)


/* HELLOFP.C 1: */
/* HELLOFP.C 2: */
3 /* HELLOFP.C 3: */
/* HELLOFP.C 4: */
/* HELLOFP.C 5: */main()
/* HELLOFP.C 6: */printf("%s\n", "Frank Borland");
/* HELLOFP.C 7: */}
/* HELLOFP.C 8: */}

180
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

Utilisation de MIDL avec CPP32


MIDL (Microsoft Interface Definition Language, langage de définition d'interface Microsoft) est un compilateur RPC. Afin d'utiliser
MIDL avec le préprocesseur C++ (CPP32.EXE), servez-vous de la commande MIDL suivante :

Option Description
-<cpp_cmd> Indique à MIDL le préprocesseur à utiliser lors du traitement d'un fichier .IDL ou .ACF. MIDL appelle le
{<CPP32>} préprocesseur pour développer les macros dans les fichiers source.
-<cpp_opt> Spécifie les options de ligne de commande pour le préprocesseur. L'option -Sr retire les informations nom
"{<options>}" de fichier et numéro de ligne dans chaque ligne de la sortie prétraitée. L'option -oCON indique que la
sortie prétraitée doit être acheminée vers la sortie standard, au lieu d'être enregistrée dans un fichier. La
bannière du préprocesseur et le fichier en cours de traitement ne sont pas transmis. L'inclusion de -oCON
dans un fichier .CFG traité par le préprocesseur provoque la transmission de la bannière.
{<options Transmet les options à CPP32.
CPP32>}
{<options MIDL>} Toutes les options de ligne de commande MIDL.
{<fichier .idl/.acf> Le fichier source traité par MIDL.

BCC32, CPP32 et UUIDs


Dans certains cas, CPP32 n'accepte pas des UUIDs valides. Une instruction UUID valide est, par exemple, de la forme :
uuid(5630EAA0-CA48-1067-B320-00DD010662DB)

Quand CPP32 rencontre 5630EAA0, il le considère comme un nombre à virgule flottante, et comme il ne s'agit pas d'un nombre
à virgule flottante valide, le préprocesseur émet une erreur. Pour contourner ce problème, encadrez l'UUID par des guillemets.
Lors de l'emploi de MIDL avec CPP32, utilisez l'option -ms_ext. L'instruction UUID devient :
uuid("5630EAA0-CA48-1067-B320-00DD010662DB")

et la ligne de commande MIDL devient :


MIDL -ms_ext -cpp_cmd CPP32 -cpp_opt " -oCON {<options CPP32>}" {<options MIDL>} {<fichier
.idl/.acf>}

Voir aussi
BCC32.EXE ( see page 171)

3.1.1.6 DCC32.EXE, le compilateur en ligne de commande Delphi.


DCC32 est le compilateur en ligne de commande Delphi (Pascal Objet).

Pour afficher l'aide de la ligne de commande, entrez :


dcc32
ou :
dcc32 —h 3
ou :
dcc32 —help
C:\>dcc32
Compilateur CodeGear Delphi pour Win32 version 18.5
Copyright (c) 1983,2007 CodeGear

Syntaxe : dcc32 [options] nomfichier [options]

181
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

-A <unité>=<alias> = Définir l'alias de l'unité


-B = Construire toutes les unités
-CC = Cible console
-CG = Cible GUI
-D<syms> = Définition conditionnelle
-E<chemin> = Répertoire de sortie EXE/DLL
-F<décalage> = Rechercher l'erreur
-GD = Fichier map détaillé
-GP = Fichier map avec les variables publiques
-GS = Fichier map avec les segments
-H = Afficher les conseils
-I<chemins> = Répertoires d'inclusion
-J = Générer le fichier .obj C
-JP = Générer le fichier objet C++
-JPN = Générer le fichier .obj C++, y compris l'espace de nommage
-JPE = Générer le fichier .obj C++, et exporter tous les symboles
-JPH = Générer le fichier .obj C++, exporter les symboles, générer les fichiers d'en-tête
.hpp
-JPHNE = Générer le fichier .obj C++, le fichier .hpp, dans espace de nommage, exporter tout
-JL = Générer le package .lib, .bpi, et tous les fichiers .hpp pour C++
-K<adresse> = Définir l'adresse de base de l'image
-LE<chemin> = Répertoire de sortie .bpl de package
-LN<chemin> = Répertoire de sortie .dcp de package
-LU<package> = Utiliser le package
-M = Make des unités modifiées
-N0<package> = Utiliser le package
-M = Make des unités modifiées
-N0<chemin> = Répertoire de sortie .dcu d'unité
-NH<chemin> = Répertoire de sortie .hpp d'unité
-NO<chemin> = Répertoire de sortie .obj d'unité
-NB<chemin> = Répertoire de sortie .bpi d'unité
-NS<espace de nommage> = Chemin de recherche de l'espace de nommage
-O<chemins> = Répertoires des objets
-P = Recherche également les noms de fichiers 8.3
-Q = Compilation silencieuse
-R<chemins> = Répertoires des ressources
-U<chemins> = Répertoires des unités
-V = Informations de débogage dans EXE
-VR = Générer le débogage distant (RSM)
-W[+|-][warn_id] = Afficher les messages d'avertissement
-Z = Générer DCPs 'jamais construits'
-$<rép> = Directive du compilateur
--help = Afficher cet écran d'aide
--version = Afficher le nom et la version
--codepage:<cp> = Spécifier le codage du fichier source
--default-namespace:<espace de nommage> = Définir l'espace de nommage
--depends = Générer les informations de dépendances d'unités
--doc = Générer la documentation XML
--drc = Générer le fichier drc des chaînes de ressources
--no-config = Ne pas charger le fichier DCC32.CFG par défaut
--description:<chaîne> = Définir la description de l'exécutable
Commutateurs du compilateur : -$<état> (les valeurs par défaut sont présentées ci-dessous)
A8 Champs d'enregistrements alignés
B- Evaluation booléenne complète
C+ Evaluer les assertions à l'exécution
D+ Informations de débogage
3 G+ Utiliser les références de données importées
H+ Utiliser les chaînes longues par défaut
I+ Vérification E/S
J- Constantes structurées affectables
L+ Symboles de débogage locaux
M- Informations de type à l'exécution
O+ Optimisations
P+ Paramètres chaîne ouverte
Q- Vérification du débordement d'entier
R- Vérification des limites

182
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

T- Opérateur @ typé
U- Division Pentium(tm) sécurisé
V+ Chaînes-var strictes
W- Générer les cadres de pile
X+ Syntaxe étendue
Y+ Infos de référence de symbole
Z1 Taille minimale des types énumérés
Création de fichiers C++ depuis DCC32
Si vous voulez générer des fichiers .hpp (et le fichier .obj correspondant) à partir d'un fichier .pas, vous devez utiliser -JPHNE.

Vous pouvez également utiliser -JL sur le fichier .dpk contenant le fichier .pas.

3.1.1.7 DCCIL.EXE, le compilateur en ligne de commande Delphi


pour .NET
DCCIL est le compilateur en ligne de commande Delphi (Pascal Objet) pour l'environnement .NET. Utilisez DCCIL pour compiler
des exécutables .NET managés.

Pour afficher l'aide de la ligne de commande, entrez :


dccil
ou :
dccil -h
Vous pouvez également entrer dccil avec l'option -help.
C:\>dccil
Compilateur CodeGear Delphi pour .NET version 19.0
Copyright (c) 1983,2007 CodeGear
.NET Framework v2.0.50727 chargé
Syntaxe : dccil [options] nomfichier [options]

-A<unité>=<alias> = Définir l'alias de l'unité


-B = Construire toutes les unités
-CC = Cible console
-CG = Cible GUI
-D<syms> = Définition conditionnelle
-E<chemin> = Répertoire de sortie EXE
-H[-] = Afficher les conseils
-I<chemins> = Répertoires d'inclusion
-K<adresse> = Définir l'adresse de base de l'image
-LE<path> = Répertoire de sortie .dll de package
-LN<chemin> = Répertoire de sortie .dcpil de package
-LU<packages> = Lier packages/assemblages
-M = Make des unités modifiées
-N0<chemin> = Répertoire de sortie .dcuil d'unité
-NS<espaces de nommage> = Chemin de recherche des espaces de nommage
-Q = Compilation silencieuse
-R<chemins> = Répertoires des ressources
-U<chemins> = Répertoires des unités
-V = Informations de débogage dans .pdb 3
-VR = Générer le débogage distant (RSM)
-W[+|-][warn_id] = Afficher les messages d'avertissement
-X = Définir le nom du fichier en sortie
-Z = Générer DCPs 'jamais construits'
-$<rép> = Directive du compilateur
--help = Afficher cet écran d'aide
--version = Afficher le nom et la version
--clrversion:v2.0.50727 = compiler avec cette version .NET CLR
--codepage:<cp> = Spécifier le codage du fichier source

183
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

--default-namespace:<espace de nommage> = Définir l'espace de nommage


--depends = Générer les informations de dépendances d'unités
--doc = Générer la documentation XML
--drc = Générer le fichier .drcil des chaînes de ressources
--no-config = Ne pas charger le fichier DCCIL.CFG par défaut
--description:<chaîne> = Définir la description de l'exécutable
--platform:<tout cpu | x86 | x64> = Format d'exécutable PE (tout cpu par défaut)
--unsafe[+|-] = Autoriser / Ne pas autoriser l'usage du code non protégé lors de la liaison
--delay-sign[+|-] = Réserver la zone clé de nom fort pour la temporisation de signature de
la clé publique
--key-container:<chaîne> = Définir le conteneur clé de nom fort
--key-file:<fichier> = Définir le fichier clé de nom fort
Commutateurs du compilateur : -$<lettre><état> <les valeurs par défaut sont présentées
ci-dessous>
A- Champs d'enregistrements alignés
B- Evaluation booléenne complète
C+ Evaluer les assertions à l'exécution
D+ Informations de débogage
I+ Vérification E/S
J- Constantes structurées affectables
L+ Symboles de débogage locaux
O+ Optimisations
P+ Paramètres chaîne ouverte
Q- Vérification du débordement d'entier
R- Vérification des limites
T- Opérateur @ typé
V+ Chaînes-var strictes
X+ Syntaxe étendue
Y+ Infos de référence de symbole

3.1.1.8 GREP.EXE, l'utilitaire de recherche de texte


GREP (Global Regular Expression Print) est un puissant programme de recherche de texte dérivé de l'utilitaire UNIX du même
nom. GREP recherche un texte dans un ou plusieurs fichiers ou dans le flux d'entrée standard.

Utilisation de GREP
Voici un exemple succinct de situation dans laquelle il peut être intéressant d'utiliser GREP. Supposons que vous souhaitiez
savoir quels sont les fichiers texte de votre répertoire en cours qui contiennent la chaîne "Bob". Vous pourriez taper :
grep Bob *.txt
GREP répond en affichant la liste des lignes de chaque fichier (s'il en existe) qui contiennent la chaîne "Bob". Comme, par
défaut, GREP n'ignore pas la casse, les chaînes "bob" et "boB" ne sont pas signalées.

GREP peut faire beaucoup plus que rechercher une chaîne fixe simple. GREP peut être utilisé pour rechercher toute chaîne
correspondant à un motif particulier. Voir GREP : La chaîne de recherche.

Syntaxe de la ligne de commande


La syntaxe générale de la ligne de commande GREP est
grep [-<options>] <chaîne de recherche> [<fichier(s)>...]
3 Pour afficher la liste des options de la ligne de commande GREP, les caractères spéciaux et les valeurs par défaut de GREP,
entrez :
grep ?
Options de la ligne de commande GREP

184
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

Option Description
<options> Se compose d'une ou plusieurs lettres précédées d'un tiret (-), qui changent le comportement de
GREP.
<chaînederecherche> Donne le motif recherché.
<fichier(s)> Indique à GREP quels sont les fichiers dans lesquels la recherche doit s'effectuer. Si vous ne spécifiez
pas de fichier, GREP recherche dans l'entrée standard ; vous pouvez ainsi utiliser les canaux de
communication et la redirection.
Les fichiers peuvent être indiqués sous la forme de noms de fichier explicites ou de noms de fichier
génériques incorporant les caractères génériques DOS ? et *. Vous pouvez par ailleurs taper un
chemin (informations de lecteur et de répertoire). Si vous listez les fichiers sans chemin, GREP
effectue sa recherche dans le répertoire en cours. Si vous ne spécifiez pas de fichier, l'entrée dans
GREP doit venir de la redirection (<) ou d'une barre verticale (|).

Redirection de la sortie à partir de GREP


Si les résultats produits par une commande GREP dépassent la hauteur de l'écran, vous pouvez rediriger la sortie dans un
fichier.

Vous pouvez, par exemple, utiliser la commande suivante :


GREP "Bob" *.txt > temp.txt
Cette commande recherche une chaîne dans tous les fichiers d'extension TXT du répertoire en cours puis place le résultat dans
un fichier nommé TEMP.TXT. Vous pouvez donner à ce fichier le nom que vous souhaitez. Pour lire TEMP.TXT (le résultat de la
recherche), utilisez n'importe quel traitement de texte.

Options de la ligne de commande GREP


Vous pouvez transmettre des options à l'utilitaire GREP sur la ligne de commande, en spécifiant un ou plusieurs caractères
précédés d'un tiret (-). Chacun de ces caractères est un commutateur que vous pouvez activer ou désactiver : Un symbole plus
(+) après un caractère active l'option ; un symbole moins (-) après le caractère désactive l'option. Le signe + est facultatif ; par
exemple, -r a la même signification que -r+. Vous pouvez spécifier plusieurs options séparément (comme -i -d -l) ou bien les
associer (comme -ild ou -il, -d, et ainsi de suite).

Voici les caractères des options GREP avec leur signification :

Options de la ligne de commande GREP

Option Description
-c Compte uniquement : Affiche seulement le nombre des lignes satisfaisant le critère de recherche. Pour chaque
fichier contenant au moins une ligne répondant au critère, GREP affiche le nom du fichier avec le nombre de lignes
répondant au critère de recherche. Les lignes elles-mêmes ne sont pas affichées. Cette option est désactivée par
défaut.
-d Recherche dans les sous-répertoires : Pour chaque spécification de fichier sur la ligne de commande, GREP
recherche tous les fichiers correspondant à la spécification, à la fois dans le répertoire indiqué et dans tous ses
sous-répertoires. Si vous ne spécifiez qu'un nom de fichier sans chemin d'accès, GREP suppose que les fichiers se 3
trouvent dans le répertoire en cours. Cette option est désactivée par défaut.
-e L'expression de recherche suit : Indique que le prochain argument est l'expression recherchée. Cette option est utile
lorsqu'on recherche une expression commençant par "-".
-i Ignorer la casse : GREP ignore les différences entre majuscules et minuscules. Quand cette option est activée,
GREP traite toutes les lettres de a à z comme si elles étaient identiques aux lettres A à Z correspondantes, dans
toutes les situations. Cette option est désactivée par défaut.

185
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

-l Ne liste que les noms de fichiers : N'affiche que le nom de chaque fichier contenant une correspondance. Après
avoir trouvé une correspondance, GREP affiche le nom du fichier et le traitement passe immédiatement au fichier
suivant. Cette option est désactivée par défaut.
-n Numéros de ligne : Chaque ligne répondant au critère de recherche qui est affichée par GREP est préfixée par son
numéro. Cette option est désactivée par défaut.
-o Format de sortie UNIX : Change le format de sortie des lignes correspondantes pour supporter plus facilement les
canaux de communication de lignes de commandes de style UNIX. Toutes les lignes de sortie sont préfixées par le
nom du fichier contenant la ligne correspondante. Cette option est désactivée par défaut.
-r Recherche d'expression régulière : Le texte défini par la chaîne_de_recherche est traité comme une expression
régulière et non comme une chaîne littérale. Cette option est activée par défaut. Une expression régulière peut
contenir une ou plusieurs occurrences d'un ou plusieurs caractères éventuellement encadrés par des guillemets.
Les symboles suivants ont une signification spéciale :
• ^ début de ligne
• . n'importe quel caractère
• * correspond à zéro, un ou plusieurs caractères
• [aeiou0-9] correspond à a, e, i, o, u et 0-9
• [^aeiou0-9] correspond à tous les caractères, à l'exception de a, e, i, o, u et 0-9
• $ fin de ligne
• \ caractère suivant considéré littéralement
• + au moins un caractère

-u Mise à jour des options : Crée une copie de GREP.EXE en l'appelant <fichier>.EXE. Les options de la ligne de
<fichier> commande sont enregistrées comme valeurs par défaut dans la nouvelle copie de GREP. Utilisez l'option -u pour
personnaliser les paramètres par défaut des options. Pour vérifier que les valeurs par défaut ont correctement été
définies, tapez fichier ? ; chaque option de l'écran d'aide est suivie d'un + ou d'un – selon sa valeur par défaut.
-v Non-correspondance : Imprime seulement les lignes non concordantes. Seules les lignes qui ne contiennent pas la
chaîne de recherche sont considérées comme des lignes non concordantes. Cette option est désactivée par défaut.
-w Recherche de mot : Le texte trouvé qui correspond à l'expression régulière n'est considéré comme une
correspondance valide que si le caractère qui le précède immédiatement et celui qui le suit immédiatement ne
peuvent pas faire partie d'un mot. Le jeu de caractères par défaut pour les mots inclut les lettres A à Z, les chiffres 0
à 9 et le caractère de soulignement ( _ ). Cette option est désactivée par défaut. Une autre forme de cette option
permet de spécifier l'ensemble des caractères acceptés pour les mots : -w[ensemble], où ensemble est une
expression régulière valide quelconque.
Si vous incluez des caractères alphabétiques dans l'ensemble, celui-ci contiendra automatiquement à la fois la
forme majuscule et la forme minuscule de chaque lettre de l'ensemble (quelle que soit la manière dont cette lettre a
été tapée), même si la recherche est sensible à la casse. Si vous utilisez l'option -w avec l'option -u, le nouvel
ensemble de caractères valides est enregistré en tant qu'ensemble par défaut.
-z Mode verbeux : GREP affiche le nom de chaque fichier faisant l'objet d'une recherche. Chaque ligne répondant au
critère de recherche est préfixée par son numéro. Le nombre de lignes correspondantes dans chaque fichier est
affiché, même s'il vaut zéro. Cette option est désactivée par défaut.
? Affiche un écran d'aide montrant les options, les caractères spéciaux et les valeurs par défaut de GREP.
3

La chaîne de recherche
La valeur de <chaîne_de_recherche> définit le motif recherché par GREP. Une chaîne de recherche peut être une expression
régulière ou une chaîne littérale.

• Dans une expression régulière, certains caractères ont des significations particulières : il s'agit d'opérateurs permettant de
contrôler la recherche. Une expression régulière est un caractère unique ou un ensemble de caractères entre crochets. Une

186
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

concaténation d'expressions régulières est une expression régulière.


• Dans une chaîne littérale, il n'y a pas d'opérateurs : Chaque caractère est traité de façon littérale.
La chaîne de recherche peut être encadrée par des guillemets pour empêcher que les espaces et les tabulations ne soient
traités comme des délimiteurs. Pour rechercher une expression qui commence par "-", utilisez l'option -e. Le texte spécifié par
le chaîne de recherche ne peut pas s'étendre sur deux lignes ; cela signifie que tout le texte nécessaire à la recherche du
motif doit se trouver sur une même ligne.
Quand vous utilisez l'option -r (qui est activée par défaut), la chaîne de recherche est traitée comme une expression régulière (et
non comme une expression littérale).
Les caractères suivants ont des significations particulières :

Symbole Description
^ Un accent circonflexe placé au début d'une expression correspond au début d'une ligne.
$ Le signe dollar placé à la fin de l'expression correspond à la fin d'une ligne.
. Un point correspond à n'importe quel caractère.
* Un astérisque placé après un caractère correspond à un nombre quelconque d'occurrences de ce caractère suivi de
n'importe quel nombre de caractères (y compris par aucun caractère). Par exemple, bo* permet de trouver bot, boo
ainsi que bo.
+ Le signe plus placé après un caractère correspond à un nombre quelconque d'occurrences de ce caractère suivi de
n'importe quel nombre de caractères (à l'exception de zéro caractère). Par exemple, bo+ permet de trouver bot et
boo, mais pas b, bo ou bt.
{} Les caractères ou expressions entre accolades sont groupés afin que l'évaluation d'un motif de recherche puisse
être contrôlée et que le texte groupé puisse être désigné par un nombre.
[] Les caractères placés entre crochets permettent de trouver l'un des caractères placés entre crochets, mais pas les
autres. Par exemple [bot] permet de trouver b, o, ou t.
[^] Un accent circonflexe placé au début d'une chaîne entre crochets signifie SAUF. Ainsi, [^bot] permet de trouver
n'importe quel caractère à l'exception de b, o, ou t.
[-] Un trait d'union placé à l'intérieur des crochets indique une plage de caractères. Par exemple, [b-o] permet de
trouver n'importe quel caractère situé entre b et o.
\ Une barre oblique inverse avant un caractère générique indique à GREP de traiter ce caractère littéralement, et non
comme un caractère générique. Par exemple, \^ correspond à ^ et n'indique pas le début d'une ligne.

Quatre des caractères "spéciaux" ($, ., * et +) n'ont pas de signification spéciale quand ils sont utilisés entre crochets. De plus, le
caractère ^ n'est considéré comme un caractère spécial que s'il suit immédiatement le début de la définition d'ensemble
(immédiatement après le délimiteur [).

Exemples GREP
Exemple 1
grep -r "[^a-z]main\ *\(" *.c
Correspond :
main(i,j:integer)
if (main ()) halt; 3
if (MAIN ()) halt;
Ne correspond pas :
mymain()
Explication : La chaîne de recherche ordonne à GREP de rechercher un mot main qui ne soit pas précédé de lettres minuscules
([^a-z]) mais suivi de zéro ou plusieurs occurrences d'espaces (\ *) puis d'une parenthèse gauche. Comme les espaces et les
tabulations sont normalement considérés comme des délimiteurs de lignes de commandes, il faut les spécifier comme
caractères littéraux pour les inclure dans une expression régulière.

187
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

Exemple 2
grep -ri [a-c]:\\data\.fil *.c *.inc
Correspond :
A:\data.fil
B:\DATA.FIL
c:\Data.Fil
Ne correspond pas :
d:\data.fil a:data.fil
Explication : Comme les caractères barre oblique inverse (\) et point (.) ont généralement une signification particulière dans les
chemins d'accès et les noms de fichiers, il faut les faire précéder du caractère d'échappement barre oblique inverse pour les
rechercher. On utilise ici l'option -i, de sorte que la recherche n'est pas sensible à la casse.

Exemple 3
grep "chaîne de recherche contenant des espaces" *.doc *.c
Correspond :
Une chaîne de recherche avec des espaces.
Ne correspond pas :
Cette chaîne de recherche comporte des espaces.
Explication : Cet exemple montre comment rechercher une chaîne contenant un texte particulier.

Exemple 4
grep -rd "[ ,.:?'\"]"$ \*.doc
Correspond :
He said hi to me.
Where are you going?
In anticipation of a unique situation,
Examples include the following:
"Many men smoke, but fu man chu."Explanation
Ne correspond pas :
He said "Hi" to me
Where are you going? I'm headed to the
Explication : Cet exemple recherche les caractères " . : ? ' ou , à la fin d'une ligne. Le guillemet à l'intérieur des crochets est
précédé d'un caractère d'échappement afin d'être traité comme un caractère normal et non comme le guillemet de fin de la
chaîne. De plus, le caractère $ apparaît en dehors des crochets. Cela montre comment il est possible de concaténer des
expressions régulières pour former une expression plus longue.

Exemple 5
grep -w[=] = *.c
Correspond :
3
i = 5;
j=5;
i += j;
Ne correspond pas :
if (i == t) j++;
/* ==================================== */
Cet exemple redéfinit l'ensemble en cours des caractères valides pour un mot par l'opérateur d'affectation (=) uniquement, puis

188
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

effectue une recherche de mots. Les instructions d'affectation C qui utilisent un signe égal unique (=) correspondent, mais pas
les tests d'égalité qui utilisent un signe égal double (==).

Voir aussi
BCC32.EXE ( see page 171)

3.1.1.9 ILINK32.EXE, le lieur incrémentiel


ILINK32 lie des modules objets (fichiers .OBJ), des modules bibliothèques (fichiers .LIB) et des ressources pour produire des
fichiers exécutables (fichiers .EXE, .DLL et .BPL). ILINK32 crée et gère une série de fichiers d'état contenant ces informations.
Ces fichiers d'état permettent aux liens suivants d'être de type incrémentiel, ce qui réduit sensiblement la durée totale des liens.

Syntaxe de la ligne de commande


ILINK32 [@<fichrép>][<options>] <démarrage> <objets>, [<exe>], [<fichmap>], [<bibliothèques>],
[<fichdéf>], [<fichres>]

Pour afficher l'aide de la ligne de commande, entrez :


ilink32

Les options de la ligne de commande du lieur sont sensibles à la casse.

Le lieur peut également utiliser un fichier de configuration nommé ILINK32.CFG contenant les options que vous devriez
généralement taper sur la ligne de commande.

Elément Description
[@<fichrép>] Un fichier de réponse est un fichier ASCII contenant les options et les noms de fichiers du lieur que vous
devriez normalement taper sur la ligne de commande. En plaçant les options et les noms de fichiers dans un
fichier de réponse, vous évitez de les saisir à chaque fois que vous liez une application.
<options> Les options contrôlant le fonctionnement du lieur. Ces options indiquent, par exemple, s'il faut produire un
fichier .EXE, .BPL ou .DLL. Elles doivent être précédées d'une barre oblique (/) ou d'un tiret (-).
<démarrage> Module d'initialisation CodeGear pour fichiers exécutables ou DLLs, qui s'occupe du classement des divers
segments du programme. Si le module d'initialisation n'est pas correctement lié, vous obtiendrez une longue
liste de messages d'erreur vous indiquant que certains identificateurs n'ont pas été résolus ou qu'aucune pile
n'a été créée.
<objets> Les fichiers .OBJ que vous voulez lier. Spécifiez le chemin si les fichiers ne sont pas dans le répertoire en
cours. Le lieur ajoute l'extension .OBJ si aucune extension n'est présente.
<exe> Le nom à donner au fichier exécutable (.EXE, .BPL ou .DLL). Si vous ne spécifiez pas de nom de fichier
exécutable, ILINK32 crée le nom de l'exécutable en ajoutant .EXE, .BPL ou .DLL au nom du premier fichier
objet énuméré. Le lieur assume ou ajoute l'extension .EXE pour les fichiers exécutables si aucune extension
n'est présente. Il ajoute également l'extension .DLL pour les bibliothèques de liaison dynamique si aucune
extension n'est présente. De même, le lieur ajoute l'extension .BPL pour les fichiers package si aucune
extension n'est présente.
<fichmap> Le nom à donner au fichier map. Si vous ne spécifiez pas de nom, le nom du fichier map est le même que le
fichier .EXE (mais avec l'extension .MAP). Le lieur ajoute l'extension .MAP si vous ne spécifiez pas
d'extension. 3

189
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

<bibliothèques> Les fichiers bibliothèque à inclure au moment de la liaison. N'utilisez pas de virgule pour séparer les
bibliothèques énumérées. Si un fichier n'est pas dans le répertoire en cours ni dans le chemin de recherche
(voir l'option /L), vous devez inclure le chemin dans l'instruction de liaison. Le lieur ajoute l'extension .LIB si
aucune extension n'est présente.
L'ordre dans lequel vous énumérez les bibliothèques est très important ; assurez-vous d'utiliser l'ordre défini
dans cette liste :
1. Bibliothèques Code Guard (si nécessaire)
2. Vos propres bibliothèques utilisateur, sachant que si une fonction est définie plusieurs fois, le lieur utilise
la première définition qu'il rencontre
3. IMPORT32.LIB (si vous créez un exécutable qui utilise l'API Windows)
4. Bibliothèques Math
5. Bibliothèques d'exécution

<fichdéf> Le fichier de définition de module pour un exécutable Windows. Si vous ne spécifiez pas de fichier de
définition de module (.DEF) alors que vous avez utilisé l'option /Twd ou /Twe, le lieur crée une application
basée sur les paramètres par défaut. Le lieur ajoute l'extension .DEF si aucune extension n'est présente.
<fichres> Une liste de fichiers .RES (fichiers ressource compilés) à lier à l'exécutable. Le lieur ajoute l'extension .RES
si aucune extension n'est présente.

Options du lieur

Option Description
@xxxx Utilise le fichier de réponse xxxx.
/A:dd Indique l'alignement de fichier (commutateur de compatibilité descendante ; utiliser /Af).
/Af:nnnn Spécifie l'alignement de fichier ; donnez une valeur hexadécimale ou décimale à nnnn. nnnn doit
être une puissance de 2. La valeur par défaut est 0x200 = frontières 512 octets.
/Ao:nnnn Spécifie l'alignement d'objet ; donnez une valeur hexadécimale ou décimale à nnnn. nnnn doit être
une puissance de 2. La valeur par défaut est 0x1000 = frontières 4096 octets.
/aa Construit une application Windows 32 bits.
/ad Construit un pilote de périphérique Windows 32 bits.
/ap Construit une application console Windows 32 bits.
/B:xxxx Spécifie l'adresse de base de l'image et retire la table de relogement.
/b:xxxx Spécifie l'adresse de base de l'image et préserve la table de relogement des DLLs. Les objets
successifs sont alignés sur les frontières d'adresse de 64K linéaires. Améliore les temps de
chargement et les performances à l'exécution. Recommandé pour la production des DLLs. Par
défaut, cette option est désactivée.
/C Actualise les fichiers d'état du lieur. Efface tous les fichiers d'état du lieur avant chaque liaison, puis
recrée les fichiers et poursuit la liaison.
/c Considère comme significative la casse dans les symboles publics et externes. Par défaut, cette
3 option est activée.
/d Chargements différés d'une DLL. La DLL spécifiée n'est chargée ou initialisée que lorsqu'un point
d'entrée de la DLL est appelé.
/D:xxxx Enregistre dans l'image PE la description spécifiée.
/Enn Spécifie le nombre maximal d'erreurs.
/GC Insère une chaîne de commentaire dans l'image directement après la table objet dans l'en-tête de
fichier PE. Vous pouvez spécifier plusieurs chaînes. Par défaut, cette option est désactivée.

190
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

/GD Génère un fichier .RC compatible Delphi (fichier DRC). Par défaut, cette option est désactivée.
/GF:xxxx Définit les indicateurs d'image.
Les indicateurs xxxx sont :
• -GF SWAPNET copie l'image dans un fichier d'échange local et l'exécute de là si l'image réside
sur une unité réseau.
• -GF SWAPCD copie l'image dans un fichier d'échange local et l'exécute si l'image réside sur un
support amovible (CD, lecteur zip).
• -GF UNIPROCESSOR empêche l'application de s'exécuter sur un système multiprocesseur.
• -GF LARGEADDRESSAWARE indique au système d'exploitation que l'application accepte les
adresses supérieures à 4 Giga-octets.
• -GF AGGRESSIVE réduit l'ensemble de travail d'une application quand celle-ci est inactive
(adapté aux écrans de veille et autres processus qu'il vaut mieux laisser à l'écart des
processus principaux).

/Gk Conserve les fichiers de sortie en cas d'erreur. Par défaut, cette option est désactivée.
/Gl Génère un fichier .LIB.
/Gpd Génère un package uniquement de conception. Valeur par défaut : le package fonctionne à la fois
à la conception et à l'exécution.
/Gpr Génère un package d'exécution uniquement. Valeur par défaut : le package fonctionne à la fois à la
conception et à l'exécution.
/Gn Ne génère pas de fichiers d'état (désactive la liaison incrémentielle). Les liens ultérieurs prendront
autant de temps que le premier. Par défaut, cette option est désactivée.
/Gs:string=[EICRWSDKP] Définit les indicateurs de section. Ajoute les indicateurs spécifiés aux indicateurs existants d'une
section donnée, mais ne peut pas retirer les indicateurs par défaut d'une section.
Indicateurs de section :
E = Exécutable
C = Contient du code
I = Contient des données initialisées
R = Lecture possible de la section
W = Ecriture possible de la section
S = La section est partagée
D = La section peut être supprimée
K = La section ne doit pas être mise en cache
P = La section ne doit pas être paginée
Exemple -GS:.rsrc=W Ce commutateur rend l'écriture possible dans la section RSRC.
/Gz Calcule la somme de contrôle (checksum) de la cible et insère le résultat dans l'en-tête PE. Utilisé
pour les pilotes du mode NT Kernel et les DLLs système. Par défaut, cette option est désactivée.
/H:xxxx Spécifie la taille du tas réservé pour l'application, en hexadécimal ou en décimal. La valeur
minimale est 0. Ce commutateur redéfinit le paramètre HEAPSIZE dans un fichier de définition de
module. Valeur par défaut : 1 Méga-octet (0x1000000).
/HC:nnnn Spécifie la taille du tas dédié à l'application. 3
/I Spécifie le répertoire des fichiers de sortie intermédiaire. Dirige les fichiers d'état du lieur, mais le
fichier MAP et les fichiers TDS sont enregistrés dans le même répertoire que l'image de sortie, à
moins qu'une autre spécification ne soit spécifiée pour le fichier MAP.

191
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

/j Indique les chemins de recherche des objets.


Exemple ILINK32 /jc:\myobjs;.\objs splash .\common\logo,,,utils logolib Cette commande indique
au lieur de rechercher SPLASH.OBJ d'abord dans le répertoire en cours. Si le fichier n'est pas
trouvé dans le répertoire en cours, le lieur le cherche ensuite dans le répertoire C:\MYOBJS, puis
dans le répertoire .\OBJs. Cependant, le lieur n'utilise pas les chemins de recherche des objets
pour trouver le fichier LOGO.OBJ car le chemin d'accès à ce fichier a été donné explicitement.
/L Spécifie le chemin de recherche des bibliothèques si aucun chemin explicite n'a été donné pour le
fichier LIB et si le lieur ne peut trouver le fichier LIB dans le répertoire en cours.
Exemple ILINK32 /Lc:\mylibs;.\libs splash .\common\logo,,,utils logolib indique au lieur de
rechercher SPLASH.LIB d'abord dans le répertoire en cours. Si le fichier n'est pas trouvé dans le
répertoire en cours, le lieur le cherche ensuite dans le répertoire C:\MYLIBS, puis dans le
répertoire .\LIBs. Cependant, le lieur n'utilise pas les chemins de recherche des bibliothèques pour
trouver le fichier LOGO.LIB car un chemin d'accès à ce fichier a été donné explicitement.
/M Inscrit dans le fichier map les identificateurs C++ substantypés, et pas le nom complet.
/m La liste des segments contient une ligne par segment montrant l'adresse de début, la longueur, le
nom et la classe du segment. Les symboles publics sont présentés en deux listes, la première liste
suit l'ordre alphabétique, la seconde l'ordre croissant des adresses. Les symboles ayant une
adresse absolue sont repérés par Abs. La liste des symboles publics est utile lors du débogage. De
nombreux débogueurs utilisent les symboles publics pour vous permettre de faire référence aux
adresses symboliques au cours du débogage.
/q Supprime la bannière de la ligne de commande.
/r Liaison commentée. Par défaut, cette option est désactivée.
/Rr Remplace les ressources.
/S:xxxx Spécifie la taille de réservation de la pile pour l'application.
/Sc:xxxx Spécifie la taille de validation de la pile pour l'application.
/s Produit un fichier map détaillé de segments.
/Tpd Cible un fichier DLL Windows 32 bits.
/Tpe Cible un fichier EXE Windows 32 bits.
/Tpp Génère un package.
/t Affiche le temps écoulé pendant la liaison.
/w Active tous les avertissements.
/w-dee Désactive l'avertissement : "Module .EXE construit avec une extension DLL ou BPL".
/w-dpl Désactive l'avertissement : "Symbole dupliqué dans la bibliothèque".
/w-dup Désactive l'avertissement : "Symbole dupliqué".
/w-exp Active l'avertissement : "Tentative d'exportation d'un symbole non public".
/w-nou Désactive l'avertissement : "Création d'un package sans unités".
/w-rty Active l'avertissement : "Impossible d'effectuer la liaison incrémentielle - Liaison complète".
/w-srd Désactive l'avertissement : "Retirer les relogements d'une DLL peut en altérer le fonctionnement".
3
/w-snf Désactive l'avertissement : "Section introuvable".
/w-uld Désactive l'avertissement : "Impossible de charger la DLL".
/x Supprime la création d'un fichier MAP.
(vide) Fichier map par défaut des segments (sans commutateur du lieur, le fichier map est créé par
défaut)

192
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

Fichiers de réponse du lieur


Vous pouvez utiliser des fichiers de réponse avec le lieur en ligne de commande pour spécifier les options du lieur.

Les fichiers de réponse sont des fichiers ASCII contenant les options et les noms de fichiers du lieur que vous devriez
normalement taper sur la ligne de commande. Les fichiers de réponse permettent d'entrer des lignes de commande plus longues
que ne l'autorisent la plupart des systèmes d'exploitation et vous évitent de saisir continuellement les mêmes informations. Les
fichiers de réponse peuvent contenir les mêmes informations que les fichiers de configuration, mais permettent également
d'inclure des noms de fichiers.

Contrairement à la ligne de commande, un fichier de réponse peut s'étendre sur plusieurs lignes. Il suffit de terminer une ligne
par le caractère plus (+) pour continuer la commande sur la ligne suivante. Notez que si une ligne se termine par une option
activée par le signe plus (par exemple /v+), ce + n'est pas considéré comme un caractère de continuation de ligne (pour
prolonger la ligne, utilisez /v+ +).

Si, à l'intérieur d'un fichier de réponse, vous séparez des composants de la ligne de commande (par exemple des fichiers .OBJ
et des fichiers .LIB) en allant à la ligne, vous ne devez pas taper la virgule utilisée pour les séparer sur la ligne de commande.

Par exemple :
/c c0ws+
myprog,myexe +
mymap +
mylib cws
ne contient pas les virgules que vous devriez taper si les informations étaient toutes sur la même ligne :
ILINK32 /c c0ws myprog,myexe,mymap,mylib cws
Pour utiliser des fichiers de réponse :

1. Entrez les options de la ligne de commande et les noms des fichiers dans un fichier texte ASCII et enregistrez-le. Les fichiers
de réponse ont généralement l'extension .RSP.
2. Tapez : ILINK32 @[<chemin>]<RESFILE.RSP> où <RESFILE.RSP> est le nom du fichier de réponse.
Vous pouvez spécifier plusieurs fichiers de réponse, comme suit :
ilink32 /c @listobjs.rsp,myexe,mymap,@listlibs.rsp
Remarque: Vous pouvez ajouter des commentaires aux fichiers de réponse en utilisant des points-virgules ; le lieur ignore tout
texte situé sur une ligne après un point-virgule.

Fichiers de définition de module


Le fichier de définition de module est un fichier texte ASCII qui fournit des informations à ILINK32 sur le contenu et les exigences
système d'une application Windows. Vous pouvez créer un fichier de définition de module en utilisant IMPDEF.EXE, et vous
pouvez créer des bibliothèques d'importation à partir de fichiers de définition de module en utilisant IMPLIB.EXE.

Si aucun fichier de définition de module n'est spécifié, les valeurs par défaut suivantes sont utilisées :
CODE PRELOAD MOVEABLE DISCARDABLE
DATA PRELOAD MOVEABLE MULTIPLE (pour les applications)
PRELOAD MOVEABLE SINGLE (pour les DLLs)
HEAPSIZE 4096 3
STACKSIZE 1048576
Pour donner à une application d'autres attributs, vous devez créer un fichier de définition de module.

Si vous supprimez l'instruction EXETYPE, le lieur peut déterminer le type d'exécutable que vous voulez produire à partir des
options de la ligne de commande.

Vous pouvez inclure une bibliothèque d'importation à la place de la section IMPORTS du fichier de définition de module.

Vous pouvez utiliser le mot réservé __declspec(dllexport) ou _export dans les définitions des fonctions d'exportation de votre

193
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

code source C et C++ pour vous passer d'une section EXPORTS. Notez cependant que si vous utilisez __declspec(dllexport) ou
_export pour exporter une fonction, celle-ci sera exportée par son nom et non par son numéro ordinal. Veuillez également noter
que __declspec(dllexport) est la méthode d'exportation préférée.

Fichiers d'état du lieur


Les quatre fichiers d'état du lieur s'appellent <Projet>.IL?, où <Projet> est tiré du nom du fichier .BPR du projet et où le caractère
situé à l'emplacement du point d'interrogation (?) identifie chacun des quatre fichiers d'état.

Fichier d'informations de débogage


Si vous incluez des informations de débogage dans l'exécutable lié final, ILINK32 stockera toujours les informations de
débogage dans un fichier .TDS séparé, nommé par défaut <Nom Projet>.TDS. Le débogueur devrait être capable de lire ce
fichier d'informations du débogueur. ILINK32 crée toujours ce fichier. Si le commutateur du lieur -v n'est pas activé, le fichier
TDS est signalé comme étant non valide.

Voir aussi
RLINK32.EXE ( see page 220)

IMPDEF.EXE ( see page 194)

Fichiers de définition de module ( see page 214)

3.1.1.10 IMPDEF.EXE, le gestionnaire de définition de module


Les bibliothèques d'importation permettent d'accéder aux fonctions d'une DLL Windows. Les bibliothèques d'importation
contiennent des enregistrements. Chaque enregistrement contient le nom d'une DLL et spécifie l'emplacement dans la DLL des
fonctions importées. Ces enregistrements sont liés à l'application par le lieur, et ils fournissent à Windows les informations
nécessaires pour résoudre les appels de fonctions de DLL. Vous pouvez substituer une bibliothèque d'importation à une partie
ou à la totalité de la section IMPORTS d'un fichier de définition de module.

IMPDEF accepte en entrée un nom de DLL et génère en sortie un fichier de définition de module avec une section EXPORTS
contenant les noms des fonctions exportées par la DLL.

Syntaxe de la ligne de commande


IMPDEF <options> <destination.def> <source.dll>

Option Description
-a Ajoute un alias '_' pour les fonctions cdecl de compatibilité avec les bibliothèques Microsoft
-h Emet des conseils

Par exemple :
IMPDEF NomDest.DEF NomSource.DLL

Pour afficher l'aide de la ligne de commande, entrez :


3
impdef

Cette commande crée un fichier de définition de module nommé NomDest.DEF à partir du fichier NomSource.DLL. Le fichier de
définition de module résultant serait de la forme :
LIBRARY <NomFichier>
DESCRIPTION '<Description>'
EXPORTS
<NomFoncExport> @<Ordinal>
.

194
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

.
.
<NomFoncExport> @<Ordinal>
• <NomFichier> désigne le nom du fichier racine de la DLL.
• '<Description>' est la valeur de l'instruction DESCRIPTION si la DLL a déjà été liée à un fichier de définition de module
incluant une instruction DESCRIPTION.
• <NomFoncExport> désigne une fonction exportée.
• <Ordinal> désigne la valeur ordinale de cette fonction (un entier).
Classes dans une DLL
IMPDEF est utile pour une DLL utilisant des classes C++. Si vous utilisez le mot clé __declspec (ou _export) lors de la définition
d'une classe, toutes les fonctions membres non inline et toutes les données membres statiques de cette classe sont exportées. Il
est plus facile de laisser IMPDEF produire lui-même un fichier de définition de module, car il liste toutes les fonctions exportées
et inclut automatiquement les fonctions membres et les données membres statiques.

Comme les noms de ces fonctions sont substantypés, il serait fastidieux de tous les énumérer dans la section EXPORTS d'un
fichier de définition de module simplement pour créer une bibliothèque d'importation à partir du fichier de définition de module. Si
vous utilisez IMPDEF pour créer le fichier de définition de module, il inclura la valeur ordinale de chaque fonction exportée. Si le
nom exporté est substantypé, IMPDEF inclura aussi le nom d'origine non substantypé de cette fonction en commentaire à la
suite de l'entrée correspondant à la fonction. Ainsi, par exemple :
LIBRARY <NomFichier>
DESCRIPTION '<Description>'
EXPORTS
<NomFoncExportSubst> @<Ordinal> ; <NomFoncExport>
.
.
.
<NomFoncExportSubst> @<Ordinal> ; <NomFoncExport>
• <NomFichier> désigne le nom du fichier racine de la DLL.
• '<Description>' est la valeur de l'instruction DESCRIPTION si la DLL a déjà été liée à un fichier de définition de module
incluant une instruction DESCRIPTION.
• <NomFoncExportSubst> désigne le nom substantypé.
• <Ordinal> désigne la valeur ordinale de cette fonction (un entier).
• <NomFoncExport> désigne le nom d'origine de la fonction.
Fonctions dans une DLL
IMPDEF crée un fichier source éditable listant toutes les fonctions exportées de la DLL. Vous pouvez modifier ce fichier .DEF
afin qu'il ne contienne que les fonctions à mettre à la disposition d'une application particulière, puis exécuter IMPLIB sur le fichier
.DEF modifié. Il en résulte une bibliothèque d'importation contenant des informations d'importation pour un sous-ensemble
particulier des fonctions d'exportation d'une DLL.

Supposons que vous soyez en train de distribuer une DLL contenant des fonctions destinées à être utilisées par plusieurs
applications. Chaque fonction d'exportation de la DLL est définie par __declspec (ou _export). Si toutes les applications
utilisaient toutes les exportations de la DLL, vous pourriez utiliser IMPLIB pour créer une bibliothèque d'importation pour la DLL.
3
Vous pourriez livrer cette bibliothèque d'importation avec la DLL et elle fournirait des informations d'importation pour toutes les
exportations de la DLL. La bibliothèque d'importation pourrait être liée à n'importe quelle application, ce qui éliminerait la
nécessité pour cette application particulière de lister chacune des fonctions de DLL qu'elle utilise dans la section IMPORTS de
son fichier de définition de module.

Mais supposons que vous ne souhaitiez mettre à la disposition d'une application particulière que quelques-unes des
exportations de la DLL. Idéalement, vous souhaiterez lier à cette application une bibliothèque d'importation personnalisée -- une
bibliothèque d'importation ne fournissant des informations d'importation que pour le sous-ensemble de fonctions utilisé par

195
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

l'application. Toutes les autres fonctions d'exportation de la DLL seront dissimulées à cette application cliente.

Pour créer une bibliothèque d'importation répondant à ces conditions, exécutez IMPDEF sur la DLL compilée et liée. IMPDEF
produit un fichier de définition de module contenant une section EXPORT qui énumère toutes les fonctions d'exportation de la
DLL. Vous pouvez éditer ce fichier de définition de module, retirer les entrées de section EXPORTS des fonctions que vous ne
voulez pas voir apparaître dans la bibliothèque d'importation personnalisée, puis exécuter IMPLIB sur le fichier de définition de
module. Il en résultera une bibliothèque d'importation ne contenant des informations d'importation que pour les fonctions
d'exportation listées dans la section EXPORTS du fichier de définition de module.

Voir aussi
ILINK32.EXE ( see page 189)

IMPLIB.EXE ( see page 196)

Fichiers de définition de module ( see page 214)

3.1.1.11 IMPLIB.EXE, l'outil bibliothèque d'importation


IMPLIB accepte en entrée des DLL et/ou des fichiers de définition de module et génère en sortie une bibliothèque d'importation.

Si vous avez créé une application Windows, vous avez déjà utilisé IMPORT32.LIB, la bibliothèque d'importation des DLLs
Windows standard. IMPORT32.LIB est liée automatiquement lors de la construction d'une application Win32 dans l'EDI de
C++Builder et lors de l'utilisation de BCC32 au niveau de la ligne de commande.

Une bibliothèque d'importation liste certaines voire toutes les fonctions exportées pour une ou plusieurs DLLs. IMPLIB crée
directement une bibliothèque d'importation à partir de DLLs ou de fichiers de définition de module pour DLLs (ou d'une
combinaison des deux).

Syntaxe de la ligne de commande


IMPLIB <options> <NomBiblio> [< FichiersDéf>... | <DLLs>... ] [@<FichierRéponse> | <nomsource>
] [<nomsource> ...]

Pour afficher l'aide de la ligne de commande, entrez :


implib

Elément de la ligne Description


de commande

<options> Une liste facultative d'une ou de plusieurs des options suivantes de la commande IMPLIB :
• -a Ajoute un alias '_' pour les fonctions cdecl à des fins de compatibilité avec les bibliothèques
Microsoft. Si l'identificateur commence déjà par un caractère de soulignement (_), il est ignoré (à
moins que vous n'utilisiez l'option -aa).
• -aa Impose la création d'un alias '_' pour les fonctions cdecl à des fins de compatibilité avec les
bibliothèques Microsoft. Si l'identificateur commence par un caractère de soulignement (_), l'option
3 -aa ajoute un second caractère de soulignement.
• -c Emet un avertissement sur les symboles sensibles à la casse.
• -f Impose les importations par nom.
• -w N'émet aucun avertissement.

<NomBiblio> Le nom de la nouvelle bibliothèque d'importation.


<FichiersDéf> Un ou plusieurs fichiers de définition de module existants pour une ou plusieurs DLLs. Il faut spécifier au
moins une DLL ou un fichier de définition de module.

196
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

<DLLs> Une ou plusieurs DLLs existantes. Il faut spécifier au moins une DLL ou un fichier de définition de
module.
@<FichierRéponse> Un fichier texte ACSII contenant une liste de fichiers DEF et DLL que vous souhaitez traiter en utilisant
IMPLIB. Dans le fichier de réponse, séparez les noms de fichiers par des espaces ou des sauts de
ligne.
<nomsource> Un fichier DEF ou DLL qui doit être traité par IMPLIB.

Exemple

implib foo.lib @respon.txt

Remarque: Une DLL peut également avoir l'extension .EXE ou .DRV, pas seulement .DLL.

Voir aussi
IMPDEF.EXE ( see page 194)

3.1.1.12 Utilisation des fichiers d'inclusion


Dans C++, les fichiers d'inclusion ont toujours l'extension de fichier .h.

Algorithmes de recherche des fichiers d'inclusion


Le compilateur CodeGear C++ recherche les fichiers inclus dans le code source via la directive #include en procédant de la
manière suivante :

• Si vous spécifiez un chemin et/ou un répertoire dans votre instruction include, le compilateur ne cherche qu'à l'emplacement
indiqué. Par exemple, si vous avez l'instruction suivante dans votre code : #include "c:\C++\include\vcl\vcl.h" le
fichier en-tête vcl.h devra se trouver dans le répertoire C:\C++\include. Par ailleurs, si vous utilisez l'instruction : #include
<vcl\vcl.h> et que vous définissez l'option Include (-I) avec le chemin d'accès C:\C++\include, le fichier vcl.h devra se
trouver dans C:\C++\include\vcl et non dans C:\C++include ni dans C:\vcl.
• Si vous entrez une instruction #include <unfichier> dans le code source, le compilateur ne recherche "unfichier" que dans les
répertoires définis par l'option Include (-I).
• Par contre, si vous entrez une instruction #include "unfichier" dans le code source, le compilateur recherche "unfichier" dans
l'ordre suivant :
1. Le répertoire du fichier contenant l'instruction #include.
2. Les répertoires des fichiers qui incluent (#include) ce fichier.
3. Le répertoire en cours
4. Les répertoires définis par l'option Include (-I).
Algorithmes de recherche des fichiers de bibliothèque
Les algorithmes de recherche de fichiers de bibliothèque sont similaires à ceux des fichiers d'inclusion :

• Bibliothèques implicites : Le compilateur CodeGear C++ recherche les bibliothèques implicites uniquement dans les
répertoires de bibliothèque spécifiés. Cet algorithme est similaire à celui utilisé pour : #include "unfichier" Les fichiers
de bibliothèque implicites sont ceux qui sont automatiquement liés, de même que le fichier objet de démarrage (C0x.OBJ). 3
• Bibliothèques explicites : Les répertoires dans lesquels le compilateur recherche les bibliothèques explicites (spécifiées par
l'utilisateur) dépendent en partie de la façon dont vous mentionnez les noms des fichiers de bibliothèque. Les fichiers de
bibliothèque explicites sont ceux que vous spécifiez sur la ligne de commande ou dans un fichier projet ; leur nom est suivi de
l'extension .LIB.
• Si vous mentionnez un nom de fichier de bibliothèque explicite sans indiquer de lecteur ni de répertoire (comme MYLIB.LIB),
le compilateur recherche d'abord la bibliothèque dans le répertoire en cours. Si la première recherche échoue, le compilateur
recherche dans les répertoires spécifiés par l'option bibliothèque (-L). Cela est similaire à l'algorithme de recherche de
#include "unfichier".

197
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

• Si vous spécifiez une bibliothèque spécifiée par l'utilisateur en indiquant le lecteur et/ou le répertoire (comme dans :
c:\montravail\malib1.lib), le compilateur CodeGear C++ effectue la recherche uniquement dans l'emplacement que vous avez
explicitement mentionné en tant que partie du nom de chemin de la bibliothèque et non pas dans les répertoires de
bibliothèque spécifiés.
Voir aussi
BCC32.EXE ( see page 171)

3.1.1.13 MAKE
MAKE.EXE est un utilitaire en ligne de commande qui vous aide à gérer les cycles de compilation et de liaison des projets.
MAKE n'est pas uniquement consacré à la compilation et à la liaison, c'est un outil plus généraliste d'exécution de commandes
basées sur les dépendances des fichiers. MAKE vous aide à construire rapidement les projets en compilant uniquement les
fichiers modifiés depuis la dernière compilation. De plus, vous pouvez définir les règles spécifiant comment doit agir MAKE dans
certaines circonstances spéciales au cours de vos constructions.

Bases de MAKE
MAKE utilise les règles que vous écrivez en plus de ses paramètres par défaut pour déterminer comment il doit compiler les
fichiers de votre projet. Par exemple, vous pouvez spécifier à quel moment construire vos projets avec les informations de
débogage et compiler vos fichiers .OBJ uniquement si les mentions date/heure du fichier source sont plus récentes que celles
du fichier .OBJ lui-même. Si vous avez besoin d'imposer la compilation d'un module, utilisez TOUCH.EXE pour modifier la
mention de l'heure d'un des fichiers dépendant du module.

Dans un fichier ASCII makefile, écrivez les règles explicites et implicites indiquant à MAKE comment traiter les fichiers de votre
projet ; MAKE déterminera s'il applique une commande à un fichier ou à un ensemble de fichiers d'après les règles que vous
définissez. Bien que vos commandes indiqueront habituellement à MAKE de compiler ou de lier un ensemble de fichiers, vous
pouvez spécifier presque n'importe quelle commande du système d'exploitation avec MAKE.

Syntaxe de la ligne de commande


MAKE [<options>...][<cible>[<cible>]]

Vous devez séparer la commande MAKE et les arguments options et cible par des espaces.

Lorsque vous spécifiez des cibles, vous pouvez utiliser des caractères génériques (comme * et ?) pour indiquer plusieurs
fichiers.

Pour afficher l'aide de la ligne de commande, entrez :


make —?

ou :
make —h

Elément de la ligne de Description


commande
3
[<options>] Les options MAKE qui contrôlent le fonctionnement de MAKE. Voir la section "Options de la
commande Make" de cette rubrique.
<cible> Le nom de la cible répertoriée dans le makefile que vous souhaitez construire.

198
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

Actions MAKE par défaut


Lorsque vous émettez une commande MAKE, MAKE recherche BUILTINS.MAK, un fichier que vous créez pour contenir les
règles par défaut de MAKE (utilisez l'option -r pour ignorer les règles par défaut). MAKE recherche ce fichier d'abord dans le
répertoire en cours puis dans le répertoire où est stocké MAKE.EXE. Après le chargement de BUILTINS.MAK, MAKE recherche
dans le répertoire en cours un fichier nommé MAKEFILE ou MAKEFILE.MAK (utilisez l'option -f pour spécifier un autre fichier
que MAKEFILE). Si MAKE ne trouve pas le makefile, il génère un message d'erreur.

Après le chargement du makefile, MAKE essaie de construire seulement la première cible explicite listée dans le makefile en
vérifiant la date et l'heure des fichiers dépendants de la première cible. Si les fichiers dépendants sont plus récents que le fichier
cible, MAKE exécute les commandes pour mettre à jour la cible.

Si l'un des fichiers dépendants de la première cible est utilisé comme cible ailleurs dans le makefile, MAKE vérifie les
dépendances de cette cible et la construit avant de construire la première cible. Cette réaction en chaîne est appelée une
dépendance liée.

Si une phase du processus de construction échoue, MAKE supprime le fichier cible qu'il était en train de construire. Utilisez la
directive precious si vous voulez que MAKE conserve la cible après l'échec de la construction.

Vous pouvez interrompre MAKE après l'émission de la commande MAKE en utilisant sur Ctrl+Break ou Ctrl+C.

A propos des makefiles


Un makefile est un fichier ASCII contenant l'ensemble des instructions utilisées par MAKE pour construire un certain projet. Bien
que MAKE suppose que votre makefile s'appelle MAKEFILE ou MAKEFILE.MAK, vous pouvez spécifier un autre nom de
makefile avec l'option -f.

MAKE construit les cibles spécifiées avec la commande make ou il construit la première cible trouvée dans le makefile. Pour
construire plus d'une cible, utilisez une cible symbolique dans votre makefile.

Les makefiles peuvent contenir les éléments suivants :

• Commentaires (précédés du signe dièse [#])


• Règles explicites et implicites
• Macros
• Directives

Cibles symboliques
Une cible symbolique force MAKE à construire plusieurs cibles dans un makefile. Lorsque vous spécifiez une cible symbolique,
la ligne des dépendances liste toutes les cibles que vous souhaitez construire (une cible symbolique utilise les dépendances
liées pour construire plus d'une cible).

Par exemple, le makefile suivant utilise la cible symbolique AllFiles pour construire à la fois FILE1.EXE et FILE2.EXE :
AllFiles: file1.exe file2.exe #Remarquez que AllFiles n'a pas de commande file1.exe:
file1.obj bcc32 file1.obj file2.exe: file2.obj bcc32 file2.obj
3
Règles pour les cibles symboliques

• Ne tapez pas de ligne de commandes après la ligne de la cible symbolique.


• Une cible symbolique doit avoir un nom unique ; ce ne peut être le nom d'un fichier de votre répertoire en cours.
• Les noms des cibles symboliques doivent respecter les règles du système d'exploitation relatives aux noms de fichiers.

199
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

BUILTINS.MAK
Vous pouvez créer le fichier facultatif BUILTINS.MAK et y stocker les règles standard et les macros que MAKE utilise lorsqu'il
construit les cibles dans un makefile. Pour ignorer ce fichier s'il existe, utilisez l'option -r de MAKE.

Voici un exemple de fichier BUILTINS.MAK :


#
# CodeGear C++ BUILTINS.MAK
#

CC = bcc32
RC = brcc32
AS = tasm32

.asm.obj:
$(AS) $(AFLAGS) $&.asm

.c.exe:
$(CC) $(CFLAGS) $&.c

.c.obj:
$(CC) $(CFLAGS) /c $&.c

.cpp.exe:
$(CC) $(CFLAGS) $&.cpp

.cpp.obj:
$(CC) $(CPPFLAGS) /c $&.cpp

.rc.res:
$(RC) $(RFLAGS) /r $&

.SUFFIXES: .exe .obj .asm .c .res .rc

!if !$d(BCEXAMPLEDIR)
BCEXAMPLEDIR = $(MAKEDIR)\..\EXAMPLES

!endif
Options de la commande MAKE
Vous pouvez utiliser des options de ligne de commande pour déterminer le comportement de MAKE. Les options de MAKE sont
sensibles à la casse des caractères et doivent être précédées d'un tiret (-) ou d'une barre oblique (/).

Vous devez séparer la commande MAKE et les arguments options et cible par des espaces. Lorsque vous spécifiez des cibles,
vous pouvez utiliser des caractères génériques (comme * et ?) pour indiquer plusieurs fichiers. Pour obtenir de l'aide sur MAKE,
tapez MAKE -?.

Par exemple, pour utiliser un fichier nommé PROJECTA.MAK comme makefile, tapez :
MAKE -fPROJECTA.MAK
De nombreuses options de la ligne de commande correspondent à des directives que vous pouvez utiliser dans le makefile.
3

Option Description
-a Vérifie les dépendances des fichiers d'inclusion et les fichiers d'inclusion imbriqués associés aux
fichiers .OBJ et met à jour le fichier .OBJ si le fichier .h a changé. Voir aussi -c.
-B Construit toutes les cibles quelle que soit la date des fichiers.

200
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

-c Met en cache les informations d'autodépendance, ce qui peut améliorer la vitesse de MAKE. Utilisée
avec -a. N'utilisez pas cette option si MAKE modifie les fichiers d'inclusion (ce qui peut se produire si
vous employez TOUCH dans le makefile ou si vous créez des fichiers en-tête ou d'inclusion au cours
du processus MAKE).
-D<macro> Définit macro par un caractère unique, ce qui fait renvoyer true à une expression !ifdef macro écrite
dans le makefile.
-D<macro>=<chaîne> Définit <macro> par <chaîne>. Si <chaîne> contient des espaces ou des tabulations, entourez
<chaîne> de guillemets. Le -D est facultatif.
-d<répertoire> Spécifie l'unité et le répertoire utilisé par MAKER (version en mode réel de MAKE) lorsqu'il transfère
les données hors de la mémoire lors du swapping. Cette option doit être utilisée avec -S. MAKE ignore
cette option.
-e Ignore une macro si son nom est celui d'une variable d'environnement. MAKE utilise la variable
d'environnement à la place de la macro.
-f<nomfichier> Utilise <nomfichier> ou <nomfichier>.MAK à la place de MAKEFILE (l'espace après -f est facultatif).
-h ou : -? Aide. Affiche les options de MAKE. Les paramètres par défaut sont suivis d'un signe plus.
-I<répertoire> Recherche les fichiers d'inclusion d'abord dans le répertoire en cours, puis dans le répertoire spécifié.
-i Ignore le statut de sortie de tous les programmes exécutés depuis le makefile et poursuit le processus
de construction.
-K Conserve les fichiers temporaires créés par MAKE (MAKE les supprime généralement).
-m Affiche la mention date et heure de chaque fichier lors de son traitement par MAKE.
-n Imprime les commandes MAKE mais ne les exécute pas. Cela sert au débogage des makefiles.
-N MAKE imite NMAKE de Microsoft.
-p Affiche toutes les définitions de macros et les règles implicites avant d'exécuter le makefile.
-q Renvoie 0 si la cible est à jour et une valeur non nulle si elle ne l'est pas (pour une utilisation avec des
fichiers batch).
-r Ignore toutes les règles définies dans BUILTINS.MAK.
-s Supprime l'affichage des commandes à l'écran (mode silencieux).
-S Transfère MAKER hors de la mémoire pendant l'exécution des commandes afin de réduire la charge
mémoire et permettre la compilation des modules volumineux. MAKE ignore cette option.
-U<macro> Annule la définition de macro précédente de <macro>.
-W<nomfichier> Ecrit MAKE dans <nomfichier>, en mettant à jour toutes les options qui ne sont pas des chaînes.

Voir aussi
Macros MAKE ( see page 206)

Directives MAKE ( see page 201)

Commandes et règles de MAKE ( see page 208)

3
3.1.1.14 Directives MAKE
Les directives de MAKE ressemblent aux directives des langages tels que Pascal et C. Dans MAKE, elles effectuent diverses
opérations de contrôle, telles que l'affichage des commandes avant leur exécution. Les directives de MAKE commencent par un
point ou par un point d'exclamation, et remplacent les options données sur la ligne de commande. Les directives qui
commencent par un point d'exclamation doivent apparaître au début d'une nouvelle ligne.

201
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

Le tableau suivant donne la liste des directives de MAKE et leur options en ligne de commande correspondantes :

Directive Option (si Description/Exemple


disponible)

.autodepend -a Active le contrôle de l'auto-dépendance.


Les auto-dépendances sont les fichiers automatiquement inclus dans les cibles que vous
construisez, comme les fichiers en-tête inclus dans votre code source C++. Si
.autodepend est actif, MAKE compare les dates et heures de tous les fichiers utilisés pour
construire le .OBJ, y compris les fichiers d'auto-dépendance. Si les dates et heures des
fichiers utilisés pour construire le .OBJ sont plus récentes que la date et heure du fichier
.OBJ, le fichier .OBJ est recompilé. Vous pouvez utiliser .autodepend (ou -a) à la place
des dépendances liées.
.cacheautodepend -c Active l'auto-dépendance en mémoire cache
!cmdswitches Utilisez + ou - suivi des lettres d'option non chaîne pour activer ou désactiver chaque
option. Les espaces et tabulations doivent apparaître avant l'opérateur + ou -, aucun ne
devant apparaître entre l'opérateur et les lettres de l'option.
!elif Equivalent du else if de C.
!else Equivalent du else de C.
!endif Termine une instruction !if, !ifdef ou !ifndef
!error Arrête MAKE et affiche un message d'erreur. La syntaxe de la directive !error est :
!error <message>
MAKE s'interrompt et affiche la chaîne suivante lorsqu'il rencontre cette directive :
Fatal makefile exit code: Erreur de directive : <message>
Imbriquez !error dans les instructions conditionnelles pour arrêter le traitement et afficher
un message d'erreur, comme cela est montré dans l'exemple suivant : !if
!$d(MYMACRO) #si MYMACRO n'est pas définie !error MYMACRO n'est
pas définie ! endif
Si MYMACRO n'est pas définie, MAKE s'interrompt et affiche :

Fatal makefile 4: Erreur de directive : MYMACRO n'est pas définie


Contrôles d'erreur : MAKE offre quatre contrôles d'erreur différents contrôles :
• La directive .ignore désactive le contrôle d'erreur pour la partie sélectionnée du fichier
make.
• L'option en ligne de commande -i désactive le contrôle d'erreur pour tout le fichier
make.
• Le préfixe -num, saisi comme partie intégrante d'une règle, désactive le contrôle
d'erreur pour la commande associée si le code de sortie dépasse le nombre spécifié.
• Le préfixe - désactive le contrôle d'erreur pour la commande associée quel que soit le
3 code de sortie.

!if Commence une instruction conditionnelle.


!ifdef Equivalent du #ifdef de C, en testant si la macro a été définie.
!ifndef Equivalent du #ifndef de C, en testant si la macro est non définie.
.ignore -i MAKE ignore la valeur de retour d'une commande.

202
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

!include Agit comme un #include C, spécifiant un fichier à inclure dans le makefile.


Cette directive est semblable à la directive #include du préprocesseur pour le langage C
ou C++ -- elle vous permet d'inclure le texte d'un autre fichier dans le makefile : !include
<nomfichier>
Vous pouvez délimiter le nom du fichier avec des guillemets (" ") ou des crochets
angulaires (< >) et imbriquer les directives dans un niveau de profondeur illimité, mais
l'écriture de directives !include dupliquées dans un makefile n'est pas autorisée. Vous
obtiendrez le message d'erreur de boucle dans le fichier d'inclusion.
Les règles, les commandes ou les directives doivent être terminées dans un fichier source
unique ; vous ne pouvez pas démarrer une commande dans un fichier !include, puis la
terminer dans le makefile. MAKE recherche les fichiers !include dans le répertoire en
cours, à moins que vous n'ayez spécifié un autre répertoire avec l'option de ligne de
commande -I.
.keep -K Conserve les fichiers temporaires créés par MAKE (MAKE les supprime habituellement).
!message Envoie un message vers stdout pendant que MAKE exécute le fichier make.
La directive !message permet d'afficher des messages à l'écran depuis un fichier make.
Ces messages vous servent à déboguer un fichier make qui ne fonctionne pas comme
vous le souhaiteriez. Par exemple, si une définition de macro vous pose des problèmes,
insérez cette ligne dans le fichier make :
!message La macro est définie comme : $(MacroName)
Lorsque MAKE interprète cette ligne, il affiche à l'écran (en supposant que la macro
s'exprime en .CPP) :
La macro est définie comme : .CPP
.noautodepend Désactive le contrôle de l'auto-dépendance.
a

.nocacheautodepend Désactive l'auto-dépendance en mémoire cache.


c

.noIgnore Désactive .Ignore.


i

.nokeep Ne conserve pas les fichiers temporaires créés par MAKE.


K

.nosilent Affiche les commandes avant que MAKE ne les exécute.


s

.noswap Indique à MAKE de ne pas sortir de la mémoire avant d'exécuter une commande.
S

.path.ext Indique à MAKE de rechercher les fichiers avec l'extension .ext dans les répertoires du
chemin
Pour indiquer à MAKE que les fichiers .c sont dans C:\SOURCE ou dans C:\CFILES et
que les fichiers .obj sont dans C:\OBJS :
.path.c = C:\CSOURCE;C:\CFILES .path.obj = C:\OBJS
.precious Enregistre les cibles même si la construction échoue. Si une construction de MAKE
échoue, le fichier cible est supprimé. La directive .precious interdit la suppression des 3
fichiers, ce qui peut être souhaitable dans le cas de certaines cibles. Par exemple, si votre
construction échoue dans l'ajout d'un module dans une bibliothèque, votre désir ne sera
pas forcément de supprimer la bibliothèque. La syntaxe de .precious est :
.precious: <cible> [<cible>...]
.silent -s MAKE exécute les commandes sans les afficher en premier.

203
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

.suffixes Définit la règle implicite pour les dépendances ambiguës. La directive .suffixes indique à
MAKE l'ordre (par extension de fichier) de construction des règles implicites. La syntaxe
de .suffixes est :
.suffixes: .<ext> [.<ext> ...]
où .<ext> représente l'extension du fichier dépendant dans les règles implicites.
Par exemple, vous pouvez inclure la ligne .suffixes: .asm .c .cpp pour dire à
MAKE d'interpréter les règles implicites en commençant par celles qui dépendent de
fichiers .ASM, puis .C, .CPP, quel que soit leur ordre dans le fichier make.
L'exemple suivant de .suffixes indique à MAKE de rechercher un fichier source avec une
extension .ASM, puis avec l'extension .C, et finalement avec l'extension .CPP. Si MAKE
trouve MYPROG.ASM, il construit MYPROG.OBJ à partir du fichier assembleur en
appelant TASM. MAKE appelle alors ILINK32 ; sinon, MAKE recherche MYPROG.C pour
construire le fichier .OBJ où il recherche MYPROG.CPP.
.suffixes: .asm .c .cpp
myprog.exe: myprog.obj
bcc32 myprog.obj
.cpp.obj:
bcc32 -P -c $<
.asm.obj:
tasm /mx $
.c.obj:
bcc32 -P- -c $<
.swap -S Indique à MAKE de sortir de la mémoire avant d'exécuter une commande.
!undef Efface la définition d'une macro. Après cela, la macro n'est pas définie. !undef (undefine)
provoque un échec du test !ifdef NomMacro. La syntaxe de la directive !undef est :
!undef NomMacro

Utilisation de macros dans les directives


La macro $d est utilisée avec la directive conditionnelle !if pour effectuer certains traitements si une macro spécifique est définie.
$d est suivie d'un nom de macro entre parenthèses ou entre accolades, comme dans l'exemple ci-dessous :
!if $d(DEBUG) #Si DEBUG est définie,
bcc32 -v f1.cpp f2.cpp #compiler avec les instructions de débogage;
!else #sinon
bcc32 -v- f1.cpp f2.cpp #ne pas inclure les informations de débogage.
!endif

Macros Null
Vous pouvez substituer les caractères .cpp par .obj en utilisant la commande de MAKE suivante :
NULLMACRO =
La ligne suivante définit une macro vide sur la ligne de commande de MAKE :
3 NULLMACRO =""
-DNULLMACRO
!if et autres directives conditionnelles
La directive !if fonctionne de la même manière que l'instruction if du C. Comme illustré ci-dessous, la syntaxe de !if et des autres
directives conditionnelles ressemble à celle des instructions conditionnelles du compilateur :

204
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

!if condition !if condition !if condition !ifdef macro


!endif !else !elif condition !endif
!endif !endif

Les expressions suivantes sont équivalentes :


!ifdef macro et !if $d(macro)
ifndef macro et !if !$d(macro)
Ces règles s'appliquent aux directives conditionnelles :

• Une directive !else est autorisée entre les directives !if, !ifdef, ou !ifndef et !endif.
• Plusieurs directives !elif sont autorisées entre les directives !if, !ifdef, ou !ifndef, !else et !endif.
• Vous ne pouvez pas répartir de règles entre plusieurs directives conditionnelles.
• Vous pouvez imbriquer les directives conditionnelles.
• !if, !ifdef et !ifndef doivent correspondre à des directives !endif dans le même fichier.
Les informations suivantes peuvent être insérées entre les directives !if et !endif :
• Définition de macro
• Règle explicite
• Règle implicite
• Directive include
• Directive !error
• Directive !undef
Dans une instruction if, l'expression conditionnelle consiste en une constante décimale, octale ou hexadécimale suivie des
opérateurs du tableau suivant :

Opérateur Description Opérateur Description


- Négation ?: Expression conditionnelle
~ Complément de bit ! NOT logique
+ Addition >> Décalage à droite
- Soustraction << Décalage à gauche
* Multiplication & AND bit-à-bit
/ Division | OR bit-à-bit
% Reste ^ XOR bit-à-bit
&& AND logique >+ Supérieur ou égal à *
|| OR logique <+ Inférieur ou égal à *
> Supérieur à == Egalité *
< Inférieur à != Inégalité * 3
• L'opérateur fonctionne également avec les expressions de type chaîne.
MAKE évalue une expression conditionnelle comme un entier signé 32 bits ou une chaîne de caractères.
Voir aussi
Utilisation de MAKE.EXE ( see page 198)

Macros MAKE ( see page 206)

205
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

Commandes et règles de MAKE ( see page 208)

3.1.1.15 Macros MAKE


Une macro est une variable que MAKE traduit par une chaîne à chaque fois qu'il rencontre la macro dans un fichier make. Par
exemple, vous pouvez définir une macro appelée LIBNAME qui représente la chaîne "mylib.lib". Pour cela, tapez la ligne
LIBNAME = mylib.lib au début de votre fichier make. Puis, lorsque MAKE rencontre la macro $(LIBNAME), il substitue la chaîne
mylib.lib. Les macros vous permettent de créer des fichiers make modèle que vous pouvez ensuite ajuster à vos besoins.

Pour utiliser une macro dans un fichier make, tapez $(NomMacro) où NomMacro est une macro définie. Vous pouvez utiliser des
parenthèses ou accolades pour délimiter NomMacro.

MAKE interprète les macros à différents moments suivant leur emplacement dans le fichier make :

• Les macros imbriquées sont interprétées lorsque la macro de niveau le plus élevé est évoquée.
• Les macros des règles et directives sont traduites lorsque MAKE regarde en premier dans le fichier make.
• Les macros des commandes sont interprétées lorsque les commandes sont exécutées.
Si MAKE trouve une macro non définie dans un fichier make, il recherche une variable d'environnement du système
d'exploitation portant le même nom (habituellement définie par SET) et utilise sa définition comme valeur. Par exemple, si
vous écrivez $(PATH) dans un fichier make sans définir PATH, MAKE utilisera la valeur de PATH définie dans
AUTOEXEC.BAT. Reportez-vous aux manuels de votre système d'exploitation pour savoir comment définir des variables
d'environnement.
Syntaxe
<NomMacro> = <texte_expansion>

Elément Description
<NomMacro> Est sensible à la casse (MACRO1 est différent de Macro1). Limité à 512 caractères.
<texte_expansion> Est limité à 4 096 caractères. Le texte peut inclure les caractères alphanumériques, les signes de
ponctuation et les espaces.

Vous devez définir chaque macro sur une ligne distincte dans le fichier make, et chaque définition de macro doit commencer sur
le premier caractère de la ligne. Pour plus de lisibilité, les définitions de macro sont habituellement mises au début du fichier
make. Si MAKE trouve plusieurs définitions de NomMacro, la nouvelle définition remplace la précédente.

Vous pouvez également définir une macro en utilisant l'option en ligne de commande -D. Aucun espace n'est admis avant ou
après le signe égal (=). Pourtant, vous pouvez définir plusieurs macros en séparant les définitions par des espaces. Les
exemples suivants montrent des macros définies sur la ligne de commande :
make -Dsourcedir=c:\projecta
make -Dcommand="bcc32 -c"
make -Dcommand=bcc32 option=-c
Remarque : Les macros définies dans un fichier make remplacent les macros définies sur la ligne de commande.

Substitution de chaînes dans les macros de MAKE


3
MAKE vous permet de substituer temporairement des caractères dans une macro déjà définie. Par exemple, si vous définissez
la macro suivante :
SOURCE = f1.cpp f2.cpp f3.cpp

Vous pouvez substituer les caractères .cpp par .obj en utilisant la commande de MAKE suivante :
$(SOURCE:.cpp=.obj)
Cette substitution ne redéfinit pas la macro.

206
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

Voici les règles de substitution dans les macros :

• Syntaxe : $(NomMacro:texte_original=nouveau_texte)
• Ne placez pas d'espaces avant ou après les deux points
• Les caractères de texte_original doivent être absolument identiques, en terme de majuscules et de minuscules, à la définition
de la macro.
MAKE vous permet également d'utiliser les macros au sein des macros de substitution. Par exemple :
MYEXT=.C
SOURCE=f1.cpp f2.cpp f3.cpp
$(SOURCE:.cpp=$(MYEXT)) #Changes 'f1.cpp' to 'f1.C', etc.
Le symbole ^ indique à MAKE d'interpréter littéralement le prochain caractère. Cela est utile pour l'insertion d'un caractère de
nouvelle ligne. Par exemple :
MYEXT=.C
SOURCE=f1.cpp f2.cpp f3.cpp
($(SOURCE):.cpp=$(MYEXT)^
) # changes 'f1.cpp f2.cpp f3.cpp' to:
# f1.C
# f2.C
# f3.C
Le symbole ^ indique ici à MAKE de changer chaque occurrence de .cpp en .C suivi du caractère de nouvelle ligne.

Vous pouvez utiliser cela pour créer des règles explicites qui génèrent des fichiers de réponse pour TLIB.EXE. Par exemple :
myfile.lib: file1.obj file2.obj file3.obj
TLIB $@ @&&!
+-$(**: = &^
+-)
!
MAKE substitue ici tous les caractères espace de la liste de dépendance par un espace suivi d'un caractère &, du caractère de
nouvelle ligne, et de "+-". Le fichier de réponse résultant devrait ressembler à :
+-file1.obj & +-file2.obj & +-file3.obj & +-
Macros par défaut de MAKE
MAKE contient plusieurs macros par défaut que vous pouvez utiliser dans vos fichiers make. Le tableau suivant donne la liste de
leur définition et leur interprétation dans les règles explicites et implicites.

Macro Interprétation implicite Interprétation explicite


$* chemin\fichier dépendant chemin\fichier cible
$< chemin\fichier dépendant+ext chemin\fichier cible+ext
$: chemin des dépendants chemin de la cible
$. fichier dépendant+ext fichier cible + ext
$& fichier dépendant fichier cible
3
$** chemin\fichier dépendant+ext tous les fichiers dépendants+ext
$? chemin\fichier dépendant+ext anciens dépendants

207
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

Macro Interprétation Commentaire


_ _MSDOS_ _ 1 Si DOS actif
_ _MAKE_ _ 0x0370 Version de MAKE en hexadécimal
MAKE make Nom du fichier exécutable MAKE
MAKEFLAGS options Les options tapées sur la ligne de commande
MAKEDIR répertoire Répertoire de MAKE.EXE

Modification des macros de MAKE par défaut


Si les macros par défaut ne donnent pas exactement la chaîne que vous voulez, les modificateurs de macro vous permettent
d'extraire des parties de la chaîne pour correspondre à votre besoin. Les modificateurs de macro sont habituellement utilisés
avec $< ou $@.

Pour modifier une macro par défaut, utilisez cette syntaxe :


$(NomMacro [modificateur])
Le tableau suivant donne la liste des modificateurs de macro, ainsi que des exemples d'utilisation :

Modificateur Partie du nom de fichier développé Exemple Résultat


D Lecteur et répertoire $(<D) C:\PROJECTA\
F Base et extension $(<F) MYSOURCE.C
B Base uniquement $(<B) MYSOURCE
R Lecteur, répertoire et base $(<R) C:\PROJA\SOURCE

Voir aussi
Utilisation de MAKE.EXE ( see page 198)

Directives MAKE ( see page 201)

Commandes et règles de MAKE ( see page 208)

3.1.1.16 Commandes et règles (explicites et implicites) de MAKE


Vous écrivez des règles explicites et implicites indiquant à MAKE comment construire les cibles de votre fichier make. En
général, ces règles sont les suivantes :

• Les règles explicites sont des instructions applicables à certains fichiers.


• Les règles implicites sont des instructions générales applicables aux fichiers non concernés par les règles explicites.
Toutes les règles que vous écrivez doivent respecter le format général suivant :
Ligne de dépendance
Ligne de commande
3
Alors que la ligne de dépendance utilise une syntaxe différente pour les règles explicites et pour les règles implicites, la syntaxe
de la ligne de commande est la même pour les deux types de règles.

MAKE supporte les lignes de dépendance multiples pour une même cible et une même cible peut avoir plusieurs lignes de
commande. Toutefois, seule une ligne de dépendance peut contenir une ligne de commande apparentée. Par exemple :
Target1: dependent1 dep2 dep3 dep4 dep5
Target1: dep6 dep7 dep8
bcc32 -c $**

208
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

Syntaxe des règles explicites


Les règles explicites spécifient les instructions que MAKE doit respecter lors de la construction de cibles spécifiques. Les règles
explicites nomment une ou plusieurs cibles suivies par un ou deux signes deux-points. Un seul signe deux-points signifie qu'une
seule règle est écrite pour la ou les cibles ; deux signes deux-points signifient que deux règles ou plus sont écrites pour la ou les
cibles.

Les règles explicites suivent cette syntaxe :


<cible> [<cible>...]:[:][{<chemin>}] [<dépendant[s]>...]
[<commandes>]

Elément Description
<cible> Spécifie le nom et l'extension du fichier à construire (une cible doit commencer une ligne dans le fichier make
-- vous ne pouvez pas faire précéder le nom de la cible par des espaces ni par des tabulations). Pour spécifier
plusieurs cibles, séparez les noms des cibles par des espaces ou des tabulations. Egalement, vous ne pouvez
pas utiliser un nom de cible plusieurs fois à l'emplacement d'une cible dans une règle explicite.
<chemin> Est une liste de répertoires indiquant à MAKE où trouver les fichiers dépendants. Séparez les répertoires
multiples par des points-virgules et entourez la spécification du chemin complet entre accolades.
<dépendant> Est le ou les fichiers dont MAKE vérifie la date et l'heure pour savoir s'ils sont plus récents que la cible.
Chaque fichier dépendant doit être précédé d'un espace. Si un dépendant apparaît ailleurs dans le fichier
make en tant que cible, MAKE met à jour ou crée cette cible avant d'utiliser le dépendant dans la cible
originale (c'est ce que l'on appelle une dépendance liée).
<commandes> N'importe quelle commande du système d'exploitation. Vous devez indenter la ligne de commandes d'au
moins un espace ou une tabulation, sinon elle serait interprétée comme une cible. Séparez les commandes
multiples par des espaces.

Si une ligne de dépendance ou de commande se poursuit sur la ligne d'après, utilisez une barre oblique inversée (\) à la fin de la
première ligne pour indiquer que la ligne se continue. Par exemple :
MYSOURCE.EXE: FILE1.OBJ\ #Ligne de dépendance FILE3.OBJ #Suite de la ligne
de dépendance
bcc32 file1.obj file3.obj #Ligne de commande

Cibles uniques avec règles multiples


Une même cible peut avoir plusieurs règles explicites. Pour spécifier plusieurs règles explicites, utilisez deux signes deux-points
(::) après le nom de la cible.

L'exemple suivant montre des cibles comportant plusieurs règles et commandes :


.cpp.obj:
bcc32 -c -ncobj $<

.asm.obj:
tasm /mx $<, asmobj\
3
mylib.lib :: f1.obj f2.obj #les deux signes deux-points spécifient plusieurs règles
echo Ajout de fichiers C
tlib mylib -+cobjf1 -+cobjf2

mylib.lib :: f3.obj f4.obj


echo Ajout de fichiers ASM
tlib mylib -+asmobjf3 -+asmobjf4
Syntaxe des règles implicites
Une règle implicite est une règle générale sur la façon dont MAKE construit les fichiers utilisant des extensions de fichier

209
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

particulières. Les règles implicites commencent soit par un chemin d'accès soit par un point. Leurs composants principaux sont
des extensions de fichier séparées par des points. La première extension appartient au dépendant, la seconde à la cible.

Si les dépendants implicites ne sont pas à jour par rapport à la cible ou s'il n'existe pas de dépendants, MAKE exécute les
commandes associées à la règle. MAKE met à jour les dépendants explicites avant de mettre à jour les dépendants implicites.

Les règles implicites suivent cette syntaxe :


[{>source_rép>}].<source_ext>[{cible_rép}].<cible_ext>:
[<commandes>]

Elément Description
<source_rép> spécifie le ou les répertoires contenant les fichiers dépendants. Vous pouvez spécifier plusieurs répertoires
en les séparant par un point-virgule.
.<source_ext> Spécifie l'extension des noms de fichier dépendant.
<cible_rép> Spécifie le répertoire où MAKE place les fichiers cible. La règle implicite sera uniquement utilisée pour les
cibles dans ce répertoire. Sans spécification d'un répertoire cible, les cibles de n'importe quel répertoire
satisferont la règle implicite.
.<cible_ext> Spécifie l'extension des noms de fichier cible. Les macros sont autorisées ici.
: (deux-points) Marque la fin de la ligne de dépendance.
<commandes> N'importe quelle commande du système d'exploitation. Vous devez indenter la ligne de commande d'au
moins un espace ou une tabulation ; sinon elle serait interprétée comme une cible.

Si deux règles implicites correspondent à une extension de cible et s'il n'existe pas de dépendant, MAKE utilise la règle implicite
dont l'extension des dépendants apparaît en premier dans la liste .SUFFIXES.

Règles explicites et commandes implicites


Une cible dans une règle explicite peut prendre sa ligne de commandes dans une règle implicite. L'exemple suivant montre une
règle implicite suivie d'une règle explicite sans ligne de commande :
.c.obj: bcc32 -c $< #Cette commande utilise une macro $< décrite ultérieurement
myprog.obj: #Cette règle explicite utilise la commande : bcc32 -c myprog.c
La commande de la règle implicite indique à MAKE de compiler MYPROG.C (la macro $< remplace le nom myprog.obj par
myprog.c).

Syntaxe de la commande MAKE


Les commandes suivent immédiatement une règle explicite ou implicite et doivent commencer sur une nouvelle ligne avec un
espace ou une tabulation. Les commandes peuvent être n'importe quelle commande du système d'exploitation, mais elles
peuvent également inclure des macros et directives MAKE, ainsi que des opérateurs spéciaux non reconnus par les systèmes
d'exploitation (notez toutefois que vous ne pouvez pas utiliser le caractère | dans les commandes).

Voici quelques exemples de commandes :


cd..
3 bcc32 -c mysource.c
COPY *.OBJ C:\PROJECTA
bcc32 -c $(SOURCE) #Macros dans "Utilisation des macros MAKE"
La syntaxe des commandes est la suivante :
[<préfixe>...] <commandes>
Préfixes des commandes

Les commandes des règles implicites et explicites peuvent disposer de préfixes qui modifient la façon dont MAKE traite les

210
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

commandes. Le tableau suivant liste les préfixes utilisables dans les fichiers make :

Préfixe Description
@ N'affiche pas la commande en cours d'exécution.
-<num> Arrête le traitement des commandes du fichier make si le code de sortie renvoyé par la commande est supérieur à
l'entier num. Normalement, MAKE arrête le traitement si le code de sortie est différent de zéro. Aucun espace n'est
autorisé entre - et <num>.
- Continue le traitement des commandes du fichier make, quel que soit les codes de sortie renvoyés.
& Interprète soit la macro $**, qui représente tous les fichiers dépendants, soit la macro $?, qui représente tous les
fichiers dépendants modifiés après le fichier cible. Exécutez la commande une fois pour chaque fichier dépendant
dans la macro interprétée.
! Se comporte comme le préfixe &.

Utilisation de @

La commande suivante utilise le préfixe @ qui empêche MAKE d'afficher la commande à l'écran :
diff.exe : diff.obj @bcc32 diff.obj

Utilisation de -<num> et —

Les préfixes -<num> et - (tiret) contrôlent le traitement du fichier make en cas d'erreur. Vous pouvez choisir de poursuivre le
traitement de MAKE si une erreur se produit ou spécifier un nombre d'erreurs à tolérer.

Dans l'exemple suivant, MAKE poursuit son traitement si BCC32 renvoie des erreurs :
target.exe : target.obj
target.obj : target.cpp
-bcc32 -c target.cpp
Utilisation de &

Le préfixe & émet une commande une fois par fichier dépendant. Il est très utile pour les commandes qui n'acceptent pas de
liste de fichiers comme paramètres. Par exemple :
copyall : file1.cpp file2.cpp
&copy $** c:\temp
invoque COPY deux fois, comme suit :
copy file1.cpp c:\temp
copy file2.cpp c:\temp
Sans le modificateur &, MAKE aurait appelé la commande COPY une seule fois. Remarque : le préfixe & ne fonctionne qu'avec
les macros $** et $!.

Opérateurs de la commande MAKE


Alors que vous pouvez utiliser n'importe quelle commande du système d'exploitation dans une section de la commande MAKE, 3
vous pouvez également utiliser les opérateurs spéciaux suivants :

Opérateur Description
< Prendre les entrées de commande dans le fichier spécifié plutôt que dans l'entrée standard.
> Envoyer la sortie de la commande dans le fichier.
>> Ajouter la sortie de la commande dans le fichier.

211
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

<< Créer un fichier inline temporaire et utiliser son contenu comme entrée standard de la commande. Créer
également un fichier de réponse temporaire lorsque -N est utilisé. Remarque : cela n'est utilisé qu'avec NMAKE
de Microsoft.
&& Créer un fichier de réponse temporaire et insérer son nom dans le fichier make.
<délimiteur> Utiliser des délimiteurs avec les fichiers de réponse temporaires. Vous pouvez utiliser n'importe quel caractère
différent de # comme délimiteur. Utilisez << et && comme délimiteur de début et de fin d'un fichier temporaire.
Tout caractère sur la même ligne et suivant immédiatement le délimiteur de début est ignoré. Le délimiteur de fin
doit être placé seul sur une ligne.

Voir aussi
Utilisation de MAKE.EXE ( see page 198)

Macros MAKE ( see page 206)

Directives MAKE ( see page 201)

3.1.1.17 Options des messages


Utilisez l'option -w pour spécifier les options des messages du compilateur CodeGear C++ :

• Pour activer un message d'avertissement particulier, entrez l'option -w avec un code d'option d'une à trois lettres.
• Pour désactiver le message d'avertissement, entrez l'option -w- avec un code d'option d'une à trois lettres.
Exemples
Pour afficher tous les messages d'erreur et d'avertissement, incluez l'option de commande -w dans votre commande BCC32 :
-w
Pour activer la gestion de l'avertissement "Combinaison de pointeurs de plusieurs types 'char'" (code d'option ucp, par défaut :
désactivée), incluez l'indicateur suivant dans votre commande BCC32 :
-wucp
Pour désactiver la gestion de l'avertissement "Déclaration ignorée" (code d'option dig, par défaut : activée), incluez l'indicateur
suivant dans votre commande BCC32 :
-w-dig
Pour afficher l'aide sur les codes des messages d'avertissement, entrez une commande du compilateur ne contenant que les
options -h et -w :
bcc32 -h -w
CodeGear C++ 5.92 pour Win32 Copyright (c) 1993, 2007 CodeGear
Options disponibles (* = paramètre par défaut, xxx = comporte des sous-options : utilisez -h
-X) :
(Remarque : -X- ou -w-XXX annulera habituellement tout ce qui a été défini ou restauré par -X)
-w Afficher tous les avertissements
-w! Renvoyer la valeur non-zéro du compilateur sur les avertissements
-wamb 8000 Les opérateurs ambigus nécessitent des parenthèses
3 -wamp 8001 & Superflu avec la fonction
* -wasc 8002 Redémarrage de la compilation en utilisant l'assemblage
-wasm 8003 Instruction assembleur inconnue
* -waus 8004 La valeur affectée à '%s' n'est jamais utilisée
* -wali 8086 Utilisation incorrecte de l'alias #pragma "NomAlias"="NomSubstitué"
* -watr 8100 La directive d'attribut '%s' est ignorée
-wbbf 8005 Les champs bit doivent être des entiers signés ou non signés
* -wbei 8006 Initialisation de %s avec %s
* -wbig 8007 La valeur hexadécimale contient trop de chiffres
* -wccc 8008 La condition est toujours %s

212
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

-wcln 8009 La constante est longue


* -wcom 8010 Caractère de continuation \ trouvé dans un commentaire //
* -wcpt 8011 Comparaison de pointeurs non portables
* -wcsu 8012 Comparaison de valeurs signées et non signées
* -wcod 8093 Utilisation incorrecte de #pragma codeseg [seg_name] ["seg_class"] [group]

-wdef 8013 Utilisation possible de '%s' avant sa définition


* -wdig 8014 Déclaration ignorée
* -wdpu 8015 Déclarer '%s' avant de l'utiliser dans un prototype
* -wdsz 8016 Taille de tableau pour 'delete' ignorée
* -wdup 8017 La redéfinition de '%s' n'est pas identique
* -weas 8018 Affectation de %s à %s
* -weff 8019 Le code n'a aucun effet
* -wext 8020 '%s' est déclaré à la fois comme external et static
-wexc 8101 Liaison C externe ignorée
* -whch 8021 Le gestionnaire de '%s' est caché par le gestionnaire précédent de '%s'
* -whid 8022 '%s' cache la fonction virtuelle '%s'
* -wias 8023 La variable tableau '%s' est near
* -wibc 8024 La classe de base '%s' est également une classe de base de '%s'
* -will 8025 Pragma mal formé
-winl 8026 Les fonctions %s ne sont pas développées inline
-winl 8027 Les fonctions contenant %s ne sont pas développées inline
* -wifr 8085 La fonction '%s' a été redéfinie comme non inline
-wimp 8102 Conversion implicite de '%s' en '%s'
* -wlin 8028 Un temporaire a été utilisé pour initialiser '%s'
* -wlvc 8029 Un temporaire a été utilisé pour le paramètre '%s'
* -wlvc 8030 Un temporaire a été utilisé pour le paramètre '%s' dans l'appel à '%s'
* -wlvc 8031 Un temporaire a été utilisé pour le paramètre %d
* -wlvc 8032 Un temporaire a été utilisé pour le paramètre %d dans l'appel à '%s'
* -wmpc 8033 La conversion en '%s' échouera pour les membres de la base virtuelle '%s'
* -wmpd 8034 Précision maximale utilisée pour le type de pointeur de membre '%s'
* -wmsg 8035 %s
* -wmes 8095 Utilisation incorrecte de #pragma message( "chaîne" )
* -wmcs 8096 Utilisation incorrecte de #pragma code_seg(["seg_name"[,"seg_class"]])
* -wmcc 8098 Constante caractère multicaractère
-wnak 8036 Mot clé non ANSI utilisé : '%s'
-wnak 8036 Mot clé non ANSI utilisé : '%s'
* -wncf 8037 Fonction non const %s appelée pour l'objet const
* -wnci 8038 Le membre de constante '%s' n'est pas initialisé
* -wncl 8039 La liste d'initialiseurs de constructeurs est ignorée
* -wnfd 8040 Corps de fonction ignoré
* -wngu 8041 Négation de la valeur non signée
* -wnin 8042 Initialiseur pour l'objet '%s' ignoré
* -wnma 8043 Définition de macro ignorée
* -wnmu 8044 Directive #undef ignorée
-wnod 8045 Aucune déclaration pour la fonction '%s'
* -wnop 8046 Pragma option pop sans option push correspondant
* -wnsf 8047 Déclaration de la fonction statique '%s(...)' ignorée
* -wnst 8048 Utilisation d'un nom qualifié pour accéder au type de membre '%s'
* -wntd 8049 Utilisation de '< <' pour les templates imbriqués au lieu de '<<'
* -wnto 8050 Aucun fichier de type OBJ n'est présent. Désactivation de l'option des types
externes.
* -wnvf 8051 Fonction non volatile %s appelée pour un objet volatile
* -wnpp 8083 Pragma pack pop sans pack push correspondant
* -wobi 8052 L'initialisation de base sans un nom de classe est maintenant obsolète
* -wobs 8053 '%s' est obsolète
* -wofp 8054 Le style de définition de fonction est maintenant obsolète 3
* -wosh 8055 Débordement possible dans l'opération de décalage
* -wovf 8056 Débordement arithmétique d'entiers
* -wonr 8097 Toutes les options ne peuvent être restaurées pour l'instant
* -wpar 8057 Le paramètre '%s' n'est jamais utilisé
* -wpch 8058 Impossible de créer l'en-tête pré-compilé : %s
* -wpck 8059 La taille de packaging de la structure a changé
* -wpia 8060 Affectation incorrecte possible
-wpin 8061 L'initialisation est seulement partiellement entre accolades
* -wpow 8062 Options et avertissements précédents non restaurés

213
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

* -wpre 8063 Préfixe surchargé 'operator %s' utilisé comme un opérateur postfixe
* -wpro 8064 Appel à une fonction sans prototype
* -wpro 8065 Appel à la fonction '%s' sans prototype
-wprc 8084 Parenthèses suggérées pour clarifier la priorité
* -wpcm 8094 Utilisation incorrecte de #pragma comment( <type> [,"chaîne"] )
* -wpsb 8099 'main' statique non traité comme un point d'entrée
* -wrch 8066 Code inaccessible
* -wret 8067 Les deux instructions return et return avec une valeur ont été utilisées
* -wrng 8068 Constante hors limites dans la comparaison
* -wrpt 8069 Conversion de pointeur non portable
* -wrvl 8070 La fonction doit renvoyer une valeur
-wsig 8071 Des chiffres significatifs peuvent être perdus pendant la conversion
* -wspa 8072 Arithmétique de pointeur suspecte
-wstu 8073 Structure '%s' non définie
-wstv 8074 Structure transmise par valeur
* -wsus 8075 Conversion de pointeur suspecte
-wstl 8087 '%s::operator==' doit être publiquement visible pour être contenu par un '%s'
-wstl 8089 '%s::operator<' doit être publiquement visible pour être contenu par un '%s'
-wstl 8090 '%s::operator<' doit être publiquement visible pour être utilisé avec '%s'
-wstl 8091 L'argument %s %s transmis à '%s' est un itérateur %s : itérateur %s requis
-wstl 8092 L'argument %s %s transmis à '%s' n'est pas un itérateur : itérateur %s requis
* -wtai 8076 L'instance de template '%s' est déjà instanciée
* -wtes 8077 La spécialisation explicite d'un membre de classe explicitement spécialisé n'a
pas de sens
* -wthr 8078 L'expression Throw viole la spécification d'exception
-wucp 8079 Mélange de pointeurs en différents types 'char'
-wuse 8080 '%s' est déclaré mais jamais utilisé
* -wvoi 8081 Les fonctions void ne doivent pas renvoyer de valeur
* -wzdi 8082 Division par zéro

3.1.1.18 Fichiers de définition de module


Utilisez les fichiers de définition de module avec ILINK32. Un fichier de définition de module est un fichier texte ASCII qui fournit
des informations à ILINK32 sur le contenu et les exigences système d'une application Windows. Utilisez IMPDEF pour créer un
fichier de définition de module.

Le fichier de définition de module nomme les fichiers .EXE ou .DLL, identifie le type d'application, énumère les fonctions
importées et exportées, décrit les attributs des segments de données et des sections de code, vous permet de spécifier les
attributs des segments de données et des sections de code supplémentaires, spécifie la taille de la pile et permet l'inclusion d'un
programme stub.

Les éléments particuliers d'un fichier de définition de module sont :

Instruction CODE

Instruction DATA

Instruction DESCRIPTION

Instruction EXETYPE

Instruction EXPORTS
3 Instruction HEAPSIZE

Instruction IMPORTS

Instruction LIBRARY

Instruction NAME

Instruction SECTIONS

Instruction SEGMENTS

214
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

Instruction STACKSIZE

Instruction STUB

Instruction SUBSYSTEM

Instruction CODE
Définit les attributs par défaut des sections de code. Les sections de code peuvent prendre n'importe quel nom, mais doivent
appartenir à des classes de sections dont le nom se termine par CODE (par exemple CODE ou MYCODE).
CODE [PRELOAD | LOADONCALL] [EXECUTEONLY | EXECUTEREAD]
• PRELOAD signifie que le code est chargé lors du chargement du programme appelant.
• LOADONCALL (valeur par défaut) signifie que le code est chargé quand il est appelé par le programme.
• EXECUTEONLY signifie qu'une section de code peut uniquement être exécutée.
• EXECUTEREAD (valeur par défaut) signifie que la section de code peut être lue et exécutée.
• FIXED (valeur par défaut) signifie que la section reste toujours au même emplacement mémoire.
• MOVEABLE signifie que la section peut être déplacée.
• DISCARDABLE signifie que la section peut être supprimée si elle n'est plus utile (implique qu'elle soit MOVEABLE).
• NONDISCARDABLE (valeur par défaut) signifie que la section ne peut pas être supprimée.
Instruction DATA
Définit les attributs des segments de données :
DATA [NONE | SINGLE | MULTIPLE]
[READONLY | READWRITE]
[PRELOAD | LOADONCALL]
[SHARED | NONSHARED]
• NONE signifie qu'aucune section de données n'a été créée. Cette option n'est disponible que pour les bibliothèques.
• SINGLE (valeur par défaut pour les .DLL) signifie qu'une seule section de données est créée et partagée par tous les
processus.
• MULTIPLE (valeur par défaut pour les .EXE) signifie qu'une section de données est créée pour chaque processus.
• READONLY signifie que la section de données peut être uniquement lue.
• READWRITE (valeur par défaut) signifie que la section de données est accessible en lecture et en écriture.
• PRELOAD signifie que la section de données est chargée lors du premier chargement d'un module utilisant cette section.
• LOADONCALL (valeur par défaut) signifie que la section de données est chargée quand on y accède pour la première fois.
LOADONCALL est ignoré pour les applications 32 bits.
• SHARED signifie qu'un exemplaire de la section de données est partagé par tous les processus.
• NONSHARED (valeur par défaut pour les programmes et DLLs) signifie qu'un exemplaire de la section de données est
chargé pour chaque processus qui a besoin d'utiliser la section.
Instruction DESCRIPTION (facultative)
Insère du texte dans le module d'application ; cette instruction est en principe utilisée pour inclure le nom de l'auteur, la date ou
3
des informations de copyright :
DESCRIPTION 'Texte'
Texte est une chaîne ASCII délimitée par des apostrophes.

Instruction EXETYPE
Définit le type d'en-tête par défaut du fichier exécutable (.EXE) pour les applications. Vous pouvez laisser cette section pour les
applications 32 bits, pour des raisons de compatibilité descendante, mais si vous devez modifier EXETYPE, reportez-vous à

215
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

l'instruction NAME.
EXETYPE [WINDOWAPI] | [WINDOWCOMPAT]
• WINDOWAPI est un exécutable Windows ; équivaut à l'option -aa de ILINK32.
• WINDOWCOMPAT est un exécutable en mode caractère compatible Windows ; équivaut à l'option -ap de ILINK32.
Instruction EXPORTS
Définit le nom et les attributs des fonctions à exporter. Le mot réservé EXPORTS indique le début des définitions. Il peut être
suivi d'un nombre quelconque de définitions d'exportation, chacune sur une ligne distincte.
EXPORTS
<NomExport> [<Ordinal>]
[RESIDENTNAME] [<Paramètre>]
• <NomExport> désigne une chaîne ASCII définissant le symbole à exporter comme suit : <NomEntrée>
[=<NomInterne>] <NomEntrée> est le nom qui figure dans la table des entrées du fichier exécutable ; il est visible de
l'extérieur. <NomInterne> est le nom utilisé à l'intérieur de l'application pour faire référence à cette entrée.
• <Ordinal> définit la valeur ordinale de la fonction, comme suit : @<ordinal> où <ordinal> est un nombre entier désignant
la valeur ordinale de la fonction. Quand un module d'application ou de DLL appelle une fonction exportée d'une DLL, le
module appelant peut désigner la fonction par son nom ou par sa valeur ordinale. Il est plus rapide d'appeler la fonction par
sa valeur ordinale car cela évite les comparaisons de chaînes pour localiser la fonction. Pour économiser la mémoire,
exportez une fonction par sa valeur ordinale (du point de vue de la DLL de la fonction) et importez/appelez une fonction par
sa valeur ordinale (du point de vue du module appelant). Quand une fonction est exportée par sa valeur ordinale, son nom se
trouve dans la table des noms non résidents. Quand elle est exportée par son nom, le nom se trouve dans la table des noms
résidents. La table des noms résidents d'un module donné est en mémoire chaque fois que ce module est chargé ; la table
des noms non résidents ne l'est pas.
• RESIDENTNAME indique que le nom de la fonction doit être en permanence résident. Cela n'est utile que pour les
exportations par valeur ordinale (où le nom n'est pas forcément résident par défaut).
• <Paramètre> est un entier facultatif qui spécifie le nombre de mots que la fonction veut transmettre comme paramètres.
Instruction HEAPSIZE
Définit le nombre d'octets requis par l'application pour son tas local. Une application utilise le tas local quand elle alloue de la
mémoire locale.
HEAPSIZE <Réserve>[, <Commit>]
• <Réserve> peut être une valeur décimale ou hexadécimale, et la valeur par défaut est 1 Mo. Pour vous aider à assurer la
compatibilité avec les applications 16 bits et les ports 32 bits, le lieur utilise la valeur par défaut de 1 Mo si vous spécifiez une
valeur inférieure à 64 Ko dans le fichier .DEF.
• <Commit> peut être une valeur décimale ou hexadécimale. Cette valeur, facultative, est par défaut de 4 Ko. La valeur
minimale de commit est 0. En outre, la valeur de commit, spécifiée ou par défaut, doit toujours être inférieure ou égale à la
taille de réserve.
La mémoire réservée est la quantité maximale de mémoire pouvant être allouée soit en mémoire physique, soit dans le fichier
de pagination. En d'autres termes, la mémoire réservée indique la taille maximale du tas. Le système d'exploitation garantit
que cette quantité de mémoire sera réservée et, si nécessaire, allouée.
La signification de la mémoire dédiée varie selon le système d'exploitation. Sous Windows NT, la mémoire dédiée est la quantité
de mémoire physique allouée au tas au chargement ou à l'initialisation de l'application. La mémoire dédiée est allouée soit en
mémoire physique, soit dans le fichier de pagination. Une valeur élevée permet de gagner du temps lorsque l'application
3 nécessite un tas plus important, mais augmente les besoins en mémoire et parfois la durée du démarrage.
Vous pouvez outrepasser les tailles de réserve ou de commit du tas spécifiées dans le fichier .DEF, en utilisant les options -H ou
-Hc sur la ligne de commande ILINK32. -H vous permet de spécifier une taille de réserve pour le tas qui soit inférieure au
minimum de 64 Ko autorisé dans le fichier .DEF.
Instruction IMPORTS
Définit le nom et les attributs des fonctions à importer des DLLs. Le mot réservé IMPORTS signale le début des définitions ; il est
suivi d'un nombre quelconque de définitions d'importation, chacune sur une ligne distincte.

216
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

IMPORTS [<NomInterne>=]<NomModule>.<Entrée>
• <NomInterne> est une chaîne ASCII qui précise le nom unique utilisé par l'application pour appeler la fonction.
• <NomModule> indique un ou plusieurs caractères ASCII majuscules qui définissent le nom du module exécutable contenant
la fonction. Ce nom doit être le même que celui du fichier exécutable. Par exemple, le fichier EXEMPLE.DLL a pour nom de
module EXEMPLE.
• <Entrée> désigne la fonction à importer : il s'agit soit d'une chaîne ASCII désignant la fonction, soit d'un entier correspondant
à la valeur ordinale de la fonction.
Au lieu d'énumérer dans l'instruction IMPORTS les fonctions DLL importées, vous pouvez spécifier une bibliothèque
d'importation pour la DLL dans la ligne de commande ILINK32 ou inclure la bibliothèque d'importation pour la DLL dans le
gestionnaire de projets de l'environnement de développement.
Vous devez utiliser __declspec(dllimport) ou __import pour importer toute fonction, classe ou données. __declspec(dllimport)
constitue la méthode préférée.
Le mot réservé IMPORTS peut également être appliqué aux variables (globales), comme suit :
[ dans le fichier source de la dll (dll.cpp) ] int sample = 100;

[ dll.def ] EXPORTS _sample

[ dans le fichier source de l'application (app.cpp) ]


int _declspec(dllimport) sample;

[ app.def ]
IMPORTS
dll._sample
Instruction LIBRARY
Définit le nom d'un module DLL. Un fichier de définition de module peut contenir soit une instruction LIBRARY pour désigner une
.DLL, soit une instruction NAME pour désigner un .EXE. Tout nom de module de bibliothèque doit correspondre au nom du
fichier exécutable. Par exemple, la bibliothèque MYLIB.DLL a pour nom de module MYLIB.
LIBRARY <NomBiblio> [INITGLOBAL | INITINSTANCE]
• <NomBiblio> (facultatif) est une chaîne ASCII qui définit le nom du module de la bibliothèque. Si vous n'indiquez pas de
NomBiblio, ILINK32 utilise le nom du fichier en supprimant l'extension. Si le fichier de définition de module ne comporte ni
instruction NAME ni instruction LIBRARY, ILINK32 utilise par défaut une instruction NAME sans paramètre NomModule.
• INITGLOBAL signifie que la routine d'initialisation de la bibliothèque est appelée.
• INITINSTANCE signifie que la routine d'initialisation de la bibliothèque est appelée chaque fois qu'un nouveau processus
utilise la bibliothèque.
Instruction NAME
Est le nom du module exécutable de l'application. Le nom du module identifie le module quand vous exportez des fonctions.
NAME doit figurer avant EXETYPE. Si NAME et EXETYPE n'indiquent pas le même type de cible, le lieur utilise le type indiqué
par NAME.
NAME <NomModule> [WINDOWSAPI] | [WINDOWCOMPAT]
• <NomModule> (facultatif) contient un ou plusieurs caractères ASCII majuscules désignant le nom du module exécutable. Ce
nom doit être le même que celui du fichier exécutable. Par exemple, une application avec le fichier exécutable
EXEMPLE.EXE aura pour nom de module EXEMPLE. Si <ModuleName> n'est pas indiqué, ILINK32 considère que le nom du 3
module correspond au nom du fichier exécutable. Par exemple, si vous n'indiquez pas de nom de module et si le fichier
exécutable s'appelle MYAPP.EXE, ILINK32 considère que le nom du module est MYAPP. Si le fichier de définition de module
ne comporte ni instruction NAME ni instruction LIBRARY, ILINK32 utilise par défaut une instruction NAME sans paramètre
<NomModule>.
• WINDOWSAPI désigne un exécutable Windows ; équivaut à l'option -aa de ILINK32.
• WINDOWCOMPAT désigne un exécutable en mode caractère compatible Windows ; équivaut à l'option -ap de ILINK32.

217
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

Instruction SECTIONS
Vous permet de définir les attributs d'une ou plusieurs sections du fichier image. Vous pouvez utiliser cette instruction pour
outrepasser les valeurs par défaut des attributs de chaque type de section.
SECTIONS<nom_section> [CLASS '<NomClasse>'] <attributs>
• SECTIONS signale le début de la liste des définitions de sections.
• Après le mot réservé SECTIONS, chaque définition de section doit figurer sur une ligne différente. Le mot réservé SECTIONS
peut être sur la même ligne que la première définition ou sur la ligne précédente. En outre, le fichier .DEF peut contenir une
ou plusieurs instructions SECTIONS. Le mot réservé SEGMENTS est accepté comme synonyme de SECTIONS.
• <NomClasse> est sensible à la casse. Le mot réservé CLASS est accepté pour des raisons de compatibilité, mais il est
ignoré.
• <Attributs> désigne un ou plusieurs des attributs suivants : EXECUTE, READ, SHARED et WRITE.
Instruction SEGMENTS
Définit les attributs des sections de code et de données supplémentaires. Le mot réservé SEGMENTS est accepté comme
synonyme de SECTIONS. La syntaxe est :
SEGMENTS <NomSegment> [CLASS '<ClassName>'] [<AllocMin>] [SHARED |
NONSHARED\ [PRELOAD | LOADONCALL]
• <NomSegment> est une chaîne de caractères qui désigne le nouveau segment. Il peut s'agir d'un nom quelconque, y
compris des noms de segments standard _TEXT et _DATA qui correspondent aux segments de code et de données
standard.
• <NomClasse> (facultatif) est le nom de classe du segment concerné. Si le nom de classe n'est pas indiqué, ILINK32 utilise le
nom de classe CODE.
• <AllocMin> (facultatif) est un entier désignant la taille d'allocation minimale pour le segment. ILINK32 ne tient pas compte de
cette valeur.
• SHARED signifie qu'un exemplaire du segment est partagé par tous les processus.
• NONSHARED (valeur par défaut pour les .EXEs et DLLs) signifie qu'un exemplaire du segment est chargé pour chaque
processus qui a besoin du segment de données.
• PRELOAD signifie que le segment est chargé immédiatement.
• LOADONCALL signifie que le segment est chargé quand on y accède ou quand il est appelé (ignoré par ILINK32). Le
compilateur de ressources peut outrepasser l'option LOADONCALL et précharger les segments.
Instruction STACKSIZE
Définit le nombre d'octets requis par l'application pour sa pile locale. Une application utilise la pile locale chaque fois qu'elle
appelle des fonctions.
STACKSIZE <Réserve>[, <Commit>]
• <Réserve> peut être une valeur décimale ou hexadécimale, et la valeur par défaut est 1 Mo. Pour vous aider à assurer la
compatibilité avec les applications 16 bits, le lieur utilise la valeur par défaut 1 Mo si vous spécifiez une valeur de réserve
inférieure à 64 Ko dans le fichier .DEF.
• <Commit> peut être une valeur décimale ou hexadécimale. Cette valeur, facultative, est par défaut de 8 Ko. La valeur
3 minimale de commit est 4 Ko. En outre, la valeur de commit, spécifiée ou par défaut, doit toujours être inférieure ou égale à la
taille de réserve.
La mémoire réservée est la quantité maximale de mémoire pouvant être allouée soit en mémoire physique, soit dans le fichier
de pagination. En d'autres termes, la mémoire réservée indique la taille maximale de la pile.
Le système d'exploitation garantit que cette quantité de mémoire sera réservée et, si nécessaire, allouée.
La signification de la mémoire dédiée varie selon le système d'exploitation. Sous Windows NT, la mémoire dédiée est la quantité
de mémoire physique allouée à la pile au chargement ou à l'initialisation de l'application. La mémoire dédiée est allouée soit
en mémoire physique, soit dans le fichier de pagination. Une valeur élevée permet de gagner du temps lorsque l'application
nécessite une pile plus importante, mais augmente les besoins en mémoire et parfois la durée du démarrage.

218
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

Vous pouvez outrepasser les tailles de réserve ou de commit de la pile spécifiées dans le fichier .DEF, en utilisant les options -S
ou -Sc sur la ligne de commande ILINK32. -S vous permet de spécifier une taille de réserve pour la pile qui soit inférieure au
minimum de 64 Ko autorisé dans le fichier .DEF.
Remarque: N'utilisez pas l'instruction STACKSIZE lorsque vous compilez des .DLLs.
Instruction STUB
Ajoute un fichier DOS exécutable désigné par NomFichier au début du module. Le stub exécutable affiche un message
d'avertissement et se termine si l'utilisateur essaie de l'exécuter dans le mauvais environnement (application Windows exécutée
sous DOS, par exemple).
STUB '<NomFichier>'
• <NomFichier> est le nom du fichier DOS exécutable qui doit être ajouté au module. Ce nom doit respecter le format des
noms de fichiers DOS. Si le fichier désigné par NomFichier n'est pas dans le répertoire en cours, ILINK32 le recherche dans
les répertoires indiqués par la variable d'environnement PATH.
C++Builder ajoute un stub prédéfini au début de toute application Windows, sauf si un autre stub a été indiqué avec l'instruction
STUB. N'utilisez pas l'instruction STUB pour inclure WINSTUB.EXE, car le lieur le fait automatiquement.
Instruction SUBSYSTEM
Vous permet de spécifier le sous-système Windows et le numéro de version du sous-système pour l'application à lier.
SUBSYSTEM [<Sous-système>,]<IDSous-système>
• <Sous-système> (facultatif) peut prendre l'une des valeurs suivantes : WINDOWS, WINDOWAPI, WINDOWCOMPAT. Si
vous ne spécifiez pas de sous-système, le lieur utilisera par défaut un sous-système WINDOWS.
• <IDSous-système> doit utiliser le format d.d où d est un nombre décimal. Par exemple, si vous voulez spécifier Windows 4.0,
utilisez l'une des instructions SUBSYSTEM suivantes : SUBSYSTEM 4.0 SUBSYSTEM WINDOWS 4.0
Vous pouvez outrepasser toute instruction SUBSYSTEM d'un fichier .DEF en utilisant les options /a et /V sur la ligne de
commande ILINK32.
Voir aussi
ILINK32 ( see page 189)

IMPDEF ( see page 194)

3.1.1.19 Fichiers en-tête précompilés


Les fichiers en-tête précompilés accélèrent de façon significative la vitesse de compilation en stockant une image de la table des
symboles dans un fichier sur disque. Ce fichier est ensuite rechargé au lieu d'analyser de nouveau tous les fichiers en-tête. Le
chargement direct de la table des symboles depuis le disque est beaucoup plus rapide que l'analyse du texte des fichiers
en-tête, en particulier si plusieurs fichiers source incluent le même fichier en-tête.

Pour utiliser les fichiers en-tête précompilés, spécifiez les diverses options -H dans votre commande BCC32.

Options des en-têtes précompilés

Option du Description Détails


compilateur 3

-H Générer et Lorsque vous activez cette option, le compilateur génère et utilise les en-têtes précompilés.
utiliser Le nom de fichier par défaut est BC32DEF.CSM pour le compilateur en ligne de
commande.
-Hu Utiliser mais Lorsque vous activez cette option, le compilateur utilise les fichiers en-tête précompilés et
ne pas pré-existants ; de nouveaux fichiers en-tête précompilés ne sont pas générés.
générer

219
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

Ne pas Lorsque vous activez cette option, le compilateur ne génère pas, ni n'utilise les en-têtes
H générer, ni précompilés. Par défaut : Ne génère pas, ni n'utilise (-H-)
utiliser
-Hc En-têtes Lorsque vous activez cette option, le compilateur met en mémoire cache les en-têtes
précompilés précompilés qu'il génère. Cette option sert lors de la précompilation de plusieurs fichiers
en cache en-tête. Pour utiliser cette option, vous devez également activer l'option Générer et utiliser
(-H) concernant les en-têtes précompilés. Par défaut, cette option est désactivée.
-He Générer les Lorsque vous activez cette option, le compilateur génère un fichier (ou des fichiers)
fichiers de contenant les informations de débogage pour tous les symboles contenus dans les en-têtes
type externe précompilés. Les noms de fichiers se terminent par l'extension .#xx, où xx vaut 00 pour le
(en-têtes premier fichier généré, sa valeur augmentant pour chaque fichier d'informations de type
précompilés) supplémentaire. L'utilisation de cette option diminue considérablement la taille de vos
fichiers .OBJ, puisque les informations de débogage sont centralisées et non dupliquées
dans chaque fichier .OBJ. Par défaut, cette option est activée.
-H=<nomfichier> Nom de fichier Utilisez cette option pour spécifier le nom de votre fichier en-tête précompilé. Lorsque vous
en-tête définissez cette option, le compilateur génère et utilise le fichier en-tête précompilé que
précompilé vous spécifiez.

-Hh=<xxx> or Arrêter la Cette option termine la compilation de l'en-tête précompilé après avoir traité le fichier
-H\”<xxx>\” précompilation spécifié par xxx. Vous pouvez utiliser cette option pour réduire l'espace disque requis pour
après le fichier les en-têtes précompilés.
en-tête La syntaxe -Hh est généralement plus facile à utiliser que la syntaxe -H. Exemples :
-Hh=myhdr.h
-H\"myhdr.h\"
-Hh="C:\Program Files\myhdr.h"
-H\"C:\Program Files\myhdr.h\"
Lorsque vous utilisez cette option, le fichier que vous spécifiez doit être inclus à partir d'un
fichier source pour que le compilateur génère un fichier en-tête précompilé.
Vous pouvez également utiliser #pragma hdrstop dans votre fichier source afin de spécifier
à quel moment arrêter la génération des en-têtes précompilés.
Vous ne pouvez pas spécifier un fichier en-tête inclus à partir d'un autre fichier en-tête. Par
exemple, vous ne pouvez pas lister un en-tête inclus par windows.h car cela aurait pour
effet de provoquer la fermeture du fichier en-tête précompilé avant que ne s'achève la
compilation de windows.h.

Voir aussi
ILINK32.EXE ( see page 189)

3.1.1.20 RLINK32.DLL, le lieur de ressources (C++)


RLINK32.DLL est le lieur de ressources qui lie des ressources sous la forme de fichiers .RES pour produire un fichier .EXE et
marque le fichier .EXE résultant comme exécutable Windows. RLINK32.DLL :
3 • Lie les ressources en combinant les tables de chaînes et les tables de messages, puis en liant ces ressources liées à
l'exécutable.
• Est appelé par ILINK32 et est utilisé pour les ressources 32 bits.
Voir aussi
BRC32.EXE ( see page 176)

ILINK32.EXE ( see page 189)

220
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

3.1.1.21 TDUMP.EXE, l'utilitaire de vidage de fichier


TDUMP.EXE produit un vidage montrant la structure d'un fichier.

TDUMP divise un fichier de manière structurelle et utilise son extension pour déterminer le format d'affichage de sortie. TDUMP
reconnaît de nombreux formats de fichiers tels qu'.EXE, .OBJ et .LIB. Si TDUMP ne reconnaît pas une extension, il produit un
vidage hexadécimal du fichier. Vous pouvez contrôler le format de sortie en utilisant les options de la ligne de commande
TDUMP au lancement du programme.

La capacité de TDUMP à visualiser la structure interne d'un fichier permet non seulement de voir le contenu d'un fichier, mais
aussi de savoir comment il est construit. De plus, comme TDUMP vérifie que la structure d'un fichier correspond à son
extension, vous pouvez aussi l'employer pour tester l'intégrité des fichiers.

Syntaxe de la ligne de commande


TDUMP [<options>] <fichentrée> [<fichlistage>] [<options>]

• <fichentrée> désigne le fichier dont vous souhaitez afficher (ou "vider") la structure.
• <fichlistage> est un nom facultatif de fichier de sortie (vous pouvez également utiliser la commande DOS standard de
redirection (>).
• <options> représente les éventuelles options de la ligne de commande TDUMP.
Pour afficher l'aide de la ligne de commande, entrez :
tdump
Vous pouvez utiliser le caractère de commutateur / ou -. Par exemple, les deux commandes suivantes sont équivalentes :
TDUMP -e1 -v demo.exe
TDUMP /el /v demo.exe
Options TDUMP

Option Description
-a, -a7 TDUMP ajuste automatiquement l'affichage de sortie en fonction du type de fichier. Vous pouvez forcer un affichage
de fichier au format ASCII en incluant l'option -a ou -a7.
-a produit un affichage de fichier ASCII qui montre le décalage et le contenu en caractères ASCII affichables. Un
caractère non affichable (comme un caractère de contrôle) apparaît sous la forme d'un point.
-a7 convertit les caractères de la partie haute du tableau ASCII en leurs équivalents de la partie basse du tableau
ASCII. Cela est utile si le fichier en cours de vidage utilise des caractères ASCII hauts comme indicateurs (comme
c'est le cas, par exemple, des fichiers WordStar).
-b# Permet d'afficher les informations à partir d'une adresse (décalage dans le fichier) particulière. Par exemple, pour
obtenir un vidage de MYFILE à partir de l'adresse 100, vous pouvez taper : TDUMP -b100 MYFILE
-C TDUMP renvoie les informations contenues dans les fichiers de format COFF (.OBJ et .LIB). Cette option est utile lors
de l'établissement de liaison avec des fichiers.OBJ et .LIB Microsoft.
-d TDUMP renvoie les éventuelles informations de débogage CodeGear 32 bits contenues dans le fichier .OBJ. Si cette 3
option est absente, TDUMP n'affiche que des données brutes.

221
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

-e, -el, Ces quatre options forcent TDUMP à afficher le fichier sous la forme d'un fichier exécutable (.EXE).
-er, L'affichage d'un fichier .EXE se compose des informations contenues dans le fichier qui sont utilisées par le système
-ex d'exploitation pour charger ce fichier. Si des informations symboliques de débogage sont présentes (Turbo Debugger
ou Microsoft CodeView), TDUMP les affiche.
TDUMP affiche des informations pour les fichiers exécutables DOS, les fichiers exécutables de NOUVEAU style (.EXE
et .DLL Microsoft Windows et OS/2), les fichiers exécutables linéaires (Linear Executable) et les fichiers exécutables
portables (Portable Executable) utilisés par Windows NT, Windows 95/98 et Windows 2000.
• -e Affiche le fichier comme un exécutable (EXE/DLL, DOS, Win16, OS/2, PE)
• -ea[:v] Affiche tous les éléments exportés non triés, ou (:v) trie par RVA (par défaut vide uniquement les éléments
exportés nommés, avec tri sur le nom) a[:v] Affiche tous les éléments exportés non triés, ou (:v) trie par RVA (par
défaut vide uniquement les éléments exportés nommés, avec tri sur le nom)
• -ed Désactive les informations de débogage EXE
• -ee[=x] Liste les éléments exportés uniquement à partir de EXE/DLL (le paramètre facultatif x permet de n'afficher
que les correspondances)
• -el Supprime les numéros de ligne dans l'affichage.
• -eiID Inclut uniquement l'ID de table .EXE (HDR, OBJ, FIX, NAM, ENT)
• -em[=x] Liste les éléments importés uniquement à partir de EXE/DLL (le paramètre facultatif x permet de
n'afficher que les correspondances)
• -em.[x] Liste les modules importés uniquement à partir de EXE/DLL (le paramètre facultatif x permet la recherche
dans les chaînes)
• -ep Désactive l'affichage de l'en-tête EXE PE
• -er Empêche l'affichage de la table de relogement
• -ex Empêche l'affichage des informations d'exécutables de Nouveau style. Cela signifie que TDUMP n'affiche
que des informations pour le programme DOS de remplacement temporaire

-h Affiche le vidage de fichier au format hexadécimal. Ce format comprend une colonne de numéros de décalage, 16
colonnes de nombres hexadécimaux et leurs équivalents ASCII (un point apparaît lorsque le caractère ASCII n'est pas
affichable).
Si TDUMP ne reconnaît pas l'extension du fichier d'entrée, il affiche le contenu du fichier au format hexadécimal (sauf
si une option est utilisée pour indiquer un autre format).
-i Spécifie les tables de débogage à utiliser.
-l, -li, Affiche le fichier de sortie sous la forme d'un fichier de bibliothèque (.LIB). Un fichier bibliothèque est un ensemble de
-le fichiers objet (voir l'option -o pour plus d'informations sur les fichiers objet). Le vidage d'un fichier bibliothèque affiche
les informations propres à la bibliothèque, les fichiers objet et les enregistrements qu'ils contiennent.
L'option -li demande à TDUMP d'afficher un format court des enregistrements "impdef" lors du vidage de bibliothèques
d'importation. Vous pouvez également spécifier une chaîne de recherche à l'aide de la syntaxe suivante : -li=<chaîne>
Par exemple, la commande suivante : tdump —li=codeptr import32.lib produit la sortie suivante : Impdef:(ord)
KERNEL32.0336=ISBADCODEPTR Cette sortie montre que la fonction est exportée par un numéro ordinal dont la
valeur (décimale) est 336. En outre, la sortie affiche le nom du module et celui de la fonction.
Si vous entrez la commande suivante : tdump —li=walk import32.lib TDUMP affiche : Impdef:(name)
KERNEL32.????=HEAPWALK Il s'agit là de la sortie correspondant à une fonction exportée par nom.
3 -le Indique à TDUMP d'afficher une forme courte des enregistrements "expdef" lors du vidage des fichiers OBJ. Vous
pouvez également spécifier une chaîne de recherche à l'aide de la syntaxe suivante : -le=<chaîne>
-m Laisse les noms C++ présents dans les fichiers objets, les fichiers exécutables et les fichiers d'informations
symboliques Turbo Debugger en format "abrégé". Cette option est utile pour déterminer comment le compilateur C++
"abrège" un nom de fonction particulier et ses arguments.

222
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

o, -oc, • -o affiche le fichier sous la forme d'un fichier objet (.OBJ). L'affichage d'un fichier objet contient des descriptions
-oi, des enregistrements de commandes qui transmettent des commandes et des données au lieur, pour lui indiquer
-ox comment créer un fichier .EXE. Le format d'affichage montre chaque enregistrement et ses données associées,
enregistrement par enregistrement.
• -oc demande à TDUMP d'effectuer un test de redondance cyclique (CRC) sur chaque enregistrement rencontré.
L'affichage ne diffère de celui produit par l'option -o que si un code CRC incorrect est rencontré (la valeur CRC de
TDUMP est différente de l'octet CRC de l'enregistrement).
• -oi<id> n'inclut dans le vidage du module objet que les types d'enregistrements spécifiés. Remplacez <id> par le
nom de l'enregistrement à afficher. Par exemple, TDUMP -oiPUBDEF MYMODULE.OBJ produit un affichage de
module objet pour MYMODULE.OBJ qui n'affiche que les enregistrements PUBDEF.
Les options -ox et -oi sont utiles pour trouver les erreurs se produisant pendant la liaison. En examinant
l'orthographe et la casse des symboles EXTDEF et PUBDEF, vous pouvez résoudre de nombreux problèmes de
liaison. Par exemple, si vous recevez du lieur un message du type "symbole externe non résolu", vous pouvez
utiliser TDUMP -oiEXTDEF pour afficher les définitions externes contenues dans le module qui provoque l'erreur.
Utilisez ensuite TDUMP -oiPUBDEF sur le module contenant le symbole public pour lequel le lieur n'a pas trouvé
de correspondance.
Le commutateur -oi permet aussi de connaître les noms et tailles des segments générés dans un module particulier.
Par exemple : TDUMP -oiSEGDEF MYMODULE.OBJ affiche les noms, attributs et tailles de tous les segments de
MYMODULE.
Remarque : Pour obtenir une liste des types d'enregistrements pour -oi et -ox, utilisez les options de ligne de
commande -oi? et -ox?.

-r TDUMP affiche des données brutes.


-R TDUMP vide les tables de relogement des images au format 32 bits PE (Win32). Par défaut, ces vidages ne sont pas
présentés.
-s, Indique à TDUMP d'afficher des chaînes. Par défaut –s affiche toutes les chaînes d'un fichier donné. Vous pouvez
-su, spécifier une chaîne, ou une partie de chaîne, à l'aide de la syntaxe suivante : -s=<chaîne> Par exemple, la
-s[xx] commande : TDUMP -s=black GoGame.exe génère toutes les chaînes suivantes contenant 'black' :
56840: IDI_BLACK
81965: Capture Black
85038: black.bmp
L'argument de chaîne facultatif gère les majuscules et les minuscules. Pour spécifier plusieurs mots d'une chaîne,
utilisez les guillemets. Par exemple : TDUMP -s="game of go" GoGame.exe L'option –su est utilisée de la même
manière avec un argument de chaîne facultatif et indique à TDUMP d'afficher les chaînes de style Unix, c'est-à-dire
sans offset. Par exemple, la commande : TDUMP -su=black GoGame.exe produit la sortie suivante :
IDI_BLACK
Capture Black
black.bmp
Pour le commutateur -s[xx], xx peut être :
• # - longueur de chaîne minimale à rechercher (par défaut : 4)
• b# - Décalage début de fichier (-b# est équivalent à -sb#)
• e# - Décalage fin de fichier
3
• f - Formatage (enveloppement) des chaînes longues
• s - Recherche des chaînes en tenant compte de la casse (par défaut : non)
• u - Format Unix : pas de décalage (ou décalages décimaux, -h pour hexadécimal)
• =x - Chaîne recherchée = x

223
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

-um Affiche les noms substantypés comme non substantypés. Vous n'avez pas besoin de reformater le texte pour n'éditer
que les noms substantypés avant d'utiliser cette option. Vous pouvez transmettre une sortie présentant des noms
substantypés n'importe où dans le texte, et seuls les noms substantypés seront affectés.
-v Affichage détaillé. Si elle est utilisée avec un fichier .OBJ ou .LIB, TDUMP produit un vidage hexadécimal du contenu
de l'enregistrement sans générer de commentaires sur les enregistrements.
Si TDUMP est utilisé sur une table de symboles Turbo Debugger, elle affiche les tables d'informations dans l'ordre
dans lequel elle les rencontre. TDUMP ne combine pas les informations de plusieurs tables, pour fournir un affichage
plus significatif par module.
-x Spécifie les tables de débogage à exclure.

3.1.1.22 TLIB.EXE, le gestionnaire de bibliothèques


TLIB est un utilitaire qui gère les bibliothèques de fichiers .OBJ (modules objet). Une bibliothèque permet de manipuler
facilement un collection de modules objet comme une unité.

Les bibliothèques fournies avec le compilateur CodeGear C++ ont été construites avec TLIB. Vous pouvez utiliser TLIB pour
construire vos propres bibliothèques ou pour modifier les bibliothèques CodeGear C++, vos bibliothèques, les bibliothèques
fournies par d'autres programmeurs ou des bibliothèques que vous avez achetées.

Quand TLIB modifie une bibliothèque existante, TLIB crée une copie de la bibliothèque d'origine et lui attribue l'extension .BAK.

Vous pouvez utiliser TLIB pour :

• Créer une nouvelle bibliothèque à partir d'un groupe de modules objet.


• Ajouter des modules objet ou d'autres bibliothèques à une bibliothèque existante.
• Retirer des modules objet d'une bibliothèque existante.
• Remplacer des modules objet d'une bibliothèque existante.
• Extraire des modules objet d'une bibliothèque existante.
• Lister le contenu d'une nouvelle bibliothèque ou d'une bibliothèque existante.
TLIB peut également créer (et inclure dans le fichier de bibliothèque) un dictionnaire étendu qui pourra être utilisé pour accélérer
la liaison.
Bien que TLIB ne soit pas essentiel pour la création de programmes exécutables avec le compilateur CodeGear C++, il s'agit
d'un outil de productivité en programmation qui est utile et peut même devenir indispensable pour les projets de
développement importants.
Syntaxe de la ligne de commande
TLIB <nombiblio> [<options>] [<opérations>] [@<fichrép>] [, <fichliste>]

Pour afficher l'aide de la ligne de commande, entrez :


tlib

Elément Description
<nombiblio> Le chemin DOS de la bibliothèque à créer ou à gérer. Chaque commande TLIB doit être accompagnée d'un
nom de bibliothèque. Les caractères génériques ne sont pas autorisés. Si aucune extension n'est spécifiée,
TLIB utilise l'extension .LIB. Il faut utiliser uniquement l'extension .LIB, car BCC32 et l'environnement de
développement intégré ont tous deux besoin de cette extension pour reconnaître les fichiers de bibliothèques.
Remarque : Si, dans le cas d'opérations d'ajout, la bibliothèque désignée n'existe pas, TLIB la crée.

224
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

<options> Reportez-vous à l'en-tête suivant immédiatement ce tableau pour obtenir des détails sur TLIB <options>.
<opérations> Décrit les actions de TLIB et est composée d'une séquence de codes d'opération sur deux caractères. Pour de
plus amples informations, voir l'en-tête ci-après dans cette rubrique.
@<fichrép> Le chemin et le nom du fichier de réponse à inclure. Vous pouvez spécifier plusieurs fichiers de réponse. Pour
de plus amples informations, voir l'en-tête ci-après dans cette rubrique.
<fichliste> Le nom du fichier texte produit par TLIB et listant le contenu de la bibliothèque. Le nom du fichier de listage (s'il
est spécifié) doit être précédé d'une virgule. Aucun listage n'est produit si vous ne spécifiez pas de nom de
fichier. Le listage est une liste alphabétique de chaque module. L'entrée de chaque module contient une liste
alphabétique de tous les symboles publics définis dans ce module. L'extension par défaut pour le fichier de
listage est .LST.

Options de la commande TLIB


TLIB reconnaît trois <options> :

• /C (sensible à la casse)
• /P (taille de page)
• /0 (zéro ; purger les enregistrements de commentaire)

Option /C de TLIB : Utilisation de symboles sensibles à la casse dans une bibliothèque


Quand vous ajoutez un module à une bibliothèque, TLIB maintient un dictionnaire de tous les symboles publics définis dans les
modules de la bibliothèque. Tous les symboles de la bibliothèque doivent être différents. Si vous tentez d'ajouter à la
bibliothèque un module qui porte le même nom qu'un symbole, TLIB affiche un message d'erreur et n'ajoute pas ce module.

Normalement, quand TLIB vérifie l'absence de symboles en double dans la bibliothèque, les lettres majuscules et minuscules ne
sont pas traitées différemment (les symboles lookup et LOOKUP, par exemple, sont traités comme des symboles en double).
Vous pouvez utiliser l'option /C pour ajouter à une bibliothèque un module incluant des symboles ne différant que par la casse.

N'utilisez pas /C si vous prévoyez d'utiliser la bibliothèque avec d'autres lieurs ou de permettre à d'autres personnes d'utiliser la
bibliothèque.

TLIB rejette normalement les symboles qui ne diffèrent que par la casse, car certains lieurs ne sont pas sensibles à la casse.
ILINK32 peut parfaitement distinguer les symboles en majuscules des symboles en minuscules. Si vous n'utilisez votre
bibliothèque qu'avec ILINK32, vous pouvez utiliser l'option /C de TLIB sans aucun problème.

Option /P de TLIB : Définition de la taille de page pour créer une bibliothèque plus grande
La taille de page de la bibliothèque détermine la taille maximale combinée de tous les modules objet de la bibliothèque qui ne
peut excéder 65 536 pages. La taille de page par défaut (c'est la valeur minimum autorisée) de 16 octets permet donc une
bibliothèque d'environ 1 Mo. Pour créer une bibliothèque plus grande, utilisez l'option /P pour accroître la taille de page. La taille
de page doit être une puissance de 2 et ne doit pas être inférieure à 16 ni supérieure à 32 768.

Tous les modules de la bibliothèque doivent commencer sur une limite de page. Par exemple, dans une bibliothèque dont la
taille de page est 32 (c'est-à-dire la taille de page immédiatement supérieure à la valeur par défaut 16), 16 octets environ par
module objet sont perdus dans le remplissage. Si vous tentez de créer une bibliothèque trop grande pour la taille de page 3
spécifiée, TLIB affiche un message d'erreur et suggère d'utiliser l'option /P avec la taille de page immédiatement supérieure.

TLIB, liste d'opérations


La liste d'opérations décrit les actions à faire exécuter par TLIB et se compose d'une suite d'opérations données l'une après
l'autre. Chaque opération est définie par un symbole d'action sur un ou deux caractères suivi d'un nom de fichier ou de module.

Vous pouvez insérer des espaces blancs avant ou après un symbole d'action ou un nom de fichier ou de module, mais pas au
milieu d'un symbole d'action sur deux caractères ou au milieu d'un nom. Vous pouvez spécifier autant d'opérations que vous le

225
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

souhaitez sur la ligne de commande, dans la limite (imposée par COMMAND.COM du DOS) d'une longueur de ligne de
127 caractères. L'ordre des opérations n'a pas d'importance. TLIB effectue toujours les opérations dans le même ordre :

Pour remplacer un module, le retirer, puis ajouter le module de remplacement.

1. Toutes les opérations d'extraction sont effectuées en premier.


2. Toutes les opérations de suppression sont effectuées ensuite.
3. Toutes les opérations d'ajout sont effectuées en dernier.
TLIB trouve le nom d'un module en retirant les informations d'unité, de chemin et d'extension éventuellement présentes dans le
nom du fichier.
Notez que TLIB adopte toujours des valeurs par défaut raisonnables. Par exemple, pour ajouter un module d'extension .OBJ au
répertoire en cours, vous n'avez besoin de spécifier que le nom du module et non le chemin et l'extension .OBJ.
Les caractères génériques ne sont jamais acceptés dans les noms de fichiers ou de modules.
TLIB reconnaît trois symboles d'action (*, +, -), que vous pouvez utiliser séparément ou par paires pour un total de cinq
opérations distinctes. L'ordre des caractères n'est pas important pour les opérations utilisant une paire de caractères.
Pour créer une bibliothèque, ajoutez des modules à une bibliothèque qui n'existe pas encore.
Symboles d'actions TLIB

Symbole Nom Description


+ Ajouter TLIB ajoute le fichier nommé à la bibliothèque. Si le fichier ne possède pas d'extension, TLIB utilise
l'extension .OBJ. Si le fichier est lui-même une bibliothèque (d'extension .LIB), l'opération ajoute tous
les modules de la bibliothèque nommée à la bibliothèque cible.
Si un module en cours d'ajout existe déjà, TLIB affiche un message et n'ajoute pas ce nouveau
module.
— Retirer TLIB retire le module nommé de la bibliothèque. Si le module n'existe pas dans la bibliothèque, TLIB
affiche un message.
Une opération de suppression ne nécessite qu'un nom de module. TLIB permet d'entrer un nom
complet avec unité, chemin et extension, mais ne prend en compte que le nom de module.
+ Extraction TLIB crée le fichier nommé en copiant le module correspondant de la bibliothèque vers le fichier. Si le
module n'existe pas, TLIB affiche un message et ne crée pas le fichier. Si le fichier nommé existe
déjà, il est remplacé.
Il n'est pas possible de renommer directement des modules dans une bibliothèque. Pour renommer
un module, il faut l'extraire et le retirer, renommer le fichier qui vient d'être créé puis le réintroduire
dans la bibliothèque.
—* or *- Extraction et TLIB copie le module nommé de la bibliothèque dans le fichier. Si le module n'existe pas, TLIB affiche
Suppression un message et ne crée pas le fichier. Si le fichier nommé existe déjà, il est remplacé. TLIB retire le
nom de fichier puis retire le fichier de la bibliothèque.
—+ or Remplacer TLIB remplace le module nommé par le fichier correspondant.
+-

Utilisation de fichiers de réponse TLIB


Un fichier de réponse est un fichier texte ASCII qui contient tout ou une partie d'une commande TLIB. Avec les fichiers de
3 réponse TLIB, vous pouvez construire des commandes TLIB qui ne tiennent pas sur une seule ligne de commande. Si vous
devez effectuer un grand nombre d'opérations ou plusieurs fois les mêmes opérations, les fichiers de réponse vous rendront la
tâche plus facile.

Les fichiers de réponse peuvent :

• Contenir plusieurs lignes de texte ; utilisez le caractère et commercial (&) à la fin d'une ligne pour indiquer la présence d'une
ligne suivante.
• Inclure une liste de commandes partielle. Vous pouvez combiner des options de la ligne de commande avec des options d'un

226
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande

fichier de réponse.
• Etre utilisés avec d'autres fichiers de réponse dans une ligne de commande TLIB unique. Exemples TLIB
Exemples TLIB
Ces exemples simples montrent quelques-unes des opérations qui peuvent être exécutées avec TLIB :

Exemple 1

Pour créer une bibliothèque nommée MYLIB.LIB avec les modules X.OBJ, Y.OBJ et Z.OBJ, tapez :
tlib mylib +x +y +z
Exemple 2

Pour créer une bibliothèque nommée MYLIB.LIB et obtenir également un listage dans MYLIB.LST, tapez :
tlib mylib +x +y +z, mylib.lst
Exemple 3

Pour obtenir un listage dans CS.LST d'une bibliothèque existante CS.LIB, tapez :
tlib cs, cs.lst
Exemple 4

Pour remplacer le module X.OBJ par une nouvelle copie, ajouter A.OBJ et supprimer Z.OBJ de MYLIB.LIB, tapez :
tlib mylib -+x +a -z
Exemple 5

Pour extraire le module Y.OBJ de MYLIB.LIB et obtenir un listage dans MYLIB.LST, tapez :
tlib mylib *y, mylib.lst
Exemple 6

Pour créer une nouvelle bibliothèque nommée ALPHA et comprenant les modules A.OBJ, B.OBJ, ..., G.OBJ en utilisant un
fichier de réponse :

1. Créez d'abord un fichier texte ALPHA.RSP avec : +a.obj +b.obj +c.obj & +d.obj +e.obj +f.obj & +g.obj
2. Utilisez ensuite la commande TLIB qui produit un fichier de listage nommé ALPHA.LST : tlib alpha @alpha.rsp,
alpha.lst
Exemple 7
Pour mettre à jour les modules Y.OBJ et Z.OBJ et supprimer les modules A.OBJ et B.OBJ de MYLIB.LIB :
tlib mylib /u Y.obj Z.obj /d A.obj B.obj

3.1.1.23 Utilisation de TOUCH.EXE


TOUCH.EXE met à jour la date d'un fichier afin qu'elle corresponde à la date et à l'heure en cours de votre système.

Syntaxe de la ligne de commande


3
touch [<options>] <nomfichier> [<nomfichier>...]

Si TOUCH ne trouve pas de fichier correspondant au nom que vous avez spécifié, il crée un fichier de longueur nulle avec la
date correcte. Pour supprimer la création automatique des fichiers, utilisez l'option -c.

TOUCH étant un exécutable 32 bits, il accepte les noms de fichiers longs. En plus, vous pouvez utiliser des noms de fichiers
contenant des caractères génériques tels que * et ? pour "toucher" plusieurs fichiers en même temps. Utilisez l'option -s pour
mettre à jour les fichiers correspondants dans tous les sous-répertoires.

227
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++

Avant d'utiliser TOUCH, vérifiez que l'horloge interne de votre système est juste.

Options TOUCH
TOUCH.EXE accepte plusieurs options sur la ligne de commande.

Options TOUCH

Option Description
-c Ne génère pas de fichier s'il n'existe pas déjà.
-d<mm>-<jj>-<aa> Définit la date du fichier par la date spécifiée.
-r<nomfichier> Définit la date et l'heure du fichier afin qu'il corresponde à ceux de <nomfichier>.
-h Affiche les informations d'aide (identique à taper TOUCH sans options ni noms de fichiers).
-s Opère dans les sous-répertoires.
t<hh>:<mm>:<ss>- Définit l'heure du fichier par l'heure spécifiée.
v- Mode commenté. Présente chaque fichier TOUCHé.

Voir aussi
Utilisation de MAKE ( see page 198)

3.1.1.24 TRIGRAPH
Les trigraphs sont des séquences de trois caractères qui remplacent certains caractères utilisés dans le langage C et qui ne sont
pas disponibles sur tous les claviers. Comme la conversion des trigraphs dans le compilateur ralentirait considérablement les
compilations, CodeGear C++ fournit un filtre nommé TRIGRAPH.EXE qui permet de gérer les séquences trigraph.

Syntaxe de la ligne de commande


trigraph [-u] <nomfichier> [...]

Options TRIGRAPH
TRIGRAPH a trois options de commande :

• -nXXX écrit les fichiers de sortie dans le répertoire nommé dans XXX.
• -u indique d'annuler l'insertion de trigraphs.
• -xXXX crée les fichiers de sortie avec l'extension XXX.
Le tableau suivant présente les séquences trigraph reconnues par TRIGRAPH :
Séquences de caractères TRIGRAPH
Le tableau suivant présente les séquences trigraph reconnues par TRIGRAPH :

Trigraph Caractère
??= #
3
??( [
??) ]
??/ \
??' ^
??< {
??> }

228
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

??- ~

3.1.2 Liste de tous les avertissements et erreurs du


compilateur C++
Cette section décrit les messages d'erreur et d'avertissement du compilateur C++ RAD Studio.

Rubriques
Nom Description
E2066: Héritage MOM invalide ( see page 272) Le compilateur émet cette erreur si la classe en cours de compilation n'a pas les
mêmes indicateurs MOM (Microsoft Object Model) correspondants que son
parent direct.
Ce message d'erreur de compilation est désapprouvé.
E2525: Vous devez définir _PCH_STATIC_CONST avant d'inclure xstring afin Vous avez essayé d'utiliser une fonctionnalité définie dans xstring, partie de la
d'utiliser cette fonctionnalité ( see page 272) bibliothèque Dinkumware standard C++. Le compilateur C++ ne peut pas
générer un en-tête précompilé car une constante (définie dans xstring) se trouve
dans l'en-tête. Si vous souhaitez inclure xstring, vous devez d'abord définir le
define _PCH_STATIC_CONST.
E2526: La propriété 'nom' utilise une autre propriété comme getter/setter ; non Les propriétés ont généralement un getter et un setter, mais une propriété ne
autorisé ( see page 272) peut pas servir de getter ou de setter à une autre propriété.
E2008: Les fonctions d'accès à la propriété publiée doivent utiliser la convention La convention d'appel pour les fonctions d'accès d'une propriété (lecture, écriture
d'appel __fastcall ( see page 272) et stockée) déclarée dans une section __published doit être __fastcall. Ceci vaut
également pour les propriétés surchargées.
Exemple :
E2122: L'appel de fonction s'est terminé par une exception non gérée 'valeur' à Ce message s'affiche lorsqu'une expression, que vous évaluez lors du
l'adresse 'adresse' ( see page 273) débogage, inclut un appel de fonction se terminant par une exception non gérée.
Par exemple si, dans la boîte de dialogue d'évaluation du débogueur, vous
demandez l'évaluation de l'expression foo()+1 et que l'exécution de la fonction
foo() provoque une erreur GP, cette évaluation génère le message d'erreur
ci-dessus.
Vous pouvez également voir ce message dans la fenêtre de suivi car elle affiche
également le résultat de l'évaluation d'une expression.
E2506: La spécialisation explicite de 'spécificateur' est ambiguë : des arguments Dans le code suivant, des arguments modèles explicites sont nécessaires :
modèles doivent être spécifiés ( see page 273)
E2483: La dimension du tableau 'spécificateur' n'a pas pu être déterminée ( Cette erreur se produira si, lors de l'instanciation d'un type, une dimension de
see page 273) tableau ne peut pas être calculée (ceci est normalement dû à une autre erreur
qui doit être indiquée).
Par exemple, si une dimension de tableau dépend d'un paramètre de modèle
mais qu'une erreur se produit alors qu'il est analysé et que l'argument de modèle
en cours de substitution ne génère pas d'expression constante légale, cette
erreur s'affiche.
E2509: Valeur hors limites ( see page 273) L'assembleur en ligne a détecté un dépassement numérique dans une de vos
expressions. Vérifiez que tous vos nombres peuvent tenir dans 32 bits.
E2510: Non concordance de taille d'opérande ( see page 273) L'aide n'est pas disponible pour cet élément.
E2050: La classe __declspec(delphireturn) 'classe' doit avoir exactement une Il s'agit d'une erreur interne du compilateur. Une classe marquée comme
donnée membre ( see page 273) delphireturn comporte plusieurs données membre non statiques.
E2530: Option non reconnue ou aide indisponible ( see page 274) Vous avez entré un élément de commande que le compilateur C++ ne peut pas
analyser, ou l'option entrée ne dispose pas d'une aide associée. Effectuez une
nouvelle tentative.
E2527: L'option 'nom' ne peut pas être définie via 'nom' ( see page 274) Une tentative de définition d'une option a été effectuée dans un fichier source 3
alors que cette option ne peut pas être définie après le démarrage de l'analyse
ou de la compilation du fichier. Définissez plutôt cette option sur la ligne de
commande ou dans un fichier .cfg.
Par exemple, si un fichier source contient un #pragma option push —v, vous
devez retirer le push ou définir /unset sur la ligne de commande ou dans un
fichier .cfg.
E2528: L'option 'nom' doit être définie avant la compilation ( see page 274) Une tentative de définition d'une option a été effectuée dans un fichier source
alors que cette option doit être définie avant le démarrage de la compilation.
Définissez plutôt cette option sur la ligne de commande, dans un fichier .cfg ou
au début du fichier source avant la ligne int foo(); .

229
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2074: La valeur après -g ou -j doit être comprise entre 0 et 255 inclus ( see Les options -g et -j de la ligne de commande peuvent être suivies par un nombre
page 274) facultatif. Le compilateur attend que ce nombre soit compris entre 0 et 255 inclus.
E2492: Les propriétés peuvent uniquement être affectées en utilisant une Les affectations de propriétés doivent être effectuées dans des instructions
instruction simple, par exemple \"prop = valeur;\" ( see page 274) d'affectation simples. Si les affectations de propriétés pouvaient devenir des
Lvalues, ce qui arrive lorsque les affectations de propriétés sont imbriquées dans
des instructions plus grandes, le getter est appelé pour créer la Lvalue, avec tous
les effets de bord causés par le getter. Le compilateur n'autorise qu'un appel soit
au getter soit au setter dans une instruction.
Par exemple :
E2505: L'instanciation explicite requiert un spécificateur de type élaboré (par Le code suivant est incorrect :
exemple, "class foo<int>") ( see page 275)
E2100: Liste de déclarateurs de modèles incorrecte ( see page 275) Une liste de déclarateurs ne doit pas suivre de déclaration de classe modèle. Par
exemple :
E2102: Impossible d'utiliser le modèle 'modèle' sans spécifier des paramètres de Le format générique d'un modèle doit être référencé en utilisant des paramètres
spécialisation ( see page 275) de spécialisation. Par exemple, pour une classe modèle nommée foo utilisant
deux paramètres modèle, une référence correcte se présenterait ainsi :
E2107: Utilisation incorrecte du modèle 'modèle' ( see page 275) Cette erreur se produit si vous tentez d'utiliser un paramètre du modèle 'modèle'
pour autre chose que pour faire référence à une spécialisation de modèle ou
pour transmettre ce paramètre comme argument du modèle 'modèle' à un autre
modèle. Par exemple :
E2105: Le qualificateur 'modèle' doit spécifier un nom de modèle membre ( see Lors de l'analyse du code qui dépend d'une certaine manière d'un paramètre de
page 276) modèle, il est parfois impossible de savoir si un nom de membre résoudra un
nom de fonction modèle ou un paramètre normal. Dans le code suivant, un
qualificateur 'modèle' est nécessaire pour savoir si l'opérateur ‘<’ (inférieur à) doit
être analysé comme caractère de début d'une liste d'arguments modèle ou
comme opérateur "inférieur à" normal :
E2066: Information non disponible ( see page 276) L'aide n'est pas disponible pour cet élément.
E2471: pragma checkoption a échoué : les options ne sont pas celles attendues Vous pouvez utiliser #pragma checkoption pour vérifier que certains
( see page 276) commutateurs sont dans l'état attendu. Si #pragma checkoption détecte qu'un
commutateur n'est pas dans l'état attendu, le compilateur affiche cette erreur.
Vous pouvez utiliser la syntaxe suivante :
E2504: 'dynamic' ne peut être utilisé qu'avec des fonctions membre non modèle Vous avez essayé d'utiliser dynamic avec une fonction membre modèle. Les
( see page 277) fonctions dynamiques sont autorisées pour les classes dérivées de TObject. Les
fonctions dynamiques occupent un emplacement dans chaque objet qui les
définit, pas dans les descendants. En d'autres termes, les fonctions dynamiques
sont des fonctions virtuelles stockées dans des tables virtuelles éparses. Si vous
appelez une fonction dynamique qui n'est pas définie dans votre objet, les tables
virtuelles de ses ancêtres sont parcourues jusqu'à ce que la fonction soit trouvée.
E2191: '__far16' ne peut être utilisé qu'avec '__pascal' ou '__cdecl' ( see page Il s'agit d'une erreur interne du compilateur. Le compilateur émet ce message si
277) le mot clé __far16 est mélangé avec un des mots clés __pascal ou __cdecl, tous
dans la même déclaration.
E2199: La fonction amie modèle 'fonction' doit être préalablement déclarée ( Inutilisé.
see page 277)
E2502: Erreur de résolution de #import : problème ( see page 277) Où problème peut concerner l'un des problèmes suivants relatifs aux différents
attributs de #include ( see page 698) :
attribut ‘attribut’ de valeur de directive d'importation non attendu. Une valeur a
été fournie pour l'attribut indiqué. Aucune n'était attendue.
')' manquante dans l'attribut 'attribut' de la directive d'importation. La valeur de
l'attribut indiqué a été incorrectement spécifiée : une parenthèse fermante est
manquante.
attribut 'attribut' de la directive de compilation non reconnu. Le token indiqué
n'est pas un attribut légitime pour la directive #import.
valeurs incorrectes pour l'attribut raw_property_prefixes. Les valeurs de l'attribut
raw_property_prefixes ont été incorrectement spécifiées.
propriété 'propriété' en double non attendue.... suite ( see page 277)
E2501: Impossible d'ouvrir le fichier d'importation 'nom_fichier' ( see page 278) Cette erreur se produit lorsque vous utilisez :
E2494: Modificateur __declspec non reconnu ( see page 278) Un modificateur __declspec non valide a été fourni.
3 E2493: Chaîne GUID incorrecte ( see page 278) La chaîne GUID n'a pas la forme d'un GUI (Globally Unique Identifier,
identificateur globalement unique).
E2499: Format __declspec(uuid(GuidString)) non valide ( see page 278) Cette erreur se produit lorsque vous avez utilisé un format incorrect pour définir
votre chaîne de GUID (GuidString). Les GUID sont définis pour les structures de
la façon suivante :
E2496: Appel non valide à uuidof(struct type|variable) ( see page 278) L'opérateur uuidof a reçu un argument incorrect.
E2511: Argument de macro non terminé ( see page 278) Un argument de macro démarré sur la ligne indiquée n'a pas été correctement
terminé.
E2489: Profondeur maximum de répétitions d'options dépassée ; vérifiez la Si cette erreur est déclenchée, cela signifie que l'instanciation récursive de
récursivité ( see page 279) modèle est trop profonde. Vérifiez la récursivité au moment de la compilation
dans votre programme et limitez-la à 256 niveaux maximum.

230
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2488: Profondeur maximum de réponse dépassée ; vérifiez la récursivité ( Si cette erreur est déclenchée, cela signifie que l'instanciation récursive de
see page 279) modèle est trop profonde. Vérifiez la récursivité au moment de la compilation
dans votre programme et limitez-la à 256 niveaux maximum.
E2491: Compte VIRDEF maximum dépassé ; vérifiez la récursivité ( see page Trop de symboles VIRDEF ont été alloués. Le compilateur impose une limite au
279) nombre de VIRDEF autorisés par unité de traduction. Cette limite est
actuellement de l'ordre de 16 384 VIRDEF.
Ceci peut se produire si un programme a plus de 16 384 fonctions.
E2230: L'initialisation de données membre en ligne nécessite une expression Les membres de classes const statiques, initialisés dans le corps de la classe,
constante intégrale ( see page 279) doivent être initialisés avec une expression constante de type intégral.
E2241: Les classes de style VCL ont besoin de destructeurs virtuels ( see Les destructeurs définis dans des classes VCL doivent être virtuels.
page 279) Exemple :
E2524: Les unions/structs anonymes ne sont pas autorisées à avoir des Le compilateur C++ nécessite que les membres d'une union ou struct anonyme
membres anonymes en C++ ( see page 280) soient nommés.
E2246: x n'est pas une hiérarchie de classes d'héritage simples, publiques, Erreur interne du compilateur. Dans certains cas, le compilateur impose des
abstraites sans données ( see page 280) restrictions sur une hiérarchie de classes. Dans ce cas, toutes les classes sont
des classes abstraites et n'ont qu'un seul parent.
E2249: = attendu ( see page 280) Le compilateur attendait le signe égal à l'endroit où l'erreur a été signalée. Il
s'agit en général d'une erreur de syntaxe ou d'une faute de frappe.
E2267: La première base doit être une classe VCL ( see page 280) Erreur interne du compilateur. Dans certains cas, le compilateur impose des
restrictions sur une hiérarchie de classes. Dans ce cas, le premier parent d'une
classe est une classe de style Delphi.
E2472: Impossible de déclarer une fonction membre via une instanciation ( see Le programme est mal formé si une déclaration, dans une classe modèle,
page 280) acquiert un type de fonction via un type dépendant d'un paramètre modèle et que
ceci entraîne une déclaration n'utilisant pas le format syntaxique d'un déclarateur
de fonction pour obtenir le type de fonction. Par exemple :
E2515: Impossible de spécialiser explicitement un membre d'une classe modèle Vous essayez de transformer un modèle générique en membre spécialisé. Par
générique ( see page 281) exemple, le code suivant est incorrect :
E2474: 'fonction' ne peut pas être déclarée comme static ou inline ( see page Vous avez essayé de déclarer un symbole comme static ou inline et ce type de
281) symbole ne peut pas être défini de la sorte. Certaines fonctions, telles que 'main'
et 'WinMain' ne peuvent pas être déclarées static ou inline. 'main' est le point
d'entrée d'applications console et 'WinMain' celui d'applications Windows.
Par exemple, cette erreur s'affiche dans les cas suivants :
E2498: Définition préalable de la structure du GUID requise ( see page 281) Cela se produit lorsque vous utilisez l'opérateur __uuidof sans inclure d'en-tête
définissant la structure du GUID. Ainsi, le code suivant affiche cette erreur :
E2295: Trop de spécialisations de modèle candidat depuis 'spécificateur' ( see Lors du référencement d'une spécialisation de modèle de classe, il se peut
page 282) qu'une même référence génère plusieurs candidats possibles. Ceci ne peut
réellement arriver que dans des spécialisations de classe partielles, lorsque
plusieurs spécialisations partielles sont en compétition pour une correspondance
possible :
E2475: 'fonction' ne peut pas être une fonction modèle ( see page 282) Certaines fonctions, telles que 'main' et 'WinMain' ne peuvent pas être déclarées
comme fonction modèle. 'main' est le point d'entrée d'applications console et
'WinMain' celui d'applications Windows.
Par exemple :
E2299: Impossible de créer une spécialisation de modèle à partir de Cette erreur se produit si vous essayez de référencer une fonction ou une classe
'spécificateur' ( see page 282) modèle de manière à ce que ne se produise aucune spécialisation de candidat
possible. Par exemple :
E2300: Impossible de générer un type correspondant de spécialisation pour Cette erreur n'est plus générée par le compilateur.
'spécificateur' ( see page 282)
E2497: Aucun GUID associé au type 'type' ( see page 282) Une variable ou un type a été utilisé dans un contexte nécessitant un GUID, mais
aucun GUID n'est associé au type. Les GUID sont associés aux types à l'aide de
__declspec(uuid(GUID)).
E2522: Fonction non const 'fonction' appelée pour un objet const ( see page La différence du type de données conduit à un appel de fonction erroné. L'objet
283) de l'appel (une fonction non-const) doit être un objet const.
E2523: Fonction non volatile 'nom' appelée pour un objet volatile ( see page Non concordance du type de données. L'erreur est le résultat d'un appel de
283) fonction erroné. L'objet de l'appel (une fonction non-volatile) doit être un objet
volatile.
E2513: Impossible d'émettre des informations RTTI pour 'paramètre' dans Le compilateur émet ce message d'erreur s'il ne parvient pas à générer des 3
'fonction' ( see page 283) informations RTTI pour le type de retour d'un paramètre. Voir Informations de
types à l'exécution pour plus d'informations.
E2512: Impossible d'émettre des informations RTTI pour le type renvoyé par Le compilateur émet ce message d'erreur s'il ne parvient pas à générer des
'fonction' ( see page 283) informations RTTI pour le type de retour d'une fonction. Voir Informations de
types à l'exécution pour plus d'informations.
E2507: 'classe' n'est pas une classe de base directe de 'classe' ( see page 283) Le premier type n'est pas une classe de base directe du second type. Une classe
de base directe fait référence aux dérivations immédiates de cette classe, et pas
aux dérivations de ses sous-classes.

231
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2529: Le chemin 'chemin' dépasse la taille maximale 'n' ( see page 283) Lors de la recherche des fichiers d'inclusion, le compilateur C++ a rencontré un
fichier dont le nom de chemin contient un nombre de caractères supérieur au
nombre de caractères maximal de Windows. Réduisez le nom du chemin.
E2495: Redéfinition de uuid non identique ( see page 283) Les GUID attachés aux structures doivent être les mêmes sur plusieurs
déclarations et définitions de la même structure. Ainsi, l'exemple suivant génère
cette erreur :
E2500: __declspec(selectany) ne s'adresse qu'aux variables initialisées et Vous ne pouvez pas utiliser __declspec(selectany) avec des variables statiques,
visibles de façon externe ( see page 284) non initialisées, etc.
E2482: Constante chaîne attendue ( see page 284) Le compilateur attendait une constante chaîne à cet emplacement, mais n'en a
pas reçu.
Cette erreur n'est plus générée par le compilateur.
E2481: Constante chaîne inattendue ( see page 284) Il y a des fois où le compilateur n'attend pas l'apparition de constante chaîne
dans l'entrée source. Par exemple :
E2386: Impossible d'impliquer le paramètre 'paramètre' dans une expression de Lors de la déclaration ou de la définition d'une spécialisation partielle de classe
spécialisation partielle complexe ( see page 284) modèle, il est incorrect d'impliquer des paramètres qui ne sont pas de type
template dans des expressions complexes. Ils ne peuvent être référencés que
par nom. Par exemple :
E2387: Les spécialisations partielles ne peuvent pas spécialiser les paramètres Une spécialisation partielle ne peut pas utiliser de paramètre modèle dans sa
dépendants non-typés ('paramètre') ( see page 284) liste d'arguments de spécialisation qui dépend d'un autre paramètre de type. Par
exemple :
E2388: La liste d'arguments de spécialisation ne peut pas être identique à la liste Lors de la déclaration d'une spécialisation partielle, sa liste d'arguments de
de paramètres de modèle primaire ( see page 284) spécialisation doit être différente de sa liste de paramètres de base. Par
exemple :
template<class T>
E2389: Non concordance dans le type d'argument de substitution et le paramètre Lors de la référenciation d'une spécialisation de modèle, tous les paramètres de
modèle 'paramètre' ( see page 285) type doivent être satisfaits en utilisant les arguments type, tous les paramètres
non type nécessitent des arguments non type et tous les paramètres modèles
template nécessitent soit un nom de modèle, soit un autre argument de modèle
template. La non concordance de ces besoins de quelque manière que ce soit
déclenchera l'erreur ci-dessus. Par exemple :
E2480: Impossible d'impliquer des paramètres de modèle dans les arguments de Une spécialisation partielle ne peut pas faire référence à d'autres paramètres de
spécialisation partielle complexe ( see page 285) modèle dans une expression d'argument sans valeur, sauf si elle est simplement
une référence directe au paramètre de modèle. Par exemple :
E2392: L'instance du modèle 'template' est déjà instanciée ( see page 285) Il y a deux façons de déclencher cette erreur. Si –A est activée (mode compatible
ANSI), alors la tentative d'instanciation explicite d'une spécialisation de modèle
qui a déjà été instanciée (soit implicitement, soit explicitement) provoquera cette
erreur. Indépendamment de –A, la tentative de spécialisation explicite d'une
spécialisation de modèle ayant déjà été instanciée (soit implicitement, soit
explicitement) déclenchera toujours cette erreur. Par exemple :
E2393: Impossible de prendre l'adresse du paramètre modèle non-typé, Un paramètre modèle n'a pas d'adresse et n'est associé à aucun “objet” réel. Par
non-référencé 'paramètre' ( see page 286) conséquent, prendre son adresse ou essayer de lui affecter une adresse, n'a
aucun sens. Par exemple :
E2399: Impossible de référencer de cette façon l'argument 'arg' du modèle dans Le compilateur ne génère plus cette erreur.
la classe modèle 'classe' ( see page 286)
E2397: L'argument du modèle ne peut pas avoir une liaison statique ou locale ( Seules les expressions constantes entières et l'adresse des variables globales
see page 286) avec un lien externe peuvent être utilisées comme arguments modèles. Par
exemple :
E2485: Impossible d'utiliser l'élément adresse de tableau comme un argument de Les arguments de modèle non-typés ne peuvent être que de type entier ou
modèle non typé ( see page 286) l'adresse d'une variable globale. Ils ne peuvent pas représenter l'adresse d'un
élément tableau. Par exemple :
E2402: Type de classe de base incorrect : type formel 'type' résolu en 'type' ( Lors de l'instanciation d'une définition de classe modèle, cette erreur se produira
see page 286) si une classe de base déclarée ne se résout pas en type de classe accessible.
Par exemple :
E2403: Le spécificateur d'appel dépendant produit une non-fonction 'nom' ( Le compilateur ne génère plus cette erreur.
see page 287)
E2404: Le qualificateur de type dépendant 'qualificateur' n'a aucun type membre Si une déclaration modèle référence un membre d'un type dépendant, le seul
nommé 'nom' ( see page 287) choix possible est d'alerter l'utilisateur de la non existence de ce membre
3 pendant l'instanciation de type pour un ensemble donné d'arguments modèles.
Par exemple :
E2405: La référence de modèle dépendante 'identificateur' fournit un symbole Si une référence de spécialisation modèle à l'intérieur d'une déclaration de
non modèle ( see page 287) modèle produit une référence à un non modèle pendant l'instanciation de type,
l'erreur ci-dessus apparaîtra. Par exemple :
E2406: Le qualificateur de type dépendant 'qualificateur' n'est pas un type class Si une référence de nom dépendant, dans une déclaration de modèle, a pour
ou struct ( see page 287) résultat une qualification de membre non-structure au moment de l'instanciation,
l'erreur ci-dessus se produit. Par exemple :

232
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2407: Le qualificateur de type dépendant 'qualificateur' n'a aucun symbole Si une déclaration modèle référence un membre d'un type dépendant, le seul
membre nommé 'nom' ( see page 288) choix possible est d'alerter l'utilisateur de la non existence de ce membre
pendant l'instanciation de type pour un ensemble donné d'arguments modèles.
Par exemple :
E2408: Les valeurs par défaut doivent être spécifiées seulement dans les Les fonctions modèles et les spécialisations partielles de classe ne peuvent pas
déclarations de modèle de classe primaire ( see page 288) utiliser les expressions par défaut dans leurs listes de paramètres modèles.
Seules les déclarations de modèles primaires peuvent faire cela. Par exemple :
E2409: Impossible de trouver une spécialisation correcte pour 'spécificateur' ( Cette erreur n'est plus générée par le compilateur.
see page 288)
E2410: Paramètres de modèle manquants pour le modèle ami 'modèle' ( see Cette erreur se produira si un modèle ami est déclaré, mais qu'aucun paramètre
page 288) de modèle n'est spécifié. Par exemple :
E2486: Impossible d'utiliser l'adresse du membre de classe comme un argument Les arguments de modèle non-typés ne peuvent être que de type entier ou
de modèle non typé ( see page 288) l'adresse d'une variable globale. Ils ne peuvent pas être l'adresse d'un membre
de classe. Par exemple :
E2411: La déclaration des paramètres par défaut d'une fonction membre après Si une fonction membre d'un modèle de classe est déclarée, puis qu'une
une spécialisation a déjà été développée ( see page 289) spécialisation de cette classe est implicitement instanciée et enfin que cette
fonction membre est définie avec les paramètres spécifiés par défaut, l'erreur
ci-dessus se produira. Par exemple :
E2412: Tentative de lier une référence membre à un type dépendant ( see Le compilateur ne génère plus cette erreur.
page 289)
E2414: Les destructeurs ne peuvent pas être déclarés comme fonctions modèles Les destructeurs ne peuvent pas être des modèles. Par exemple :
( see page 289)
E2473: Spécialisation explicite de 'spécificateur' incorrecte ( see page 289) La tentative de spécialisation explicite d'une donnée membre statique ou de
toute donnée non modèle provoquera cette erreur.
E2490: Spécialisation dans des classes modèle non encore implémentées ( La spécialisation explicite et partielle de classes et de fonctions membres
see page 289) modèles, dans des classes modèles et des classes modèles imbriquées, n'est
pas supportée.
E2416: Déclaration de fonction modèle incorrecte ( see page 290) Le compilateur ne génère plus cette erreur.
E2417: Impossible de spécifier des paramètres de modèle dans la spécialisation Le compilateur ne génère plus cette erreur.
explicite de 'spécificateur' ( see page 290)
E2418: Profondeur d'instanciation maximum dépassée ; vérifiez la récursivité ( Le compilateur ne supporte que 256 niveaux d'instanciation avant de déclencher
see page 290) cette erreur. Le problème principal est le contrôle de la profondeur de la pile, car
l'analyseur utilise des fonctions récursives pour gérer l'instanciation de type. Voici
un exemple de ce qui pourrait produire une telle erreur :
E2420: Une instanciation explicite ne peut être utilisée que sur l'étendue globale Une instanciation explicite ne peut être spécifiée à aucun autre niveau que celui
( see page 290) de l'étendue globale ou de l'espace de nommage. Par exemple :
E2422: Le type d'argument ne correspond pas dans la redéclaration du Cette erreur se produit si un modèle est déclaré à un point de l'unité de
paramètre modèle 'paramètre' ( see page 290) traduction puis redéclaré avec des paramètres de modèle d'un type différent à un
autre emplacement. Par exemple :
E2423: Spécialisation ou instanciation explicite d'un modèle non existant La tentative de spécialisation ou d'instanciation explicite d'un modèle qui n'existe
'modèle' ( see page 291) pas est incorrecte. Par exemple :
E2479: Impossible d'avoir à la fois une classe modèle et une fonction appelée Aucune autre fonction ou aucun autre type ne peut avoir le même nom qu'une
'nom' ( see page 291) classe modèle. Par exemple :
E2484: Le nom de la classe modèle 'classe' ne peut pas être surchargé ( see La tentative de déclaration d'une fonction écrasant le nom d'une classe modèle
page 291) provoquera cette erreur. Par exemple :
E2426: La spécialisation explicite de 'spécificateur' nécessite une déclaration Selon le standard, une spécialisation explicite de n'importe quel modèle
'template<>' ( see page 291) nécessite toujours désormais la syntaxe de déclarateur “template<>”. Par
exemple :
E2487: Impossible de spécifier des arguments de fonction par défaut pour des Une spécialisation explicite d'une fonction ne peut pas déclarer d'arguments de
spécialisations explicites ( see page 291) fonction par défaut. Par exemple :
E2427: 'main' ne peut pas être une fonction modèle ( see page 292) 'main' ne peut pas être déclarée comme fonction modèle. 'main' est le point
d'entrée d'une application console, et doit être déclarée en fonction __cdecl
normale.
Ce message d'erreur ne doit pas se produire car il a été remplacé par un autre
message (E2475).
E2429: Ce n'est pas une spécialisation partielle correcte de 'spécificateur' ( see Erreur interne du compilateur.
page 292) 3
E2430: Le nombre de paramètres de modèles ne correspond pas dans la Cette erreur se produira si un modèle est redéclaré avec un nombre différent de
redéclaration de 'spécificateur' ( see page 292) paramètres de modèle. Par exemple :
E2477: Trop peu de paramètres de modèle ont été déclarés pour le modèle Cette erreur se produira si une déclaration, ou une définition, de membre se
'modèle' ( see page 292) produit hors d'une classe modèle et que cette déclaration externe utilise un
nombre de paramètres de modèle différent de celui de la classe parent. Par
exemple :
E2478: Trop de paramètres de modèle ont été déclarés pour le modèle 'modèle' Cette erreur se produira si une déclaration, ou une définition, de membre se
( see page 292) produit hors d'une classe modèle et que cette déclaration externe utilise un
nombre de paramètres de modèle différent de celui de la classe parent. Par
exemple :

233
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2431: Les paramètres de modèle non-typé ne peuvent pas être de type virgule Les paramètres de modèle non-typé sont restreints aux types qu'ils peuvent
flottante, classe ou void ( see page 293) prendre. Les types virgule flottante, classe et void sont incorrects. Par exemple :
E2434: Les paramètres de modèle manquent dans la déclaration de modèle Dans un contexte où au moins un paramètre de modèle est clairement requis, si
('template<...>') ( see page 293) aucun paramètre n'est trouvé, cette erreur se produira. Par exemple :
E2435: Trop d'ensembles de paramètres de modèles ont été spécifiés ( see Cette erreur se produira si un modèle de membre est défini hors de sa classe
page 293) parent et que trop d'ensembles de paramètres de modèles sont déclarés. Par
exemple :
E2436: Le type par défaut de l'argument modèle 'arg' ne nomme pas une classe Si un paramètre modèle template va avoir un type par défaut, ce type doit être
modèle primaire ( see page 293) soit un nom de classe modèle générique, soit un autre paramètre de modèle
template.
E2437: 'typename' doit être suivi par un nom de type dépendant qualifié ( see Dès que le mot clé "typename" est utilisé dans une déclaration ou une définition
page 293) de modèle, il doit toujours nommer un type dépendant. Par exemple :
E2438: Les arguments du modèle template doivent nommer une classe ( see Un paramètre de modèle template doit toujours déclarer le nom d'une nouvelle
page 294) classe. Par exemple :
E2439: 'typename' n'est autorisé que dans les déclarations modèle ( see page Le mot clé "typename" ne doit être utilisé que dans des déclarations et des
294) définitions de modèle.
E2440: Impossible de créer une spécialisation depuis 'spécificateur' car ce type Le compilateur ne génère plus cette erreur.
n'est pas encore défini ( see page 294)
E2441: Instanciation de 'spécificateur' ( see page 294) Dès qu'une erreur du compilateur se produit lors de l'instanciation d'un type de
modèle, le contexte de ce qui était en cours d'instanciation à ce moment là sera
rapporté à l'utilisateur, afin de faciliter la détection du problème.
E2503: Version manquante ou incorrecte de TypeLibImport.dll ( see page 294) Cette erreur se produit lorsque le compilateur essaie d'accéder au fichier
TypeLibImport.dll mais soit ne peut pas le trouver, soit est altéré, soit une
mauvaise version est installée sur votre ordinateur. Vous pouvez le réinstaller à
partir du CD du produit.
E2470: Il faut inclure l'en-tête <typeinfo> pour utiliser typeid ( see page 294) Lorsque vous utilisez la fonction 'typeid', vous devez inclure l'en-tête <typeinfo>,
sinon vous obtiendrez des erreurs de syntaxe.
Par exemple, considérez un cas test avec le code suivant :
E2514: Impossible (pour le moment) d'utiliser la résolution des surcharges de Vous tentez de surcharger un membre pendant l'instanciation du modèle. Vous
membre pendant l'instanciation de modèle ( see page 295) ne pouvez pas avoir d'appels de fonctions constantes surchargées dans des
initialiseurs de limites de tableau, par exemple.
E2508: 'using' ne peut pas faire référence à une spécialisation de modèle ( see Le mot clé using ne peut pas faire référence à une spécialisation de modèle.
page 295)
E2462: 'virtual' ne peut être utilisé qu'avec des fonctions membre non modèle ( Le mot clé 'virtual' ne peut s'appliquer qu'aux fonctions membres normales, non
see page 295) aux fonctions membres modèles.
Considérez un cas de test avec le code suivant :
W8086: Utilisation incorrecte de l'alias #pragma "NomAlias"="NomSubstitué" ( L'alias de la directive #pragma est utilisé pour indiquer au lien que deux noms
see page 295) d'identificateurs sont équivalents. Vous devez placer les deux noms entre
guillemets.
Vous obtenez cet avertissement si vous n'utilisez pas l'alias pragma
correctement. Par exemple, les deux lignes suivantes génèrent cet
avertissement :
W8099: main statique n'est pas traité comme un point d'entrée ( see page 296) La fonction main a été créée en tant que fonction statique, ce qui l'empêche
d'être utilisée en tant que point d'entrée valide.
Soit :
W8093: Utilisation incorrecte de #pragma codeseg [nom_seg] ["classe_seg"] La directive #pragma codeseg peut être utilisée pour définir ou réinitialiser le
[groupe] ( see page 296) nom, la classe ou le groupe d'un segment. Vous devez suivre exactement la
syntaxe stipulée dans le message d'avertissement, et tous les noms sont
facultatifs.
Les lignes suivantes sont toutes correctes :
W8094: Utilisation incorrecte de #pragma comment( <type> [,"chaîne"] ) ( see La directive #pragma comment peut être utilisée pour émettre des
page 296) enregistrements de commentaires de liaison.
Dans ce message, <type> peut être l'un des éléments suivants :

• user

3 • lib
• exestr
• linker
Le type doit figurer ici mais la chaîne est facultative.
W8085: Fonction 'fonction' redéfinie comme non-en ligne ( see page 296) Cet avertissement est utilisé pour indiquer qu'une certaine fonction, qui a été
déclarée en ligne dans un emplacement, est redéfinie dans un autre
emplacement comme non inline.

234
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

W8105: Membre %s '%s' dans la classe sans constructeur ( see page 297) Une classe contenant des membres constante ou des membres référence (ou
les deux) doit avoir au moins un constructeur défini par l'utilisateur.
Dans le cas contraire, il est impossible d'initialiser les membres.
W8095: Utilisation incorrecte de #pragma message( "chaîne" ) ( see page 297) Vous pouvez utiliser pragma message pour émettre un message en direction de
la ligne de commande ou de la fenêtre de message. Vous obtenez cet
avertissement si vous utilisez une syntaxe incorrecte. Ainsi
W8098: Constante caractère multicaractère ( see page 297) Cet avertissement est émis lorsque le compilateur détecte une constante entière
multicaractère, telle que :
W8096: Utilisation incorrecte de #pragma code_seg(["nom_seg"[,"classe_seg"]]) Pragma code_seg est identique à pragma codeseg, mais il vous permet de
( see page 297) modifier uniquement le nom et la classe du segment de code. Si vous utilisez la
mauvaise syntaxe, vous obtenez cet avertissement.
Les exemples suivants illustrent l'utilisation correcte :
W8083: Pragma pack pop sans pack push correspondant ( see page 297) Chaque #pragma pack(pop) doit avoir un #pragma pack(push) correspondant le
précédant dans la même unité de traduction. Des paires de 'push' et de 'pop'
peuvent être imbriquées.
Par exemple :
W8097: Toutes les options ne peuvent pas être restaurées pour l'instant ( see Votre programme présente un #pragma pop à un emplacement qui ne lui permet
page 298) pas de restaurer des options.
Par exemple :
W8084: Nous suggérons des parenthèses pour clarifier la priorité ( see page Cet avertissement indique que plusieurs opérateurs utilisés dans une expression
298) peuvent entraîner une confusion sur les règles de priorité d'opérateur
applicables. Cet avertissement permet de créer du code plus compréhensible et
potentiellement moins ambigu.
Par exemple, compilez le code suivant en utilisant l'option –w de la ligne de
commande :
W8092: L'argument 'type' 'spécificateur' transmis à 'fonction' n'est pas un Un argument qui n'est pas un itérateur est en cours d'utilisation avec un
itérateur : itérateur 'type' requis ( see page 298) algorithme STL qui requiert un itérateur.
W8087: 'opérateur::opérateur==' doit être publiquement visible pour être contenu Un type en cours d'utilisation avec un conteneur STL présente un 'opérateur=='
par un 'type' ( see page 298) privé.
W8090: 'type::opérateur<' doit être publiquement visible pour être utilisé avec Un type en cours d'utilisation avec un conteneur STL présente un
'type' ( see page 299) 'opérateur<'.privé. Le type que vous essayez d'utiliser doit devenir public.
W8089: 'type::opérateur<' doit être publiquement visible pour être contenu par un Le type en cours d'utilisation pour un conteneur STL a un 'opérateur<' privé. Le
'type' ( see page 299) type contenu (type::opérateur) doit être de type public.
Par exemple, si vous essayez d'instancier un type de classe "vecteur<blah>",
l'erreur est la suivante :
W8091: L'argument 'type' 'spécificateur' transmis à 'fonction' est un itérateur Une catégorie d'itérateur incorrecte est en cours d'utilisation avec un algorithme
'catégorie d'itérateur' : itérateur 'catégorie d'itérateur' requis ( see page 299) STL.
W8076: L'instance du modèle 'spécificateur' est déjà instanciée ( see page 299) Vous essayez d'instancier explicitement un modèle déjà instancié de façon
implicite.
Cette erreur se produit si –A n'est pas activée et qu'une tentative d'instanciation
explicite d'une spécialisation (qui a déjà été instanciée implicitement ou
explicitement) est effectuée.
W8077: La spécialisation explicite d'un membre de classe explicitement Erreur interne. Cet avertissement n'est plus généré par le compilateur.
spécialisé n'a pas de sens ( see page 299) Le code suivant est incorrect :
Messages d'information ( see page 299) Le compilateur affiche les informations d'état pendant la compilation si vous avez
coché "Afficher les messages généraux" sur la page Compilateur de la boîte de
dialogue Options du projet. La plupart des messages se comprennent
d'eux-mêmes et fournissent des informations sur la compilation et la liaison, par
exemple :
E2196: Impossible de prendre l'adresse de la fonction membre 'fonction' ( see Une expression prend l'adresse d'une fonction membre de classe, mais cette
page 300) fonction membre est introuvable dans le programme en cours de débogage. Ce
message est affiché par l'évaluateur.
F1002: Impossible de créer le fichier de sortie 'nomfichier' ( see page 300) Cette erreur se produit si le disque de travail est plein ou protégé en écriture.
Elle se produit également si le répertoire de sortie n'existe pas.
Solutions
Si le disque est plein, supprimez des fichiers et relancez la compilation.
Si le disque est protégé en écriture, placez les fichiers source sur un autre disque 3
accessible en écriture et relancez la compilation.
F1003: Erreur de directive : 'message' ( see page 300) Ce message s'affiche lorsqu'une directive #error est traitée dans le fichier
source.
'message' est le texte de la directive #error.
F1004: Erreur interne du compilateur ( see page 300) Une erreur s'est produite dans la logique interne du compilateur. Cette erreur ne
devrait en général jamais s'afficher. Elle n'est là que si aucun message plus
spécifique n'est disponible.

235
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

F1006: Appel incorrect d'une fonction intrinsèque ( see page 300) Vous avez utilisé une fonction intrinsèque sans fournir de prototype. Vous avez
peut-être fourni un prototype pour une fonction intrinsèque, mais pas celle que le
compilateur attendait.
F1007: Arborescence d'expression irréductible ( see page 301) Une expression sur la ligne indiquée du fichier source a empêché la génération
du code attendu. Evitez d'utiliser cette expression. Contactez CodeGear si une
expression génère régulièrement ce message d'erreur.
F1009: Impossible d'ouvrir le fichier d'entrée 'nomfichier' ( see page 301) Cette erreur se produit si le fichier source est introuvable.
Vérifiez le nom du fichier. Vérifiez qu'il est sur le disque et le répertoire spécifiés.
Vérifiez que les chemins d'accès aux répertoires sont corrects. Si plusieurs
chemins d'accès sont requis, séparez-les par un point-virgule.
F1011: Echec d'allocation de registre ( see page 301) Cause possible
Une expression sur la ligne spécifiée du fichier source était tellement complexe
qu'elle a empêché la génération du code attendu.
Solutions
Simplifiez l'expression. Si ceci ne résout pas le problème, n'utilisez pas cette
expression.
Contactez CodeGear si une expression génère régulièrement ce message
d'erreur.
F1012: Débordement de pile du compilateur ( see page 301) La pile du compilateur a débordé. Ceci peut entre autres être causé par des
instructions imbriquées en profondeur dans un corps de fonction (par exemple,
if/else) ou par des expressions avec un grand nombre d'opérandes. Vous devez
simplifier votre code si ce message se produit. Ajouter de la mémoire ne servirait
à rien dans ce cas.
F1013: Erreur d'écriture du fichier de sortie ( see page 301) Erreur DOS empêchant l'EDI de C++ d'écrire un fichier .OBJ, .EXE ou temporaire.
Solutions
Vérifiez que le répertoire de sortie dans la boîte de dialogue Répertoires est un
répertoire valide.
Vérifiez la place disponible sur le disque.
F1000: Limite de la table du compilateur dépassée ( see page 301) L'une des tables internes du compilateur a débordé.
Ceci signifie généralement que le module compilé contient trop de corps de
fonctions.
Ce problème ne peut pas être résolu en augmentant la mémoire disponible pour
le compilateur. Vous devez simplifier le fichier à compiler.
F1005: Fichiers d'inclusion imbriqués trop profondément ( see page 302) Ce message signale (directement ou indirectement) les directives #include
récursives.
F1008: Plus de mémoire ( see page 302) L'espace de travail est saturé.
Cette erreur peut se produire dans les cas suivants :

• La mémoire virtuelle disponible est insuffisante pour


compiler un fichier. Dans ce cas, fermez les applications
inutilisées. Vous pouvez également essayer de
reconfigurer votre ordinateur pour augmenter la mémoire
virtuelle ou de scinder le fichier source compilé en
plusieurs composants distincts plus petits. Vous pouvez
également compiler le fichier sur un système disposant de
plus de mémoire.
• Le compilateur a détecté une expression trop complexe
ou trop longue à la ligne indiquée et ses réserves ne lui
permettent pas de l'analyser. Scindez cette expression en
plusieurs... suite ( see page 302)
F1010: Impossible d'ouvrir 'nomfichier' ( see page 302) Cette erreur se produit si le fichier spécifié ne peut être ouvert.
Vérifiez qu'il est sur le disque et le répertoire spécifiés. Vérifiez que les chemins
d'accès aux répertoires sont corrects. Si plusieurs chemins d'accès sont requis,
séparez-les par un point-virgule.
3 E2000: Instructions 286/287 non activées ( see page 302) Utilisez l'option de ligne de commande "-2" du compilateur pour activer les
instructions 286/287. Sachez que le code résultant ne peut être exécuté sur des
machines 8086 et 8088.
Fin de programme anormale ( see page 302) Le programme appelé a été abandonné car il n'y avait pas assez de mémoire
pour son exécution.
Ce message peut être provoqué par des écrasements en mémoire.
E2009: Tentative d'accorder ou de réduire l'accès à 'identificateur' ( see page Une classe dérivée C++ peut modifier les droits d'accès d'un membre classe de
302) base, mais seulement en lui redonnant les droits de la classe de base.
Elle ne peut ajouter ni supprimer aucun droit d'accès.

236
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2011: Il est incorrect de prendre l'adresse d'un champ de bits ( see page 303) Vous ne pouvez pas prendre l'adresse d'un champ de bits, mais vous pouvez
prendre celle des autres types de champs.
E2010: Impossible d'ajouter ou de soustraire des symboles relogeables ( see Les seules opérations arithmétiques possibles sur un symbole relogeable dans
page 303) un opérande d'assembleur sont l'addition et la soustraction d'une constante.
Les variables, les procédures, les fonctions et les libellés sont des symboles
relogeables.
E2013: 'fonction1' ne peut pas être distinguée de 'fonction2' ( see page 303) Les listes de types de paramètres dans la déclaration de ces deux fonctions sont
trop semblables pour les différencier.
Modifiez l'ordre des paramètres ou le type d'un paramètre dans une déclaration.
E2014: Membre ambigu : 'membre1' et 'membre2' ( see page 303) Vous devez indiquer le nom correct de la classe de base de la référence du
membre.
Dans la classe C++ 'classe', le membre 'membre' peut se trouver dans plusieurs
classes de base et ne pas avoir été qualifié ; vous ne pouvez alors pas en
distinguer les différentes occurrences.
Ceci concerne uniquement l'héritage multiple, où le nom de membre dans
chaque classe de base n'est pas masqué par le même nom de membre dans
une classe dérivée sur le même chemin.
Le langage C++ impose ce test d'ambiguïté avant la vérification des droits
d'accès (private, protected, public).
Il est possible de... suite ( see page 303)
E2015: Ambiguïté entre 'fonction1' et 'fonction2' ( see page 303) Ces deux fonctions surchargées nommées n'ont pu être utilisées avec les
paramètres fournis.
Cette ambiguïté n'est pas autorisée.
E2017: Nom de membre 'nom' ambigu ( see page 303) Lorsqu'un nom de membre de structure est utilisé dans un assembleur en ligne,
ce nom doit être unique. S'il est défini dans plusieurs structures, toutes les
définitions doivent correspondre à son type et à son décalage dans les
structures. Dans ce cas, un nom de membre ambigu a été utilisé.
Par exemple :
E2019: 'identificateur' ne peut pas être déclaré dans une union anonyme ( see Le compilateur a détecté une déclaration pour une fonction membre ou un
page 304) membre statique dans une union anonyme.
Ces unions ne peuvent contenir que des données membre.
E2020: Union anonyme globale non statique ( see page 304) En C++, une union globale anonyme au niveau du fichier doit être statique.
E2022: Taille de tableau trop grande ( see page 304) Le tableau déclaré est d'une taille supérieure à 64 Ko et le mot-clé 'huge' n'a pas
été utilisé.
Si vous avez besoin d'un tableau de cette taille, utilisez le modificateur 'huge' de
la façon suivante :
E2024: Impossible de modifier un objet const ( see page 304) Ce message indique une opération illégale sur un objet déclaré comme const,
telle qu'une affectation concernant cet objet.
E2025: Affectation de 'this' non autorisée, utilisez plutôt l'opérateur X:: new ( Dans les précédentes versions de C++, la seule façon de contrôler l'allocation
see page 304) d'une classe d'objets consistait à affecter le paramètre 'this' au sein d'un
constructeur.
Ceci n'est plus autorisé ; une méthode plus sûre consiste à définir un opérateur
new de fonction membre.
Par exemple :
E2026: Instruction d'assembleur trop longue ( see page 304) La longueur des instructions de l'assembleur en ligne ne peut pas être
supérieure à 480 octets.
E2001: Constructeurs et destructeurs non autorisés dans la section __automated Seules les déclarations de fonctions membre sont autorisées dans les sections
( see page 305) __automated.
Exemple :
E2002: Seules les fonctions __fastcall sont autorisées dans la section La convention d'appel pour les fonctions déclarées dans une section
__automated ( see page 305) __automated doit être __fastcall.
Exemple :
E2003: Définition de données membre non autorisée dans la section Seules les déclarations de fonctions membre sont autorisées dans les sections
__automated ( see page 305) __automated.
Exemple :
E2004: Seule la clause read (lecture) ou write (écriture) est autorisée dans la
déclaration de propriété de la section __automated ( see page 305)
Les spécificateurs de stockage stored, default et nodefault ne sont pas autorisés
dans les déclarations de propriétés d'une section __automated.
3
Exemple :
E2005: Redéclaration de propriété non autorisée dans la section __automated Si vous déclarez une propriété dans une section __automated, il doit s'agir d'une
( see page 306) nouvelle déclaration. Les propriétés surchargées ne sont pas autorisées.
Exemple :
E2027: L'adresse d'un emplacement mémoire est obligatoire ( see page 306) Votre fichier source a utilisé l'opérateur "adresse de" (&) avec une expression qui
ne peut être utilisée ainsi (par exemple, une variable registre).

237
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2028: L'opérateur -> doit renvoyer un pointeur ou une classe ( see page 306) La fonction de l'opérateur C++ '->' doit être déclarée comme renvoyant une
classe ou un pointeur sur une classe (ou struct ou union).
Dans ces deux cas, il doit s'agir d'un élément auquel l'opérateur '->' peut
s'appliquer.
E2029: 'identificateur' doit être une classe ou une structure précédemment Vous tentez de déclarer 'identificateur' comme une classe de base, mais il ne
définie ( see page 306) s'agit pas d'une classe ou il n'est pas entièrement défini.
Modifiez son nom ou changez l'ordre des déclarations.
E2030: Caractère de fin de ligne mal placé ( see page 306) Le compilateur a détecté une instruction break en dehors d'un switch ou d'une
boucle.
Vous pouvez utiliser l'instruction break uniquement dans des instructions switch
ou des boucles.
E2031: Transtypage impossible de 'type1' en 'type2' ( see page 307) La conversion du type 'ident1' en type 'ident2' n'est pas autorisée.
En C++, vous ne pouvez pas convertir un pointeur de fonction membre en
pointeur de fonction normal.
Par exemple :
E2033: Instruction continue mal placée ( see page 308) Le compilateur a détecté une instruction continue en dehors d'une boucle.
E2034: Impossible de convertir 'type1' en 'type2' ( see page 308) Une affectation, une initialisation ou une expression requiert la conversion de
type spécifiée, mais cette conversion n'est pas autorisée.
En C++, le compilateur ne convertit un pointeur de fonction que si la signature
des fonctions est identique. La signature désigne les arguments et le type de
retour de la fonction. Par exemple :
E2036: L'opérateur de conversion ne peut pas avoir de spécification de type de Cette fonction membre de conversion de type C++ spécifie un type de retour
retour ( see page 308) différent du type lui-même.
Une déclaration d'opérateur de fonction de conversion ne peut spécifier de type
de retour.
E2037: Le constructeur 'constructeur' n'est pas autorisé ( see page 308) Les constructeurs au format
E2039: Séparateur décimal mal placé ( see page 309) Le compilateur a détecté, dans une constante à virgule flottante, un séparateur
décimal comme faisant partie de l'exposant.
E2041: Utilisation incorrecte du mot clé default ( see page 309) Le compilateur n'a pas détecté le signe deux-points après le mot clé default.
E2042: Déclarer l'opérateur delete (void*) ou (void*, size_t) ( see page 309) E2043 Déclarer l'opérateur delete[] (void*) ou (void*, size_t)Erreur du compilateur
Déclarez l'opérateur delete avec :
1.Un seul paramètre void*, ou
2.Un second paramètre de type size_t
Si vous utilisez la seconde méthode, elle sera utilisée de préférence à la
première version.
L'opérateur delete global ne peut être déclaré qu'avec un seul paramètre.
E2044: L'opérateur delete doit retourner void ( see page 309) E2044 L'opérateur delete[] doit retourner voidErreur du compilateur
Cet opérateur delete surchargé C++ a été déclaré d'une autre façon.
Déclarez l'opérateur delete avec :
1.Un seul paramètre void*, ou
2.Un second paramètre de type size_t
Si vous utilisez la seconde méthode, elle sera utilisée de préférence à la
première version.
L'opérateur delete global ne peut être déclaré qu'avec un seul paramètre.
E2045: Le nom du destructeur doit correspondre au nom de la classe ( see Dans une classe C++, le tilde (~) introduit une déclaration pour le destructeur de
page 309) classe.
Le nom du destructeur doit être identique à celui de la classe.
Dans votre fichier source, le "~" précédait un autre nom.

238
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2048: Directive de préprocesseur inconnue : 'identificateur' ( see page 310) Le compilateur a détecté le caractère # en début de ligne. Le nom de directive
qui suivait le # ne faisait pas partie des directives suivantes :

• define ( see page 696)


• else ( see page 693)
• endif ( see page 693)
• if ( see page 693)
• ifdef ( see page 694)
• ifndef ( see page 694)
• include ( see page 698)
• line ( see page 699)
• pragma
• undef ( see page 698)
E2046: Format de nom de fichier incorrect dans la directive include OU format de Les noms de fichiers de directives include et line doivent être placés entre
nom de fichier incorrect dans la directive line ( see page 310) guillemets ("nomfichier.h") ou entre crochets (<nomfichier.h>).
Le nom du fichier n'était pas délimité par ces caractères.
Si une macro était utilisée, le texte d'expansion n'est pas entouré par des
guillemets.
E2051: Utilisation incorrecte du point ( see page 310) Un identificateur doit immédiatement suivre l'opérateur point (.). C'est un
message rare qui ne peut se produire que dans certaines instructions
assembleur en ligne spécialisées.
Exemple
E2053: Directive elif mal placée ( see page 311) Le compilateur a détecté une directive #elif sans directive #if, #ifdef ou
#ifndef correspondante.
E2054: Instruction else mal placée ( see page 311) Le compilateur a détecté une instruction else sans instruction "if"
correspondante.
Cause possible

• une instruction "else" en trop ;


• un point-virgule de trop ;
• des accolades manquantes ;
• une erreur de syntaxe dans une instruction "if" précédente.
E2055: Directive else mal placée ( see page 311) Le compilateur a détecté une directive #else sans directive #if, #ifdef ou
#ifndef correspondante.
E2056: Directive endif mal placée ( see page 311) Le compilateur a détecté une directive #endif sans directive #if, #ifdef ou
#ifndef correspondante.
E2059: Langage inconnu, doit être du C ou du C++ ( see page 311) Dans la construction C++
E2060: Utilisation incorrecte de la virgule flottante ( see page 311) Les opérandes à virgule flottante ne sont pas autorisés avec ces opérateurs :

• décalages (SHL, SHR) ;


• booléens binaires (AND, OR, XOR, NOT) ;
• conditionnels (? :) ;
• indirection (*)
• certains autres.
3
Le compilateur a détecté un opérande à virgule flottante
utilisé avec l'un de ces opérateurs interdits.
E2061: Les amis doivent être des fonctions ou des classes ( see page 312) Un ami d'une classe C++ doit être une fonction ou une autre classe.
E2062: Indirection incorrecte ( see page 312) L'opérateur d'indirection (*) requiert un pointeur comme opérande.
Exemple

239
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2063: Initialisation incorrecte ( see page 312) Il n'existe que deux types d'initialisations :

• expressions constantes ;
• adresse d'une variable extern globale ou statique, plus ou
moins une constante.
E2064: Impossible d'initialiser 'type1' avec 'type2' ( see page 312) Vous tentez d'initialiser un objet de type 'type1' avec une valeur de type 'type2'.
Ceci n'est pas autorisé.
Les règles d'initialisation sont les mêmes que celles d'affectation.
E2068: 'identificateur' n'est pas une donnée membre non statique et ne peut pas Seules les données membre peuvent être initialisées dans les initialisateurs d'un
être initialisé ici ( see page 312) constructeur.
Ce message signifie que la liste comporte un membre statique ou un membre de
fonction.
Les membres statiques doivent être initialisés en dehors de la classe, par
exemple :
E2069: Utilisation incorrecte d'un pointeur de membre ( see page 312) Les pointeurs sur des membres de classes peuvent être uniquement transmis
comme arguments de fonctions ou utilisés avec les opérateurs suivants :

• assignment
• comparaison
E2071: L'opérateur new doit avoir un paramètre initial de type size_t ( see E2071 L'opérateur new[] doit avoir un paramètre initial de type size_tErreur du
page 313) compilateur
L'opérateur new peut être déclaré avec un nombre de paramètres arbitraire.
Il doit toujours en avoir au moins un, la quantité de mémoire à allouer.
E2072: L'opérateur new[] doit renvoyer un objet de type void ( see page 313) Cet opérateur new surchargé C++ a été déclaré d'une autre façon.
E2075: Option 'type' incorrecte : option ( see page 314) Une erreur s'est produite dans le fichier de configuration ou dans une option de
la ligne de commande. Le compilateur n'a peut-être pas reconnu un paramètre
du fichier de configuration comme paramètre autorisé ; recherchez un éventuel
tiret (-) précédent. Il se peut aussi que le compilateur n'ait pas reconnu le
paramètre de la ligne de commande comme paramètre autorisé.
Cette erreur peut également se produire si vous utilisez une option #pragma
dans votre code avec une option non valide.
E2076: Opérateur surchargeable attendu ( see page 314) Presque tous les opérateurs C++ peuvent être surchargés.
Voici les seuls qui ne peuvent pas être surchargés :

• le point de sélection de champ (.)


• le point étoile (.*)
• le double deux points (::)
• l'expression conditionnelle (?:)
Les opérateurs de préprocesseur (# et ##) ne sont pas des
opérateurs du langage C ou C++ et ne peuvent donc pas
être surchargés.
Les autres signes de ponctuation n'appartenant pas à des
opérateurs, tels que le point-virgule (;), ne peuvent pas
être surchargés.
E2080: La fonction 'fonction' doit être déclarée avec un paramètre ( see page Cette fonction opérateur C++ a été déclarée avec plusieurs paramètres.
314)
E2077: 'opérateur' doit être déclaré avec un ou sans paramètre ( see page 314) Lorsque l'opérateur "++" ou "--" est déclaré comme fonction membre, il doit être
déclaré comme acceptant :

• aucun paramètre (pour la version à préfixe de l'opérateur),


3 ou
• un seul paramètre de type int (pour la version à suffixe).
E2079: 'fonction' doit être déclarée sans paramètres ( see page 314) Cette fonction opérateur C++ a été déclarée avec des paramètres.

240
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2078: 'opérateur' doit être déclaré avec un ou deux paramètres ( see page Lorsque l'opérateur "++" ou "--" est déclaré comme fonction non membre, il doit
315) être déclaré comme acceptant :

• un seul paramètre (pour la version à préfixe de


l'opérateur), ou
• deux paramètres (pour la version à suffixe)
E2081: 'fonction' doit être déclarée avec deux paramètres ( see page 315) Cette fonction opérateur C++ n'a pas été déclarée avec deux paramètres.
E2082: 'identificateur' doit être une fonction membre ou avoir un paramètre de La plupart des fonctions opérateur C++ doivent avoir un paramètre implicite ou
type classe ( see page 315) explicite de type classe.
Cette fonction opérateur a été déclarée en dehors d'une classe et n'a pas de
paramètre explicite de type classe.
E2083: Le dernier paramètre de 'opérateur' doit être de type 'int' ( see page Lorsque l'opérateur à suffixe ++ ou -- est surchargé, le dernier paramètre doit
315) être déclaré avec le type int.
E2084: Les noms de paramètres sont utilisés seulement avec un corps de Lorsque vous déclarez une fonction (sans la définir avec un corps de fonction),
fonction ( see page 315) vous devez utiliser des parenthèses vides ou un prototype de fonction.
Une liste de noms de paramètres seule n'est pas autorisée.
Exemples de déclarations
E2085: Addition de pointeurs incorrecte ( see page 315) Votre fichier source a tenté d'ajouter deux pointeurs.
E2086: Soustraction de pointeurs incorrecte ( see page 316) Ce message s'affiche car vous avez essayé de soustraire un pointeur à un non
pointeur.
E2087: Utilisation incorrecte du pointeur ( see page 316) Les pointeurs ne peuvent être utilisés qu'avec ces opérateurs :

• addition (+)
• soustraction (–)
• affectation (=)
• comparaison (==)
• indirection (*)
• flèche (->)
Votre fichier source a utilisé un pointeur avec un autre
opérateur.
Exemple
E2088: Syntaxe incorrecte pour la définition de fonctions pures ( see page 316) Les fonctions virtuelles pures sont spécifiées par ajout de "= 0" à la déclaration :
E2089: L'identificateur 'identificateur' ne peut pas avoir un qualificateur de type L'identificateur qualificateur de classe C++ "::" ne peut pas être utilisé ici.
( see page 316) Les qualificateurs sont interdits sur :

• les noms typedef ;


• les déclarations de fonctions (sauf les définitions au
niveau du fichier) ;
• les variables locales ou les paramètres de fonctions ;
• un membre de classe, sauf si vous utilisez sa propre
classe comme qualificateur (ceci est redondant mais
autorisé).
E2090: Le qualificateur 'identificateur' n'est pas un nom de classe ou d'espace de Le qualificateur C++ dans la construction qual::identificateur n'est pas le nom
nommage ( see page 317) d'une structure ou d'une classe.
E2092: La classe de stockage 'classe de stockage' n'est pas autorisée ici ( see Cette classe de stockage n'est pas autorisée ici.
page 317) Il est probable que deux classes de stockage ont été spécifiées, alors qu'une
seule ne peut l'être.
3
E2096: Opération de structure incorrecte ( see page 317) Les structures ne peuvent être utilisées qu'avec des opérateurs point (.), adresse
(&) ou affectation (=), ou transmis à ou depuis une fonction en tant que
paramètres.
Le compilateur a détecté une structure utilisée avec un autre opérateur.
E2104: Utilisation incorrecte du mot clé template ( see page 317) Vous ne pouvez utiliser un nom de classe modèle que si vous ne spécifiez pas
ses arguments à l'intérieur d'une définition de modèle.
Il n'est pas possible d'utiliser un nom de classe modèle sans spécifier ses
arguments en dehors d'une définition de modèle.

241
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2108: Utilisation incorrecte de typedef 'identificateur' ( see page 317) Votre fichier source contient un symbole typedef à la place d'une variable dans
une expression.
Vérifiez la déclaration du symbole et les éventuelles fautes de frappe.
E2109: Type non autorisé ( see page 317) Votre fichier source a déclaré un type interdit ; par exemple, une fonction
renvoyant une fonction ou un tableau.
E2110: Conversion de type incompatible ( see page 317) La conversion demandée ne peut être effectuée.
E2113: Conflits de fonction virtuelle 'fonction1' avec la classe de base 'base' ( Une fonction virtuelle a les mêmes types d'arguments qu'une fonction dans une
see page 318) classe de base, mais diffère sur les points suivants :

• Type de retour
• Convention d'appel
• Spécification d'exception (liste throw)
E2114: Plusieurs classes de base nécessitent des noms de classes explicites ( Dans un constructeur de classe C++, s'il existe plusieurs classes de base
see page 318) immédiates, chaque appel de constructeur de classe de base dans l'en-tête du
constructeur doit inclure le nom de la classe de base.
E2115: Champ de bits trop grand ( see page 318) Cette erreur se produit lorsque vous fournissez un champ de bits de plus de
16 bits.
E2116: Les champs de bits doivent contenir au moins un bit ( see page 318) Vous ne pouvez pas déclarer un champ de bits nommé avec 0 (ou moins) bit.
Vous pouvez déclarer un champ de bits non nommé avec 0 bit.
Cette convention est utilisée pour forcer l'alignement du champ de bits suivant
avec une limite d'octets ou une limite de mots.
W8005: Les champs de bits doivent être des entiers signés ou non signés ( En C ANSI, les champs de bits ne peuvent être que des entiers signés ou non
see page 318) signés (pas de char ni de long, par exemple).
E2119: Pause utilisateur ( see page 318) Vous avez tapé Ctrl+Pause pendant la compilation dans l'EDI.
(Ceci n'est pas une erreur, uniquement une confirmation.)
E2111: Le type 'nomtype' ne peut pas être défini ici ( see page 319) Les types classe et énumération ne peuvent pas être définis dans un type retour
de fonction, un type argument de fonction, un type opérateur de conversion ou le
type spécifié dans un transtypage.
Vous devez définir le type spécifié avant de l'utiliser dans les contextes ci-dessus.
Remarque : Ce message d'erreur résulte souvent d'un point-virgule (;)
manquant dans une déclaration de classe. Vérifiez que toutes les déclarations de
classe précédant la ligne à l'origine de l'erreur se terminent par un point-virgule.
E2121: ) manquante dans l'appel de fonction ( see page 319) La liste d'arguments d'appel de fonction contient une erreur de syntaxe (par
exemple, parenthèse manquante ou nombre impair de parenthèses).
E2123: La classe 'classe' ne doit pas contenir des fonctions pures ( see page La classe déclarée ne peut pas être abstraite et ne peut donc pas contenir des
319) fonctions pures.
E2126: Case a contourné l'initialisation d'une variable locale ( see page 319) En C++, il est illégal de contourner l'initialisation d'une variable locale.
Cette erreur indique qu'un libellé CASE peut transférer le contrôle au-delà de
cette variable locale.
E2127: Instruction case manquante : ( see page 319) Une instruction case doit avoir une expression constante suivie du signe
deux-points.
L'expression dans cette instruction ne comportait pas de signe deux-points ou
comportait un symbole de trop avant le signe.
E2128: Case en dehors du switch ( see page 319) Le compilateur a détecté une instruction case en dehors d'une instruction switch.
Cela est souvent provoqué par des accolades mal appariées.
E2129: Constante caractère trop longue (ou vide) ( see page 319) Les constantes caractère ne peuvent comporter qu'un ou deux caractères.
E2133: Impossible d'exécuter la commande 'commande' ( see page 320) Le lieur ou l'assembleur est introuvable, ou le disque est endommagé.
E2134: Accolade fermante manquante dans une instruction composée ( see Le compilateur a atteint la fin du fichier source et n'a détecté aucune accolade
page 320) fermante.
Vérifiez le nombre d'accolades fermantes et ouvrantes.
E2137: Un destructeur pour 'classe' est nécessaire dans l'expression Si le compilateur doit créer une variable locale temporaire dans une expression
conditionnelle ( see page 320) conditionnelle, il ne sait pas où appeler le destructeur car la variable n'a pas
forcément été initialisée.
3 La variable temporaire peut être créée explicitement avec classname(val, val) ou
implicitement par un autre code.
Vous devez réécrire votre code pour éliminer cette valeur temporaire.
E2135: Un constructeur/destructeur ne peut pas être déclaré 'const' ou 'volatile' Un constructeur ou un destructeur a été déclaré const ou volatile.
( see page 320) Ceci n'est pas autorisé.
E2138: Conflit de modificateurs de type ( see page 320) Cette erreur se produit lorsqu'une déclaration inclut plusieurs modificateurs
d'adressage sur un pointeur ou plusieurs modificateurs de langage pour une
fonction.
Un seul modificateur de langage (par exemple, __cdecl, __pascal, ou
__fastcall) peut être spécifié pour une fonction.

242
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2136: Un constructeur ne peut pas avoir de spécification de type de retour ( Les constructeurs C++ ont un type de retour implicite utilisé par le compilateur,
see page 320) mais vous ne pouvez pas déclarer un type de retour ni renvoyer une valeur.
E2038: Impossible de déclarer ou de définir 'identificateur' ici : espace de Vous avez tenté de déclarer un modèle à un emplacement illégal ou un membre
nommage incorrect ( see page 321) d'espace de nommage en dehors de son espace de nommage.
E2154: Impossible de définir 'identificateur' en utilisant un alias d'espace de Vous ne pouvez pas utiliser un alias d'espace de nommage (namespace) pour
nommage ( see page 321) définir un membre d'espace de nommage en dehors de son espace de
nommage.
E2421: Impossible d'utiliser le type local 'identificateur' comme argument modèle Un type local a été utilisé dans un argument réel de type modèle. Ceci est illégal.
( see page 321)
E2035: Les conversions d'une classe en elle-même ou en classe de base ne Vous avez tenté de définir un opérateur de conversion visant à transtyper une
sont pas autorisées ( see page 321) classe en la même classe ou en une classe de base.
E2139: ; manquant dans la déclaration ( see page 321) Votre fichier source contient une déclaration de champ struct ou union non suivie
d'un point-virgule.
Vérifiez qu'il ne manque aucun point-virgule dans les lignes précédentes.
E2140: La déclaration n'est pas autorisée ici ( see page 321) Les déclarations ne peuvent être utilisées comme instructions de contrôle dans
les instructions while, for, do, if ou switch.
E2141: Erreur de syntaxe de déclaration ( see page 321) Votre fichier source contient une déclaration comportant trop ou pas assez de
symboles.
Vérifiez que vous n'avez pas oublié de point-virgule ou de parenthèse dans cette
ligne ou dans les lignes précédentes.
E2142: La classe de base 'classe' contient des fonctions qui peuvent être Cette erreur se produit lorsqu'une classe contenant une fonction DDVT tente
réparties de façon dynamique ( see page 322) d'hériter de fonctions DDVT de plusieurs classes parent.
A ce jour, les tables virtuelles réparties dynamiquement ne gèrent pas l'utilisation
des héritages multiples.
E2143: La fonction 'fonction' de classe de base correspondante a un numéro de Si une fonction DDVT est déclarée dans une classe dérivée, la fonction de classe
répartition différent ( see page 322) de base correspondante doit avoir le même numéro de répartition que la fonction
dérivée.
E2144: La fonction de classe de base correspondante 'fonction' n'est pas Si une fonction DDVT est déclarée dans une classe dérivée, la fonction de classe
dynamique ( see page 322) de base correspondante doit également être dynamique.
E2145: Les fonctions 'fonction1' et 'fonction2' utilisent le même numéro de Cette erreur indique un problème concernant la table virtuelle répartie
répartition ( see page 322) dynamiquement (DDVT).
E2146: Vous devez fournir un identificateur à déclarer ( see page 322) Dans ce contexte, un identificateur était attendu pour terminer la déclaration.
Il peut s'agir d'un typedef sans nom ou d'un point-virgule en trop au niveau du
fichier.
En C++, il peut s'agir d'un nom de classe utilisé à la place d'un autre type
d'identificateur.
E2147: 'identificateur' ne peut pas démarrer une déclaration de paramètre ( Un identificateur non défini a été détecté en début d'argument dans un
see page 322) déclarateur de fonction.
Souvent, le nom du type est mal orthographié ou sa déclaration est absente.
Ceci est généralement dû au fait que le fichier d'en-tête approprié n'a pas été
inclus.
E2150: Mauvaise correspondance de type dans la valeur de l'argument par La valeur par défaut du paramètre n'a pas pu être convertie en type du
défaut ( see page 323) paramètre.
Ce message est affiché lorsque le paramètre n'a pas de nom.
Lorsque vous compilez des programmes C++, ce message est toujours précédé
d'un autre expliquant la raison exacte de cette non concordance de types.
Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'",
mais la non concordance peut venir d'un autre problème.
E2152: L'expression par défaut ne doit pas utiliser des variables locales ( see Une expression d'argument par défaut ne peut pas utiliser de variables locales
page 323) ou d'autres paramètres.
E2153: La directive define nécessite un identificateur ( see page 323) Le premier caractère autre qu'un espace après #define doit être un
identificateur.
Le compilateur a détecté un autre caractère.
E2155: Trop d'instructions default ( see page 323) Le compilateur a détecté plusieurs instructions par défaut dans un même switch.
E2156: Default en dehors du switch ( see page 323) Le compilateur a détecté une instruction default en dehors d'une instruction
switch. 3
Vérifiez le nombre d'accolades fermantes et ouvrantes.
E2158: L'opérande de 'delete' doit être un pointeur non-const ( see page 323) Vous ne pouvez pas supprimer une variable autre qu'un pointeur ni un pointeur
sur une constante.
Par exemple :
E2159: Tentative de dériver une classe far depuis la base huge 'base' ( see Cette erreur n'est plus générée par le compilateur.
page 324)
E2160: Tentative de dériver une classe far depuis la base near 'base' ( see Si une classe est déclarée (ou prend par défaut la valeur) near, toutes les
page 324) classes dérivées doivent également être near.

243
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2161: Tentative de dériver une classe huge depuis la base far 'base' ( see Cette erreur n'est plus générée par le compilateur.
page 324)
E2162: Tentative de dériver une classe huge depuis la base near 'base' ( see Cette erreur n'est plus générée par le compilateur.
page 324)
E2163: Tentative de dériver une classe near depuis la base far 'base' ( see Si une classe est déclarée (ou prend par défaut la valeur) far, toutes les classes
page 324) dérivées doivent également être far.
E2164: Tentative de dériver une classe near depuis la base huge 'base' ( see Cette erreur n'est plus générée par le compilateur.
page 324)
E2165: Un destructeur ne peut pas avoir de spécification de type de retour ( Les destructeurs C++ ne renvoient jamais de valeur et vous ne pouvez pas
see page 324) déclarer de type de retour ni renvoyer une valeur.
E2166: Le destructeur de 'classe' n'est pas accessible ( see page 325) Le destructeur de cette classe C++ est protégé ou privé et vous ne pouvez pas y
accéder ici pour détruire la classe.
Si un destructeur de classe est privé, la classe ne peut pas être détruite ni
utilisée. Ceci est probablement une erreur.
Un destructeur protégé n'est accessible que depuis des classes dérivées.
Ceci garantit qu'aucune instance d'une classe de base n'est créée et que seules
des classes en sont dérivées.
E2167: 'fonction' a été précédemment déclarée avec le langage 'langage' ( see Un seul modificateur de langage (cdecl pascal) peut être fourni pour une fonction.
page 325) Cette fonction a été déclarée avec des modificateurs différents en deux endroits.
E2168: Division par zéro ( see page 325) Votre fichier source contient une division ou un reste dans une expression
constante avec un diviseur zéro.
E2169: 'identificateur' spécifie des accès multiples ou dupliqués ( see page Une classe de base peut être déclarée publique ou privée, mais pas les deux.
325) Ce spécificateur d'accès ne peut apparaître plusieurs fois pour une classe de
base.
E2170: La classe de base 'classe' est incluse plusieurs fois ( see page 325) Une classe C++ peut être dérivée d'un grand nombre de classes de base, mais
elle ne peut être dérivée qu'une fois directement d'une classe précise.
E2171: Le corps a déjà été défini pour la fonction 'fonction' ( see page 325) Une fonction de ce nom et de ce type a déjà été fournie comme corps de
fonction.
Un corps de fonction ne peut être fourni qu'une fois.
Une cause de cette erreur est la non déclaration d'un constructeur par défaut que
vous implémentez. Par exemple :
E2172: Case dupliqué ( see page 326) Chaque libellé case d'une instruction switch doit avoir une valeur unique
d'expression constante.
E2175: Trop de classes de stockage dans la déclaration ( see page 326) Une déclaration ne peut pas avoir plusieurs classes de stockage (Auto, Register,
Static ou Extern).
E2176: Trop de types dans la déclaration ( see page 326) Une déclaration ne peut pas avoir plusieurs types de base. Voici des exemples
de types de base :

• char
• class
• int
• float
• double
• struct
• union
• enum
• typedef name
E2179: virtual spécifié plusieurs fois ( see page 326) Le mot réservé C++ "virtual" ne peut apparaître qu'une fois dans une déclaration
de fonction membre.
3 E2007: Dispid n'est autorisé que dans les sections __automated ( see page La définition des dispid n'est possible que dans les sections __automated.
326) Exemple :
Erreur de division ( see page 327) Vous avez essayé de diviser un entier par zéro, ce qui est incorrect.
E2182: Paramètre incorrect pour __emit__ ( see page 327) Certaines restrictions s'appliquent à l'insertion directe de valeurs littérales dans
votre code avec la fonction __emit__.
Par exemple, vous ne pouvez pas fournir à __emit__ une variable locale comme
paramètre.
E2183: Le fichier doit contenir au moins une déclaration externe ( see page Cette unité de compilation est logiquement vide (elle ne contient aucune
327) déclaration externe).
ANSI C et C++ exigent qu'un élément soit déclaré dans l'unité de compilation.

244
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2184: Erreur de syntaxe pour une énumération ( see page 327) Une déclaration enum ne contenait pas de liste d'identificateurs au bon format.
E2185: La valeur de 'identificateur' n'est pas un entier ( see page 327) Tous les énumérateurs doivent avoir une valeur représentable sous forme
d'entier.
Vous avez tenté d'affecter une valeur autre qu'un entier.
Si vous avez besoin d'une constante de cette valeur, utilisez un entier const.
E2186: Fin de fichier inattendue dans le commentaire qui commence à la ligne Le fichier source se termine au milieu d'un commentaire.
'numéro de ligne' ( see page 327) Cette erreur est généralement due à l'omission d'un symbole de fermeture de
commentaire (*/).
E2187: Fin de fichier inattendue dans l'instruction conditionnelle qui commence à Le fichier source s'est terminé avant que le compilateur (ou MAKE) ne détecte
la ligne 'numéro de ligne' ( see page 327) une instruction #endif.
#endif est mal orthographié ou manquant.
Toute instruction #if doit avoir son #endif correspondant.
E2188: Syntaxe de l'expression ( see page 328) Ceci est un message d'erreur générique, qui s'affiche si le compilateur détecte
une erreur grave lors de l'analyse d'une expression.
Cause possible
Cette erreur est généralement due à l'un des problèmes suivants :

• deux opérateurs consécutifs ;


• parenthèses manquantes ;
• point-virgule manquant dans l'instruction précédente.
Solutions
Si la syntaxe de la ligne concernée semble correcte,
recherchez l'erreur dans la ligne précédente.
Essayez de déplacer la ligne comportant l'erreur à un autre
endroit du fichier et recompilez.
Si l'erreur se produit toujours dans l'instruction déplacée,
l'erreur de syntaxe se trouve dans cette instruction.
Si l'erreur se produit dans une autre instruction, l'erreur de
syntaxe... suite ( see page 328)
E2190: Accolade fermante inattendue ( see page 328) Une accolade droite en trop a été trouvée. Recherchez une accolade fermante
manquante.
Astuce :
L'EDI permet de rechercher les accolades correspondantes. Si vous placez le
curseur sur le caractère '{' ou '}', maintenez la touche Ctrl enfoncée, appuyez sur
'Q' puis sur '{' ou sur '}', le curseur se place sur l'accolade correspondante.
E2189: La variable extern ne peut pas être initialisée ( see page 328) La classe de stockage externe appliquée à une variable signifie que la variable
est déclarée mais pas définie ici ; aucun stockage ne lui est alloué.
Vous ne pouvez donc pas initialiser la variable dans la déclaration.
E2344: Déclaration précédente de 'identificateur' ( see page 328) Ce message d'erreur ne s'affiche qu'après les messages "Déclaration multiple
pour 'identificateur'" et "Non concordance de type dans la redéclaration de
'identificateur'". Il indique où la définition précédente de l'identificateur a été
détectée par le compilateur, de telle sorte que vous n'avez pas besoin de la
chercher.
E2192: Trop peu de paramètres dans l'appel ( see page 328) Ce message d'erreur se produit lorsqu'un appel à une fonction avec un prototype
(via un pointeur de fonction) n'a pas assez d'arguments. Les prototypes
requièrent tous les paramètres. Vérifiez que votre appel à une fonction a le
même nombre de paramètres que son prototype.
E2193: Trop peu de paramètres dans l'appel à 'fonction' ( see page 329) Ce message d'erreur se produit lorsqu'un appel à une fonction nommé (déclarée
avec un prototype) n'a pas assez d'arguments.
Vérifiez que votre appel à la fonction a le même nombre de paramètres que son
prototype. 3
E2194: Impossible de trouver le fichier 'nomfichier' ( see page 329) Le compilateur ne trouve pas le fichier spécifié sur la ligne de commande.
E2197: Nom de fichier trop long ( see page 329) Le nom de fichier fourni dans une directive #include était trop long et n'a pas
pu être traité par le compilateur.
Les noms de fichiers complets sous DOS ne doivent pas comporter plus de
79 caractères.
E2195: Impossible d'évaluer l'appel de fonction ( see page 329) Ce message d'erreur s'affiche si vous tentez de construire explicitement un objet
ou d'appeler une fonction virtuelle.
Dans une évaluation d'expression du débogueur intégré, les appels à certaines
fonctions (notamment les fonctions de conversion implicite, les constructeurs, les
destructeurs, les opérateurs surchargés et les fonctions inline) ne sont pas gérés.

245
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2198: Ce n'est pas un type de format d'expression correct ( see page 329) Un spécificateur de format incorrect suit une expression dans la fenêtre
d'évaluation ou de suivi du débogueur. Un spécificateur de format valide est une
valeur de répétition facultative suivie d'un caractère de formatage (c, d, f[n], h, x,
m, p, r ou s).
E2200: Les fonctions ne peuvent pas faire partie d'une structure ou d'une union Ce champ struct ou union C était déclaré comme fonction type plutôt que comme
( see page 329) pointeur sur une fonction.
Les fonctions sous forme de champs ne sont autorisées qu'en langage C++.
Erreur de calcul à virgule flottante : Erreur de division par 0 OU de calcul à Ces erreurs fatales proviennent d'une opération à virgule flottante pour laquelle
virgule flottante : Erreur de domaine ou de calcul à virgule flottante : le résultat n'est pas fini :
Dépassement de capacité ( see page 329)
• Une division par 0 signifie que le résultat est exactement
+INF ou -INF, par exemple 1.0/0.0.
• Un domaine signifie que le résultat est un NAN (not a
number, valeur non numérique), comme 0.0/0.0.
• Un dépassement de capacité signifie que le résultat est
+INF (infinité) ou -INF avec une perte de précision
complète, comme l'affectation de 1e200*1e200 à un
double.
Erreur de calcul à virgule flottante : Faute de pile ( see page 330) La pile a virgule flottante a débordé. Cette erreur peut être due à un code
assembleur qui a utilisé trop de registres ou à une mauvaise déclaration d'une
fonction à virgule flottante.
Le programme affiche le message d'erreur et appelle abort et _exit.
Ces erreurs de virgule flottante peuvent être évitées en masquant l'exception
pour qu'elle ne se produise pas ou en interceptant l'exception avec un signal.
Erreur de calcul à virgule flottante : Perte de précision partielle OU Erreur de Ces exceptions sont masquées par défaut, car les débordements inférieurs sont
calcul à virgule flottante : Débordement inférieur ( see page 330) convertis en zéro et les pertes de précision sont ignorées.
E2201: Trop de données globales définies dans le fichier ( see page 330) La somme des déclarations de données globales dépasse 64 Ko. Ceci inclut
toutes les données stockées dans le DGROUP (toutes les variables globales,
chaînes littérales et locales statiques).
Solutions
Recherchez dans les déclarations les tableaux trop volumineux. Vous pouvez
également supprimer des variables de DGROUP.
Voici comment :

• Déclarez les variables comme automatiques. Ceci utilise


l'espace de la pile.
• A partir du tas, allouez dynamiquement de la mémoire
pour ces variables à l'aide de calloc, malloc ou farmalloc.
Ceci nécessite l'utilisation de pointeurs.
Les chaînes littérales sont également placées dans le
DGROUP. Procurez-vous le fichier farstr.zip sur notre
BBS afin d'extraire... suite ( see page 330)
E2203: Goto évite l'initialisation d'une variable locale ( see page 330) En C++, il est interdit de contourner l'initialisation d'une variable locale.
Cette erreur indique une instruction goto qui peut transférer le contrôle au-delà
de cette variable locale.
E2204: Le groupe a dépassé la taille maximum : 'nom' ( see page 330) La taille totale des segments d'un groupe (par exemple, DGROUP) dépasse
64 Ko.
E2206: Caractère 'caractère' (0x'valeur') incorrect ( see page 331) Le compilateur a détecté un caractère incorrect dans le fichier d'entrée.
La valeur hexadécimale de ce caractère est affichée.
Ceci peut également être causé par des paramètres superflus transmis à une
macro de fonction.

3 E2207: Conversion implicite de 'type1' en 'type2' non autorisée ( see page 331) Lorsqu'une fonction membre d'une classe est appelée avec un pointeur sur une
classe dérivée, la valeur du pointeur doit être implicitement convertie pour pointer
sur la classe de base appropriée.
Dans ce cas, une telle conversion implicite est interdite.
E2208: Impossible d'accéder à une portée inactive ( see page 331) Vous avez essayé d'évaluer ou d'inspecter une variable locale sur une fonction
qui n'est actuellement pas active. (ce message est généré par le débogueur
intégré lors de l'évaluation d'une expression).

246
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2209: Impossible d'ouvrir le fichier include 'nomfichier' ( see page 331) Le compilateur n'a pas trouvé le fichier indiqué.
Cause possible

• Le fichier indiqué n'existe pas.


• Un fichier #include s'est inclus lui-même.
• FILES n'est pas défini dans le fichier CONFIG.SYS de
votre répertoire racine.
Solutions
• Vérifiez que le fichier indiqué existe.
• Définissez FILES = 20 dans CONFIG.SYS.
E2210: Le membre de référence 'membre' n'est pas initialisé ( see page 331) Les références doivent toujours être initialisées, dans le constructeur de la classe.
Un membre de classe de type référence doit avoir un initialisateur dans tous les
constructeurs de cette classe.
Ceci signifie que vous ne pouvez pas compter sur le compilateur pour générer
des constructeurs pour une telle classe car il ne sait pas comment initialiser les
références.
E2212: La fonction a été définie inline après avoir été utilisée comme extern ( Les fonctions ne peuvent passer à l'état inline (en ligne) après avoir été utilisées.
see page 332) Avancez la définition inline dans le fichier ou supprimez-la entièrement.
Le compilateur a détecté quelque chose ressemblant à ceci :
E2211: L'assemblage en ligne n'est pas autorisé dans les fonctions inline et Le compilateur ne gère pas les instructions inline d'assembleur dans une fonction
template ( see page 332) en ligne ou modèle C++.
Supprimez le code inline assembleur ou, dans le cas d'une fonction en ligne,
transformez-la en macro et supprimez la classe de stockage en ligne.
F1001: Erreur du générateur de code interne ( see page 332) Une erreur s'est produite dans la logique interne du générateur de code.
Contactez le Support technique CodeGear.
E2413: Déclaration de modèle incorrecte ( see page 332) Après le déclarateur d'un membre modèle, un point-virgule, une initialisation ou
un corps étaient attendus, mais un autre token, illégal, a été détecté. Ce
message s'affiche lorsqu'un membre modèle est déclaré en dehors du modèle
mais que la syntaxe était erronée.
E2070: Utilisation incorrecte de l'espace de nommage 'identificateur' ( see Un identificateur d'espace de nommage (namespace) a été utilisé de façon
page 332) incorrecte, par exemple dans une expression.
E2214: Impossible d'avoir des 'données fonction/statique non inline' dans une Tous les membres de classes déclarées locales auprès d'une fonction doivent
classe locale ( see page 333) être entièrement définis dans la définition de la classe.
Ceci signifie que les classes locales ne peuvent pas contenir de données
membre statiques et que toutes leurs fonctions membre doivent avoir un corps
défini dans la définition de la classe.
E2215: Spécification de lien non autorisée ( see page 333) Les spécifications de lien telles que extern "C" ne sont autorisées qu'au niveau
du fichier.
Déplacez cette déclaration de fonction au niveau du fichier.
E2216: Impossible de créer turboc.$ln ( see page 333) Le compilateur ne peut pas créer le fichier temporaire TURBOC.$LN car il est
incapable d'accéder au disque, ou le disque est plein.
E2218: Les modèles ne peuvent être déclarés qu'au niveau d'un espace de Les modèles ne peuvent pas être déclarés à l'intérieur d'une classe ou d'une
nommage ou d'une classe ( see page 333) fonction. Ils sont uniquement autorisés dans la portée globale ou au niveau du
fichier.
Par exemple :
E2217: Les données locales dépassent la limite de taille du segment ( see Les variables locales dans la fonction en cours occupent plus de 64 Ko.
page 333)
E2219: Nombre incorrect d'arguments dans l'appel de la macro 'macro' ( see Votre fichier source a appelé la macro nommée avec un nombre incorrect
page 333) d'arguments.
E2220: Séparateur d'arguments de macro incorrect ( see page 334) Dans une définition de macro, les arguments doivent être séparés par une
virgule.
Le compilateur a détecté un autre caractère après un nom d'argument.
Ceci est correct :
3
E2221: Erreur de syntaxe dans l'argument de macro ( see page 334) Un argument dans une définition de macro doit être un identificateur.
Le compilateur a détecté autre chose qu'un caractère identificateur alors qu'un
argument était attendu.
E2222: Développement de macro trop long ( see page 334) Une macro ne peut pas être développée à plus de 4 096 caractères.
E2223: Trop de séparateurs décimaux ( see page 334) Le compilateur a détecté une constante à virgule flottante avec plusieurs
séparateurs décimaux.
E2224: Trop d'exposants ( see page 334) Le compilateur a détecté plusieurs exposants dans une constante à virgule
flottante.

247
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2225: Trop d'initialiseurs ( see page 334) Le compilateur a détecté plus d'initialisateurs que permis par la déclaration
initialisée.
E2226: Paramètre supplémentaire dans l'appel ( see page 334) Un appel à une fonction, via un pointeur défini avec un prototype, comporte trop
d'arguments.
E2227: Paramètre supplémentaire dans l'appel de fonction ( see page 334) Un appel à la fonction nommée (définie avec un prototype) comporte trop
d'arguments.
E2228: Trop de messages d'erreur ou d'avertissement ( see page 335) Le nombre d'erreurs ou d'avertissements dépasse la limite autorisée.
E2233: Impossible d'initialiser un membre de classe ici ( see page 335) Les membres des structures, des unions et des classes C++ ne peuvent pas
posséder d'initialisateurs.
L'ensemble d'une structure ou d'une union peut être initialisé à l'aide
d'initialisateurs placés entre accolades.
Une classe C++ ne peut être initialisée que par un constructeur.
E2232: Membre 'membre' constante/référence dans la classe sans constructeur Une classe contenant des membres constants ou des membres référence (ou les
( see page 335) deux) doit avoir au moins un constructeur défini par l'utilisateur.
Dans le cas contraire, il est impossible d'initialiser les membres.
E2229: Le membre 'membre' a le même nom que sa classe ( see page 335) Une donnée membre statique, un énumérateur, un membre d'une union
anonyme ou un type imbriqué ne peut pas avoir le même nom que sa classe.
Seule une fonction membre ou un membre non statique peut avoir le même nom
que sa classe.
E2234: Référence mémoire attendue ( see page 335) L'assembleur intégré requiert une référence mémoire.
Vous avez sans doute oublié de placer des crochets autour d'un opérande de
registre d'index.
E2231: Le membre 'membre' ne peut pas être utilisé sans objet ( see page 335) Ce message signifie que vous avez écrit class::member, où 'member' est un
membre ordinaire (non statique) et qu'il n'existe aucune classe à associer à ce
membre.
Par exemple, il est possible d'écrire :
E2235: Une fonction membre doit être appelée ou son adresse prise ( see Une référence à une fonction membre doit être appelée, ou son adresse doit être
page 336) prise avec l'opérateur "&".
Dans ce cas, une fonction membre a été utilisée dans un contexte illégal.
Par exemple :
O2237: Les programmes DPMI doivent utiliser le modèle de mémoire large ( Le compilateur ne génère plus cette erreur.
see page 336)
E2238: Plusieurs déclarations pour 'identificateur' ( see page 336) Cet identificateur a été incorrectement déclaré plusieurs fois.
Le problème peut être provoqué par des déclarations conflictuelles, comme :

• int a; double a;
• une fonction déclarée de deux façons différentes, ou
• un libellé répété dans la même fonction, ou
• une déclaration répétée ailleurs que dans une fonction
extern ou une variable simple.
Ceci peut également se produire si vous incluez deux fois le
même fichier d'en-tête. Par exemple, avec :
E2239: 'identificateur' doit être une fonction membre ( see page 337) La plupart des fonctions opérateur C++ peuvent être des fonctions membre ou
non membre, mais celles-ci doivent être des membres de classes :

• opérateur =
• opérateur ->
• opérateur ( )
• conversions de types
3 Cette fonction opérateur n'est pas une fonction membre alors
qu'elle devrait l'être.
E2240: Conversion de pointeur near non autorisée ( see page 337) Un pointeur near ne peut pas être converti en pointeur far dans la zone
d'évaluation d'expression lorsque aucun programme n'est exécuté. Ceci
s'explique par le fait que la conversion a besoin de la valeur en cours de DS
dans le programme utilisateur, alors que celui-ci n'existe pas.
E2243: Un tableau alloué avec 'new' ne peut pas avoir d'initialisateur ( see Lorsque vous initialisez un vecteur (un tableau) de classes, vous devez utiliser le
page 337) constructeur qui n'a pas d'arguments.
Il s'agit du constructeur par défaut, ce qui signifie que vous ne pouvez pas
transmettre des arguments au constructeur lorsque vous initialisez ce vecteur.

248
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2244: 'new' et 'delete' ne sont pas gérés ( see page 337) Le débogueur intégré ne gère pas l'évaluation des opérateurs new et delete.
E2245: Impossible d'allouer une référence ( see page 337) Vous avez tenté de créer une référence à l'aide de l'opérateur new.
Ceci n'est pas autorisé car les références ne sont pas des objets et ne peuvent
pas être créées avec new.
E2309: Assembleur Inline non autorisé ( see page 337) Votre fichier source contient des instructions inline d'assembleur et vous le
compilez depuis l'EDI.
Vous devez utiliser la commande BCC pour compiler ce source depuis la ligne
de commande DOS.
E2250: Aucune classe de base à initialiser ( see page 338) Ce constructeur de classe C++ tente d'appeler implicitement un constructeur de
classe de base, mais cette classe a été déclarée sans classe de base.
Vérifiez vos déclarations.
E2254: : attendu après private/protected/private ( see page 338) Lorsqu'ils sont utilisés en début de section private, protected ou public d'une
classe C++, les mots réservés "private", "protected" et "public" doivent être suivis
du signe deux points.
E2255: Utiliser :: pour prendre l'adresse d'une fonction membre ( see page 338) Si f est une fonction membre de la classe c, prenez son adresse avec la syntaxe
E2256: Pas de : qui suit le ? ( see page 338) Les opérateurs point d'interrogation (?) et deux points (:) ne correspondent pas
dans cette expression.
Le caractère ":" a peut-être été oublié, ou des parenthèses sont mal imbriquées
ou manquantes.
E2257: , attendue ( see page 338) Une virgule était attendue dans une liste de déclarations, d'initialisations ou de
paramètres.
Ce problème vient en général d'un élément de syntaxe manquant en amont du
fichier ou dans l'un des en-têtes inclus.
E2258: Une déclaration était attendue ( see page 338) Une déclaration était attendue ici et aucune n'a été détectée.
Vérifiez qu'il ne manque pas de délimiteur tel qu'une virgule, un point-virgule, une
parenthèse fermante ou une accolade fermante.
E2259: Valeur par défaut manquante ( see page 339) Lorsqu'une fonction C++ déclare un paramètre avec une valeur par défaut, tous
les paramètres suivants doivent avoir une valeur par défaut.
Dans cette déclaration, un paramètre avec une valeur par défaut était suivi d'un
paramètre sans valeur par défaut.
E2260: Une valeur par défaut manque après le paramètre 'paramètre' ( see Tous les paramètres suivant le premier paramètre avec une valeur par défaut
page 339) doivent également avoir une valeur par défaut.
E2263: La gestion des exceptions n'est pas activée ( see page 339) Un bloc 'try' a été détecté alors que la gestion des exceptions est désactivée.
E2264: Expression attendue ( see page 339) Une expression était attendue ici, mais le symbole en cours ne peut servir de
début à une expression.
Ce message peut se produire si l'expression de contrôle d'un if ou d'un while est
attendue ou si une variable est initialisée.
Ce message est en général causé par un symbole manquant ou en trop.
E2266: Aucun nom de fichier donné ( see page 339) La ligne de commande ne contenait aucun nom de fichier. Vous devez spécifier
un nom de fichier source.
E2265: Aucun signe de fin dans le nom de fichier ( see page 339) Le nom de fichier inclus dans une instruction #include ne comporte pas de
guillemet ou de crochet fermant.
E2271: Il manque un libellé à l'instruction goto ( see page 339) Le mot clé goto doit être suivi d'un identificateur.
E2272: Identificateur attendu ( see page 339) Un identificateur était attendu ici, mais aucun n'a été détecté.
En C, un identificateur est attendu dans les situations suivantes :

• dans une liste de paramètres dans un en-tête de fonction


de style ancien ;
• après les mots réservés struct ou union lorsque les
accolades sont omises ;
• comme nom de membre dans une structure ou une union
(à l'exception des champs de bits de largeur 0).
En C++, un identificateur est attendu dans les situations 3
suivantes :
• dans une liste de classes de base desquelles une autre
classe est dérivée, suivant un double deux-points (::) ;
• après le mot réservé "operator" lorsque aucun symbole...
suite ( see page 339)
E2275: Accolade ouvrante attendue ( see page 340) Une accolade gauche était attendue en début de bloc ou d'initialisation.
E2276: ( attendue ( see page 340) Une parenthèse gauche était attendue avant la liste des paramètres.

249
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2274: < attendu ( see page 340) Le mot clé template n'est pas suivi de "<".
Chaque déclaration de modèle doit inclure des paramètres formels placés entre
"< >", immédiatement après le mot clé template.
E2277: Lvalue nécessaire ( see page 340) La partie de gauche d'un opérateur d'affectation doit être une expression
adressable.
Les expressions adressables comprennent notamment :

• les variables numériques ou pointeurs ;


• les références de champs de structure ou indirection par
pointeur ;
• les éléments de tableau indicés.
E2278: Les classes de base multiples ne sont pas gérées pour les classes Les classes Delphi ne peuvent pas avoir plusieurs classes de base.
Delphi ( see page 340) Exemple :
E2280: Identificateur de membre attendu ( see page 340) Le nom d'une structure ou d'un membre de classe C++ était attendu ici, mais
aucun n'a été détecté. La partie droite d'un opérateur point (.) ou flèche (->) doit
être le nom d'un membre dans la structure ou la classe à gauche de l'opérateur.
E2279: Impossible de trouver le constructeur par défaut pour initialiser le Lorsque ceci se produit :
membre 'identificateur' ( see page 341)
1. Une classe C++ 'classe1' contient un membre de 'classe2,'
and
2. Vous souhaitez construire un objet de type 'classe1' (mais
pas depuis un autre objet de type 'classe1'). Il doit exister
un constructeur classe2::classe2() pour que le membre
puisse être construit.
Ce constructeur sans paramètre est appelé constructeur par
défaut.
Le compilateur fournit automatiquement un constructeur par
défaut sauf si vous avez défini un constructeur pour la
classe 'classe2'.
Dans ce cas, le compilateur ne fournit pas automatiquement
le constructeur par défaut (c'est à vous de le faire).
E2310: Seules les fonctions membre peuvent être 'const' ou 'volatile' ( see Un autre élément qu'une fonction membre de classe a été déclaré const ou
page 341) volatile.
E2311: La fonction non-virtuelle 'fonction' est déclarée pure ( see page 341) Seules les fonctions virtuelles peuvent être déclarées pure, car les classes
dérivées doivent pouvoir les outrepasser.
E2283: Utilisez . ou -> pour appeler 'fonction' ( see page 341) Vous avez tenté d'appeler une fonction membre sans fournir d'objet. C'est
nécessaire pour appeler une fonction membre.
E2284: Utilisez . ou -> pour appeler 'membre', ou & pour prendre son adresse ( Une référence à un membre de classe non statique sans objet a été détectée.
see page 341) Un tel membre ne peut pas être utilisé sans objet, ou son adresse doit être prise
à l'aide de l'opérateur &.
E2285: Impossible de trouver une correspondance pour le(s) 'argument(s)' ( Aucune fonction C++ n'a été détectée avec les paramètres correspondant aux
see page 342) arguments fournis. Vérifiez les paramètres transmis à la fonction ou surchargez
la fonction pour les paramètres en cours de transmission.
E2286: Résolution de fonction surchargée non gérée ( see page 342) Dans une évaluation d'expression du débogueur intégré, la résolution de
fonctions ou d'opérateurs surchargés n'est pas gérée, y compris pour prendre
une adresse.
E2287: Nom manquant dans le paramètre 'numéro' ( see page 342) Dans un en-tête de définition de fonction, ce paramètre ne contenait qu'un
'numéro' de spécificateur de type, mais aucun nom de paramètre.
Ceci n'est pas autorisé en C.
3 Cela est autorisé en C++, mais il n'existe aucun moyen de faire référence au
paramètre dans la fonction.
E2288: Pointeur sur structure nécessaire du côté gauche de -> ou ->* ( see Seul un pointeur peut apparaître à gauche de la flèche (->) en C ou en C++.
page 342) En C++, un opérateur -> est autorisé.

250
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2290: ] manquant dans 'code' ( see page 342) Cette erreur est générée dans les cas suivants :

• Votre fichier source a déclaré un tableau dans lequel les


limites ne comportent pas de crochet fermant.
• Le spécificateur de tableau dans un opérateur n'a pas de
crochet fermant.
• L'opérateur [ ] a été déclaré comme opérateur [.
• Un crochet fermant manque dans une expression d'indice.
Ajoutez le crochet ou corrigez la déclaration.
Recherchez les opérateurs manquants ou en trop, ou les
parenthèses en nombre impair.
E2291: Accolade attendue ( see page 342) Une accolade fermante était attendue à la fin d'un bloc ou d'une initialisation.
E2292: La fonction doit renvoyer une valeur ( see page 343) Votre fichier source a déclaré la fonction en cours comme renvoyant un type
autre que int ou void, mais le compilateur a détecté un retour sans valeur.
Ceci signifie généralement qu'une erreur s'est produite.
Les fonctions déclarées comme renvoyant int sont exemptes car les anciennes
versions de C ne géraient pas les types de retour de fonction void.
E2293: ) attendue ( see page 343) Une parenthèse fermante était attendue en fin de liste de paramètres.
E2294: Structure nécessaire sur le côté gauche de . ou .* ( see page 343) La partie gauche d'un opérateur point (.) (ou point-étoile en C++, .*) doit être de
type structure. Ce n'est pas le cas ici.
Cette erreur peut se produire lorsque vous créez une instance d'une classe à
l'aide de parenthèses vides puis tentez d'accéder à un membre de cet 'objet'.
E2312: 'constructeur' n'est pas une classe de base non ambiguë de 'classe' ( Un constructeur de classe C++ tente d'appeler ce constructeur de classe de
see page 343) base.
Cette erreur peut se produire également si vous tentez de modifier les droits
d'accès de 'class::constructor.'
Vérifiez vos déclarations.
E2313: Expression constante nécessaire ( see page 343) Les tableaux doivent être déclarés avec une taille constante.
Cette erreur est généralement causée par une faute de frappe dans une
constante #define.
E2296: Modèles non gérés ( see page 343) Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande
H2ASH. Consultez le fichier "tsm_util.txt" pour de plus amples informations.
E2314: Appel d'une non fonction ( see page 343) Le nom appelé n'est pas déclaré comme fonction.
Cette erreur est généralement causée par une déclaration de fonction incorrecte
ou par une faute de frappe dans le nom de la fonction.
E2321: La déclaration ne spécifie pas un repère ou un identificateur ( see page Cette déclaration ne déclare rien.
344) Ceci peut indiquer un struct ou un union sans repère ou sans variable dans la
déclaration. C++ exige que quelque chose soit déclaré.
Par exemple :
E2297: 'this' ne peut être utilisé que dans une fonction membre ( see page 344) En C++, "this" est un mot réservé qui ne peut être utilisé que dans les fonctions
membre de classe.
E2316: 'identificateur' n'est pas un membre de 'structure' ( see page 344) Vous tentez de référencer 'identificateur' comme un membre de 'structure', à tort.
Vérifiez vos déclarations.
E2317: 'identificateur' n'est pas un paramètre ( see page 344) Dans la section de déclaration des paramètres d'une définition de fonction de
style ancien, 'identificateur' est déclaré mais pas listé comme paramètre.
Supprimez la déclaration ou ajoutez 'identificateur' comme paramètre.
E2319: 'identificateur' n'est pas une classe de base publique de 'type de classe' L'opérande de droite d'un opérateur ".*", "->*" ou "::" n'était pas un pointeur vers
( see page 344) un membre d'une classe qui soit identique au (ou une classe de base non
ambiguë du) type de classe de l'opérande de gauche.

251
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2320: Expression de type scalaire attendue ( see page 344) Les opérateurs "!", "++" et "--" exigent une expression de type scalaire.
Seuls ces types sont autorisés :

• char
• short
• int
• long
• enum
• float
• double
• long double
• pointer
E2302: Pas d'informations de type ( see page 345) Le débogueur intégré n'a pas d'information de type pour cette variable. Vérifiez
que vous avez compilé le module avec les informations de débogage. Si oui, il se
peut que le module ait été compilé par un autre compilateur ou assembleur.
E2303: Nom de type attendu ( see page 345) L'une des erreurs ci-dessous s'est produite :

• Lors de la déclaration d'une variable de niveau fichier ou


d'un champ struct, ni un nom de type, ni une classe de
stockage n'ont été fournis.
• Lors de la déclaration d'un typedef, aucun type n'a été
fourni pour le nom.
• Lors de la déclaration d'un destructeur pour une classe
C++, le nom du destructeur n'était pas un nom de type (il
doit être identique au nom de sa classe).
• Lors de la spécification d'un nom de classe de base C++,
ce nom n'était pas un nom de classe.
E2304: La variable 'variable' Constant/Reference doit être initialisée ( see page Cet objet C++ est déclaré en tant que constante ou référence, mais n'est pas
345) initialisé.
Il doit l'être au moment de la déclaration.
E2305: Impossible de trouver 'class::class' ('class' &) pour copier un vecteur OU Lorsque la classe C++ 'classe1' contient un vecteur (un tableau) de classe
Impossible de trouver 'class'::operator=('class'&) pour copier un vecteur ( see 'classe2' et que vous souhaitez générer un objet de type 'classe1' à partir d'un
page 345) autre objet de type 'classe 1', vous devez utiliser ce constructeur :
E2306: Les classes de base virtuelles ne sont pas gérées par les classes Delphi Les classes de style Delphi ne peuvent pas être virtuellement dérivées, y compris
( see page 346) depuis d'autres classes de style Delphi.
Exemple :
E2308: L'instruction 'do' doit avoir un 'while' ( see page 346) Votre fichier source contient une instruction do sans mot-clé while de fin.
E2322: Format numérique incorrect ( see page 346) Le compilateur a détecté une virgule décimale dans un nombre hexadécimal.
E2324: Constante numérique trop grande ( see page 346) Les chaînes et les séquences d'échappement plus grandes que 77 (en
hexadécimal ou en octal) ne peuvent être générées.
Des constantes caractères de deux octets peuvent être spécifiées en utilisant
une seconde barre oblique inverse. Par exemple,
E2282: Nom d'espace de nommage attendu ( see page 347) Le nom d'un symbole d'espace de nommage était attendu.
E2334: Le membre de l'espace de nommage 'identificateur' a été déclaré en Les membres d'espace de nommage (namespace) doivent être déclarés dans
dehors de son espace de nommage ( see page 347) leur espace de nommage. Vous ne pouvez utiliser qu'une qualification explicite
pour définir un membre d'espace de nommage (par exemple, pour donner un
3 corps à une fonction déclarée dans un espace de nommage). La déclaration
elle-même doit être à l'intérieur de l'espace de nommage.
E2325: Chiffre octal incorrect ( see page 347) Le compilateur a détecté une constante octale contenant un chiffre non octal (8
ou 9).

252
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2329: Combinaison incorrecte d'instruction et d'opérandes ( see page 347) L'assembleur intégré n'accepte pas cette combinaison d'opérandes.
Causes possibles

• Il y a trop (ou trop peu) d'opérandes pour cette instruction


assembleur.
• Le nombre d'opérandes est correct, mais leur type ou leur
ordre ne correspond pas à l'instruction.
E2327: Les opérateurs ne doivent pas avoir de valeurs d'argument par défaut ( Il est illégal pour les opérateurs surchargés d'avoir des valeurs d'arguments par
see page 347) défaut.
E2330: Un opérateur doit être déclaré comme une fonction ( see page 347) Un opérateur surchargé a été déclaré avec autre chose qu'un type de fonction.
Par exemple :
E2333: Le membre de classe 'membre' a été déclaré en dehors de sa classe ( Les fonctions membre de classe C++ ne peuvent être déclarées que dans la
see page 348) déclaration de classe.
A la différences des fonctions non membre, elles ne peuvent être pas déclarées
plusieurs fois, ni à un autre endroit.
E2335: 'fonction' surchargée ambiguë dans ce contexte ( see page 348) Le seul moment où un nom de fonction surchargée peut être utilisé ou affecté
sans appeler la fonction est lorsqu'il est affecté l'adresse de la fonction
surchargée à une variable ou à un paramètre du type approprié de pointeur de
fonction.
Dans ce cas, un nom de fonction surchargée a été utilisé dans un autre contexte.
Le code ci-dessous, par exemple, générera cette erreur :
E2339: Impossible de surcharger 'main' ( see page 348) main ne peut pas être surchargée.
E2336: Le pointeur sur la fonction surchargée 'fonction' ne correspond pas à Une variable ou un paramètre reçoit (ou est initialisé avec) l'adresse d'une
'type' ( see page 348) fonction surchargée.
Cependant, le type de la variable ou du paramètre ne correspond à aucune
fonction surchargée ayant le nom spécifié.
E2337: Seule une fonction d'un ensemble de fonctions surchargées peut être "C" Les fonctions C++ sont par défaut surchargées, et le compilateur affecte un
( see page 348) nouveau nom à chaque fonction.
Si vous souhaitez passer outre l'affectation de ce nom par le compilateur en
déclarant la fonction extern "C", vous ne pouvez le faire que pour une fonction
d'un ensemble de fonctions de même nom.
Dans le cas contraire, le lieur trouverait plusieurs fonctions globales de même
nom.
E2338: Les overlays ne sont supportés que dans les modèles mémoire medium, Le compilateur ne génère plus cette erreur.
large et huge ( see page 348)
E2340: Non concordance de type dans le paramètre 'nombre' ( see page 349) La fonction appelée, via un pointeur de fonction, a été déclarée avec un
prototype.
Cependant, le numéro de paramètre indiqué (en comptant de gauche à droite à
partir de 1) n'a pas pu être converti dans le type du paramètre déclaré.
Lorsque vous compilez des programmes C++, ce message est toujours précédé
d'un autre expliquant la raison exacte de cette non concordance de types.
Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'",
mais la non concordance peut avoir de nombreuses autres causes.
E2341: Non concordance de type dans le paramètre 'numéro' dans l'appel à Votre fichier source a déclaré cette fonction avec un prototype et le numéro de
'fonction' ( see page 349) paramètre indiqué (en comptant de gauche à droite à partir de 1) n'a pas pu être
converti dans le type du paramètre déclaré.
Lorsque vous compilez des programmes C++, ce message est toujours précédé
d'un autre expliquant la raison exacte de cette non concordance de types.
Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'",
mais la non concordance peut avoir de nombreuses autres causes.
E2342: Non concordance de type dans le paramètre 'paramètre' ( see page La fonction appelée, via un pointeur fonction, a été déclarée dans votre fichier
349) source avec un prototype.
Cependant, le paramètre indiqué n'a pas pu être converti dans le type du
paramètre déclaré.
Lorsque vous compilez des programmes C++, ce message est toujours précédé
d'un autre expliquant la raison exacte de cette non concordance de types. 3
Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'",
mais la non concordance peut avoir de nombreuses autres causes.
E2343: Non concordance de type dans le paramètre 'paramètre' dans l'appel à Votre fichier source a déclaré cette fonction avec un prototype, et le paramètre
'fonction' ( see page 349) indiqué n'a pas pu être converti dans le type du paramètre déclaré.
Lorsque vous compilez des programmes C++, ce message est toujours précédé
d'un autre expliquant la raison exacte de cette non concordance de types.
Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'",
mais la non concordance peut avoir de nombreuses autres causes.

253
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2345: L'accès peut seulement être changé en public ou protected ( see page Une classe dérivée C++ peut modifier les droits d'accès d'un membre de classe
350) de base, mais uniquement en public ou protected.
Un membre de classe de base ne peut être private.
E2349: Conversion de pointeur non portable ( see page 350) Une conversion implicite entre un pointeur et un type intégral est requise, mais
les types ne sont pas de la même taille. Vous devez utiliser un transtypage
explicite (cast).
Cette conversion n'est peut-être pas logique, aussi devez-vous vérifier que c'est
bien ce que vous souhaitez.
E2350: Impossible de définir un pointeur ou une référence sur une référence ( Il est illégal d'avoir un pointeur sur une référence ou une référence sur une
see page 350) référence.
E2352: Impossible de créer une instance de la classe abstraite 'classe' ( see Les classes abstraites (celles qui contiennent des fonctions virtuelles pures) ne
page 350) peuvent être utilisées directement, mais uniquement en dérivé.
Lorsque vous dérivez une classe de base abstraite, avec l'intention de créer des
instances de cette classe dérivée, vous devez outrepasser chaque fonction
virtuelle pure de la classe de base de la façon exacte dont elle est déclarée.
Par exemple :
E2354: Deux opérandes doivent être évalués de même type ( see page 351) Les types d'expressions des deux côtés du signe deux-points dans l'opérateur
d'expression conditionnelle (?:) doivent être identiques, à l'exception des
conversions habituelles.
Voici quelques exemples de conversions habituelles :

• char en int
• float en double
• de void* en un pointeur précis
Dans cette expression, les deux côtés s'évaluent en des
types différents qui ne sont pas automatiquement
convertis.
Ceci peut être une erreur, ou vous devez simplement
transtyper un type en un autre.
Lorsque vous compilez des programmes C++, ce message
est toujours précédé d'un autre expliquant la raison
exacte de cette non concordance de types.
Cet autre message est généralement... suite ( see page
351)
E2355: Fonction modèle récursive : 'x' a instancié 'y' ( see page 351) Le compilateur a détecté une instance récursive de fonction modèle. Par
exemple :
E2356: Non concordance de type dans la redéclaration de 'identificateur' ( see Votre fichier source a redéclaré une variable avec un type différent de son type
page 351) d'origine.
Cause possible
Ceci peut se produire si une fonction est appelée puis déclarée pour renvoyer
autre chose qu'un entier.
Solutions
Vous devez déclarer la fonction avant son premier appel.
E2357: Référence initialisée avec 'type1', nécessite lvalue de type 'type2' ( see Une variable de référence non déclarée constante doit être initialisée avec une
page 352) lvalue du type approprié.
Dans ce cas, l'initialisateur n'était pas une lvalue ou son type ne correspondait
pas à la référence initialisée.
E2358: Le membre référence 'membre' a besoin d'un temporaire pour Vous avez fourni une valeur initiale pour un type de référence qui n'était pas une
l'initialisation ( see page 352) lvalue du type référencé.
Ceci force le compilateur à créer un temporaire pour l'initialisation.
Etant donné qu'il n'existe aucun endroit spécifique pour stocker ce temporaire,
3 l'initialisation est illégale.

254
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2360: Combinaison de registre incorrecte (ex : [BP+BX]) ( see page 352) L'assembleur intégré a détecté une combinaison illégale de registres dans une
instruction.
Voici les seules combinaisons autorisées :

• [BX]
• [BP]
• [SI]
• [DI]
• [BX+SI]
• [BX+DI]
• [BP+SI]
• [BP+DI]
Les autres combinaisons de registres d'index ne sont pas
autorisées.
E2361: 'spécificateur' a déjà été inclus ( see page 352) Ce spécificateur de type se trouve plusieurs fois dans cette déclaration.
Supprimez ou modifiez l'une des occurrences.
E2362: Le nombre de répétitions a besoin d'une lvalue ( see page 352) L'expression précédant la virgule dans la fenêtre de suivi ou d'évaluation doit être
une région de stockage accessible. Ces expressions, par exemple, ne sont pas
correctes :
E2363: Tentative de renvoyer une référence à la variable locale 'identificateur' ( Cette fonction C++ renvoie un type référence et vous tentez de renvoyer une
see page 353) référence à une variable locale (auto).
Ceci n'est pas autorisé car la variable référencée disparaît lorsque la fonction se
termine.
Vous pouvez renvoyer une référence à une variable statique ou globale ou
modifier la fonction de façon à ce qu'elle renvoie une valeur.
E2364: Tentative de renvoyer une référence à un objet local ( see page 353) Vous avez tenté de renvoyer une référence à un objet temporaire dans une
fonction qui renvoie un type référence. Ceci peut être le fait d'un constructeur ou
d'un appel à une fonction.
Cet objet disparaîtra lorsque la fonction renverra son résultat, ce qui rendra la
référence illégale.
E2365: Un pointeur membre est nécessaire à droite de .* ou ->* ( see page La partie droite d'un opérateur C++ point-étoile (.*) ou flèche-étoile (->*) doit être
353) déclarée comme pointeur sur un membre de la classe spécifiée par la partie
gauche de cet opérateur.
Dans ce cas, la partie droite n'est pas un pointeur de membre.
E2366: Impossible d'hériter une classe non-RTTI depuis la base RTTI (E2367) Lorsque des fonctions virtuelles sont présentes, l'attribut RTTI de toutes les
OU Impossible d'hériter une classe RTTI depuis la base non-RTTI ( see page classes de base doit être identique à celui de la classe dérivée.
353)
E2368: RTTI non disponible pour une évaluation d'expression ( see page 353) Les expressions nécessitant RTTI ne sont pas gérées par l'évaluateur
d'expressions dans le débogueur intégré. Ce message d'erreur n'est affiché que
par l'évaluateur d'expressions (en cas d'inspection, d'évaluation ou de suivi),
jamais par le compilateur.
E2371: sizeof ne peut pas être appliqué à un champ de bits ( see page 354) sizeof renvoie la taille d'un objet données en octets, ce qui ne s'applique pas à
un champ bit.
E2372: sizeof ne peut pas être appliqué à une fonction ( see page 354) sizeof ne peut s'appliquer qu'aux objets données, mais pas aux fonctions.
Vous pouvez demander la taille d'un pointeur sur une fonction.
E2373: Un champ de bits ne peut pas être statique ( see page 354) Seules les données membre de classe C++ standard peuvent être déclarées
comme statiques. Les champs bit ne le peuvent pas.
E2374: La fonction 'fonction' ne peut pas être statique ( see page 354) Seules les fonctions membre ordinaires et les opérateurs new et delete peuvent
être déclarés statiques.
Les constructeurs, les destructeurs et les autres opérateurs ne peuvent être
statiques. 3

255
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

Débordement de pile ( see page 354) Cette erreur est signalée lorsque vous compilez une fonction en activant l'option
de test de dépassement de la pile, mais qu'il n'y a pas assez d'espace dans la
pile pour allouer les variables locales de la fonction.
Cette erreur peut également être causée par les actions suivantes :

• une récursivité infinie, ou


• une procédure en langage assembleur qui ne conserve
pas le projet de pile
• un tableau important dans une fonction
E2376: ( manquante dans l'instruction ( see page 354) Dans une instruction do, for, if, switch ou while, le compilateur n'a pas trouvé de
parenthèse manquante après le mot-clé while ou l'expression de test.
E2377: ) manquante dans l'instruction ( see page 354) Dans une instruction do, for, if, switch ou while, le compilateur n'a pas trouvé de
parenthèse droite après le mot-clé while ou l'expression de test.
E2378: ; manquant dans l'instruction do-while ou for ( see page 355) Dans une instruction do ou for, le compilateur n'a pas trouvé de point-virgule
après la parenthèse droite.
E2379: ; manquante dans l'instruction ( see page 355) Le compilateur a détecté une instruction non suivie d'un point-virgule.
E2380: Constante chaîne ou caractère non terminée ( see page 355) Le compilateur n'a pas trouvé de guillemet fermant après le début d'une
constante chaîne ou caractère.
E2381: Taille de la structure trop grande ( see page 355) Votre fichier source a déclaré une structure de taille supérieure à 64 Ko.
E2382: Les effets de bord ne sont pas autorisés ( see page 355) Les effets de bord tels que les affectations, "++" ou "--" ne sont pas autorisés
dans la fenêtre de suivi du débogueur. Une erreur fréquente consiste à utiliser "x
= y" (non autorisé) à la place de "x == y" pour tester l'égalité de x et de y.
E2383: L'expression de sélection switch doit être de type entier ( see page 355) L'expression de sélection entre parenthèses dans une instruction switch doit
s'évaluer comme un type entier (char, short, int, long, enum).
Vous devez pouvoir utiliser un transtypage explicite pour satisfaire à cette
obligation.
E2433: Spécialisation après la première utilisation du modèle ( see page 355) Une règle ANSI C++ exige qu'une spécialisation de modèle de fonction soit
déclarée avant sa première utilisation. Ce message d'erreur ne s'affiche que
lorsque l'option de conformité ANSI (-A) est activée.
E2384: Impossible d'appeler une fonction membre de classe near avec un ou E2385 Ne peut pas appeler la fonction 'fonction' membre de classe near avec
pointeur de type 'type' ( see page 355) un pointeur de type 'type'
Les fonctions membre de classe near ne peuvent pas être appelées à l'aide d'un
pointeur de membre.
Ceci vaut également pour les appels utilisant des pointeurs sur des membres.
(Notez bien que les classes sont near par défaut dans les modèles de mémoire
tiny, small et medium.)
Modifiez le pointeur en near ou déclarez la classe comme far.
E2390: Non concordance de type dans le paramètre 'numéro' du nom de classe La valeur d'argument de modèle fournie pour le paramètre indiqué ne
modèle 'modèle' ( see page 356) correspondait pas au type de paramètre formel du modèle.
Lorsque vous compilez des programmes C++, ce message est toujours précédé
d'un autre expliquant la raison exacte de cette non concordance de types.
Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'",
mais la non concordance peut avoir de nombreuses autres causes.
E2391: Non concordance de type dans le paramètre 'paramètre' du nom de La valeur d'argument de modèle fournie pour le paramètre indiqué ne
classe modèle 'modèle' ( see page 356) correspondait pas au type de paramètre formel du modèle.
Lorsque vous compilez des programmes C++, ce message est toujours précédé
d'un autre expliquant la raison exacte de cette non concordance de types.
Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'",
mais la non concordance peut avoir de nombreuses autres causes.
E2394: Trop peu d'arguments passés au modèle 'modèle' ( see page 356) Un nom de classe modèle n'a pas de valeurs pour certains de ses paramètres
formels.
E2395: Trop d'arguments passés au modèle 'modèle' ( see page 356) Ce nom de classe modèle contient trop de valeurs pour ses paramètres formels.
E2396: L'argument du modèle doit être une expression constante ( see page Un argument de classe modèle non typé doit être une expression constante du
356) type approprié.
3 Ceci inclut notamment les expressions constantes entières et les adresses
d'objets ou de fonctions comportant des membres ou des liens externes.
E2401: Liste des arguments de modèles incorrecte ( see page 356) Cette erreur indique une liste d'arguments de modèles illégale.
Dans une déclaration de modèle, le mot-clé template doit être suivi d'une liste
d'arguments formels placés entre les délimiteurs < et >.
E2400: L'argument de modèle non typé doit être de type scalaire ( see page Un argument de modèle formel non typé doit être de type scalaire ; il peut être de
357) type entier, énumération ou pointeur.
E2415: Les fonctions modèle doivent avoir seulement des 'arguments de type' Une fonction modèle a été déclarée avec un argument non typé.
( see page 357) Ce n'est pas autorisé avec une fonction modèle car il n'y a aucun moyen de
spécifier la valeur lorsque la fonction est appelée.

256
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2425: 'membre' n'est pas un membre de type modèle correct ( see page 357) Le membre d'un modèle avec des arguments réels dépendant des arguments
formels d'un modèle englobant a été détecté comme n'étant pas membre d'un
modèle spécifié dans une instance précise.
E2428: Les modèles doivent être des classes ou des fonctions ( see page 357) La déclaration dans une déclaration de modèle doit spécifier un type de classe
ou une fonction.
E2432: Le qualificateur 'template' doit nommer une classe modèle ou une Lorsque vous définissez un membre de classe modèle, les arguments réels dans
instance de fonction ( see page 357) le nom de la classe modèle utilisés comme opérande gauche pour l'opérateur "::"
doivent correspondre aux arguments formels de la classe modèle.
E2442: Deux points consécutifs ( see page 357) Etant donné que les points de suspension contiennent trois points (...) et qu'un
point décimal ou un opérateur de sélection de membre utilise un point (.), deux
points consécutifs ne peuvent être valides dans un programme C.
E2443: La classe de base 'classe' est initialisée plus d'une fois ( see page 357) Dans un constructeur de classe C++, la liste des initialisations suivant l'en-tête
de constructeur comporte plusieurs fois la classe de base 'classe'.
E2444: Le membre 'membre' est initialisé plus d'une fois ( see page 358) Dans un constructeur de classe C++, la liste des initialisations suivant l'en-tête
du constructeur comporte plusieurs fois le même nom de membre.
E2445: La variable 'identificateur' est initialisée plus d'une fois ( see page 358) Cette variable a plusieurs initialisations. Il est possible de déclarer plusieurs fois
une variable de niveau fichier, mais elle ne peut avoir qu'une initialisation (même
si deux sont identiques).
E2446: La définition de fonction ne peut pas être une déclaration typedef ( see En C ANSI, un corps de fonction ne peut être défini par un typedef avec un type
page 358) de fonction.
Redéfinissez le corps de la fonction.
E2132: Les modèles et les opérateurs surchargés ne peuvent pas avoir de lien C Vous avez tenté d'utiliser une spécification de lien avec un modèle ou un
( see page 358) opérateur surchargé. La cause la plus probable de ce message d'erreur est que
vous avez encapsulé la déclaration dans une spécification de lien extern "C".
E2447: 'identificateur' doit être un repère d'énumération précédemment défini ( Cette déclaration tente de référencer 'identificateur' comme repère d'un type
see page 358) enum, mais il n'a pas été déclaré de la sorte.
Corrigez son nom ou déplacez les déclarations.
E2448: Etiquette non définie 'identificateur' ( see page 358) Le label nommé a un goto dans la fonction, mais aucune définition de label.
E2449: La taille de 'identificateur' est inconnue ou zéro ( see page 358) Cet identificateur a été utilisé dans un contexte où sa taille était requise.
Un repère struct n'a peut-être été que déclaré (struct n'étant pas encore défini),
ou un tableau extern a été déclaré sans taille.
Il n'est, dans ce cas, pas permis de référencer un tel élément (comme sizeof) ou
de déréférencer un pointeur sur ce type.
Restructurez votre déclaration de telle façon que la taille de 'identificateur' soit
disponible.
E2450: Structure 'structure' non définie ( see page 359) La structure nommée a été utilisée dans le fichier source, probablement sur un
pointeur vers une structure, mais n'avait aucune définition dans le fichier source.
Ceci est probablement le fait d'un nom de structure mal orthographié ou d'une
déclaration manquante.
E2451: Symbole 'identificateur' non défini ( see page 359) L'identificateur spécifié n'a aucune déclaration.
Causes possibles

• La déclaration de l'identificateur est en commentaire.


• Faute de frappe à cet endroit ou dans la déclaration.
• Erreur dans la déclaration de l'identificateur.
• Le fichier d'en-tête dans lequel l'identificateur est déclaré
n'a pas été inclus en utilisant #include
Ces outils peuvent vous aider à repérer le problème :
GREP ( see page 184)
E2453: La taille du type 'identificateur' est inconnue ou égale à zéro ( see page Ce type a été utilisé dans un contexte où sa taille est requise.
359) Par exemple, un repère struct n'a peut-être été que déclaré (struct n'étant pas
encore défini).
Il n'est, dans ce cas, pas permis de référencer un tel élément (comme sizeof) ou
3
de déréférencer un pointeur sur ce type.
Restructurez vos déclarations de telle façon que la taille de ce type soit
disponible.
E2452: La taille du type est inconnue ou zéro ( see page 359) Ce message d'erreur indique qu'un tableau de dimension non spécifiée imbriqué
dans une autre structure est initialisé alors que l'option -A (ANSI) est activée. Par
exemple :
E2454: Une union ne peut pas être un type de base ( see page 359) Une union ne peut être utilisée comme type de base pour un autre type de
classe.

257
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2455: Une union ne peut pas avoir un type de base ( see page 360) En général, une classe C++ peut être de type union, mais une telle classe ne
peut être dérivée d'une autre classe.
E2456: Le membre de l'union 'membre' est de classe type avec 'constructeur' (ou Une union ne peut contenir de membres de classe type avec des constructeurs
destructeur ou opérateur =) ( see page 360) définis par l'utilisateur, des destructeurs ou l'opérateur =.
E2461: '%s' nécessite une initialisation/finalisation d'exécution ( see page 360) Ce message s'affiche lorsqu'une variable globale déclarée comme __thread
(fonctionnalité réservée à Win32) ou qu'un membre données statiques d'une
classe modèle est initialisé avec une valeur non constante.
Ce message s'affiche également lorsqu'une variable globale déclarée comme
__thread (fonctionnalité réservée à Win32) ou qu'un membre données statiques
d'une classe modèle est de type classe avec un constructeur ou un destructeur.
E2464: 'virtual' ne peut être utilisé qu'avec des fonctions membre ( see page Des données membre ont été déclarées avec le spécificateur virtual.
360) Seules les fonctions membre peuvent l'être.
Par exemple :
E2465: Les unions ne peuvent pas avoir de fonctions membre virtuelles ( see Une union ne peut avoir de fonctions virtuelles comme membres.
page 360)
E2466: void & n'est pas un type correct ( see page 360) Une référence se rapporte toujours à un objet, mais un objet ne peut être de type
void.
Donc, le type void n'est pas autorisé.
E2467: Une fonction Void ne peut pas renvoyer une valeur ( see page 361) Une fonction avec un type de retour void contient une instruction de retour qui
renvoie une valeur ; par exemple, un entier.
Par défaut, ce message est affiché.
E2468: Une valeur de type void n'est pas autorisée ( see page 361) Une valeur de type void n'est en fait pas une valeur, aussi ne peut-elle
apparaître dans un contexte où une valeur réelle est requise.
Les contextes requérant une valeur sont notamment :

• la partie droite d'une affectation ;


• un argument de fonction ;
• l'expression de contrôle d'une instruction if, for ou while.
E2469: Impossible d'utiliser le modèle mémoire tiny ou huge avec Windows ( Le compilateur ne génère plus cette erreur.
see page 361)
E2006: Les programmes protégés par CodeGuard doivent utiliser le modèle de Le compilateur ne génère plus cette erreur.
mémoire large et être prévus pour Windows ( see page 361)
E2269: La fonction 'fonction' n'est pas disponible ( see page 361) Vous avez tenté d'appeler une fonction connue de l'évaluateur mais absente du
programme en cours de débogage. Il peut s'agir, par exemple, d'une fonction en
ligne.
E2124: Appel de fonction incorrect ( see page 361) Un appel de fonction demandé a échoué car la fonction n'est pas disponible dans
le programme ou un paramètre ne peut pas être évalué, etc. Ce message est
affiché par l'évaluateur.
E2213: 'expression' incorrecte dans la redéfinition de portée ( see page 361) L'évaluateur affiche ce message en cas d'erreur de redéfinition de portée dans
une expression que vous suivez ou inspectez. Vous pouvez spécifier une table
de symboles, une unité de compilation, un nom de fichier source, etc. comme
portée de l'expression, et le message s'affichera si le compilateur ne peut pas
accéder à cet élément.
E2236: 'identificateur' manquant dans la redéfinition de portée ( see page 362) La syntaxe d'une redéfinition de portée est incomplète. Ce message est affiché
par l'évaluateur.
Fonction virtuelle pure appelée ( see page 362) Ceci est une erreur d'exécution. Cette erreur est générée si le corps d'une
fonction virtuelle pure n'a jamais été générée et que, pour une raison
quelconque, le compilateur a essayé de l'appeler.
E2095: Littéral chaîne non autorisé dans ce contexte ( see page 362) Ce message d'erreur est affiché par l'évaluateur lorsqu'une chaîne littérale
apparaît dans un contexte autre qu'un appel de fonction.
Fin anattendue pendant la compilation [Module Seg#:offset] OU Fin inattendue Si l'une de ces erreurs se produit, elle indique un échec catastrophique des outils
pendant la liaison [Module Seg#:offset] ( see page 362) CodeGear. Vous devez contacter CodeGear pour signaler le problème et trouver
une possibilité de contournement pour votre cas particulier. En isolant le cas de
test le plus rapidement possible, vous augmenterez les chances de CodeGear ou
3 de vous-même de trouver un palliatif au problème.
D'une manière générale, les échecs du compilateur peuvent être palliés en
déplaçant le code source en cours de compilation. Les cas simples peuvent être
un changement de l'ordre des déclarations de variable ou des fonctions dans le
module source. Le déplacement de... suite ( see page 362)
E2012: Impossible de prendre l'adresse de 'main' ( see page 362) En C++, il est illégal de prendre l'adresse de la fonction main.
E2016: Redéfinition ambiguë du membre de base virtuel 'fonction_de_base': Une fonction virtuelle dans une classe de base virtuelle a été redéfinie avec deux
'fonction_dérivée' ( see page 362) ou plusieurs fonctions différentes dans des chemins différents de la hiérarchie
d'héritage. Par exemple,

258
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2021: Un tableau doit avoir au moins un élément ( see page 363) En langage ANSI C et C++, un tableau doit être défini avec au moins un élément
(les objets de taille nulle sont interdits).
L'astuce souvent utilisée consiste à déclarer un élément de tableau d'une
structure comme ayant une taille nulle, puis à allouer l'espace nécessaire avec
malloc.
Sachez que, même si vous avez recours à cette astuce, vous devez déclarer
l'élément de tableau comme comportant au moins un élément si vous compilez
en mode ANSI strict.
Les déclarations (par opposition aux définitions) de tableaux de taille inconnue
sont autorisées.
Exemple
E2023: Tableau de références non autorisé ( see page 363) Il est illégal d'avoir un tableau de références, car les pointeurs sur références ne
sont pas autorisés et les noms de tableaux sont convertis en pointeurs.
E2032: Utilisation incorrecte d'un pointeur de clôture (closure) ( see page 363) Une variable pointeur closure est utilisée de façon incorrecte. L'utilisation des
variables closure est limitée. Par exemple, vous pouvez assigner une fonction à
une variable closure et exécuter cette fonction via la variable closure, mais vous
ne pouvez pas utiliser une variable closure comme une variable pointeur.
E2040: Terminaison de déclaration incorrecte ( see page 363) Une déclaration a un symbole de terminaison en trop ou incorrect, tel qu'un
point-virgule placé après le corps de la fonction.
Une fonction membre C++ déclarée dans une classe avec un point-virgule entre
l'en-tête et l'accolade ouvrante génère également cette erreur.
E2047: Syntaxe de la directive 'directive' incorrecte ( see page 364) Une définition de macro commence ou se termine par l'opérateur ##, ou contient
l'opérateur # non suivi par un nom d'argument de macro.
Exemple :
E2049: Le type de classe 'type' ne peut pas être marqué comme Les classes marquées comme delphireturn sont des classes spéciales que le
__declspec(delphireturn) ( see page 364) compilateur doit reconnaître par le nom. Ces classes sont prédéfinies dans les
en-têtes.
Certaines classes delphireturn sont des Variant, AnsiString et Currency.
Vous ne pouvez pas marquer comme delphireturn des classes définies par
l'utilisateur.
E2052: Conflits de la fonction dynamique 'fonction' avec la classe de base Certains des modificateurs de cette fonction dynamique sont en conflit avec la
'classe' ( see page 364) définition de la même fonction dans la classe de base. Les deux fonctions
doivent avoir les mêmes modificateurs. Les modificateurs suivants (entre autres)
peuvent être à l'origine de ces conflits :

• __export
• __import
• declspec(naked)
• declspec(package)
• __fastcall
E2057: Spécification d'exception non autorisée ici ( see page 364) Les déclarations de type de pointeur de fonction ne peuvent pas contenir des
spécifications d'exceptions.
E2058: La variable de gestion des exceptions ne peut pas être utilisée ici ( see Vous avez tenté d'utiliser l'une des valeurs de gestion des exceptions qui sont
page 364) réservées à des structures précises de gestion des exceptions, telles que
GetExceptionCode().
E2065: L'utilisation du symbole d'espace de nommage 'symbole' crée un conflit Si vous définissez une fonction dans un espace de nommage dont le nom peut
avec un intrinsèque du même nom ( see page 365) être remplacé par un appel à un intrinsèque quand -Oi est activé, vous ne
pouvez pas avoir une déclaration "using" qui fait référence à ce membre.
Par exemple, des appels à "strcmp" sont remplacés par l'intrinsèque
"__strcmp__" quand -Oi est activé. Cela signifie que la déclaration "using
N::strcmp;" devient "using N::__strcmp__", puisque le remplacement de token
intervient avant que l'analyseur du compilateur ne puisse voir les tokens.
Dans ce cas, une erreur s'affiche car le compilateur ne sait pas comment traiter
"N::__strcmp__".
E2067: Le type renvoyé par 'main' doit être int ( see page 365) En C++, la fonction main comporte certaines restrictions, l'une d'elles étant 3
qu'elle ne peut pas être déclarée avec un type de retour autre que int.
E2073: Rien n'est autorisé après l'option pragma pop ( see page 365) L'option #pragma pop ne peut être suivie que de commentaires, de blancs ou
d'une fin de ligne.
E2091: Les fonctions ne peuvent pas renvoyer des tableaux ou des fonctions ( Une fonction a été définie comme renvoyant un tableau ou une fonction. Vérifiez
see page 365) si la valeur de retour souhaitée est un pointeur sur un tableau ou une fonction
(peut-être le symbole * a-t-il été oublié) ou si la définition de la fonction contenait
une demande d'un type de données incorrect.
E2093: Opérateur 'opérateur' non implémenté dans le type 'type' pour les L'opérateur que vous appelez n'est pas défini dans cette classe. Quand vous
arguments du même type ( see page 365) avez une expression x + x, où x est de type classe X, l'opérateur + doit être défini
dans la classe X et doit être accessible.

259
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2094: Opérateur 'opérateur' non implémenté dans le type 'type' pour les L'opérateur que vous appelez n'est pas défini dans cette classe. Quand vous
arguments de type 'type' ( see page 365) avez une expression x + x, où x est de type classe X, l'opérateur + doit être défini
dans la classe X et doit être accessible.
E2097: Instanciation explicite uniquement autorisée dans les fichiers ou les L'opérateur d'instanciation explicite "template" ne peut être utilisé qu'à un niveau
espaces de nommage ( see page 366) global ou dans un espace de nommage. Il ne peut par exemple pas être utilisé
pour qualifier une classe locale ou un membre de classe.
E2098: Un déclarateur de spécialisation explicite "template<>" est maintenant Quand vous spécialisez une fonction, par exemple en fournissant la définition de
nécessaire ( see page 366) "foo<int>" pour que foo appelle l'argument "int", vous devez désormais
commencer la déclaration par un opérateur de spécialisation explicite.
E2099: Spécialisation explicite uniquement autorisée dans les fichiers ou les L'opérateur de spécialisation explicite template<> ne peut être utilisé qu'à un
espaces de nommage ( see page 366) niveau global ou dans un espace de nommage. Il ne peut par exemple pas être
utilisé pour qualifier une classe locale ou un membre de classe.
E2101: Le mot clé 'export' doit précéder une déclaration de modèle ( see page Dans une déclaration de modèle, le mot clé 'export' ne peut se trouver qu'avant
366) le mot clé "template". Il ne peut pas être utilisé ailleurs.
E2103: Une instanciation explicite doit être utilisée avec une classe ou une L'opérateur d'instanciation explicite "template" ne peut être utilisé que pour faire
fonction modèle ( see page 366) référence à des modèles. Il ne peut pas être utilisé avec autre chose que des
modèles.
E2106: Une spécialisation explicite doit être utilisée avec une classe ou une L'opérateur de spécialisation explicite template<> ne peut être utilisé qu'en face
fonction modèle ( see page 366) d'une classe ou d'une fonction modèle. S'il est utilisé avec une classe normale, il
ne signifie rien et génère donc une erreur.
E2112: Directive d'unité inconnue : 'directive' ( see page 366) Vous ne pouvez pas utiliser ce nom comme une directive unit. A la place, utilisez
l'une des directives unit suivantes : weak, smart_init ou deny.
E2118: Les champs de bits doivent être de type entier ( see page 367) En C++, les champs de bits doivent être de type entier. Ceci inclut les
énumérations.
E2120: Impossible d'appeler 'main' depuis le programme ( see page 367) C++ n'autorise pas les appels récursifs de main( ).
E2125: Le compilateur n'a pas pu générer de constructeur de copie pour la Le compilateur doit parfois générer une fonction membre pour l'utilisateur.
classe 'classe' OU Le compilateur n'a pas pu générer de constructeur par défaut Lorsque cela n'est pas possible à cause des règles du langage, le compilateur
pour la classe 'classe' OU Le compilateur n'a pas pu générer d'opérateur = pour affiche l'un de ces messages d'erreur.
la classe 'classe' ( see page 367)
E2130: Définition de propriété circulaire ( see page 367) Indique qu'une définition de propriété dépend (directement ou non) d'elle-même.
Exemple :
E2131: Les objets de type 'type' ne peuvent pas être initialisés avec des { } ( Les structures C ordinaires peuvent être initialisées avec un ensemble de valeurs
see page 367) placées entre accolades.
Les classes C++ ne peuvent être initialisées avec des constructeurs que si la
classe a des constructeurs, des membres privés, des fonctions ou des classes
de base qui sont virtuelles.
E2148: La valeur de l'argument par défaut a été redéclarée pour le paramètre Lorsqu'un paramètre d'une fonction C++ est déclaré comme ayant une valeur par
'paramètre' ( see page 367) défaut, cette valeur ne peut être modifiée, redéclarée ou omise dans une autre
déclaration de cette fonction.
E2149: La valeur de l'argument par défaut a été redéclarée ( see page 368) Lorsqu'un paramètre d'une fonction C++ est déclaré comme ayant une valeur par
défaut, cette valeur ne peut être modifiée, redéclarée ou omise dans une autre
déclaration de cette fonction.
E2151: Mauvaise correspondance de type dans la valeur par défaut pour le La valeur par défaut du paramètre n'a pas pu être convertie en type du
paramètre 'paramètre' ( see page 368) paramètre.
Ce message est affiché lorsque le paramètre n'a pas de nom.
Lorsque vous compilez des programmes C++, ce message est toujours précédé
d'un autre expliquant la raison exacte de cette non concordance de types.
Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'",
mais la non concordance peut avoir de nombreuses autres causes.
E2157: La suppression d'un objet nécessite exactement une conversion en Si une personne utilise l'opérateur 'delete' sur un objet (pas un pointeur sur un
opérateur de pointeur ( see page 368) objet, mais l'objet lui-même), le standard exige de définir exactement une
"conversion en opérateur de pointeur" qui produira le pointeur libéré. Par
exemple :
E2173: Le gestionnaire dupliqué pour 'type1' avait déjà 'type2' ( see page 368) Vous ne pouvez pas spécifier deux gestionnaires pour un même type.
E2174: Le gestionnaire spécifié doit être le dernier ( see page 368) Dans une liste de gestionnaires catch, si le gestionnaire spécifié est présent, il
doit être le dernier de la liste.
3 E2177: Redéclaration de #pragma package avec différents arguments ( see Vous pouvez avoir plusieurs instructions de paquet #pragma dans un fichier
page 369) source tant qu'elles ont les mêmes arguments. Cette erreur se produit si le
compilateur rencontre plusieurs paquets #pragma comportant chacun des
arguments différents.
E2178: Conflit de nom VIRDEF pour 'fonction' ( see page 369) Le compilateur doit tronquer les noms substantypés à une certaine longueur en
raison de la limite imposée par le lieur. Cette opération peut (c'est très rare)
affecter deux noms au même lieur. Si ces deux noms sont des noms VIRDEF, le
compilateur affiche ce message d'erreur. La meilleure solution consiste à
changer le nom de 'fonction' pour éviter le conflit.
E2180: Numéro dispid déjà utilisé par l'identificateur ( see page 369) Les dispid doivent être uniques ; le compilateur vérifie que c'est bien le cas.
Exemple :

260
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2181: Impossible de redéfinir une fonction 'dynamique/virtuelle' avec une Lorsque vous déclarez une fonction dynamique, vous ne pouvez pas redéfinir
fonction 'dynamique/virtuelle' ( see page 369) cette fonction dans une classe dérivée avec une fonction virtuelle de même nom
et de même type. De même, quand la fonction est déclarée virtuelle, vous ne
pouvez pas la redéfinir avec une fonction dynamique dans une classe dérivée.
E2202: Goto est interdit dans un gestionnaire d'exception ( see page 369) Il est interdit de passer à un bloc try ou à un gestionnaire d'exception associé à
un bloc try.
E2205: Type 'type' incorrect dans la section __automated ( see page 369) Seuls certains types sont autorisés dans les sections __automated.
Exemple :
E2242: Le spécificateur a besoin d'un type de classe de style Delphi ( see Les spécificateurs de stockage stored, default et nodefault ne sont autorisés que
page 370) dans les déclarations de propriétés des types de classes de style Delphi.
Exemple :
E2247: 'membre' n'est pas accessible ( see page 370) Vous tentez de référencer le membre de classe C++ 'membre', mais il est privé
ou protégé et ne peut être référencé depuis cette fonction.
Ceci se produit parfois lorsque vous tentez d'appeler une fonction membre
surchargée accessible (ou un constructeur), alors que les arguments
correspondent à une fonction inaccessible.
La résolution surchargée est toujours vérifiée avant l'accessibilité.
Si cela pose problème, tentez un transtypage explicite d'un ou de plusieurs
paramètres pour sélectionner la fonction accessible désirée.
Les constructeurs de classes de base virtuelles doivent être accessibles dans la
portée de la classe la plus dérivée. Ceci s'explique par le fait... suite ( see page
370)
E2248: Impossible de trouver un constructeur par défaut pour initialiser un Lorsque vous déclarez un tableau d'une classe ayant des constructeurs, vous
élément de tableau de type 'classe' ( see page 371) devez initialiser explicitement chaque élément du tableau, ou la classe doit
posséder un constructeur par défaut.
Le compilateur définira un constructeur par défaut pour une classe si vous n'en
définissez aucun.
E2251: Impossible de trouver un constructeur par défaut pour initialiser la classe Lorsque la classe dérivée C++ 'classe2' est construite, chaque classe de base
de base 'classe' ( see page 371) 'classe1' doit d'abord être construite.
Si le constructeur pour 'classe2' ne spécifie aucun constructeur pour 'classe1'
(dans l'en-tête de 'classe2'), il doit exister un constructeur classe1::classe1() pour
la classe de base.
Ce constructeur sans paramètre est appelé constructeur par défaut.
Le compilateur fournit automatiquement un constructeur par défaut sauf si vous
avez défini un constructeur pour 'classe1'.
Dans ce cas, le compilateur ne fournit pas automatiquement le constructeur par
défaut ; c'est à vous de le faire.
E2252: 'catch' attendu ( see page 371) Dans un programme C++, un bloc 'try' doit être suivi d'au moins un bloc 'catch'.
E2253: La convention d'appel doit être attribuée au type de fonction, non au La convention d'appel n'est pas à la bonne place dans la déclaration de closure.
closure ( see page 371) Par exemple,
E2261: L'utilisation d'un dispid avec une propriété nécessite un getter ou un Cette propriété a besoin d'un getter ou d'un setter.
setter ( see page 372)
E2262: '__except' ou '__finally' attendu après '__try' ( see page 372) En C, un bloc '__try' doit être suivi d'un bloc gestionnaire '__except' ou '__finally'.
E2270: > attendu ( see page 372) Le caractère ">" de fermeture n'a pas été détecté dans un nouveau transtypage
(par exemple, dynamic_cast).
E2273: 'main' ne peut pas être déclaré comme statique ou en ligne ( see page Vous ne pouvez pas déclarer main comme statique ni en ligne. Par exemple,
372) vous ne pouvez pas utiliser static int main() ni inline int main().
E2281: Identificateur1 nécessite la définition de Identificateur2 comme type Pour utiliser Identificateur1, une définition de Identificateur2 doit être présente
pointeur ( see page 372) (un type).
Voici un exemple où __classid est le premier identificateur et TClass (qui se
trouve dans clx.h) le second :
E2289: Les sections __published ou __automated ne sont gérées que par les Le compilateur doit générer un type spécial de vtable pour les classes contenant
classes Delphi ( see page 372) des sections __published et __automated. Ces sections ne sont donc gérées
que par les classes de style Delphi.
Exemple :
E2298: Impossible de créer 'fonction' à partir de la fonction modèle 'modèle' ( Un appel à une fonction modèle a été détecté, mais aucune fonction modèle
see page 373) correspondante ne peut être générée à partir du modèle de la fonction. 3
E2301: Impossible d'utiliser des modèles dans les arguments closure ; utilisez un Lorsque vous déclarez un type closure, les arguments transmis à ce closure
typedef ( see page 373) doivent être de type simple. Les modèles ne sont pas acceptés. Pour transmettre
à un closure une référence à un objet de type modèle, vous devez déclarer un
typedef, qui compte comme un nom de type simple.
Exemple :
E2307: Le type 'type' n'est pas une classe définie avec des fonctions virtuelles Un dynamic_cast a été utilisé avec un pointeur sur un type classe qui est indéfini
( see page 373) ou ne possède pas de fonctions membre virtuelles.

261
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

E2315: 'Membre' n'est pas un membre de 'classe', car le type n'est pas encore Le membre est en train d'être référencé alors que la classe n'a pas encore été
défini ( see page 373) entièrement définie. Cela peut arriver si vous déclarez d'avance la classe X,
déclarez une variable pointeur sur X, et référencez un membre via ce pointeur ;
par exemple :
E2318: 'type' n'est pas un type de classe polymorphe ( see page 374) Cette erreur est générée si l'option -RT du compilateur (pour les informations
d'exécution) est désactivée et si :
dynamic_cast a été utilisé avec un pointeur sur une classe
ou
vous avez tenté de supprimer un pointeur sur un objet d'une classe possédant un
destructeur virtuel.
E2323: Suffixe numérique incorrect ( see page 374) Un littéral numérique est suivi d'un suffixe non reconnu par le compilateur.
Exemple :
E2326: Utilisez __declspec(spec1[, spec2]) pour combiner plusieurs __declspecs Si vous utilisez plusieurs modificateurs __declspec, le compilateur générera une
( see page 374) erreur s'ils ne sont pas combinés en un seul __declspec. Par exemple :
E2328: Les classes avec des propriétés ne peuvent pas être copiées par valeur Cette erreur se produit si vous essayez d'utiliser l'opérateur d'affectation par
( see page 374) défaut. Par exemple, le code suivant génère cette erreur avec deux libellés sur
une fiche :
E2331: Nombre de contextes d'option admissibles dépassé ( see page 374) Vous avez entremêlé trop de changements d'options de code source (en utilisant
l'option #pragma) entre les déclarations de modèles. Par exemple :
E2332: La variable 'variable' a été optimisée et n'est pas disponible ( see page Vous avez tenté d'inspecter, de surveiller ou d'accéder d'une autre façon à une
375) variable que l'optimisateur a supprimée.
Cette variable ne se voit jamais affecter de valeur et n'a aucun emplacement de
pile.
E2476: Impossible de surcharger 'fonction' ( see page 375) Vous ne pouvez pas surcharger la fonction spécifiée. Cette erreur s'affiche si
vous avez essayé de déclarer une fonction avec le même nom qu'une autre
fonction, mais la redéclaration est illégale. Par exemple, si les deux fonctions
disposent du type de liaison 'extern "C"', seule une fonction 'extern "C"' peut
recevoir un nom.
E2346: Le spécificateur d'accès 'x' de la propriété 'propriété' doit être une Seules les fonctions membre ou les données membre sont autorisées dans les
fonction membre ( see page 375) spécifications d'accès des propriétés.
Exemple :
E2347: Non concordance de paramètre dans le spécificateur d'accès Les paramètres de la fonction membre utilisés pour accéder à une propriété ne
'spécificateur' de la propriété 'propriété' ( see page 375) correspondent pas aux paramètres attendus.
Exemple :
E2348: Spécificateur de stockage non autorisé pour les propriétés de tableau ( Les propriétés de tableaux ne peuvent avoir de spécification de stockage.
see page 375) Exemple :
E2351: Membres de données statiques non autorisés dans les sections Seules les données membre non statiques et les fonctions membre sont
__published ou __automated ( see page 376) autorisées dans les sections __published ou __automated.
Exemple :
E2353: La classe 'classe' est abstraite car 'membre = 0' ( see page 376) Ce message s'affiche immédiatement après le message "Impossible de créer
une instance de la classe abstraite 'classe'". Il vous permet de comprendre
pourquoi une classe précise est considérée comme abstraite par le compilateur.
Considérez l'exemple suivant de tentative illégale d'instanciation d'une classe
abstraite :
E2359: Le membre référence 'membre' a été initialisé avec un paramètre Tentative de lier un membre référence à un paramètre constructeur. Etant donné
non-référence ( see page 376) que le paramètre cessera d'exister lorsque le constructeur retournera à son
appelant, ce code ne fonctionnera jamais correctement.
E2369: Impossible d'utiliser le résultat d'une affectation de propriété comme une Le résultat de l'affectation d'une propriété est une lvalue. Cela implique par
rvalue ( see page 377) exemple que les affectations de propriétés en chaîne ne sont pas autorisées ;
par exemple, x = y = 5, où x et y sont toutes deux des propriétés. Certaines
affectations de propriétés imbriquées peuvent également produire des erreurs ;
par exemple, x != ( y = z ), où y est une propriété.
E2370: Nom de type simple attendu ( see page 377) Pour garantir l'interopérabilité entre Delphi et C++, il existe des restrictions sur
les noms de type mentionnés dans les listes de paramètres des types closure
publiés. Les types de paramètres doivent être des noms de type simple avec un
modificateur const et une notation de pointeur ou de référence facultatifs.
3 Ainsi, lorsque vous déclarez un type closure, les arguments transmis à ce
closure doivent être de type simple. Par exemple, les modèles ne sont pas
acceptés. Pour transmettre à un closure une référence à un objet de type
modèle, vous devez déclarer un typedef, qui compte comme un nom de... suite
( see page 377)
E2398: L'argument 'argument' de la fonction modèle n'est pas utilisé dans les L'argument spécifié n'a pas été utilisé dans la liste d'arguments de la fonction.
types d'argument ( see page 377) La liste d'arguments d'une fonction modèle doit utiliser tous les arguments
formels du modèle, sans quoi il est impossible de générer une instance de
fonction modèle basée sur les types d'arguments réels.

262
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

E2419: Erreur pendant l'instanciation du modèle 'modèle' ( see page 377) Une erreur s'est produite pendant l'instanciation d'un modèle particulier. Ce
message suit toujours un autre message d'erreur qui indique ce qui ne va pas
réellement. Ce message est affiché pour aider à repérer l'instanciation du modèle
qui a causé le problème.
E2424: Classe modèle imbriquée trop profondément : 'class' ( see page 377) Le compilateur impose une certaine limite sur le niveau d'imbrication des classes
modèle. Cette limite n'est en général dépassée que par une dépendance
récursive de classe modèle.
Lorsque ceci se produit, le compilateur affiche ce message d'erreur pour toutes
les classes modèle imbriquées. Ceci facilite en général la recherche de la
récursivité.
Ce message d'erreur est toujours suivi de l'erreur fatale "Out of memory"
(mémoire saturée).
E2457: Les classes de style Delphi doivent être prises par référence ( see Un objet de style Delphi ne peut être intercepté que par pointeur.
page 378) Exemple :
E2458: Les classes Delphi doivent être dérivées de classes Delphi ( see page Vous ne pouvez pas dériver une classe Delphi d'une classe non Delphi.
378) Exemple :
E2459: Les classes de style Delphi doivent être construites en utilisant Les classes de style Delphi ne peuvent pas être définies statiquement. Elles
l'opérateur new ( see page 378) doivent être construites sur le tas.
Exemple :
E2460: Les classes de style Delphi nécessitent que la gestion d'exception soit Si vous utilisez des classes Delphi dans votre programme, vous ne pouvez pas
activée ( see page 379) désactiver la gestion d'exceptions (option -x- du compilateur) lorsque vous
compilez votre source.
E2463: 'base' est une classe de base virtuelle indirecte de 'classe' ( see page Vous ne pouvez pas créer un pointeur sur un membre C++ d'une classe de base
379) virtuelle.
Vous avez tenté de créer un tel pointeur (soit directement, soit par transtypage)
et d'accéder à un membre inaccessible de l'une de vos classes de base.
Affectation de pointeur Null ( see page 379) Lorsqu'un programme de modèle mémoire de taille petite ou moyenne se
termine, une vérification est effectuée pour déterminer si le contenu des premiers
octets dans le segment de données du programme a changé. Ces octets ne
devraient jamais être modifiés par un programme qui s'exécute. S'ils ont été
modifiés, ce message s'affiche pour vous informer que (probablement) une
valeur a été stockée dans un pointeur non initialisé.
Le programme peut sembler fonctionner correctement dans tous les autres cas ;
toutefois, il s'agit d'une erreur importante qui devrait être corrigée
immédiatement. Un échec à corriger un pointeur non initialisé peut conduire à...
suite ( see page 379)
E2268: Appel à une fonction 'fonction' non définie ( see page 379) Votre fichier source a déclaré la fonction en cours comme renvoyant un autre
type que void en C++ (ou int en C), mais le compilateur a détecté un retour
sans valeur. Toutes les fonctions int sont exemptes en C car, dans les
anciennes versions de C, il n'existait pas de type void pour indiquer qu'une
fonction ne renvoyait rien.
E2375: Débordement de pile assembleur ( see page 379) L'assembleur n'a plus de mémoire disponible pendant la compilation. Analysez la
portion de code repérée par le message d'erreur pour vérifier qu'elle utilise
correctement la mémoire.
Initialisation d'une énumération avec un type ( see page 379) Vous tentez d'initialiser une variable enum avec un type différent. Par exemple,
<nom> n'est pas un identificateur correct ( see page 380) L'identificateur est incorrect. Vérifiez que le premier caractère est une lettre ou un
caractère de soulignement (_). Les caractères suivants doivent être des lettres,
des chiffres ou des caractères de soulignement, et l'identificateur ne doit contenir
aucun espace.
Exemple pour les messages d'erreur d'"utilisation temporaire..." ( see page 380) Dans cet exemple, la fonction f requiert une référence à un entier (int), et c est un
caractère (char) :
Application en cours d'exécution ( see page 380) L'application que vous tentez d'exécuter est déjà en cours d'exécution.
Pour Windows, assurez-vous que la boucle des messages du programme s'est
correctement terminée.
Formats en virgule flottante Printf/Scanf non liés ( see page 380) Les formats en virgule flottante contiennent des informations de formatage qui
sont utilisées pour manipuler des nombres en virgule flottante dans certaines
fonctions de la bibliothèque d'exécution, telles que scanf() et atof().
Généralement, vous devez éviter la liaison des formats en virgule flottante (qui
prennent environ 1K) s'ils ne sont pas requis par votre application. Toutefois,
3
vous devez explicitement lier les formats en virgule flottante pour les
programmes qui manipulent des champs d'une manière limitée et spécifique.
Reportez-vous à la liste suivante des causes potentielles (listées de la plus
courante à la moins courante) pour déterminer comment résoudre cette erreur :...
suite ( see page 380)

263
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

W8000: Les opérateurs ambigus requièrent des parenthèses ( see page 381) (Option de ligne de commande affichant cet avertissement : -wamb)
Cet avertissement s'affiche lorsque deux opérateurs de décalage (shift),
relationnels ou booléens binaires sont utilisés sans parenthèses.
Cet avertissement est également affiché si un opérateur d'addition ou de
soustraction apparaît sans parenthèses avec un opérateur de décalage.
W8060: Affectation peut-être incorrecte ( see page 381) (Option de la ligne de commande pour supprimer l'avertissement : -w-pia)
Cet avertissement est généré lorsque le compilateur rencontre un opérateur
d'affectation comme opérateur principal d'une expression conditionnelle (faisant
partie d'une instruction 'if', 'while' ou 'do-while').
Il s'agit en général d'une faute de frappe dans l'opérateur d'égalité.
Pour supprimer cet avertissement, placez l'affectation entre parenthèses et
comparez l'ensemble à zéro de façon explicite.
Par exemple, ce code
W8002: Redémarrage de la compilation avec l'assembleur ( see page 381) (Option de la ligne de commande pour supprimer l'avertissement : -w-asc)
Le compilateur a détecté un asm sans instruction inline ou #pragma
correspondante.
La compilation redémarre en utilisant les fonctionnalités du langage assembleur.
Par défaut = Activé.
W8003: Instruction assembleur inconnue ( see page 381) (Option de la ligne de commande pour supprimer l'avertissement : -w-asm)
Le compilateur a détecté une instruction assembleur en ligne avec un opcode
non autorisé ou un token inconnu. Vérifiez l'orthographe de l'opcode ou du token.
Remarque : Vous obtenez un message d'erreur distinct de l'assembleur si
vous saisissez un code source assembleur interdit.
Par défaut, cet avertissement est désactivé.
W8052: Initialisation de base sans nom de classe maintenant obsolète ( see (Option de la ligne de commande pour supprimer l'avertissement : -w-obi)
page 382) Les précédentes versions de C++ vous permettaient d'initialiser une classe de
base en faisant suivre l'en-tête du constructeur par une liste de paramètres du
constructeur de classe de base.
Nous vous recommandons désormais d'inclure le nom de la classe de base.
Ceci facilite la lecture du code. C'est de plus nécessaire lorsque vous avez
plusieurs classes de base.
Ancienne méthode
E2117: Les champs de bits doivent être des entiers signés ou non signés ( see (Option de ligne de commande affichant cet avertissement : -wbbf)
page 382) En C ANSI, les champs de bits ne peuvent pas être de type char signé ou char
non signé.
Lorsque vous ne compilez pas en ANSI strict, le compilateur autorise ces
constructions mais affiche cet avertissement.
W8064: Appel à une fonction sans prototype ( see page 382) (Option de la ligne de commande pour supprimer l'avertissement : -w-pro)
Ce message s'affiche si l'avertissement "Prototypes requis" est activé et que
vous appelez une fonction sans fournir de prototype au préalable.
W8065: Appel à la fonction 'fonction' sans prototype ( see page 382) Ce message s'affiche si l'avertissement "Prototypes requis" est activé et que
vous appelez une fonction sans fournir au préalable un prototype pour cette
fonction.
W8009: La constante est longue ( see page 382) (Option de ligne de commande affichant cet avertissement : -wcln)
Le compilateur a détecté l'une des situations suivantes :

• une constante décimale est supérieure à 32 767, ou


• une constante octale, hexadécimale ou décimale est
supérieure à 65 535 et n'est pas suivie de la lettre l ou L.
La constante est considérée comme un entier long.
W8008: La condition est toujours vraie OU W8008 La condition est toujours (Option de la ligne de commande pour supprimer l'avertissement : -w-ccc)
fausse ( see page 383) Lorsque le compilateur rencontre une comparaison constante qui (en raison de la
nature de la valeur comparée) est toujours true ou false, il affiche cet
avertissement et évalue la condition lors de la compilation.
3 Par exemple :
W8012: Comparaison de valeurs signées et non signées ( see page 383) (Option de la ligne de commande pour supprimer l'avertissement : -w-csu)
Etant donné que les limites des types signés et non signés sont différentes, le
résultat d'une comparaison ordonnée d'une valeur non signée avec une valeur
signée peut être inattendu.
Exemple :

264
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

W8010: Caractère de continuation \ trouvé dans un commentaire // ( see page (Option de la ligne de commande pour supprimer l'avertissement : -w-com)
383) Cet avertissement s'affiche lorsqu'un commentaire C++ // se poursuit à la ligne
suivante avec le caractère barre oblique inversée (\).
Le but de ce message est de vous prévenir au cas où des lignes contenant du
code source seraient à tort intégrées à un commentaire car le commentaire se
termine par une barre oblique inversée.
Si cet avertissement s'affiche, vérifiez que la ligne suivant le commentaire // est
bien une ligne de commentaire. Si ce n'est pas le cas, supprimez la barre oblique
inversée ou placez un autre caractère après... suite ( see page 383)
W8080: 'identificateur' est déclaré mais jamais utilisé ( see page 383) (Option de ligne de commande affichant cet avertissement : -wuse)
L'identificateur spécifié n'a jamais été utilisé. Ce message peut se produire en
cas de variables locales ou statiques. Il s'affiche lorsque le fichier source déclare
la variable locale ou statique nommée comme faisant partie du bloc qui se
termine, alors que la variable n'a jamais été utilisée.
Dans le cas de variables locales, cet avertissement se produit lorsque le
compilateur rencontre l'accolade fermante de l'instruction composée ou de la
fonction. Dans le cas de variables statiques, cet avertissement se produit lorsque
le compilateur rencontre la fin du fichier source.
Par... suite ( see page 383)
W8014: Déclaration ignorée ( see page 384) (Option de la ligne de commande pour supprimer l'avertissement : -w-dig)
Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande
H2ASH. Consultez le fichier "tsm_util.txt" pour de plus amples informations.
Par défaut = Activé.
W8068: Constante hors limites dans la comparaison ( see page 384) (Option de la ligne de commande pour supprimer l'avertissement : -w-rng)
Votre fichier source inclut une comparaison comportant une sous-expression
constante qui est en dehors de la plage autorisée par le type de l'autre
sous-expression.
Par exemple, il est inutile de comparer une valeur non signée avec -1.
Pour obtenir une constante non signée supérieure à 32 767 (décimal), vous
devez :

• convertir la constante en non signé -- par exemple, (non


signé) 65535, ou
• ajouter la lettre "u" ou "U" à la constante -- par exemple,
65535u.
Même si ce message s'affiche, le compilateur génère le code
permettant d'effectuer la comparaison.
Même... suite ( see page 384)
W8016: Taille de tableau ignorée pour 'delete' ( see page 384) (Option de la ligne de commande pour supprimer l'avertissement : -w-dsz)
L'EDI de C++ affiche cet avertissement lorsque vous avez spécifié la taille d'un
tableau lors de sa suppression.
Avec les nouvelles spécifications de C++, vous n'avez plus besoin de le faire. Le
compilateur ignore cette construction.
Cet avertissement permet aux anciens codes de se compiler.
W8082: Division par zéro ( see page 385) (Option de la ligne de commande pour supprimer l'avertissement : -w-zdi)
Une expression de division ou de reste a un zéro littéral comme diviseur.
W8018: Affectation de 'type' à 'énumération' ( see page 385) (Option de la ligne de commande pour supprimer l'avertissement : -w-eas)
Affectation d'une valeur entière à un type enum.
Ceci est une erreur dans C++, mais elle est réduite à un avertissement pour
permettre aux programmes existants de s'exécuter.
W8006: Initialisation de 'identificateur' avec 'identificateur' ( see page 385) (Option de la ligne de commande pour supprimer l'avertissement : -w-bei)
Vous tentez d'initialiser une variable enum avec un type différent.
Par exemple, l'initialisation suivante affichera cet avertissement car 2 est de type
int et non de type enum count :
3
W8001: & superflu avec une fonction ( see page 385) (Option de ligne de commande affichant cet avertissement : -wamp)
L'opérateur adresse de (&) n'est pas nécessaire avec un nom de fonction ; ces
opérateurs ne sont pas pris en compte.
W8020: 'identificateur' est déclaré à la fois externe et statique ( see page 385) (Option de la ligne de commande pour supprimer l'avertissement : -w-ext)
Cet identificateur est apparu dans une déclaration qui l'a marqué implicitement
ou explicitement comme global ou externe, ainsi que dans une déclaration
statique.
L'identificateur est considéré comme statique.
Vérifiez toutes les déclarations pour cet identificateur.

265
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

W8007: La valeur hexadécimale contient plus de trois chiffres ( see page 386) (Option de ligne de commande supprimant cet avertissement : -w-big)
Dans les anciennes versions de C, une séquence d'échappement hexadécimale
pouvait contenir plus de trois chiffres.
Le standard ANSI autorise un nombre quelconque de chiffres, à la condition que
la valeur tienne dans un octet.
Cet avertissement s'affiche lorsque vous avez une séquence d'échappement
hexadécimale longue avec des zéros de début (\x00045, par exemple).
Les anciennes versions de C interprètent cette chaîne différemment.
W8024: La classe de base 'classe1' est aussi une classe de base de 'classe2' ( (Option de la ligne de commande pour supprimer l'avertissement : -w-ibc)
see page 386) Une classe hérite directement et indirectement de la même classe de base. Il est
recommandé d'éviter ce genre de programmation pour des raisons de portabilité.
W8022: 'fonction1' cache la fonction virtuelle 'fonction2' ( see page 386) (Option de la ligne de commande pour supprimer l'avertissement : -w-hid)
Une fonction virtuelle dans une classe de base est généralement redéfinie par
une déclaration dans une classe dérivée.
Dans ce cas, une déclaration de même nom mais de types d'arguments
différents rend les fonctions virtuelles inaccessibles aux autres classes dérivées.
W8023: La variable tableau 'identificateur' est near ( see page 386) (Option de la ligne de commande pour supprimer l'avertissement : -w-ias)
Lorsque vous activez l'option Far Data Threshold, le compilateur définit
automatiquement comme far toutes les variables globales de taille supérieure au
seuil.
Si la variable est un tableau initialisé avec une taille non spécifiée, sa taille totale
n'est pas connue lorsque le compilateur doit décider s'il doit en faire une variable
near ou far, aussi le compilateur la définit-il comme near.
Le compilateur affiche cet avertissement si le nombre d'initialisateurs fournis pour
le tableau fait en sorte que la taille totale de la variable dépasse le seuil de taille
des... suite ( see page 386)
W8061: L'initialisation est partiellement entre accolades ( see page 387) (Option de ligne de commande affichant cet avertissement : -wpin)
Lorsque des structures sont initialisées, les accolades peuvent être utilisées pour
marquer l'initialisation de chaque membre de la structure. Si un membre est un
tableau ou une structure, utilisez des paires d'accolades imbriquées. Ceci
garantit que le compilateur placera les bonnes valeurs dans les membres
appropriés. Lorsque des accolades facultatives sont omises, le compilateur
affiche cet avertissement.
W8038: Le membre constante 'identificateur' n'est pas initialisé ( see page 387) (Option de la ligne de commande pour supprimer l'avertissement : -w-nci)
Cette classe C++ contient un membre constant 'membre' qui n'a pas
d'initialisation.
Notez que les membres constants ne peuvent être qu'initialisés ; ils ne peuvent
être la destination d'une affectation.
W8071: La conversion peut perdre des chiffres significatifs ( see page 387) (Option de ligne de commande affichant cet avertissement : -wsig)
Pour un opérateur d'affectation ou dans d'autres circonstances, votre fichier
source requiert une conversion d'un type de données intégral vers un autre type
de données intégral plus petit.
Etant donné que les variables de type de données intégral n'ont pas la même
taille, ce type de conversion peut influer sur le fonctionnement de votre
programme.
W8043: Définition de macro ignorée ( see page 387) (Option de la ligne de commande pour supprimer l'avertissement : -w-nma)
Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande
H2ASH. Consultez le fichier "tsm_util.txt" pour de plus amples informations.
W8017: La redéfinition de 'x' n'est pas identique ( see page 387) (Option de la ligne de commande pour supprimer l'avertissement : -w-dup)
Votre fichier source a redéfini la macro 'ident' avec du texte qui n'était pas
exactement celui de la première définition de la macro.
Le nouveau texte remplace l'ancien.
W8079: Mélange de pointeurs de plusieurs types 'char' ( see page 387) (Option de ligne de commande affichant cet avertissement : -wucp)
Vous avez converti un pointeur char signé en un pointeur char non signé, ou vice
versa, sans utiliser de transtypage explicite. Ceci n'est pas grave, bien
qu'incorrect.
W8067: Instructions de retour avec et sans valeur utilisées ( see page 388) (Option de la ligne de commande pour supprimer l'avertissement : -w-ret)
3 La fonction en cours a des instructions de retour avec et sans valeurs.
Cette situation est autorisée en langage C, mais génère presque toujours une
erreur.
Il est possible qu'une instruction de retour ait été omise à la fin de la fonction.

266
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

W8048: Utilisez un nom qualifié pour accéder au type membre 'identificateur' ( (Option de la ligne de commande pour supprimer l'avertissement : -w-nst)
see page 388) Dans les anciennes spécifications de C++, les noms de typedef et de repères
déclarés dans des classes étaient directement visibles dans la portée globale.
Dans les nouvelles spécifications de C++, ces noms doivent être précédés de
classe::qualificateur s'ils doivent être utilisés en dehors de la portée de leur
classe.
Le compilateur affiche cet avertissement lorsqu'un nom est défini de façon
unique dans une seule classe. Le compilateur autorise cette utilisation sans
classe::. Cela permet aux anciennes versions de code de se compiler.
W8039: Liste d'initialiseurs de constructeurs ignorée ( see page 388) (Option de la ligne de commande pour supprimer l'avertissement : -w-ncl)
Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande
H2ASH. Consultez le fichier "tsm_util.txt" pour de plus amples informations.
W8040: Corps de fonction ignoré ( see page 388) (Option de la ligne de commande pour supprimer l'avertissement : -w-nfd)
Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande
H2ASH. Consultez le fichier "tsm_util.txt" pour de plus amples informations.
W8042: Initialiseur pour l'objet 'x' ignoré ( see page 388) (Option de la ligne de commande pour supprimer l'avertissement : -w-nin)
Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande
H2ASH. Consultez le fichier "tsm_util.txt" pour de plus amples informations.
W8044: Directive #undef ignorée ( see page 389) (Option de la ligne de commande pour supprimer l'avertissement : -w-nmu)
Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande
H2ASH. Consultez le fichier "tsm_util.txt" pour de plus amples informations.
W8037: Fonction non const 'fonction' appelée pour un objet const ( see page (Option de ligne de commande supprimant cet avertissement : -w-ncf)
389) Une fonction membre non constante a été appelée pour un objet const.
(Ceci est une erreur réduite en avertissement pour permettre aux programmes
existants de s'exécuter.)
W8051: Fonction non volatile 'fonction' appelée pour un objet volatile ( see (Option de la ligne de commande pour supprimer l'avertissement : -w-nvf)
page 389) En C++, une fonction membre de classe a été appelée pour un objet volatile du
type de la classe, mais la fonction n'a pas été déclarée avec volatile après
l'en-tête de fonction. Seule une fonction membre volatile peut être appelée pour
un objet volatile.
Par exemple, si vous avez :
W8019: Le code n'a pas d'effet ( see page 389) (Option de la ligne de commande pour supprimer l'avertissement : -w-eff)
Cet avertissement s'affiche lorsque le compilateur rencontre une instruction
comportant des opérateurs sans effet.
Par exemple, l'instruction
W8057: Paramètre 'paramètre' jamais utilisé ( see page 390) (Option de la ligne de commande pour supprimer l'avertissement : -w-par)
Le paramètre nommé, déclaré dans la fonction, n'a jamais été utilisé dans le
corps de la fonction.
Ceci est peut-être une erreur, souvent causée par une faute de frappe dans le
nom du paramètre.
Cet avertissement s'affiche également si l'identificateur est redéclaré comme une
variable automatique (locale) dans le corps de la fonction.
Le paramètre est masqué par la variable automatique et reste inutilisé.
W8070: La fonction doit renvoyer une valeur ( see page 390) (Option de la ligne de commande pour supprimer l'avertissement : -w-rvl)
Cette fonction a été déclarée (peut-être implicitement) pour renvoyer une valeur.
Le compilateur a détecté une instruction de retour sans valeur de retour, ou a
atteint la fin de la fonction sans rencontrer d'instruction de retour.
Renvoyez une valeur ou modifiez la déclaration de la fonction pour renvoyer void.
W8047: Déclaration de la fonction statique function ignorée ( see page 390) (Option de la ligne de commande pour supprimer l'avertissement : -w-nsf)
Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande
H2ASH. Consultez le fichier "tsm_util.txt" pour de plus amples informations.
W8041: Valeur non signée rendue négative ( see page 390) (Option de la ligne de commande pour supprimer l'avertissement : -w-ngu)
Il est normalement inutile de rendre négative une valeur non signée car le
résultat sera toujours non signé.
Exemple :
W8054: Ce style de définition de fonction est maintenant obsolète ( see page (Option de ligne de commande supprimant cet avertissement : -w-ofp) 3
390) En C++, cette ancienne définition de fonction C est illégale :
W8025: Pragma mal formé ( see page 391) (Option de la ligne de commande pour supprimer l'avertissement : -w-ill)
Un pragma ne correspond pas à l'un des pragmas attendus par le compilateur.
W8063: Opérateur de préfixe surchargé 'opérateur' utilisé comme un opérateur (Option de la ligne de commande pour supprimer l'avertissement : -w-pre)
de suffixe ( see page 391) La spécification C++ vous permet de surcharger les versions à préfixe et à
suffixe des opérateurs "++" et "--".
Lorsque l'opérateur de préfixe est surchargé, mais est utilisé dans un contexte de
suffixe, le compilateur utilise l'opérateur de préfixe et affiche cet avertissement.
Cet avertissement permet aux anciens codes de se compiler.

267
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

W8015: Déclarez 'type' avant de l'utiliser dans le prototype ( see page 391) (Option de la ligne de commande pour supprimer l'avertissement : -w-dpu)
Lorsqu'un prototype de fonction fait référence à un type structure non déclaré, la
déclaration dans le prototype est différente de la déclaration en dehors du
prototype.
Par exemple,
W8069: Conversion de pointeur non portable ( see page 391) (Option de la ligne de commande pour supprimer l'avertissement : -w-rpt)
Une valeur entière différente de zéro est utilisée dans un contexte où un pointeur
ou une valeur entière est requis ; la taille du type entier et du pointeur est la
même.
Utilisez un transtypage explicite si vous devez absolument effectuer cette tâche.
W8066: Code inatteignable ( see page 392) (Option de la ligne de commande pour supprimer l'avertissement : -w-rch)
Une instruction break, continue, goto ou return n'était pas suivie d'un libellé ou de
la fin d'une boucle ou d'une fonction.
Le compilateur vérifie les boucles while, do et for avec une condition de test
constante et tente de détecter celles qui sont erronées.
W8029: Un temporaire a été utilisé pour le paramètre '???' ( see page 392) (Option de la ligne de commande pour supprimer l'avertissement : -w-lvc)
En C++, une variable ou un paramètre de type référence doit se voir affecter une
référence à un objet du même type. Si les types ne sont pas identiques, la valeur
est affectée à un temporaire du bon type, et l'adresse du temporaire est affectée
à la variable ou au paramètre de référence.
Cet avertissement signifie que la variable ou le paramètre de référence ne
désigne pas ce qui était prévu, mais une variable temporaire autrement inutilisée.
Dans l'exemple ci-dessous, la fonction f requiert une référence à un entier (int),...
suite ( see page 392)
W8031: Temporaire utilisé pour le paramètre 'paramètre' OU W8029 Temporaire (Option de la ligne de commande pour supprimer l'avertissement : -w-lvc)
utilisé pour le paramètre 'numéro' OU W8030 Temporaire utilisé pour le En C++, une variable ou un paramètre de type référence doit se voir affecter une
paramètre 'paramètre' dans l'appel à 'fonction' OU W8032 Temporaire utilisé référence à un objet du même type.
pour le paramètre 'numéro' dans l'appel à 'fonction' ( see page 392) Si les types ne sont pas identiques, la valeur est affectée à un temporaire du bon
type, et l'adresse du temporaire est affectée à la variable ou au paramètre de
référence.
Cet avertissement signifie que la variable ou le paramètre de référence ne
désigne pas ce qui était prévu, mais une variable temporaire autrement inutilisée.
W8032: Un temporaire a été utilisé pour le paramètre 2 dans l'appel à '???' ( (Option de la ligne de commande pour supprimer l'avertissement : -w-lvc)
see page 392) En C++, une variable ou un paramètre de type référence doit se voir affecter une
référence à un objet du même type. Si les types ne sont pas identiques, la valeur
est affectée à un temporaire du bon type, et l'adresse du temporaire est affectée
à la variable ou au paramètre de référence.
Cet avertissement signifie que la variable ou le paramètre de référence ne
désigne pas ce qui était prévu, mais une variable temporaire autrement inutilisée.
Dans l'exemple ci-dessous, la fonction f requiert une référence à un entier (int),...
suite ( see page 392)
W8028: Variable temporaire utilisée pour initialiser 'identificateur' ( see page (Option de la ligne de commande pour supprimer l'avertissement : -w-lin)
393) En C++, une variable ou un paramètre de type référence doit se voir affecter une
référence à un objet du même type.
Si les types ne sont pas identiques, la valeur est affectée à un temporaire du bon
type, et l'adresse du temporaire est affectée à la variable ou au paramètre de
référence.
Cet avertissement signifie que la variable ou le paramètre de référence ne
désigne pas ce qui était prévu, mais une variable temporaire autrement inutilisée.
Exemple
Dans cet exemple, la fonction f requiert une référence à un entier... suite ( see
page 393)
W8074: Structure transmise par valeur ( see page 393) (Option de ligne de commande affichant cet avertissement : -wstv)
Cet avertissement est généré dès qu'une structure est transmise par une valeur
comme argument.
Une erreur de programmation fréquente consiste à laisser un opérateur "adresse
de" (&) en dehors d'une structure lors de sa transmission comme argument.
3 Etant donné que les structures peuvent être transmises par valeur, cette
omission est acceptable.
Cet avertissement attire simplement votre attention sur cette erreur.
W8011: Comparaison de pointeur non portable ( see page 393) (Option de la ligne de commande pour supprimer l'avertissement : -w-cpt)
Votre fichier source a comparé un pointeur avec un non pointeur autre que la
constante 0.
Il est recommandé d'utiliser un transtypage pour supprimer cet avertissement si
la comparaison est correcte.

268
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

W8075: Conversion de pointeur suspecte ( see page 394) (Option de la ligne de commande pour supprimer l'avertissement : -w-sus)
Le compilateur a détecté une conversion de pointeur à cause de laquelle le
pointeur pointe sur un type différent.
Utilisez un transtypage pour supprimer cet avertissement si la conversion est
correcte.
Cet avertissement est en général affiché lorsque le compilateur C convertit un
pointeur de fonction d'un type en un autre (le compilateur C++ génère une erreur
lorsque vous lui demandez d'effectuer cette conversion). Ce message peut être
supprimé en faisant un transtypage. En voici une occurrence fréquente pour les
programmeurs sous Windows :
W8059: La taille de la structure a changé ( see page 394) (Option de la ligne de commande pour supprimer l'avertissement : -w-pck)
Ce message d'avertissement s'affiche lorsque l'alignement de la structure est
modifié après l'inclusion d'un fichier.
Ce message vous prévient si un fichier inclus change la compression d'une
structure mais ne restaure pas, au final, le paramètre d'origine. Si ceci est voulu,
vous pouvez spécifier la directive #pragma nopackwarning en fin de fichier inclus
pour désactiver cet avertissement pour ce fichier précis.
L'avertissement peut être également désactivé avec #pragma warn -pck.
8045: Pas de déclaration pour la fonction 'fonction' ( see page 394) (Option de ligne de commande affichant cet avertissement : -wnod)
Ce message s'affiche si vous appelez une fonction sans l'avoir déclarée.
En C, vous pouvez déclarer une fonction sans présenter de prototype :
W8073: Structure 'structure' non définie ( see page 395) (Option de la ligne de commande pour afficher l'avertissement = -wstu)
Votre fichier source a utilisé la structure nommée dans une ligne avant celle où
l'erreur est signalée (probablement sur un pointeur vers une structure), mais
n'avait aucune définition pour la structure.
Ceci est probablement le fait d'un nom de structure mal orthographié ou d'une
déclaration manquante.
W8013: Utilisation possible de 'identificateur' avant sa définition ( see page 395) (Option de ligne de commande affichant cet avertissement : -wdef)
Votre fichier source a utilisé la variable 'identificateur' dans une expression avant
qu'une valeur ne lui ait été affectée.
Le compilateur utilise une analyse simple du programme pour reconnaître cette
erreur.
Si l'utilisation d'une variable se produit physiquement avant toute affectation, cet
avertissement est généré.
Bien sûr, le déroulement du programme peut affecter la valeur avant que le
programme ne l'utilise.
W8004: 'identificateur' a une valeur qui n'est jamais utilisée ( see page 395) (Option de la ligne de commande pour supprimer l'avertissement : -w-aus)
La variable apparaît dans une affectation mais n'est pas utilisée dans la fonction
qui vient de se terminer.
Cet avertissement ne s'affiche que lorsque le compilateur rencontre l'accolade de
fin.
Le commutateur #pragma warn -aus a une granularité de niveau fonction.
Vous ne pouvez pas désactiver cet avertissement pour des variables
individuelles dans une fonction ; il est activé ou désactivé pour la fonction entière.
W8081: Les fonctions void ne peuvent pas renvoyer de valeur ( see page 395) (Option de la ligne de commande pour supprimer l'avertissement : -w-voi)
Votre fichier source a déclaré la fonction en cours comme retournant void, mais
le compilateur a détecté une instruction de retour avec une valeur. La valeur de
cette instruction sera ignorée.
Exemple :
W8078: L'expression throw viole la spécification d'exception ( see page 396) (Option de la ligne de commande pour supprimer l'avertissement : -w-thr)
Cet avertissement s'affiche lorsque vous ajoutez une spécification d'exception à
une définition de fonction et que vous déclenchez un type dans le corps de la
fonction qui n'est pas mentionné dans la spécification d'exception.
Le programme suivant génère cet avertissement :
W8021: Le gestionnaire de 'type1' est caché par le gestionnaire précédent de (Option de la ligne de commande pour supprimer l'avertissement : -w-hch)
'type2' ( see page 396) Cet avertissement s'affiche lorsqu'un gestionnaire pour un type 'D' dérivé du type
'B' est spécifié après un gestionnaire pour 'B', car le gestionnaire pour 'D' ne sera
jamais appelé. 3
W8056: Débordement arithmétique d'entiers ( see page 396) Le compilateur a détecté une condition de débordement dans une expression de
calcul sur des entiers.
Par exemple :

269
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

W8035: Message défini par l'utilisateur ( see page 396) Le message d'erreur pour lequel vous avez demandé de l'aide est un
avertissement défini par l'utilisateur.
En code C++, les messages définis par l'utilisateur sont introduits à l'aide de la
syntaxe #pragma du compilateur de messages.
Remarque : En plus des messages que vous introduisez avec #pragma,
des avertissements définis par l'utilisateur peuvent être générés par des
bibliothèques d'autres fournisseurs. Contactez ces fournisseurs pour obtenir de
l'aide sur l'un de leurs messages.
W8049: Utilisez '> >' pour les modèles imbriqués au lieu de '>>' ( see page 396) (Option de la ligne de commande pour supprimer l'avertissement : -w-ntd)
Un espace est nécessaire pour séparer le ">" fermant dans un nom de modèle
imbriqué, mais comme il est fréquemment oublié, le compilateur accepte un ">>"
avec cet avertissement.
W8026: Les fonctions avec des spécifications d'exception ne sont pas Egalement :Les fonctions prenant des arguments classe par valeur ne sont pas
développées en ligne ( see page 397) développées en ligne
(Option de la ligne de commande pour supprimer l'avertissement : -w-inl)
Les spécifications d'exceptions ne sont pas développées en ligne : vérifiez si
votre code en ligne contient des spécifications d'exceptions.
Les fonctions acceptant des arguments "classe par valeur" ne sont pas
développées en ligne : lorsque la gestion des exceptions est activée, les
fonctions acceptant des arguments de classe par valeur ne peuvent pas être
développées en ligne.
Remarque : Les fonctions acceptant des paramètres de classe par référence
ne sont pas concernées par cette restriction.
W8058: Impossible de créer un en-tête précompilé : 'raison' ( see page 397) (Option de la ligne de commande pour supprimer l'avertissement : -w-pch)
Cet avertissement s'affiche lorsque les en-têtes précompilés sont activés mais
que le compilateur n'a pas pu en générer un pour l'une des raisons suivantes :
RaisonExplication
Echec d'écriture. Le compilateur n'a pas pu écrire le fichier d'en-tête précompilé.
Cela se produit lorsque vous spécifiez un emplacement invalide pour la mise en
cache des en-têtes précompilés ou si le disque est plein.
Code de l'en-tête. L'un des en-têtes contenait un corps de fonction non inline.
données initialisées dans l'en-tête. L'un des en-têtes contenait une définition de
variable globale (en C, une... suite ( see page 397)
W8046: Option pragma pop sans option push correspondante ( see page 397) Le compilateur a rencontré une option #pragma pop avant une précédente option
#pragma push ou, dans le cas d'une imbrication, il y a plus d'occurrences
d'options #pragma pop que d'options #pragma push.
W8050: Aucun fichier OBJ présent. Désactivation de l'option des types externes. (Option de la ligne de commande pour supprimer l'avertissement : -w-nto)
( see page 397) Un fichier d'en-tête précompilé fait référence à un fichier de types d'objet, mais
ce fichier est introuvable. Cette erreur n'est pas fatale mais augmente la taille de
vos fichiers objets de façon indue.

270
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

W8027: Les fonctions contenant 'instruction' ne sont pas développées en ligne (Option de la ligne de commande pour supprimer l'avertissement : -w-inl)
( see page 398) où :
'instruction' peut être un de ces éléments :

• Variables statiques
• Initialiseurs d'agrégation
• Certaines instructions de retour
• Destructeurs locaux
• Certaines instructions if
• Classes locales
• Instructions de retour manquantes
• Mots réservés non autorisés listés "Mots réservés"
ci-après.
Mots réservés
Les fonctions contenant l'un de ces mots réservés ne
peuvent pas être développées en ligne, même si elles
sont spécifiées comme telles :
asmexcept
breakfinally
casefor
continuegoto
defaultswitch
dowhile
La fonction reste valide, mais sera traitée comme une
fonction statique ordinaire (non globale).
Une copie de la fonction apparaîtra dans chaque unité...
suite ( see page 398)
W8036: Mot clé non ANSI utilisé : 'mot clé' ( see page 398) (Option de ligne de commande affichant cet avertissement : -wnak)
Un mot clé non ANSI (tel que '__fastcall') a été utilisé alors que vous aviez
demandé une conformité ANSI stricte à l'aide de l'option -A.
W8053: 'identificateur' obsolète ( see page 399) (Option de la ligne de commande pour supprimer l'avertissement : -w-obs)
Cet avertissement s'affiche si vous utilisez une fonction de lien "C" spécifiée. Il
vous prévient si des fonctions sont "obsolètes".
Voici un exemple de son utilisation :
W8103: Le chemin 'chemin' et le nom de fichier 'nomfichier' dépassent la taille (Option de ligne de commande affichant cet avertissement : -wstv)
maximale 'n' ( see page 399) Lors de la recherche des fichiers d'inclusion, le compilateur C++ a rencontré un
fichier dont le chemin et le nom de fichier contiennent un nombre de caractères
supérieur au nombre de caractères maximal de Windows. Renommez les
chemins et les noms de fichiers que vous pouvez, et raccourcissez leurs noms si
possible.
W8062: Options et avertissements précédents non restaurés ( see page 399) Le compilateur n'a pas rencontré une option #pragma pop après une précédente
option #pragma push ou, lors d'une imbrication, il y a plus d'occurrences
d'options #pragma push que d'options #pragma pop.
W8055: Débordement possible dans une opération shift ( see page 399) Le compilateur a détecté des cas où le nombre de bits décalés est supérieur au 3
nombre de bits de la variable affecté. Par exemple :
W8072: Arithmétique de pointeur suspecte ( see page 399) Ce message indique un effet non prévu d'un calcul sur pointeur (ou d'un indice
de tableau) détecté dans une expression.
Exemple :

271
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

W8033: La conversion en 'type' échouera pour les membres de la base virtuelle (Option de la ligne de commande pour supprimer l'avertissement : -w-mpc)
'classe' ( see page 400) Cet avertissement ne s'affiche que si l'option -Vv est utilisée.
Cet avertissement peut s'afficher lorsqu'un pointeur de membre d'un type est
transtypé en un pointeur de membre d'un autre type et que la classe du pointeur
de membre converti a des bases virtuelles.
Si cet avertissement s'affiche, cela signifie que, à l'exécution, si la conversion du
pointeur de membre ne peut s'effectuer, le résultat du transtypage sera un
pointeur de membre NULL.
W8034: Précision maximum utilisée pour le type pointeur membre 'type' ( see (Option de la ligne de commande pour supprimer l'avertissement : -w-mpd)
page 400) Lors de la déclaration d'un type de pointeur de membre, sa classe n'a pas été
entièrement définie et l'option -Vmd a été utilisée, le compilateur doit utiliser la
représentation la plus générique (et la moins efficace) pour ce type de pointeur
de membre. Ceci peut entraîner la création d'un code moins efficace (et rendre le
type de pointeur de membre plus volumineux que nécessaire) et générer des
problèmes de compilation séparée ; voir l'option -Vm du compilateur pour plus de
détails.

3.1.2.1 E2066: Héritage MOM invalide


Le compilateur émet cette erreur si la classe en cours de compilation n'a pas les mêmes indicateurs MOM (Microsoft Object
Model) correspondants que son parent direct.

Ce message d'erreur de compilation est désapprouvé.

3.1.2.2 E2525: Vous devez définir _PCH_STATIC_CONST avant


d'inclure xstring afin d'utiliser cette fonctionnalité
Vous avez essayé d'utiliser une fonctionnalité définie dans xstring, partie de la bibliothèque Dinkumware standard C++. Le
compilateur C++ ne peut pas générer un en-tête précompilé car une constante (définie dans xstring) se trouve dans l'en-tête. Si
vous souhaitez inclure xstring, vous devez d'abord définir le define _PCH_STATIC_CONST.

3.1.2.3 E2526: La propriété 'nom' utilise une autre propriété comme


getter/setter ; non autorisé
Les propriétés ont généralement un getter et un setter, mais une propriété ne peut pas servir de getter ou de setter à une autre
propriété.

3.1.2.4 E2008: Les fonctions d'accès à la propriété publiée doivent


utiliser la convention d'appel __fastcall
La convention d'appel pour les fonctions d'accès d'une propriété (lecture, écriture et stockée) déclarée dans une section
__published doit être __fastcall. Ceci vaut également pour les propriétés surchargées.
3
Exemple :
struct__declspec(delphiclass) clxclass{int__fastcall Getter1(void); int__cdecl
Getter2(void); __published:int __property ip1 = {read = Getter1}; // OKint __property ip2 =
{read = Getter2}; // Erreur};

272
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.5 E2122: L'appel de fonction s'est terminé par une exception


non gérée 'valeur' à l'adresse 'adresse'
Ce message s'affiche lorsqu'une expression, que vous évaluez lors du débogage, inclut un appel de fonction se terminant par
une exception non gérée. Par exemple si, dans la boîte de dialogue d'évaluation du débogueur, vous demandez l'évaluation de
l'expression foo()+1 et que l'exécution de la fonction foo() provoque une erreur GP, cette évaluation génère le message d'erreur
ci-dessus.

Vous pouvez également voir ce message dans la fenêtre de suivi car elle affiche également le résultat de l'évaluation d'une
expression.

3.1.2.6 E2506: La spécialisation explicite de 'spécificateur' est


ambiguë : des arguments modèles doivent être spécifiés
Dans le code suivant, des arguments modèles explicites sont nécessaires :
template<class T> void foo(T);
template<class T> void foo(T *);
template<> void foo(int *); // erreur, doit stipuler 'foo<int>' ou 'foo<int *>'

3.1.2.7 E2483: La dimension du tableau 'spécificateur' n'a pas pu


être déterminée
Cette erreur se produira si, lors de l'instanciation d'un type, une dimension de tableau ne peut pas être calculée (ceci est
normalement dû à une autre erreur qui doit être indiquée).

Par exemple, si une dimension de tableau dépend d'un paramètre de modèle mais qu'une erreur se produit alors qu'il est
analysé et que l'argument de modèle en cours de substitution ne génère pas d'expression constante légale, cette erreur s'affiche.

3.1.2.8 E2509: Valeur hors limites


L'assembleur en ligne a détecté un dépassement numérique dans une de vos expressions. Vérifiez que tous vos nombres
peuvent tenir dans 32 bits.

3.1.2.9 E2510: Non concordance de taille d'opérande


L'aide n'est pas disponible pour cet élément.

3
3.1.2.10 E2050: La classe __declspec(delphireturn) 'classe' doit
avoir exactement une donnée membre
Il s'agit d'une erreur interne du compilateur. Une classe marquée comme delphireturn comporte plusieurs données membre non
statiques.

273
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.11 E2530: Option non reconnue ou aide indisponible


Vous avez entré un élément de commande que le compilateur C++ ne peut pas analyser, ou l'option entrée ne dispose pas
d'une aide associée. Effectuez une nouvelle tentative.

3.1.2.12 E2527: L'option 'nom' ne peut pas être définie via 'nom'
Une tentative de définition d'une option a été effectuée dans un fichier source alors que cette option ne peut pas être définie
après le démarrage de l'analyse ou de la compilation du fichier. Définissez plutôt cette option sur la ligne de commande ou dans
un fichier .cfg.

Par exemple, si un fichier source contient un #pragma option push —v, vous devez retirer le push ou définir /unset sur la
ligne de commande ou dans un fichier .cfg.

3.1.2.13 E2528: L'option 'nom' doit être définie avant la compilation


Une tentative de définition d'une option a été effectuée dans un fichier source alors que cette option doit être définie avant le
démarrage de la compilation. Définissez plutôt cette option sur la ligne de commande, dans un fichier .cfg ou au début du
fichier source avant la ligne int foo(); .

3.1.2.14 E2074: La valeur après -g ou -j doit être comprise entre 0 et


255 inclus
Les options -g et -j de la ligne de commande peuvent être suivies par un nombre facultatif. Le compilateur attend que ce nombre
soit compris entre 0 et 255 inclus.

3.1.2.15 E2492: Les propriétés peuvent uniquement être affectées en


utilisant une instruction simple, par exemple \"prop = valeur;\"
Les affectations de propriétés doivent être effectuées dans des instructions d'affectation simples. Si les affectations de propriétés
pouvaient devenir des Lvalues, ce qui arrive lorsque les affectations de propriétés sont imbriquées dans des instructions plus
grandes, le getter est appelé pour créer la Lvalue, avec tous les effets de bord causés par le getter. Le compilateur n'autorise
qu'un appel soit au getter soit au setter dans une instruction.

Par exemple :
class myClass
{
3 int X;
public:
int __property x = { read=getx, write=putx };
int getx() { return X; }
void putx(int val) { X = val; }
} OneClass;
int value(int);
int main()
{
return value(OneClass.x = 4); // Ceci provoque une erreur

274
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.16 E2505: L'instanciation explicite requiert un spécificateur de


type élaboré (par exemple, "class foo<int>")
Le code suivant est incorrect :
template<class T> class foo;
template foo<int>; // mot-clé 'class' manquant
Voir aussi
Fonctions de modèles implicites et explicites ( see page 451)

3.1.2.17 E2100: Liste de déclarateurs de modèles incorrecte


Une liste de déclarateurs ne doit pas suivre de déclaration de classe modèle. Par exemple :
template<class T>
class foo {
} object_name; // Ceci provoque une erreur

3.1.2.18 E2102: Impossible d'utiliser le modèle 'modèle' sans


spécifier des paramètres de spécialisation
Le format générique d'un modèle doit être référencé en utilisant des paramètres de spécialisation. Par exemple, pour une classe
modèle nommée foo utilisant deux paramètres modèle, une référence correcte se présenterait ainsi :
foo<int, char>
Voici les deux seuls cas dans lesquels vous pouvez faire référence au modèle en n'utilisant que son nom (foo) :

• Lors de la transmission du nom du modèle comme argument du modèle 'modèle'


• Lors de la déclaration des membres de ce modèle classe, pour faire référence au type de modèle d'inclusion.
Par exemple :
template<class T>
class foo
{
public:
foo(); // utilisation correcte du seul nom de modèle
foo& operator=(const foo&);
};
foo<foo> x; // erreur : ce n'est pas un argument modèle template
foo y; // erreur : des paramètres de spécialisation sont nécessaires

3.1.2.19 E2107: Utilisation incorrecte du modèle 'modèle' 3


Cette erreur se produit si vous tentez d'utiliser un paramètre du modèle 'modèle' pour autre chose que pour faire référence à une
spécialisation de modèle ou pour transmettre ce paramètre comme argument du modèle 'modèle' à un autre modèle. Par
exemple :
template<template<class T> class U>
class foo;
template<template<class T> class U>
class bar

275
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

{
U x;// erreur : ce n'est pas une spécialisation
U<U> y;// ok : utilisé comme spécialisation et comme
// argument du modèle 'modèle'
U<bar> z;// ok : utilisé pour faire référence à une spécialisation
};

3.1.2.20 E2105: Le qualificateur 'modèle' doit spécifier un nom de


modèle membre
Lors de l'analyse du code qui dépend d'une certaine manière d'un paramètre de modèle, il est parfois impossible de savoir si un
nom de membre résoudra un nom de fonction modèle ou un paramètre normal. Dans le code suivant, un qualificateur 'modèle'
est nécessaire pour savoir si l'opérateur ‘<’ (inférieur à) doit être analysé comme caractère de début d'une liste d'arguments
modèle ou comme opérateur "inférieur à" normal :
template<class T>
void foo(T a)
{
a.member<10>();
}
Même si cela semble évident pour vous, le compilateur ne sait pas que ce "membre" fait référence à une fonction modèle de
membre ; c'est pour cette raison qu'il analyse la ligne de code comme suit :
a.member < (10>());
Afin d'indiquer au compilateur que le caractère "inférieur à" est au début d'une liste d'arguments de modèles, le qualificateur
'modèle' est nécessaire :
a.template member<10>(); // "membre" doit être un modèle de membre
Si le qualificateur 'modèle' est utilisé dans une situation où "membre" ne se résout pas en modèle de membre, le message
d'erreur ci-dessus apparaît.

3.1.2.21 E2066: Information non disponible


L'aide n'est pas disponible pour cet élément.

3.1.2.22 E2471: pragma checkoption a échoué : les options ne sont


pas celles attendues
Vous pouvez utiliser #pragma checkoption pour vérifier que certains commutateurs sont dans l'état attendu. Si #pragma
checkoption détecte qu'un commutateur n'est pas dans l'état attendu, le compilateur affiche cette erreur.

Vous pouvez utiliser la syntaxe suivante :

3 #pragma checkoption <options>


Par exemple :
#pragma checkoption -O2
OR
#pragma checkoption -C -O2
Le compilateur vérifie si les options sont activées. Si elles le sont toutes, rien ne se produit. Si l'une d'entre elles est inactivée,
cette erreur s'affiche.

276
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.23 E2504: 'dynamic' ne peut être utilisé qu'avec des fonctions


membre non modèle
Vous avez essayé d'utiliser dynamic avec une fonction membre modèle. Les fonctions dynamiques sont autorisées pour les
classes dérivées de TObject. Les fonctions dynamiques occupent un emplacement dans chaque objet qui les définit, pas dans
les descendants. En d'autres termes, les fonctions dynamiques sont des fonctions virtuelles stockées dans des tables virtuelles
éparses. Si vous appelez une fonction dynamique qui n'est pas définie dans votre objet, les tables virtuelles de ses ancêtres
sont parcourues jusqu'à ce que la fonction soit trouvée.

3.1.2.24 E2191: '__far16' ne peut être utilisé qu'avec '__pascal' ou


'__cdecl'
Il s'agit d'une erreur interne du compilateur. Le compilateur émet ce message si le mot clé __far16 est mélangé avec un des
mots clés __pascal ou __cdecl, tous dans la même déclaration.

3.1.2.25 E2199: La fonction amie modèle 'fonction' doit être


préalablement déclarée
Inutilisé.

3.1.2.26 E2502: Erreur de résolution de #import : problème


Où problème peut concerner l'un des problèmes suivants relatifs aux différents attributs de #include ( see page 698) :

attribut ‘attribut’ de valeur de directive d'importation non attendu. Une valeur a été fournie pour l'attribut indiqué. Aucune n'était
attendue.

')' manquante dans l'attribut 'attribut' de la directive d'importation. La valeur de l'attribut indiqué a été incorrectement spécifiée :
une parenthèse fermante est manquante.

attribut 'attribut' de la directive de compilation non reconnu. Le token indiqué n'est pas un attribut légitime pour la directive
#import.

valeurs incorrectes pour l'attribut raw_property_prefixes. Les valeurs de l'attribut raw_property_prefixes ont été incorrectement
spécifiées.

propriété 'propriété' en double non attendue. L'attribut #import indiqué a été spécifié plusieurs fois – ceci est une erreur.

méthode get en double non attendue pour la propriété 'propriété'. La méthode get pour la propriété indiquée a été spécifiée
plusieurs fois. 3
méthode put en double non attendue pour la propriété 'propriété'. La méthode put pour la propriété indiquée a été spécifiée
plusieurs fois.

méthode put-reference en double non attendue pour la propriété 'propriété'. La méthode put-reference pour la propriété indiquée
a été spécifiée plusieurs fois.

aucune valeur de retour spécifiée pour la méthode get 'méthode' de la propriété. La méthode get de la propriété indiquée ne
fournit pas le type de valeur retournée correct.

277
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

aucune valeur de retour spécifiée pour la méthode put 'méthode' de la propriété. La méthode put de la propriété indiquée ne
fournit pas le type de valeur retournée correct.

impossible de charger la bibliothèque de types dans 'nom_fichier'. La bibliothèque de types indiquée n'a pas pu être ouverte.

impossible d'obtenir un nom de bibliothèque de types. Le compilateur n'a pas pu obtenir un nom de bibliothèque pour la
bibliothèque de types en cours.

Voir aussi
#include ( see page 698)

3.1.2.27 E2501: Impossible d'ouvrir le fichier d'importation


'nom_fichier'
Cette erreur se produit lorsque vous utilisez :
#import "unfichier.h"
et que le fichier que vous essayez d'importer n'existe pas ou que le compilateur ne peut pas le trouver.

3.1.2.28 E2494: Modificateur __declspec non reconnu


Un modificateur __declspec non valide a été fourni.

3.1.2.29 E2493: Chaîne GUID incorrecte


La chaîne GUID n'a pas la forme d'un GUI (Globally Unique Identifier, identificateur globalement unique).

3.1.2.30 E2499: Format __declspec(uuid(GuidString)) non valide


Cette erreur se produit lorsque vous avez utilisé un format incorrect pour définir votre chaîne de GUID (GuidString). Les GUID
sont définis pour les structures de la façon suivante :
class __declspec(uuid("19a76fe0-7494-11d0-8816-00a0c903b83c")) foo{};
Par exemple, les codes suivants génèrent l'erreur ci-dessus :
class __declspec(uuid(19a76fe0-7494-11d0-8816-00a0c903b83c)) foo{}; //Guillemets manquants
ou
class __declspec(uuid"7494-11d0-8816-00a0c903b83c")) foo{}; // Parenthèse ouvrante manquante

3 3.1.2.31 E2496: Appel non valide à uuidof(struct type|variable)


L'opérateur uuidof a reçu un argument incorrect.

3.1.2.32 E2511: Argument de macro non terminé


Un argument de macro démarré sur la ligne indiquée n'a pas été correctement terminé.

278
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.33 E2489: Profondeur maximum de répétitions d'options


dépassée ; vérifiez la récursivité
Si cette erreur est déclenchée, cela signifie que l'instanciation récursive de modèle est trop profonde. Vérifiez la récursivité au
moment de la compilation dans votre programme et limitez-la à 256 niveaux maximum.

3.1.2.34 E2488: Profondeur maximum de réponse dépassée ; vérifiez


la récursivité
Si cette erreur est déclenchée, cela signifie que l'instanciation récursive de modèle est trop profonde. Vérifiez la récursivité au
moment de la compilation dans votre programme et limitez-la à 256 niveaux maximum.

3.1.2.35 E2491: Compte VIRDEF maximum dépassé ; vérifiez la


récursivité
Trop de symboles VIRDEF ont été alloués. Le compilateur impose une limite au nombre de VIRDEF autorisés par unité de
traduction. Cette limite est actuellement de l'ordre de 16 384 VIRDEF.

Ceci peut se produire si un programme a plus de 16 384 fonctions.

3.1.2.36 E2230: L'initialisation de données membre en ligne


nécessite une expression constante intégrale
Les membres de classes const statiques, initialisés dans le corps de la classe, doivent être initialisés avec une expression
constante de type intégral.

3.1.2.37 E2241: Les classes de style VCL ont besoin de destructeurs


virtuels
Les destructeurs définis dans des classes VCL doivent être virtuels.

Exemple :
struct__declspec(delphiclass) vclclass1
{
~vclclass1() {} // Erreur
};
struct__declspec(delphiclass) vclclass2
3
{
virtual ~vclclass2() {} // OK
};

279
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.38 E2524: Les unions/structs anonymes ne sont pas autorisées


à avoir des membres anonymes en C++
Le compilateur C++ nécessite que les membres d'une union ou struct anonyme soient nommés.

3.1.2.39 E2246: x n'est pas une hiérarchie de classes d'héritage


simples, publiques, abstraites sans données
Erreur interne du compilateur. Dans certains cas, le compilateur impose des restrictions sur une hiérarchie de classes. Dans ce
cas, toutes les classes sont des classes abstraites et n'ont qu'un seul parent.

3.1.2.40 E2249: = attendu


Le compilateur attendait le signe égal à l'endroit où l'erreur a été signalée. Il s'agit en général d'une erreur de syntaxe ou d'une
faute de frappe.

3.1.2.41 E2267: La première base doit être une classe VCL


Erreur interne du compilateur. Dans certains cas, le compilateur impose des restrictions sur une hiérarchie de classes. Dans ce
cas, le premier parent d'une classe est une classe de style Delphi.

3.1.2.42 E2472: Impossible de déclarer une fonction membre via une


instanciation
Le programme est mal formé si une déclaration, dans une classe modèle, acquiert un type de fonction via un type dépendant
d'un paramètre modèle et que ceci entraîne une déclaration n'utilisant pas le format syntaxique d'un déclarateur de fonction pour
obtenir le type de fonction. Par exemple :
template<class T>
struct A {
static T t;
};
typedef int function();
A<function> a;// erreur : déclare A<function>::t
// comme fonction membre statique
Autre exemple :

3 Dans l'exemple ci-dessous, le membre de modèle 'a' présente un type 'T'. Si le modèle est instancié avec T comme type de
fonction, cela implique que 'a' soit une fonction membre. Cela n'est pas autorisé et le message d'erreur s'affiche.
template<T& x> class foo { T a; }
int func(int);
template class foo<func>;

280
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.43 E2515: Impossible de spécialiser explicitement un membre


d'une classe modèle générique
Vous essayez de transformer un modèle générique en membre spécialisé. Par exemple, le code suivant est incorrect :
template<typename T>
class foo {
template<typename U>
class bar {
};
};
template<typename T>
template<>
class foo<T>::bar<char> {
};
La deuxième déclaration dans l'exemple est une erreur, car elle tente de spécialiser explicitement bar<char> en foo<T>.

3.1.2.44 E2474: 'fonction' ne peut pas être déclarée comme static ou


inline
Vous avez essayé de déclarer un symbole comme static ou inline et ce type de symbole ne peut pas être défini de la sorte.
Certaines fonctions, telles que 'main' et 'WinMain' ne peuvent pas être déclarées static ou inline. 'main' est le point d'entrée
d'applications console et 'WinMain' celui d'applications Windows.

Par exemple, cette erreur s'affiche dans les cas suivants :


static int main() // Ceci provoque une erreur
{}
ou
inline int main() { return 0; }

3.1.2.45 E2498: Définition préalable de la structure du GUID requise


Cela se produit lorsque vous utilisez l'opérateur __uuidof sans inclure d'en-tête définissant la structure du GUID. Ainsi, le code
suivant affiche cette erreur :
class __declspec(uuid("19a76fe0-7494-11d0-8816-00a0c903b83c")) foo{};
int main()
{
__uuidof(foo);
return 0;
}
Cette erreur peut être corrigée ainsi :
#include <windows.h> // Extraira la structure du GUID
3
class __declspec(uuid("19a76fe0-7494-11d0-8816-00a0c903b83c")) foo{};
int main()
{
__uuidof(foo);
return 0;
}

281
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.46 E2295: Trop de spécialisations de modèle candidat depuis


'spécificateur'
Lors du référencement d'une spécialisation de modèle de classe, il se peut qu'une même référence génère plusieurs candidats
possibles. Ceci ne peut réellement arriver que dans des spécialisations de classe partielles, lorsque plusieurs spécialisations
partielles sont en compétition pour une correspondance possible :
template<class T, class U>
class foo;
template<class T>
class foo<T, T *>;
template<class T>
class foo<T *, T>;
foo<int *, int *> x; // erreur : quelle spécialisation partielle utiliser ?
Dans cet exemple, les deux spécialisations partielles sont correctes et aucune n'est plus spécialisée que l'autre, ce qui provoque
une erreur.

3.1.2.47 E2475: 'fonction' ne peut pas être une fonction modèle


Certaines fonctions, telles que 'main' et 'WinMain' ne peuvent pas être déclarées comme fonction modèle. 'main' est le point
d'entrée d'applications console et 'WinMain' celui d'applications Windows.

Par exemple :
template <class T> int main() // Ceci provoque une erreur
{}
Voir aussi
functiontemplates.xml ( see page 451)

3.1.2.48 E2299: Impossible de créer une spécialisation de modèle à


partir de 'spécificateur'
Cette erreur se produit si vous essayez de référencer une fonction ou une classe modèle de manière à ce que ne se produise
aucune spécialisation de candidat possible. Par exemple :
template<class T>
class foo;
foo<10> x; // erreur : les arguments ne sont pas corrects pour 'foo'

3.1.2.49 E2300: Impossible de générer un type correspondant de


3 spécialisation pour 'spécificateur'
Cette erreur n'est plus générée par le compilateur.

3.1.2.50 E2497: Aucun GUID associé au type 'type'


Une variable ou un type a été utilisé dans un contexte nécessitant un GUID, mais aucun GUID n'est associé au type. Les GUID

282
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

sont associés aux types à l'aide de __declspec(uuid(GUID)).

3.1.2.51 E2522: Fonction non const 'fonction' appelée pour un objet


const
La différence du type de données conduit à un appel de fonction erroné. L'objet de l'appel (une fonction non-const) doit être un
objet const.

3.1.2.52 E2523: Fonction non volatile 'nom' appelée pour un objet


volatile
Non concordance du type de données. L'erreur est le résultat d'un appel de fonction erroné. L'objet de l'appel (une fonction
non-volatile) doit être un objet volatile.

3.1.2.53 E2513: Impossible d'émettre des informations RTTI pour


'paramètre' dans 'fonction'
Le compilateur émet ce message d'erreur s'il ne parvient pas à générer des informations RTTI pour le type de retour d'un
paramètre. Voir Informations de types à l'exécution pour plus d'informations.

3.1.2.54 E2512: Impossible d'émettre des informations RTTI pour le


type renvoyé par 'fonction'
Le compilateur émet ce message d'erreur s'il ne parvient pas à générer des informations RTTI pour le type de retour d'une
fonction. Voir Informations de types à l'exécution pour plus d'informations.

3.1.2.55 E2507: 'classe' n'est pas une classe de base directe de


'classe'
Le premier type n'est pas une classe de base directe du second type. Une classe de base directe fait référence aux dérivations
immédiates de cette classe, et pas aux dérivations de ses sous-classes.

3.1.2.56 E2529: Le chemin 'chemin' dépasse la taille maximale 'n'


3
Lors de la recherche des fichiers d'inclusion, le compilateur C++ a rencontré un fichier dont le nom de chemin contient un
nombre de caractères supérieur au nombre de caractères maximal de Windows. Réduisez le nom du chemin.

3.1.2.57 E2495: Redéfinition de uuid non identique


Les GUID attachés aux structures doivent être les mêmes sur plusieurs déclarations et définitions de la même structure. Ainsi,
l'exemple suivant génère cette erreur :

283
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

class __declspec(uuid("19a76fe0-7494-11d0-8816-00a0c903b83c")) foo;


class __declspec(uuid("00000000-7494-11d0-8816-00a0c903b83c")) foo{}

3.1.2.58 E2500: __declspec(selectany) ne s'adresse qu'aux variables


initialisées et visibles de façon externe
Vous ne pouvez pas utiliser __declspec(selectany) avec des variables statiques, non initialisées, etc.

3.1.2.59 E2482: Constante chaîne attendue


Le compilateur attendait une constante chaîne à cet emplacement, mais n'en a pas reçu.

Cette erreur n'est plus générée par le compilateur.

3.1.2.60 E2481: Constante chaîne inattendue


Il y a des fois où le compilateur n'attend pas l'apparition de constante chaîne dans l'entrée source. Par exemple :
class foo { "Bonjour"; };

3.1.2.61 E2386: Impossible d'impliquer le paramètre 'paramètre'


dans une expression de spécialisation partielle complexe
Lors de la déclaration ou de la définition d'une spécialisation partielle de classe modèle, il est incorrect d'impliquer des
paramètres qui ne sont pas de type template dans des expressions complexes. Ils ne peuvent être référencés que par nom. Par
exemple :
template<class T, int U>
class foo;
template<int U>
class foo<char, U * 3>;// erreur : "U * 3" est une expression complexe
template<int U>
class foo<char, U>;// OK : "U" est une expression simple, référencée par le nom

3.1.2.62 E2387: Les spécialisations partielles ne peuvent pas


spécialiser les paramètres dépendants non-typés ('paramètre')
Une spécialisation partielle ne peut pas utiliser de paramètre modèle dans sa liste d'arguments de spécialisation qui dépend d'un
autre paramètre de type. Par exemple :
template<class T, int U>
class foo;
3 template<class T, T U>
class foo<T *, U>; // erreur : 'U' dépend du type

3.1.2.63 E2388: La liste d'arguments de spécialisation ne peut pas


être identique à la liste de paramètres de modèle primaire
Lors de la déclaration d'une spécialisation partielle, sa liste d'arguments de spécialisation doit être différente de sa liste de

284
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

paramètres de base. Par exemple :

template<class T>
class foo;
template<class T>
class foo<T *>; // OK : est plus spécialisé que le modèle primaire
template<class T>
class foo<T>; // erreur : identique au modèle primaire

3.1.2.64 E2389: Non concordance dans le type d'argument de


substitution et le paramètre modèle 'paramètre'
Lors de la référenciation d'une spécialisation de modèle, tous les paramètres de type doivent être satisfaits en utilisant les
arguments type, tous les paramètres non type nécessitent des arguments non type et tous les paramètres modèles template
nécessitent soit un nom de modèle, soit un autre argument de modèle template. La non concordance de ces besoins de quelque
manière que ce soit déclenchera l'erreur ci-dessus. Par exemple :
template<class T, int U, template<class V> class W>
class foo;
foo<char, 10, foo> x; // OK : tous les types de paramètre correspondent
foo<10, char, int> y; // erreur : aucun type de paramètre ne correspond !

3.1.2.65 E2480: Impossible d'impliquer des paramètres de modèle


dans les arguments de spécialisation partielle complexe
Une spécialisation partielle ne peut pas faire référence à d'autres paramètres de modèle dans une expression d'argument sans
valeur, sauf si elle est simplement une référence directe au paramètre de modèle. Par exemple :
template<int A, int B, int C> class foo;
template<int A> class foo<A+5, A, A+10>;
La spécialisation partielle présente deux arguments illégaux. 'A+5' est une expression complexe car elle utilise 'A' d'une façon
autre que comme simple argument direct. La référence à 'A' dans le second argument est correcte, mais le troisième argument
est aussi illégal car il fait référence à 'A' de façon complexe également.

3.1.2.66 E2392: L'instance du modèle 'template' est déjà instanciée


Il y a deux façons de déclencher cette erreur. Si –A est activée (mode compatible ANSI), alors la tentative d'instanciation
explicite d'une spécialisation de modèle qui a déjà été instanciée (soit implicitement, soit explicitement) provoquera cette erreur.
Indépendamment de –A, la tentative de spécialisation explicite d'une spécialisation de modèle ayant déjà été instanciée (soit
implicitement, soit explicitement) déclenchera toujours cette erreur. Par exemple :
template<class T>
class foo;
foo<char> x; // provoque l'instanciation implicite de "foo<char>"
template<> 3
class foo<char> { }; // erreur : "foo<char>" déjà instancié
template class foo<char>; // erreur dans le mode –A, sinon avertissement

285
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.67 E2393: Impossible de prendre l'adresse du paramètre


modèle non-typé, non-référencé 'paramètre'
Un paramètre modèle n'a pas d'adresse et n'est associé à aucun “objet” réel. Par conséquent, prendre son adresse ou essayer
de lui affecter une adresse, n'a aucun sens. Par exemple :
template<int U>
void foo()
{
int *x = &U;// erreur : impossible de prendre l'adresse du paramètre
}

3.1.2.68 E2399: Impossible de référencer de cette façon l'argument


'arg' du modèle dans la classe modèle 'classe'
Le compilateur ne génère plus cette erreur.

3.1.2.69 E2397: L'argument du modèle ne peut pas avoir une liaison


statique ou locale
Seules les expressions constantes entières et l'adresse des variables globales avec un lien externe peuvent être utilisées
comme arguments modèles. Par exemple :
template<char *x>
class foo;
const char *p = "Bonjour";
extern char *q;
foo<p> x;// OK : "p" est visible vers l'extérieur
foo<q> y;// OK : "q" est aussi globalement visible
foo<"Bonjour"> z;// erreur : le littéral chaîne a un lien statique

3.1.2.70 E2485: Impossible d'utiliser l'élément adresse de tableau


comme un argument de modèle non typé
Les arguments de modèle non-typés ne peuvent être que de type entier ou l'adresse d'une variable globale. Ils ne peuvent pas
représenter l'adresse d'un élément tableau. Par exemple :
int x[100];
template<int T>
class foo;
foo<&x[0]> y;// erreur : ce n'est pas une adresse entière ni globale

3
3.1.2.71 E2402: Type de classe de base incorrect : type formel 'type'
résolu en 'type'
Lors de l'instanciation d'une définition de classe modèle, cette erreur se produira si une classe de base déclarée ne se résout
pas en type de classe accessible. Par exemple :
template<class T>
class foo : public T { };

286
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

foo<int> x;// erreur : "int" n'est pas une classe de base correcte
foo<bar> y;// erreur : "bar" est un type inconnu

3.1.2.72 E2403: Le spécificateur d'appel dépendant produit une


non-fonction 'nom'
Le compilateur ne génère plus cette erreur.

3.1.2.73 E2404: Le qualificateur de type dépendant 'qualificateur' n'a


aucun type membre nommé 'nom'
Si une déclaration modèle référence un membre d'un type dépendant, le seul choix possible est d'alerter l'utilisateur de la non
existence de ce membre pendant l'instanciation de type pour un ensemble donné d'arguments modèles. Par exemple :
template<class T>
class foo
{
typename T::A x; // nous attendons que "A" soit un type membre
};
struct bar { };
foo<bar> y;// erreur : "bar" n'a pas de type membre nommé "A"

3.1.2.74 E2405: La référence de modèle dépendante 'identificateur'


fournit un symbole non modèle
Si une référence de spécialisation modèle à l'intérieur d'une déclaration de modèle produit une référence à un non modèle
pendant l'instanciation de type, l'erreur ci-dessus apparaîtra. Par exemple :
template<class T>
class foo
{
typename T::template A<int> x; // "A" doit être un modèle membre
};
struct bar {
struct A { };
};
foo<bar> y;// erreur : bar::A est une classe non modèle !

3.1.2.75 E2406: Le qualificateur de type dépendant 'qualificateur'


n'est pas un type class ou struct
Si une référence de nom dépendant, dans une déclaration de modèle, a pour résultat une qualification de membre non-structure
au moment de l'instanciation, l'erreur ci-dessus se produit. Par exemple :
3
template<class T>
class foo
{
typename T::A x; // nous attendons que "A" soit un type membre
};
foo<int> y;// erreur : "int" ne peut pas être qualifié; ce n'est pas une classe

287
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.76 E2407: Le qualificateur de type dépendant 'qualificateur' n'a


aucun symbole membre nommé 'nom'
Si une déclaration modèle référence un membre d'un type dépendant, le seul choix possible est d'alerter l'utilisateur de la non
existence de ce membre pendant l'instanciation de type pour un ensemble donné d'arguments modèles. Par exemple :
template<class T>
class foo
{
foo(int *a = T::A); // nous attendons que "A" soit une donnée membre
};
struct bar { };
foo<bar> y;// erreur : "bar" n'a pas de membre nommé "A"

3.1.2.77 E2408: Les valeurs par défaut doivent être spécifiées


seulement dans les déclarations de modèle de classe primaire
Les fonctions modèles et les spécialisations partielles de classe ne peuvent pas utiliser les expressions par défaut dans leurs
listes de paramètres modèles. Seules les déclarations de modèles primaires peuvent faire cela. Par exemple :
template<class T = int>
class foo;// OK : modèle de classe primaire
template<class T = int>
void bar();// erreur : fonction modèle
template<class T = int>
class foo<T *>;// erreur : spécialisation partielle

3.1.2.78 E2409: Impossible de trouver une spécialisation correcte


pour 'spécificateur'
Cette erreur n'est plus générée par le compilateur.

3.1.2.79 E2410: Paramètres de modèle manquants pour le modèle


ami 'modèle'
Cette erreur se produira si un modèle ami est déclaré, mais qu'aucun paramètre de modèle n'est spécifié. Par exemple :
template<class T>
class foo;
class bar {
friend class foo;// erreur : les paramètres de modèle ont été oubliés !
};
3
3.1.2.80 E2486: Impossible d'utiliser l'adresse du membre de classe
comme un argument de modèle non typé
Les arguments de modèle non-typés ne peuvent être que de type entier ou l'adresse d'une variable globale. Ils ne peuvent pas
être l'adresse d'un membre de classe. Par exemple :
struct bar {

288
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

int x;
} y;
template<int T>
class foo;
foo<&y.x> z;// erreur : ce n'est pas une adresse entière ni globale

3.1.2.81 E2411: La déclaration des paramètres par défaut d'une


fonction membre après une spécialisation a déjà été développée
Si une fonction membre d'un modèle de classe est déclarée, puis qu'une spécialisation de cette classe est implicitement
instanciée et enfin que cette fonction membre est définie avec les paramètres spécifiés par défaut, l'erreur ci-dessus se produira.
Par exemple :
template<int i>
class foo {
void method(int a, int b = i);
};
foo<10> x;
template<int i>
void foo<i>::method(int a = i, int b); // erreur !

3.1.2.82 E2412: Tentative de lier une référence membre à un type


dépendant
Le compilateur ne génère plus cette erreur.

3.1.2.83 E2414: Les destructeurs ne peuvent pas être déclarés


comme fonctions modèles
Les destructeurs ne peuvent pas être des modèles. Par exemple :
class foo {
template<class T>
virtual ~foo();// erreur : n'essayez pas ceci chez vous !
};

3.1.2.84 E2473: Spécialisation explicite de 'spécificateur' incorrecte


La tentative de spécialisation explicite d'une donnée membre statique ou de toute donnée non modèle provoquera cette erreur.

3.1.2.85 E2490: Spécialisation dans des classes modèle non encore


implémentées 3
La spécialisation explicite et partielle de classes et de fonctions membres modèles, dans des classes modèles et des classes
modèles imbriquées, n'est pas supportée.

289
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.86 E2416: Déclaration de fonction modèle incorrecte


Le compilateur ne génère plus cette erreur.

3.1.2.87 E2417: Impossible de spécifier des paramètres de modèle


dans la spécialisation explicite de 'spécificateur'
Le compilateur ne génère plus cette erreur.

3.1.2.88 E2418: Profondeur d'instanciation maximum dépassée ;


vérifiez la récursivité
Le compilateur ne supporte que 256 niveaux d'instanciation avant de déclencher cette erreur. Le problème principal est le
contrôle de la profondeur de la pile, car l'analyseur utilise des fonctions récursives pour gérer l'instanciation de type. Voici un
exemple de ce qui pourrait produire une telle erreur :
template<int T>
class foo {
public:
static const int x = foo<T – 1>::x;
};
template<int T>
class foo<1> {
public:
static const int x = 1;
};
int main() {
int y = foo<100000>::x;// erreur : profondeur d'instanciation dépassée
}

3.1.2.89 E2420: Une instanciation explicite ne peut être utilisée que


sur l'étendue globale
Une instanciation explicite ne peut être spécifiée à aucun autre niveau que celui de l'étendue globale ou de l'espace de
nommage. Par exemple :
template<class T>
class foo { };
template class foo<char>;// OK : étendue globale
int main() {
template class foo<int>:// erreur : étendue locale
}
3
3.1.2.90 E2422: Le type d'argument ne correspond pas dans la
redéclaration du paramètre modèle 'paramètre'
Cette erreur se produit si un modèle est déclaré à un point de l'unité de traduction puis redéclaré avec des paramètres de
modèle d'un type différent à un autre emplacement. Par exemple :
template<class T>

290
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

class foo;
// ...le temps passe ...
template<int T>
class foo;// erreur : type par rapport au paramètre non-type

3.1.2.91 E2423: Spécialisation ou instanciation explicite d'un modèle


non existant 'modèle'
La tentative de spécialisation ou d'instanciation explicite d'un modèle qui n'existe pas est incorrecte. Par exemple :
template<class T>
class foo;
template class bar<char>;// erreur : qu'est-ce que "bar" ??
template<>
class bar<int> { };// erreur : on retrouve ce "bar"...

3.1.2.92 E2479: Impossible d'avoir à la fois une classe modèle et une


fonction appelée 'nom'
Aucune autre fonction ou aucun autre type ne peut avoir le même nom qu'une classe modèle. Par exemple :
void foo();// erreur : il existe une classe modèle nommée "foo"
template<class T>
class foo;

3.1.2.93 E2484: Le nom de la classe modèle 'classe' ne peut pas être


surchargé
La tentative de déclaration d'une fonction écrasant le nom d'une classe modèle provoquera cette erreur. Par exemple :
template<class T>
class foo;
void foo();// erreur : il existe une classe modèle nommée "foo"

3.1.2.94 E2426: La spécialisation explicite de 'spécificateur'


nécessite une déclaration 'template<>'
Selon le standard, une spécialisation explicite de n'importe quel modèle nécessite toujours désormais la syntaxe de déclarateur
“template<>”. Par exemple :
template<class T>
class foo;
template<>
class foo<char>;// OK : "template<>" a été fourni
class foo<int>;// erreur : "template<>" nécessaire
3
3.1.2.95 E2487: Impossible de spécifier des arguments de fonction
par défaut pour des spécialisations explicites
Une spécialisation explicite d'une fonction ne peut pas déclarer d'arguments de fonction par défaut. Par exemple :
template<class T>
void foo(T a);

291
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

template<>
void foo<int>(int a = 10);// erreur : valeur par défaut non autorisée

3.1.2.96 E2427: 'main' ne peut pas être une fonction modèle


'main' ne peut pas être déclarée comme fonction modèle. 'main' est le point d'entrée d'une application console, et doit être
déclarée en fonction __cdecl normale.

Ce message d'erreur ne doit pas se produire car il a été remplacé par un autre message (E2475).

3.1.2.97 E2429: Ce n'est pas une spécialisation partielle correcte de


'spécificateur'
Erreur interne du compilateur.

3.1.2.98 E2430: Le nombre de paramètres de modèles ne correspond


pas dans la redéclaration de 'spécificateur'
Cette erreur se produira si un modèle est redéclaré avec un nombre différent de paramètres de modèle. Par exemple :
template<class T>
class foo;
template<class T, int U>
class foo;// erreur : non concordance du compte de paramètres !

3.1.2.99 E2477: Trop peu de paramètres de modèle ont été déclarés


pour le modèle 'modèle'
Cette erreur se produira si une déclaration, ou une définition, de membre se produit hors d'une classe modèle et que cette
déclaration externe utilise un nombre de paramètres de modèle différent de celui de la classe parent. Par exemple :
template<class T, class U>
class foo {
void method();
};
template<class T>
void foo<T>::method() { }// erreur : trop peu de paramètres de modèle !

3.1.2.100 E2478: Trop de paramètres de modèle ont été déclarés


pour le modèle 'modèle'
3 Cette erreur se produira si une déclaration, ou une définition, de membre se produit hors d'une classe modèle et que cette
déclaration externe utilise un nombre de paramètres de modèle différent de celui de la classe parent. Par exemple :
template<class T, class U>
class foo {
void method();
};
template<class T, class U, class V>
void foo<T, U, V>::method() { }// erreur : trop de paramètres !

292
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.101 E2431: Les paramètres de modèle non-typé ne peuvent pas


être de type virgule flottante, classe ou void
Les paramètres de modèle non-typé sont restreints aux types qu'ils peuvent prendre. Les types virgule flottante, classe et void
sont incorrects. Par exemple :
template<float U>
class foo;// erreur : "U" ne peut pas être de type "flottant"

3.1.2.102 E2434: Les paramètres de modèle manquent dans la


déclaration de modèle ('template<...>')
Dans un contexte où au moins un paramètre de modèle est clairement requis, si aucun paramètre n'est trouvé, cette erreur se
produira. Par exemple :
template<class T, template<> class U>
class foo;// erreur : les paramètres de modèle template nécessitent
// la déclaration d'au moins un paramètre réel

3.1.2.103 E2435: Trop d'ensembles de paramètres de modèles ont


été spécifiés
Cette erreur se produira si un modèle de membre est défini hors de sa classe parent et que trop d'ensembles de paramètres de
modèles sont déclarés. Par exemple :
template<class T>
class foo
{
template<class U>
void method(U a);
};
template<class T> template<class U> template<class V>
void foo<T>::method(U a);// erreur : trop de paramètres définis !

3.1.2.104 E2436: Le type par défaut de l'argument modèle 'arg' ne


nomme pas une classe modèle primaire
Si un paramètre modèle template va avoir un type par défaut, ce type doit être soit un nom de classe modèle générique, soit un
autre paramètre de modèle template.
template<class T>
class foo;
template<template<class T> class U = foo>
class bar;// OK : "foo" est un modèle primaire de qualification 3
template<template<class T> class U = int>
class baz;// erreur : "int" n'est pas une classe modèle

3.1.2.105 E2437: 'typename' doit être suivi par un nom de type


dépendant qualifié
Dès que le mot clé "typename" est utilisé dans une déclaration ou une définition de modèle, il doit toujours nommer un type

293
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

dépendant. Par exemple :


struct bar { };
template<class T>
class foo {
typename T::A *x;// OK : nomme un type qualifié
typename T y;// erreur : ce n'est pas un type qualifié
typename bar z;// erreur : ce n'est pas un type dépendant
};

3.1.2.106 E2438: Les arguments du modèle template doivent


nommer une classe
Un paramètre de modèle template doit toujours déclarer le nom d'une nouvelle classe. Par exemple :
template<template<class T> int U>
class foo;// erreur : "U" n'est pas un nom d'indicateur de classe
template<template<class T> class V>
class bar;// OK : "V" est un nom d'indicateur de classe

3.1.2.107 E2439: 'typename' n'est autorisé que dans les déclarations


modèle
Le mot clé "typename" ne doit être utilisé que dans des déclarations et des définitions de modèle.

3.1.2.108 E2440: Impossible de créer une spécialisation depuis


'spécificateur' car ce type n'est pas encore défini
Le compilateur ne génère plus cette erreur.

3.1.2.109 E2441: Instanciation de 'spécificateur'


Dès qu'une erreur du compilateur se produit lors de l'instanciation d'un type de modèle, le contexte de ce qui était en cours
d'instanciation à ce moment là sera rapporté à l'utilisateur, afin de faciliter la détection du problème.

3.1.2.110 E2503: Version manquante ou incorrecte de


TypeLibImport.dll
Cette erreur se produit lorsque le compilateur essaie d'accéder au fichier TypeLibImport.dll mais soit ne peut pas le trouver, soit
est altéré, soit une mauvaise version est installée sur votre ordinateur. Vous pouvez le réinstaller à partir du CD du produit.
3

3.1.2.111 E2470: Il faut inclure l'en-tête <typeinfo> pour utiliser


typeid
Lorsque vous utilisez la fonction 'typeid', vous devez inclure l'en-tête <typeinfo>, sinon vous obtiendrez des erreurs de syntaxe.

Par exemple, considérez un cas test avec le code suivant :

294
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

int func()
{
char * name = typeid(int).name(); // Ceci provoque une erreur
}

3.1.2.112 E2514: Impossible (pour le moment) d'utiliser la résolution


des surcharges de membre pendant l'instanciation de modèle
Vous tentez de surcharger un membre pendant l'instanciation du modèle. Vous ne pouvez pas avoir d'appels de fonctions
constantes surchargées dans des initialiseurs de limites de tableau, par exemple.

3.1.2.113 E2508: 'using' ne peut pas faire référence à une


spécialisation de modèle
Le mot clé using ne peut pas faire référence à une spécialisation de modèle.

3.1.2.114 E2462: 'virtual' ne peut être utilisé qu'avec des fonctions


membre non modèle
Le mot clé 'virtual' ne peut s'appliquer qu'aux fonctions membres normales, non aux fonctions membres modèles.

Considérez un cas de test avec le code suivant :


template <class T>
class myTemplateClass
{
virtual int func1(); // Ceci est valable
template <class T> virtual int func2(); // Ceci provoque une erreur
};
class myClass
{
virtual int func1(); // Ceci est valable
template <class T> virtual int func2(); // Ceci provoque une erreur
};

3.1.2.115 W8086: Utilisation incorrecte de l'alias #pragma


"NomAlias"="NomSubstitué"
L'alias de la directive #pragma est utilisé pour indiquer au lien que deux noms d'identificateurs sont équivalents. Vous devez
placer les deux noms entre guillemets.

Vous obtenez cet avertissement si vous n'utilisez pas l'alias pragma correctement. Par exemple, les deux lignes suivantes
génèrent cet avertissement : 3
#pragma alias foo=bar
#pragma alias "foo" = bar
Pour de plus amples informations sur l'usage de ce pragma, voir la référence "#pragma alias" ci-dessous.

Voir aussi
#pragma alias

295
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.116 W8099: main statique n'est pas traité comme un point


d'entrée
La fonction main a été créée en tant que fonction statique, ce qui l'empêche d'être utilisée en tant que point d'entrée valide.

Soit :
static void main(int argc, char**argv)
{
}
La syntaxe ci-dessus est une syntaxe C valide mais ne peut pas être appelée en tant que routine de démarrage car elle a été
déclarée en tant que fonction statique.

3.1.2.117 W8093: Utilisation incorrecte de #pragma codeseg


[nom_seg] ["classe_seg"] [groupe]
La directive #pragma codeseg peut être utilisée pour définir ou réinitialiser le nom, la classe ou le groupe d'un segment. Vous
devez suivre exactement la syntaxe stipulée dans le message d'avertissement, et tous les noms sont facultatifs.

Les lignes suivantes sont toutes correctes :


#pragma codeseg
#pragma codeseg foo
#pragma codeseg foo "bar"
#pragma codeseg foo "bar" foobar
Celles-ci ne le sont pas :
#pragma codeseg ###
#pragma codeseg "foo" "bar"
#pragma codeseg foo "bar" foobar morefoobar

3.1.2.118 W8094: Utilisation incorrecte de #pragma comment( <type>


[,"chaîne"] )
La directive #pragma comment peut être utilisée pour émettre des enregistrements de commentaires de liaison.

Dans ce message, <type> peut être l'un des éléments suivants :

• user
• lib
• exestr
• linker
3 Le type doit figurer ici mais la chaîne est facultative.

3.1.2.119 W8085: Fonction 'fonction' redéfinie comme non-en ligne


Cet avertissement est utilisé pour indiquer qu'une certaine fonction, qui a été déclarée en ligne dans un emplacement, est
redéfinie dans un autre emplacement comme non inline.

296
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.120 W8105: Membre %s '%s' dans la classe sans constructeur


Une classe contenant des membres constante ou des membres référence (ou les deux) doit avoir au moins un constructeur
défini par l'utilisateur.

Dans le cas contraire, il est impossible d'initialiser les membres.

3.1.2.121 W8095: Utilisation incorrecte de #pragma message(


"chaîne" )
Vous pouvez utiliser pragma message pour émettre un message en direction de la ligne de commande ou de la fenêtre de
message. Vous obtenez cet avertissement si vous utilisez une syntaxe incorrecte. Ainsi
#pragma message( "bonjour" )
est correct, mais le code suivant génère l'avertissement :
#pragma message( mal formulé )

3.1.2.122 W8098: Constante caractère multicaractère


Cet avertissement est émis lorsque le compilateur détecte une constante entière multicaractère, telle que :
int foo = 'abcd';
Le problème soulevé par cette construction est que l'ordre des octets des caractères dépend de l'implémentation.

3.1.2.123 W8096: Utilisation incorrecte de #pragma


code_seg(["nom_seg"[,"classe_seg"]])
Pragma code_seg est identique à pragma codeseg, mais il vous permet de modifier uniquement le nom et la classe du segment
de code. Si vous utilisez la mauvaise syntaxe, vous obtenez cet avertissement.

Les exemples suivants illustrent l'utilisation correcte :


#pragma code_seg()
#pragma code_seg("foo")
#pragma code_seg("foo", "bar")
Les exemples incorrects suivants génèrent tous l'avertissement :
#pragma code_seg(foo)
#pragma code_seg(foo, bar)

3.1.2.124 W8083: Pragma pack pop sans pack push correspondant 3

Chaque #pragma pack(pop) doit avoir un #pragma pack(push) correspondant le précédant dans la même unité de traduction.
Des paires de 'push' et de 'pop' peuvent être imbriquées.

Par exemple :
#pragma pack( push )
#pragma pack( push )
#pragma pack( pop )

297
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

#pragma pack( pop )


#pragma pack( pop ) // Ceci provoque une erreur

3.1.2.125 W8097: Toutes les options ne peuvent pas être restaurées


pour l'instant
Votre programme présente un #pragma pop à un emplacement qui ne lui permet pas de restaurer des options.

Par exemple :
#pragma option push -v
int main()
{
int i;
i = 1;
#pragma option pop
return i;
}
Pour cet exemple, compilez avec -v-. Le message s'affiche car le premier #pragma génère la modification d'état des
informations de débogage (activation). Ensuite, au milieu de la fonction, là où il est inutile de modifier l'état des informations de
débogage, #pragma pop essaie de rétablir l'état antérieur.

3.1.2.126 W8084: Nous suggérons des parenthèses pour clarifier la


priorité
Cet avertissement indique que plusieurs opérateurs utilisés dans une expression peuvent entraîner une confusion sur les règles
de priorité d'opérateur applicables. Cet avertissement permet de créer du code plus compréhensible et potentiellement moins
ambigu.

Par exemple, compilez le code suivant en utilisant l'option –w de la ligne de commande :


int j, k, l;
int main()
{
return j < k & l; // Ceci provoque une erreur
}
//

3.1.2.127 W8092: L'argument 'type' 'spécificateur' transmis à


'fonction' n'est pas un itérateur : itérateur 'type' requis
Un argument qui n'est pas un itérateur est en cours d'utilisation avec un algorithme STL qui requiert un itérateur.

3 3.1.2.128 W8087: 'opérateur::opérateur==' doit être publiquement


visible pour être contenu par un 'type'
Un type en cours d'utilisation avec un conteneur STL présente un 'opérateur==' privé.

298
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.129 W8090: 'type::opérateur<' doit être publiquement visible


pour être utilisé avec 'type'
Un type en cours d'utilisation avec un conteneur STL présente un 'opérateur<'.privé. Le type que vous essayez d'utiliser doit
devenir public.

3.1.2.130 W8089: 'type::opérateur<' doit être publiquement visible


pour être contenu par un 'type'
Le type en cours d'utilisation pour un conteneur STL a un 'opérateur<' privé. Le type contenu (type::opérateur) doit être de type
public.

Par exemple, si vous essayez d'instancier un type de classe "vecteur<blah>", l'erreur est la suivante :
'blah::opérateur<' doit être publiquement visible pour être contenu par un 'vecteur'

3.1.2.131 W8091: L'argument 'type' 'spécificateur' transmis à


'fonction' est un itérateur 'catégorie d'itérateur' : itérateur 'catégorie
d'itérateur' requis
Une catégorie d'itérateur incorrecte est en cours d'utilisation avec un algorithme STL.

3.1.2.132 W8076: L'instance du modèle 'spécificateur' est déjà


instanciée
Vous essayez d'instancier explicitement un modèle déjà instancié de façon implicite.

Cette erreur se produit si –A n'est pas activée et qu'une tentative d'instanciation explicite d'une spécialisation (qui a déjà été
instanciée implicitement ou explicitement) est effectuée.

3.1.2.133 W8077: La spécialisation explicite d'un membre de classe


explicitement spécialisé n'a pas de sens
Erreur interne. Cet avertissement n'est plus généré par le compilateur.

Le code suivant est incorrect :


template<class T> class foo { int x; } 3
template<> class foo<int> { int y; }
template<> int foo<int>::y; // error: impossible de spécialiser explicitement 'foo<int>::x'

3.1.2.134 Messages d'information


Le compilateur affiche les informations d'état pendant la compilation si vous avez coché "Afficher les messages généraux" sur la
page Compilateur de la boîte de dialogue Options du projet. La plupart des messages se comprennent d'eux-mêmes et

299
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

fournissent des informations sur la compilation et la liaison, par exemple :


Compilation [C++] : D:\Program Files\Borland\CBuilder\Bin\Unit1.cpp
Vous pouvez également voir un message tel que
[C++] Inclusion de clx.h au lieu de clx.h en raison du commutateur -Hr
Ce message indique que le fichier en-tête précompilé géré par l'EDI a été remplacé en raison des classes CLX supplémentaires
incluses dans le projet. Cela n'indique pas une condition d'échec. Le nom du fichier en-tête inclus peut parfois être le même s'il
est inclus avec une instruction #define différente.

3.1.2.135 E2196: Impossible de prendre l'adresse de la fonction


membre 'fonction'
Une expression prend l'adresse d'une fonction membre de classe, mais cette fonction membre est introuvable dans le
programme en cours de débogage. Ce message est affiché par l'évaluateur.

3.1.2.136 F1002: Impossible de créer le fichier de sortie 'nomfichier'


Cette erreur se produit si le disque de travail est plein ou protégé en écriture.

Elle se produit également si le répertoire de sortie n'existe pas.

Solutions

Si le disque est plein, supprimez des fichiers et relancez la compilation.

Si le disque est protégé en écriture, placez les fichiers source sur un autre disque accessible en écriture et relancez la
compilation.

3.1.2.137 F1003: Erreur de directive : 'message'


Ce message s'affiche lorsqu'une directive #error est traitée dans le fichier source.

'message' est le texte de la directive #error.

3.1.2.138 F1004: Erreur interne du compilateur


Une erreur s'est produite dans la logique interne du compilateur. Cette erreur ne devrait en général jamais s'afficher. Elle n'est là
que si aucun message plus spécifique n'est disponible.

3 3.1.2.139 F1006: Appel incorrect d'une fonction intrinsèque


Vous avez utilisé une fonction intrinsèque sans fournir de prototype. Vous avez peut-être fourni un prototype pour une fonction
intrinsèque, mais pas celle que le compilateur attendait.

300
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.140 F1007: Arborescence d'expression irréductible


Une expression sur la ligne indiquée du fichier source a empêché la génération du code attendu. Evitez d'utiliser cette
expression. Contactez CodeGear si une expression génère régulièrement ce message d'erreur.

3.1.2.141 F1009: Impossible d'ouvrir le fichier d'entrée 'nomfichier'


Cette erreur se produit si le fichier source est introuvable.

Vérifiez le nom du fichier. Vérifiez qu'il est sur le disque et le répertoire spécifiés.

Vérifiez que les chemins d'accès aux répertoires sont corrects. Si plusieurs chemins d'accès sont requis, séparez-les par un
point-virgule.

3.1.2.142 F1011: Echec d'allocation de registre


Cause possible

Une expression sur la ligne spécifiée du fichier source était tellement complexe qu'elle a empêché la génération du code attendu.

Solutions

Simplifiez l'expression. Si ceci ne résout pas le problème, n'utilisez pas cette expression.

Contactez CodeGear si une expression génère régulièrement ce message d'erreur.

3.1.2.143 F1012: Débordement de pile du compilateur


La pile du compilateur a débordé. Ceci peut entre autres être causé par des instructions imbriquées en profondeur dans un
corps de fonction (par exemple, if/else) ou par des expressions avec un grand nombre d'opérandes. Vous devez simplifier votre
code si ce message se produit. Ajouter de la mémoire ne servirait à rien dans ce cas.

3.1.2.144 F1013: Erreur d'écriture du fichier de sortie


Erreur DOS empêchant l'EDI de C++ d'écrire un fichier .OBJ, .EXE ou temporaire.

Solutions

Vérifiez que le répertoire de sortie dans la boîte de dialogue Répertoires est un répertoire valide.

Vérifiez la place disponible sur le disque.

3
3.1.2.145 F1000: Limite de la table du compilateur dépassée
L'une des tables internes du compilateur a débordé.

Ceci signifie généralement que le module compilé contient trop de corps de fonctions.

Ce problème ne peut pas être résolu en augmentant la mémoire disponible pour le compilateur. Vous devez simplifier le fichier à
compiler.

301
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.146 F1005: Fichiers d'inclusion imbriqués trop profondément


Ce message signale (directement ou indirectement) les directives #include récursives.

3.1.2.147 F1008: Plus de mémoire


L'espace de travail est saturé.

Cette erreur peut se produire dans les cas suivants :

• La mémoire virtuelle disponible est insuffisante pour compiler un fichier. Dans ce cas, fermez les applications inutilisées. Vous
pouvez également essayer de reconfigurer votre ordinateur pour augmenter la mémoire virtuelle ou de scinder le fichier
source compilé en plusieurs composants distincts plus petits. Vous pouvez également compiler le fichier sur un système
disposant de plus de mémoire.
• Le compilateur a détecté une expression trop complexe ou trop longue à la ligne indiquée et ses réserves ne lui permettent
pas de l'analyser. Scindez cette expression en plusieurs instructions.

3.1.2.148 F1010: Impossible d'ouvrir 'nomfichier'


Cette erreur se produit si le fichier spécifié ne peut être ouvert.

Vérifiez qu'il est sur le disque et le répertoire spécifiés. Vérifiez que les chemins d'accès aux répertoires sont corrects. Si
plusieurs chemins d'accès sont requis, séparez-les par un point-virgule.

3.1.2.149 E2000: Instructions 286/287 non activées


Utilisez l'option de ligne de commande "-2" du compilateur pour activer les instructions 286/287. Sachez que le code résultant ne
peut être exécuté sur des machines 8086 et 8088.

3.1.2.150 Fin de programme anormale


Le programme appelé a été abandonné car il n'y avait pas assez de mémoire pour son exécution.

Ce message peut être provoqué par des écrasements en mémoire.

3.1.2.151 E2009: Tentative d'accorder ou de réduire l'accès à


'identificateur'
3 Une classe dérivée C++ peut modifier les droits d'accès d'un membre classe de base, mais seulement en lui redonnant les droits
de la classe de base.

Elle ne peut ajouter ni supprimer aucun droit d'accès.

302
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.152 E2011: Il est incorrect de prendre l'adresse d'un champ de


bits
Vous ne pouvez pas prendre l'adresse d'un champ de bits, mais vous pouvez prendre celle des autres types de champs.

3.1.2.153 E2010: Impossible d'ajouter ou de soustraire des symboles


relogeables
Les seules opérations arithmétiques possibles sur un symbole relogeable dans un opérande d'assembleur sont l'addition et la
soustraction d'une constante.

Les variables, les procédures, les fonctions et les libellés sont des symboles relogeables.

3.1.2.154 E2013: 'fonction1' ne peut pas être distinguée de


'fonction2'
Les listes de types de paramètres dans la déclaration de ces deux fonctions sont trop semblables pour les différencier.

Modifiez l'ordre des paramètres ou le type d'un paramètre dans une déclaration.

3.1.2.155 E2014: Membre ambigu : 'membre1' et 'membre2'


Vous devez indiquer le nom correct de la classe de base de la référence du membre.

Dans la classe C++ 'classe', le membre 'membre' peut se trouver dans plusieurs classes de base et ne pas avoir été qualifié ;
vous ne pouvez alors pas en distinguer les différentes occurrences.

Ceci concerne uniquement l'héritage multiple, où le nom de membre dans chaque classe de base n'est pas masqué par le
même nom de membre dans une classe dérivée sur le même chemin.

Le langage C++ impose ce test d'ambiguïté avant la vérification des droits d'accès (private, protected, public).

Il est possible de voir ce message même si un seul (ou aucun) membre est accessible.

3.1.2.156 E2015: Ambiguïté entre 'fonction1' et 'fonction2'


Ces deux fonctions surchargées nommées n'ont pu être utilisées avec les paramètres fournis.

Cette ambiguïté n'est pas autorisée.


3

3.1.2.157 E2017: Nom de membre 'nom' ambigu


Lorsqu'un nom de membre de structure est utilisé dans un assembleur en ligne, ce nom doit être unique. S'il est défini dans
plusieurs structures, toutes les définitions doivent correspondre à son type et à son décalage dans les structures. Dans ce cas,
un nom de membre ambigu a été utilisé.

Par exemple :

303
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

struct A
{
int a;
int b;
};
...
asm ax,.a;

3.1.2.158 E2019: 'identificateur' ne peut pas être déclaré dans une


union anonyme
Le compilateur a détecté une déclaration pour une fonction membre ou un membre statique dans une union anonyme.

Ces unions ne peuvent contenir que des données membre.

3.1.2.159 E2020: Union anonyme globale non statique


En C++, une union globale anonyme au niveau du fichier doit être statique.

3.1.2.160 E2022: Taille de tableau trop grande


Le tableau déclaré est d'une taille supérieure à 64 Ko et le mot-clé 'huge' n'a pas été utilisé.

Si vous avez besoin d'un tableau de cette taille, utilisez le modificateur 'huge' de la façon suivante :
int huge array[70000L]; /* Alloue 140 000 octets */
ou allouez-le dynamiquement avec farmalloc( ) ou farcalloc( ) de la façon suivante :
int huge *array = (int huge *) farmalloc (sizeof (int) * 70000); ?? Allouer 140 000 octets

3.1.2.161 E2024: Impossible de modifier un objet const


Ce message indique une opération illégale sur un objet déclaré comme const, telle qu'une affectation concernant cet objet.

3.1.2.162 E2025: Affectation de 'this' non autorisée, utilisez plutôt


l'opérateur X:: new
Dans les précédentes versions de C++, la seule façon de contrôler l'allocation d'une classe d'objets consistait à affecter le
paramètre 'this' au sein d'un constructeur.

Ceci n'est plus autorisé ; une méthode plus sûre consiste à définir un opérateur new de fonction membre.
3 Par exemple :
this = malloc(n);

3.1.2.163 E2026: Instruction d'assembleur trop longue


La longueur des instructions de l'assembleur en ligne ne peut pas être supérieure à 480 octets.

304
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.164 E2001: Constructeurs et destructeurs non autorisés dans


la section __automated
Seules les déclarations de fonctions membre sont autorisées dans les sections __automated.

Exemple :
struct__declspec(delphiclass) clxclass
{
__automated:
int__fastcall fooInt(int);// OK
clxclass() {}// Erreur
};

3.1.2.165 E2002: Seules les fonctions __fastcall sont autorisées


dans la section __automated
La convention d'appel pour les fonctions déclarées dans une section __automated doit être __fastcall.

Exemple :
struct__declspec(delphiclass) clxclass
{
__automated:
int__fastcall fooInt(int);// OK
int__cdecl barInt(int);// Erreur
};

3.1.2.166 E2003: Définition de données membre non autorisée dans


la section __automated
Seules les déclarations de fonctions membre sont autorisées dans les sections __automated.

Exemple :
struct__declspec(delphiclass) clxclass
{
__automated:
int__fastcall fooInt(int);// OK
intmemInt;// Erreur
};

3.1.2.167 E2004: Seule la clause read (lecture) ou write (écriture) est


autorisée dans la déclaration de propriété de la section __automated
3
Les spécificateurs de stockage stored, default et nodefault ne sont pas autorisés dans les déclarations de propriétés d'une
section __automated.

Exemple :
struct__declspec(delphiclass) clxclass
{
int __fastcall Get(void);
__automated:
int __property ip1 = { read = Get }; // OK

305
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

int __property ip2 = { read = Get, default = 42 }; // Erreur


};

3.1.2.168 E2005: Redéclaration de propriété non autorisée dans la


section __automated
Si vous déclarez une propriété dans une section __automated, il doit s'agir d'une nouvelle déclaration. Les propriétés
surchargées ne sont pas autorisées.

Exemple :
struct__declspec(delphiclass) clxbaseclass
{
int __fastcall Get(void);
void __fastcall Set(int);
int __property ip1 = { read = Get, write = Set };
};
structclxderivedclass : clxbaseclass
{
int __fastcall NewGetter(void);
__automated:
__property ip1;// Erreur
int __property ip2 = { read = Get, write = Set }; // OK
};

3.1.2.169 E2027: L'adresse d'un emplacement mémoire est


obligatoire
Votre fichier source a utilisé l'opérateur "adresse de" (&) avec une expression qui ne peut être utilisée ainsi (par exemple, une
variable registre).

3.1.2.170 E2028: L'opérateur -> doit renvoyer un pointeur ou une


classe
La fonction de l'opérateur C++ '->' doit être déclarée comme renvoyant une classe ou un pointeur sur une classe (ou struct ou
union).

Dans ces deux cas, il doit s'agir d'un élément auquel l'opérateur '->' peut s'appliquer.

3.1.2.171 E2029: 'identificateur' doit être une classe ou une structure


précédemment définie
3 Vous tentez de déclarer 'identificateur' comme une classe de base, mais il ne s'agit pas d'une classe ou il n'est pas entièrement
défini.

Modifiez son nom ou changez l'ordre des déclarations.

3.1.2.172 E2030: Caractère de fin de ligne mal placé


Le compilateur a détecté une instruction break en dehors d'un switch ou d'une boucle.

306
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

Vous pouvez utiliser l'instruction break uniquement dans des instructions switch ou des boucles.

3.1.2.173 E2031: Transtypage impossible de 'type1' en 'type2'


La conversion du type 'ident1' en type 'ident2' n'est pas autorisée.

En C++, vous ne pouvez pas convertir un pointeur de fonction membre en pointeur de fonction normal.

Par exemple :
class A {
public:
int myex();
};
typedef int (*fp)();
test()
{
fp myfp = (fp) &A::myex; //erreur
return myfp();
}
Ceci est dû au fait qu'une fonction membre classe accepte un paramètre masqué, le pointeur this, et donc se comporte
différemment d'un pointeur de fonction normal.

Une fonction membre statique se comporte comme un pointeur de fonction normal et peut être transtypée.

Par exemple :
class A {
public:
static int myex();
};
typedef int (*fp)();
test()
{
fp myfp = (fp) &A::myex; //ok
return myfp();
}
Cependant, les fonctions membre statiques ne peuvent accéder qu'aux données membre statiques de la classe.

En C

• Un pointeur peut être converti en un type intégral ou en un autre pointeur.


• Un type intégral peut être converti en n'importe quel type intégral, flottant ou pointeur.
• Un type flottant peut être converti en type intégral ou flottant.
Les structures et les tableaux ne peuvent pas être convertis.
Il est en général impossible de convertir un type void.
En C++
Les conversions et les constructeurs définis par l'utilisateur sont vérifiés. Si l'un est introuvable, les règles précédentes
s'appliquent (sauf pour les pointeurs sur des membres de classe). 3
Parmi les types intégraux, seule une constante zéro peut être convertie en pointeur de membre.
Un pointeur de membre peut être converti en type intégral ou en un pointeur de membre similaire.
Un pointeur de membre similaire pointe sur des données membre (ou sur une fonction) si l'original le fait. La classe qualifiante
du type en cours de conversion doit être la même que celle de (ou une classe de base de) l'original.

307
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.174 E2033: Instruction continue mal placée


Le compilateur a détecté une instruction continue en dehors d'une boucle.

3.1.2.175 E2034: Impossible de convertir 'type1' en 'type2'


Une affectation, une initialisation ou une expression requiert la conversion de type spécifiée, mais cette conversion n'est pas
autorisée.

En C++, le compilateur ne convertit un pointeur de fonction que si la signature des fonctions est identique. La signature désigne
les arguments et le type de retour de la fonction. Par exemple :
myex( int );
typedef int ( *ffp )( float );
test()
{
ffp fp = myex; //erreur
}
Etant donné que myex accepte un entier comme argument et que fp est un pointeur sur une fonction acceptant une valeur
flottante comme argument, le compilateur ne convertit pas la fonction.

Si vous souhaitez toutefois effectuer la conversion, vous devez réaliser un transtypage :


myex( int );
typedef int ( *ffp )( float );
test()
{
ffp fp = (ffp)myex; //ok
}

3.1.2.176 E2036: L'opérateur de conversion ne peut pas avoir de


spécification de type de retour
Cette fonction membre de conversion de type C++ spécifie un type de retour différent du type lui-même.

Une déclaration d'opérateur de fonction de conversion ne peut spécifier de type de retour.

3.1.2.177 E2037: Le constructeur 'constructeur' n'est pas autorisé


Les constructeurs au format
X(X); //{ Erreur
};

3 ne sont pas autorisés.

Voici la syntaxe correcte pour un constructeur de copie :


class X {
X(const X&);// Constructeur de copie
};

308
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.178 E2039: Séparateur décimal mal placé


Le compilateur a détecté, dans une constante à virgule flottante, un séparateur décimal comme faisant partie de l'exposant.

3.1.2.179 E2041: Utilisation incorrecte du mot clé default


Le compilateur n'a pas détecté le signe deux-points après le mot clé default.

3.1.2.180 E2042: Déclarer l'opérateur delete (void*) ou (void*, size_t)


E2043 Déclarer l'opérateur delete[] (void*) ou (void*, size_t)Erreur du compilateur

Déclarez l'opérateur delete avec :

1.Un seul paramètre void*, ou

2.Un second paramètre de type size_t

Si vous utilisez la seconde méthode, elle sera utilisée de préférence à la première version.

L'opérateur delete global ne peut être déclaré qu'avec un seul paramètre.

3.1.2.181 E2044: L'opérateur delete doit retourner void


E2044 L'opérateur delete[] doit retourner voidErreur du compilateur

Cet opérateur delete surchargé C++ a été déclaré d'une autre façon.

Déclarez l'opérateur delete avec :

1.Un seul paramètre void*, ou

2.Un second paramètre de type size_t

Si vous utilisez la seconde méthode, elle sera utilisée de préférence à la première version.

L'opérateur delete global ne peut être déclaré qu'avec un seul paramètre.

3.1.2.182 E2045: Le nom du destructeur doit correspondre au nom


de la classe
Dans une classe C++, le tilde (~) introduit une déclaration pour le destructeur de classe.

Le nom du destructeur doit être identique à celui de la classe.


3
Dans votre fichier source, le "~" précédait un autre nom.

309
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.183 E2048: Directive de préprocesseur inconnue :


'identificateur'
Le compilateur a détecté le caractère # en début de ligne. Le nom de directive qui suivait le # ne faisait pas partie des directives
suivantes :

• define ( see page 696)


• else ( see page 693)
• endif ( see page 693)
• if ( see page 693)
• ifdef ( see page 694)
• ifndef ( see page 694)
• include ( see page 698)
• line ( see page 699)
• pragma
• undef ( see page 698)

3.1.2.184 E2046: Format de nom de fichier incorrect dans la directive


include OU format de nom de fichier incorrect dans la directive line
Les noms de fichiers de directives include et line doivent être placés entre guillemets ("nomfichier.h") ou entre crochets
(<nomfichier.h>).

Le nom du fichier n'était pas délimité par ces caractères.

Si une macro était utilisée, le texte d'expansion n'est pas entouré par des guillemets.

3.1.2.185 E2051: Utilisation incorrecte du point


Un identificateur doit immédiatement suivre l'opérateur point (.). C'est un message rare qui ne peut se produire que dans
certaines instructions assembleur en ligne spécialisées.

Exemple
struct foo {
int x;
int y;
}p = {0,0};
int y;
3 int main (void)
{
asm mov eax.(foo)x, 1;
asm mov eax.(foo)4, 1; /* Erreur : Utilisation incorrecte du point */
return 0;
}

310
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.186 E2053: Directive elif mal placée


Le compilateur a détecté une directive #elif sans directive #if, #ifdef ou #ifndef correspondante.

3.1.2.187 E2054: Instruction else mal placée


Le compilateur a détecté une instruction else sans instruction "if" correspondante.

Cause possible

• une instruction "else" en trop ;


• un point-virgule de trop ;
• des accolades manquantes ;
• une erreur de syntaxe dans une instruction "if" précédente.

3.1.2.188 E2055: Directive else mal placée


Le compilateur a détecté une directive #else sans directive #if, #ifdef ou #ifndef correspondante.

3.1.2.189 E2056: Directive endif mal placée


Le compilateur a détecté une directive #endif sans directive #if, #ifdef ou #ifndef correspondante.

3.1.2.190 E2059: Langage inconnu, doit être du C ou du C++


Dans la construction C++
extern "nom" type func( /*...*/ );
le "nom" doit être "C" ou "C++" (n'oubliez pas les guillemets) ; les autres noms de langage ne sont pas reconnus.

Vous pouvez déclarer ainsi une fonction Pascal externe sans que le compilateur ne la renomme :
extern "C" int pascal func( /*...*/ );
Pour déclarer une fonction C++ (éventuellement surchargée) comme fonction Pascal et permettre son changement de nom par
le compilateur (pour autoriser la surcharge), vous pouvez saisir le code suivant :
extern int pascal func( /*...*/ );

3.1.2.191 E2060: Utilisation incorrecte de la virgule flottante 3


Les opérandes à virgule flottante ne sont pas autorisés avec ces opérateurs :

• décalages (SHL, SHR) ;


• booléens binaires (AND, OR, XOR, NOT) ;
• conditionnels (? :) ;
• indirection (*)

311
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

• certains autres.
Le compilateur a détecté un opérande à virgule flottante utilisé avec l'un de ces opérateurs interdits.

3.1.2.192 E2061: Les amis doivent être des fonctions ou des classes
Un ami d'une classe C++ doit être une fonction ou une autre classe.

3.1.2.193 E2062: Indirection incorrecte


L'opérateur d'indirection (*) requiert un pointeur comme opérande.

Exemple
int main (void)
{
int p;
*p = 10; /* ERREUR : indirection incorrecte */
return 0;
}

3.1.2.194 E2063: Initialisation incorrecte


Il n'existe que deux types d'initialisations :

• expressions constantes ;
• adresse d'une variable extern globale ou statique, plus ou moins une constante.

3.1.2.195 E2064: Impossible d'initialiser 'type1' avec 'type2'


Vous tentez d'initialiser un objet de type 'type1' avec une valeur de type 'type2'. Ceci n'est pas autorisé.

Les règles d'initialisation sont les mêmes que celles d'affectation.

3.1.2.196 E2068: 'identificateur' n'est pas une donnée membre non


statique et ne peut pas être initialisé ici
Seules les données membre peuvent être initialisées dans les initialisateurs d'un constructeur.

Ce message signifie que la liste comporte un membre statique ou un membre de fonction.

Les membres statiques doivent être initialisés en dehors de la classe, par exemple :

3 class A { static int i; };


int A::i = -1;

3.1.2.197 E2069: Utilisation incorrecte d'un pointeur de membre


Les pointeurs sur des membres de classes peuvent être uniquement transmis comme arguments de fonctions ou utilisés avec
les opérateurs suivants :

• assignment

312
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

• comparaison

->
• ?:
• &&
• ||
Le compilateur a détecté un pointeur membre utilisé avec un autre opérateur.
Pour appeler un pointeur de fonction membre, vous devez fournir une instance de la classe.
Par exemple :
class A {
public:
myex();
};
typedef int (A::*Amfptr)();
myex()
{
Amfptr mmyex = &A::myex;
return (*mmyex)(); //erreur
}
Le code suivant entraînera une compilation :
cl_ass A {
public:
myex();
};
typedef int (A::*Amfptr)();
foo()
{
A a;
Amfptr mmyex = &A::myex;
return (a.*mmyex)();
}

3.1.2.198 E2071: L'opérateur new doit avoir un paramètre initial de


type size_t
E2071 L'opérateur new[] doit avoir un paramètre initial de type size_tErreur du compilateur

L'opérateur new peut être déclaré avec un nombre de paramètres arbitraire.

Il doit toujours en avoir au moins un, la quantité de mémoire à allouer.

3.1.2.199 E2072: L'opérateur new[] doit renvoyer un objet de type


3
void
Cet opérateur new surchargé C++ a été déclaré d'une autre façon.

313
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.200 E2075: Option 'type' incorrecte : option


Une erreur s'est produite dans le fichier de configuration ou dans une option de la ligne de commande. Le compilateur n'a
peut-être pas reconnu un paramètre du fichier de configuration comme paramètre autorisé ; recherchez un éventuel tiret (-)
précédent. Il se peut aussi que le compilateur n'ait pas reconnu le paramètre de la ligne de commande comme paramètre
autorisé.

Cette erreur peut également se produire si vous utilisez une option #pragma dans votre code avec une option non valide.

3.1.2.201 E2076: Opérateur surchargeable attendu


Presque tous les opérateurs C++ peuvent être surchargés.

Voici les seuls qui ne peuvent pas être surchargés :

• le point de sélection de champ (.)


• le point étoile (.*)
• le double deux points (::)
• l'expression conditionnelle (?:)
Les opérateurs de préprocesseur (# et ##) ne sont pas des opérateurs du langage C ou C++ et ne peuvent donc pas être
surchargés.
Les autres signes de ponctuation n'appartenant pas à des opérateurs, tels que le point-virgule (;), ne peuvent pas être
surchargés.

3.1.2.202 E2080: La fonction 'fonction' doit être déclarée avec un


paramètre
Cette fonction opérateur C++ a été déclarée avec plusieurs paramètres.

3.1.2.203 E2077: 'opérateur' doit être déclaré avec un ou sans


paramètre
Lorsque l'opérateur "++" ou "--" est déclaré comme fonction membre, il doit être déclaré comme acceptant :

• aucun paramètre (pour la version à préfixe de l'opérateur), ou


• un seul paramètre de type int (pour la version à suffixe).

3
3.1.2.204 E2079: 'fonction' doit être déclarée sans paramètres
Cette fonction opérateur C++ a été déclarée avec des paramètres.

314
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.205 E2078: 'opérateur' doit être déclaré avec un ou deux


paramètres
Lorsque l'opérateur "++" ou "--" est déclaré comme fonction non membre, il doit être déclaré comme acceptant :

• un seul paramètre (pour la version à préfixe de l'opérateur), ou


• deux paramètres (pour la version à suffixe)

3.1.2.206 E2081: 'fonction' doit être déclarée avec deux paramètres


Cette fonction opérateur C++ n'a pas été déclarée avec deux paramètres.

3.1.2.207 E2082: 'identificateur' doit être une fonction membre ou


avoir un paramètre de type classe
La plupart des fonctions opérateur C++ doivent avoir un paramètre implicite ou explicite de type classe.

Cette fonction opérateur a été déclarée en dehors d'une classe et n'a pas de paramètre explicite de type classe.

3.1.2.208 E2083: Le dernier paramètre de 'opérateur' doit être de


type 'int'
Lorsque l'opérateur à suffixe ++ ou -- est surchargé, le dernier paramètre doit être déclaré avec le type int.

3.1.2.209 E2084: Les noms de paramètres sont utilisés seulement


avec un corps de fonction
Lorsque vous déclarez une fonction (sans la définir avec un corps de fonction), vous devez utiliser des parenthèses vides ou un
prototype de fonction.

Une liste de noms de paramètres seule n'est pas autorisée.

Exemples de déclarations
int func(); /* déclaration sans prototype -- OK */
int func(int, int); /* déclaration avec prototype -- OK */
int func(int i, int j); /* noms de paramètres dans prototype -- OK */
int func(i, j); /* noms de paramètres seuls -- ILLEGAL */
3
3.1.2.210 E2085: Addition de pointeurs incorrecte
Votre fichier source a tenté d'ajouter deux pointeurs.

315
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.211 E2086: Soustraction de pointeurs incorrecte


Ce message s'affiche car vous avez essayé de soustraire un pointeur à un non pointeur.

3.1.2.212 E2087: Utilisation incorrecte du pointeur


Les pointeurs ne peuvent être utilisés qu'avec ces opérateurs :

• addition (+)
• soustraction (–)
• affectation (=)
• comparaison (==)
• indirection (*)
• flèche (->)
Votre fichier source a utilisé un pointeur avec un autre opérateur.
Exemple
int main (void)
{
char *p;
p /= 7; /* ERREUR : mauvaise utilisation du pointeur */
return 0;
}

3.1.2.213 E2088: Syntaxe incorrecte pour la définition de fonctions


pures
Les fonctions virtuelles pures sont spécifiées par ajout de "= 0" à la déclaration :
class A { virtual void f () = 0;}
class B : public A { void f () {}; }
Vous avez écrit quelque chose de semblable mais qui n'était pas correct.

3.1.2.214 E2089: L'identificateur 'identificateur' ne peut pas avoir un


qualificateur de type
L'identificateur qualificateur de classe C++ "::" ne peut pas être utilisé ici.

Les qualificateurs sont interdits sur :


3
• les noms typedef ;
• les déclarations de fonctions (sauf les définitions au niveau du fichier) ;
• les variables locales ou les paramètres de fonctions ;
• un membre de classe, sauf si vous utilisez sa propre classe comme qualificateur (ceci est redondant mais autorisé).

316
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.215 E2090: Le qualificateur 'identificateur' n'est pas un nom de


classe ou d'espace de nommage
Le qualificateur C++ dans la construction qual::identificateur n'est pas le nom d'une structure ou d'une classe.

3.1.2.216 E2092: La classe de stockage 'classe de stockage' n'est


pas autorisée ici
Cette classe de stockage n'est pas autorisée ici.

Il est probable que deux classes de stockage ont été spécifiées, alors qu'une seule ne peut l'être.

3.1.2.217 E2096: Opération de structure incorrecte


Les structures ne peuvent être utilisées qu'avec des opérateurs point (.), adresse (&) ou affectation (=), ou transmis à ou depuis
une fonction en tant que paramètres.

Le compilateur a détecté une structure utilisée avec un autre opérateur.

3.1.2.218 E2104: Utilisation incorrecte du mot clé template


Vous ne pouvez utiliser un nom de classe modèle que si vous ne spécifiez pas ses arguments à l'intérieur d'une définition de
modèle.

Il n'est pas possible d'utiliser un nom de classe modèle sans spécifier ses arguments en dehors d'une définition de modèle.

3.1.2.219 E2108: Utilisation incorrecte de typedef 'identificateur'


Votre fichier source contient un symbole typedef à la place d'une variable dans une expression.

Vérifiez la déclaration du symbole et les éventuelles fautes de frappe.

3.1.2.220 E2109: Type non autorisé


Votre fichier source a déclaré un type interdit ; par exemple, une fonction renvoyant une fonction ou un tableau.

3
3.1.2.221 E2110: Conversion de type incompatible
La conversion demandée ne peut être effectuée.

317
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.222 E2113: Conflits de fonction virtuelle 'fonction1' avec la


classe de base 'base'
Une fonction virtuelle a les mêmes types d'arguments qu'une fonction dans une classe de base, mais diffère sur les points
suivants :

• Type de retour
• Convention d'appel
• Spécification d'exception (liste throw)

3.1.2.223 E2114: Plusieurs classes de base nécessitent des noms de


classes explicites
Dans un constructeur de classe C++, s'il existe plusieurs classes de base immédiates, chaque appel de constructeur de classe
de base dans l'en-tête du constructeur doit inclure le nom de la classe de base.

3.1.2.224 E2115: Champ de bits trop grand


Cette erreur se produit lorsque vous fournissez un champ de bits de plus de 16 bits.

3.1.2.225 E2116: Les champs de bits doivent contenir au moins un


bit
Vous ne pouvez pas déclarer un champ de bits nommé avec 0 (ou moins) bit.

Vous pouvez déclarer un champ de bits non nommé avec 0 bit.

Cette convention est utilisée pour forcer l'alignement du champ de bits suivant avec une limite d'octets ou une limite de mots.

3.1.2.226 W8005: Les champs de bits doivent être des entiers signés
ou non signés
En C ANSI, les champs de bits ne peuvent être que des entiers signés ou non signés (pas de char ni de long, par exemple).

3
3.1.2.227 E2119: Pause utilisateur
Vous avez tapé Ctrl+Pause pendant la compilation dans l'EDI.

(Ceci n'est pas une erreur, uniquement une confirmation.)

318
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.228 E2111: Le type 'nomtype' ne peut pas être défini ici


Les types classe et énumération ne peuvent pas être définis dans un type retour de fonction, un type argument de fonction, un
type opérateur de conversion ou le type spécifié dans un transtypage.

Vous devez définir le type spécifié avant de l'utiliser dans les contextes ci-dessus.
Remarque : Ce message d'erreur résulte souvent d'un point-virgule (;) manquant dans une déclaration de classe. Vérifiez que
toutes les déclarations de classe précédant la ligne à l'origine de l'erreur se terminent par un point-virgule.

3.1.2.229 E2121: ) manquante dans l'appel de fonction


La liste d'arguments d'appel de fonction contient une erreur de syntaxe (par exemple, parenthèse manquante ou nombre impair
de parenthèses).

3.1.2.230 E2123: La classe 'classe' ne doit pas contenir des


fonctions pures
La classe déclarée ne peut pas être abstraite et ne peut donc pas contenir des fonctions pures.

3.1.2.231 E2126: Case a contourné l'initialisation d'une variable


locale
En C++, il est illégal de contourner l'initialisation d'une variable locale.

Cette erreur indique qu'un libellé CASE peut transférer le contrôle au-delà de cette variable locale.

3.1.2.232 E2127: Instruction case manquante :


Une instruction case doit avoir une expression constante suivie du signe deux-points.

L'expression dans cette instruction ne comportait pas de signe deux-points ou comportait un symbole de trop avant le signe.

3.1.2.233 E2128: Case en dehors du switch


Le compilateur a détecté une instruction case en dehors d'une instruction switch.

Cela est souvent provoqué par des accolades mal appariées. 3

3.1.2.234 E2129: Constante caractère trop longue (ou vide)


Les constantes caractère ne peuvent comporter qu'un ou deux caractères.

319
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.235 E2133: Impossible d'exécuter la commande 'commande'


Le lieur ou l'assembleur est introuvable, ou le disque est endommagé.

3.1.2.236 E2134: Accolade fermante manquante dans une instruction


composée
Le compilateur a atteint la fin du fichier source et n'a détecté aucune accolade fermante.

Vérifiez le nombre d'accolades fermantes et ouvrantes.

3.1.2.237 E2137: Un destructeur pour 'classe' est nécessaire dans


l'expression conditionnelle
Si le compilateur doit créer une variable locale temporaire dans une expression conditionnelle, il ne sait pas où appeler le
destructeur car la variable n'a pas forcément été initialisée.

La variable temporaire peut être créée explicitement avec classname(val, val) ou implicitement par un autre code.

Vous devez réécrire votre code pour éliminer cette valeur temporaire.

3.1.2.238 E2135: Un constructeur/destructeur ne peut pas être


déclaré 'const' ou 'volatile'
Un constructeur ou un destructeur a été déclaré const ou volatile.

Ceci n'est pas autorisé.

3.1.2.239 E2138: Conflit de modificateurs de type


Cette erreur se produit lorsqu'une déclaration inclut plusieurs modificateurs d'adressage sur un pointeur ou plusieurs
modificateurs de langage pour une fonction.

Un seul modificateur de langage (par exemple, __cdecl, __pascal, ou __fastcall) peut être spécifié pour une fonction.

3.1.2.240 E2136: Un constructeur ne peut pas avoir de spécification


3 de type de retour
Les constructeurs C++ ont un type de retour implicite utilisé par le compilateur, mais vous ne pouvez pas déclarer un type de
retour ni renvoyer une valeur.

320
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.241 E2038: Impossible de déclarer ou de définir 'identificateur'


ici : espace de nommage incorrect
Vous avez tenté de déclarer un modèle à un emplacement illégal ou un membre d'espace de nommage en dehors de son
espace de nommage.

3.1.2.242 E2154: Impossible de définir 'identificateur' en utilisant un


alias d'espace de nommage
Vous ne pouvez pas utiliser un alias d'espace de nommage (namespace) pour définir un membre d'espace de nommage en
dehors de son espace de nommage.

3.1.2.243 E2421: Impossible d'utiliser le type local 'identificateur'


comme argument modèle
Un type local a été utilisé dans un argument réel de type modèle. Ceci est illégal.

3.1.2.244 E2035: Les conversions d'une classe en elle-même ou en


classe de base ne sont pas autorisées
Vous avez tenté de définir un opérateur de conversion visant à transtyper une classe en la même classe ou en une classe de
base.

3.1.2.245 E2139: ; manquant dans la déclaration


Votre fichier source contient une déclaration de champ struct ou union non suivie d'un point-virgule.

Vérifiez qu'il ne manque aucun point-virgule dans les lignes précédentes.

3.1.2.246 E2140: La déclaration n'est pas autorisée ici


Les déclarations ne peuvent être utilisées comme instructions de contrôle dans les instructions while, for, do, if ou switch.

3.1.2.247 E2141: Erreur de syntaxe de déclaration 3

Votre fichier source contient une déclaration comportant trop ou pas assez de symboles.

Vérifiez que vous n'avez pas oublié de point-virgule ou de parenthèse dans cette ligne ou dans les lignes précédentes.

321
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.248 E2142: La classe de base 'classe' contient des fonctions


qui peuvent être réparties de façon dynamique
Cette erreur se produit lorsqu'une classe contenant une fonction DDVT tente d'hériter de fonctions DDVT de plusieurs classes
parent.

A ce jour, les tables virtuelles réparties dynamiquement ne gèrent pas l'utilisation des héritages multiples.

3.1.2.249 E2143: La fonction 'fonction' de classe de base


correspondante a un numéro de répartition différent
Si une fonction DDVT est déclarée dans une classe dérivée, la fonction de classe de base correspondante doit avoir le même
numéro de répartition que la fonction dérivée.

3.1.2.250 E2144: La fonction de classe de base correspondante


'fonction' n'est pas dynamique
Si une fonction DDVT est déclarée dans une classe dérivée, la fonction de classe de base correspondante doit également être
dynamique.

3.1.2.251 E2145: Les fonctions 'fonction1' et 'fonction2' utilisent le


même numéro de répartition
Cette erreur indique un problème concernant la table virtuelle répartie dynamiquement (DDVT).

3.1.2.252 E2146: Vous devez fournir un identificateur à déclarer


Dans ce contexte, un identificateur était attendu pour terminer la déclaration.

Il peut s'agir d'un typedef sans nom ou d'un point-virgule en trop au niveau du fichier.

En C++, il peut s'agir d'un nom de classe utilisé à la place d'un autre type d'identificateur.

3.1.2.253 E2147: 'identificateur' ne peut pas démarrer une


3 déclaration de paramètre
Un identificateur non défini a été détecté en début d'argument dans un déclarateur de fonction.

Souvent, le nom du type est mal orthographié ou sa déclaration est absente. Ceci est généralement dû au fait que le fichier
d'en-tête approprié n'a pas été inclus.

322
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.254 E2150: Mauvaise correspondance de type dans la valeur


de l'argument par défaut
La valeur par défaut du paramètre n'a pas pu être convertie en type du paramètre.

Ce message est affiché lorsque le paramètre n'a pas de nom.

Lorsque vous compilez des programmes C++, ce message est toujours précédé d'un autre expliquant la raison exacte de cette
non concordance de types.

Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'", mais la non concordance peut venir d'un autre
problème.

3.1.2.255 E2152: L'expression par défaut ne doit pas utiliser des


variables locales
Une expression d'argument par défaut ne peut pas utiliser de variables locales ou d'autres paramètres.

3.1.2.256 E2153: La directive define nécessite un identificateur


Le premier caractère autre qu'un espace après #define doit être un identificateur.

Le compilateur a détecté un autre caractère.

3.1.2.257 E2155: Trop d'instructions default


Le compilateur a détecté plusieurs instructions par défaut dans un même switch.

3.1.2.258 E2156: Default en dehors du switch


Le compilateur a détecté une instruction default en dehors d'une instruction switch.

Vérifiez le nombre d'accolades fermantes et ouvrantes.

3.1.2.259 E2158: L'opérande de 'delete' doit être un pointeur


non-const
Vous ne pouvez pas supprimer une variable autre qu'un pointeur ni un pointeur sur une constante. 3
Par exemple :
const int x=10;
const int * a = &x;
int * const b = new int;
int &c = *b;
delete a; //incorrect - suppression d'un pointeur sur une constante
delete b; //correct

323
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

delete c; //illégal - l'opérande n'est pas de type pointeur


//utilisez 'delete&c' à la place

3.1.2.260 E2159: Tentative de dériver une classe far depuis la base


huge 'base'
Cette erreur n'est plus générée par le compilateur.

3.1.2.261 E2160: Tentative de dériver une classe far depuis la base


near 'base'
Si une classe est déclarée (ou prend par défaut la valeur) near, toutes les classes dérivées doivent également être near.

3.1.2.262 E2161: Tentative de dériver une classe huge depuis la base


far 'base'
Cette erreur n'est plus générée par le compilateur.

3.1.2.263 E2162: Tentative de dériver une classe huge depuis la base


near 'base'
Cette erreur n'est plus générée par le compilateur.

3.1.2.264 E2163: Tentative de dériver une classe near depuis la base


far 'base'
Si une classe est déclarée (ou prend par défaut la valeur) far, toutes les classes dérivées doivent également être far.

3.1.2.265 E2164: Tentative de dériver une classe near depuis la base


huge 'base'
Cette erreur n'est plus générée par le compilateur.

3 3.1.2.266 E2165: Un destructeur ne peut pas avoir de spécification


de type de retour
Les destructeurs C++ ne renvoient jamais de valeur et vous ne pouvez pas déclarer de type de retour ni renvoyer une valeur.

324
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.267 E2166: Le destructeur de 'classe' n'est pas accessible


Le destructeur de cette classe C++ est protégé ou privé et vous ne pouvez pas y accéder ici pour détruire la classe.

Si un destructeur de classe est privé, la classe ne peut pas être détruite ni utilisée. Ceci est probablement une erreur.

Un destructeur protégé n'est accessible que depuis des classes dérivées.

Ceci garantit qu'aucune instance d'une classe de base n'est créée et que seules des classes en sont dérivées.

3.1.2.268 E2167: 'fonction' a été précédemment déclarée avec le


langage 'langage'
Un seul modificateur de langage (cdecl pascal) peut être fourni pour une fonction.

Cette fonction a été déclarée avec des modificateurs différents en deux endroits.

3.1.2.269 E2168: Division par zéro


Votre fichier source contient une division ou un reste dans une expression constante avec un diviseur zéro.

3.1.2.270 E2169: 'identificateur' spécifie des accès multiples ou


dupliqués
Une classe de base peut être déclarée publique ou privée, mais pas les deux.

Ce spécificateur d'accès ne peut apparaître plusieurs fois pour une classe de base.

3.1.2.271 E2170: La classe de base 'classe' est incluse plusieurs fois


Une classe C++ peut être dérivée d'un grand nombre de classes de base, mais elle ne peut être dérivée qu'une fois directement
d'une classe précise.

3.1.2.272 E2171: Le corps a déjà été défini pour la fonction 'fonction'


Une fonction de ce nom et de ce type a déjà été fournie comme corps de fonction.

Un corps de fonction ne peut être fourni qu'une fois.


3
Une cause de cette erreur est la non déclaration d'un constructeur par défaut que vous implémentez. Par exemple :
class A {
public:
virtual myex();
};
A::A() {} // erreur
Le constructeur par défaut n'ayant pas été déclaré dans la déclaration de classe, le compilateur a dû en générer un, ce qui
entraîne le message d'erreur lorsqu'il en détecte un. Voici un exemple de syntaxe correcte :

325
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

class A {
public:
A();
virtual myex();
};
A::A() {}

3.1.2.273 E2172: Case dupliqué


Chaque libellé case d'une instruction switch doit avoir une valeur unique d'expression constante.

3.1.2.274 E2175: Trop de classes de stockage dans la déclaration


Une déclaration ne peut pas avoir plusieurs classes de stockage (Auto, Register, Static ou Extern).

3.1.2.275 E2176: Trop de types dans la déclaration


Une déclaration ne peut pas avoir plusieurs types de base. Voici des exemples de types de base :

• char
• class
• int
• float
• double
• struct
• union
• enum
• typedef name

3.1.2.276 E2179: virtual spécifié plusieurs fois


Le mot réservé C++ "virtual" ne peut apparaître qu'une fois dans une déclaration de fonction membre.

3.1.2.277 E2007: Dispid n'est autorisé que dans les sections


__automated
La définition des dispid n'est possible que dans les sections __automated.
3
Exemple :
struct__declspec(delphiclass) clxclass
{
int __fastcall foo1(void) __dispid(42);// Erreur
__automated:
int __fastcall foo2(void) __dispid(43);// OK
};

326
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.278 Erreur de division


Vous avez essayé de diviser un entier par zéro, ce qui est incorrect.

3.1.2.279 E2182: Paramètre incorrect pour __emit__


Certaines restrictions s'appliquent à l'insertion directe de valeurs littérales dans votre code avec la fonction __emit__.

Par exemple, vous ne pouvez pas fournir à __emit__ une variable locale comme paramètre.

3.1.2.280 E2183: Le fichier doit contenir au moins une déclaration


externe
Cette unité de compilation est logiquement vide (elle ne contient aucune déclaration externe).

ANSI C et C++ exigent qu'un élément soit déclaré dans l'unité de compilation.

3.1.2.281 E2184: Erreur de syntaxe pour une énumération


Une déclaration enum ne contenait pas de liste d'identificateurs au bon format.

3.1.2.282 E2185: La valeur de 'identificateur' n'est pas un entier


Tous les énumérateurs doivent avoir une valeur représentable sous forme d'entier.

Vous avez tenté d'affecter une valeur autre qu'un entier.

Si vous avez besoin d'une constante de cette valeur, utilisez un entier const.

3.1.2.283 E2186: Fin de fichier inattendue dans le commentaire qui


commence à la ligne 'numéro de ligne'
Le fichier source se termine au milieu d'un commentaire.

Cette erreur est généralement due à l'omission d'un symbole de fermeture de commentaire (*/).

3.1.2.284 E2187: Fin de fichier inattendue dans l'instruction 3


conditionnelle qui commence à la ligne 'numéro de ligne'
Le fichier source s'est terminé avant que le compilateur (ou MAKE) ne détecte une instruction #endif.
#endif est mal orthographié ou manquant.

Toute instruction #if doit avoir son #endif correspondant.

327
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.285 E2188: Syntaxe de l'expression


Ceci est un message d'erreur générique, qui s'affiche si le compilateur détecte une erreur grave lors de l'analyse d'une
expression.

Cause possible

Cette erreur est généralement due à l'un des problèmes suivants :

• deux opérateurs consécutifs ;


• parenthèses manquantes ;
• point-virgule manquant dans l'instruction précédente.
Solutions
Si la syntaxe de la ligne concernée semble correcte, recherchez l'erreur dans la ligne précédente.
Essayez de déplacer la ligne comportant l'erreur à un autre endroit du fichier et recompilez.
Si l'erreur se produit toujours dans l'instruction déplacée, l'erreur de syntaxe se trouve dans cette instruction.
Si l'erreur se produit dans une autre instruction, l'erreur de syntaxe est probablement dans le code proche.

3.1.2.286 E2190: Accolade fermante inattendue


Une accolade droite en trop a été trouvée. Recherchez une accolade fermante manquante.

Astuce :

L'EDI permet de rechercher les accolades correspondantes. Si vous placez le curseur sur le caractère '{' ou '}', maintenez la
touche Ctrl enfoncée, appuyez sur 'Q' puis sur '{' ou sur '}', le curseur se place sur l'accolade correspondante.

3.1.2.287 E2189: La variable extern ne peut pas être initialisée


La classe de stockage externe appliquée à une variable signifie que la variable est déclarée mais pas définie ici ; aucun
stockage ne lui est alloué.

Vous ne pouvez donc pas initialiser la variable dans la déclaration.

3.1.2.288 E2344: Déclaration précédente de 'identificateur'


Ce message d'erreur ne s'affiche qu'après les messages "Déclaration multiple pour 'identificateur'" et "Non concordance de type
dans la redéclaration de 'identificateur'". Il indique où la définition précédente de l'identificateur a été détectée par le compilateur,
de telle sorte que vous n'avez pas besoin de la chercher.
3

3.1.2.289 E2192: Trop peu de paramètres dans l'appel


Ce message d'erreur se produit lorsqu'un appel à une fonction avec un prototype (via un pointeur de fonction) n'a pas assez
d'arguments. Les prototypes requièrent tous les paramètres. Vérifiez que votre appel à une fonction a le même nombre de
paramètres que son prototype.

328
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.290 E2193: Trop peu de paramètres dans l'appel à 'fonction'


Ce message d'erreur se produit lorsqu'un appel à une fonction nommé (déclarée avec un prototype) n'a pas assez d'arguments.

Vérifiez que votre appel à la fonction a le même nombre de paramètres que son prototype.

3.1.2.291 E2194: Impossible de trouver le fichier 'nomfichier'


Le compilateur ne trouve pas le fichier spécifié sur la ligne de commande.

3.1.2.292 E2197: Nom de fichier trop long


Le nom de fichier fourni dans une directive #include était trop long et n'a pas pu être traité par le compilateur.

Les noms de fichiers complets sous DOS ne doivent pas comporter plus de 79 caractères.

3.1.2.293 E2195: Impossible d'évaluer l'appel de fonction


Ce message d'erreur s'affiche si vous tentez de construire explicitement un objet ou d'appeler une fonction virtuelle.

Dans une évaluation d'expression du débogueur intégré, les appels à certaines fonctions (notamment les fonctions de
conversion implicite, les constructeurs, les destructeurs, les opérateurs surchargés et les fonctions inline) ne sont pas gérés.

3.1.2.294 E2198: Ce n'est pas un type de format d'expression correct


Un spécificateur de format incorrect suit une expression dans la fenêtre d'évaluation ou de suivi du débogueur. Un spécificateur
de format valide est une valeur de répétition facultative suivie d'un caractère de formatage (c, d, f[n], h, x, m, p, r ou s).

3.1.2.295 E2200: Les fonctions ne peuvent pas faire partie d'une


structure ou d'une union
Ce champ struct ou union C était déclaré comme fonction type plutôt que comme pointeur sur une fonction.

Les fonctions sous forme de champs ne sont autorisées qu'en langage C++.

3.1.2.296 Erreur de calcul à virgule flottante : Erreur de division par


3
0 OU de calcul à virgule flottante : Erreur de domaine ou de calcul à
virgule flottante : Dépassement de capacité
Ces erreurs fatales proviennent d'une opération à virgule flottante pour laquelle le résultat n'est pas fini :

• Une division par 0 signifie que le résultat est exactement +INF ou -INF, par exemple 1.0/0.0.
• Un domaine signifie que le résultat est un NAN (not a number, valeur non numérique), comme 0.0/0.0.

329
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

• Un dépassement de capacité signifie que le résultat est +INF (infinité) ou -INF avec une perte de précision complète, comme
l'affectation de 1e200*1e200 à un double.

3.1.2.297 Erreur de calcul à virgule flottante : Faute de pile


La pile a virgule flottante a débordé. Cette erreur peut être due à un code assembleur qui a utilisé trop de registres ou à une
mauvaise déclaration d'une fonction à virgule flottante.

Le programme affiche le message d'erreur et appelle abort et _exit.

Ces erreurs de virgule flottante peuvent être évitées en masquant l'exception pour qu'elle ne se produise pas ou en interceptant
l'exception avec un signal.

3.1.2.298 Erreur de calcul à virgule flottante : Perte de précision


partielle OU Erreur de calcul à virgule flottante : Débordement
inférieur
Ces exceptions sont masquées par défaut, car les débordements inférieurs sont convertis en zéro et les pertes de précision sont
ignorées.

3.1.2.299 E2201: Trop de données globales définies dans le fichier


La somme des déclarations de données globales dépasse 64 Ko. Ceci inclut toutes les données stockées dans le DGROUP
(toutes les variables globales, chaînes littérales et locales statiques).

Solutions

Recherchez dans les déclarations les tableaux trop volumineux. Vous pouvez également supprimer des variables de DGROUP.

Voici comment :

• Déclarez les variables comme automatiques. Ceci utilise l'espace de la pile.


• A partir du tas, allouez dynamiquement de la mémoire pour ces variables à l'aide de calloc, malloc ou farmalloc. Ceci
nécessite l'utilisation de pointeurs.
Les chaînes littérales sont également placées dans le DGROUP. Procurez-vous le fichier farstr.zip sur notre BBS afin d'extraire
les chaînes littérales et de les placer dans leur propre segment.

3.1.2.300 E2203: Goto évite l'initialisation d'une variable locale


En C++, il est interdit de contourner l'initialisation d'une variable locale.

3 Cette erreur indique une instruction goto qui peut transférer le contrôle au-delà de cette variable locale.

3.1.2.301 E2204: Le groupe a dépassé la taille maximum : 'nom'


La taille totale des segments d'un groupe (par exemple, DGROUP) dépasse 64 Ko.

330
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.302 E2206: Caractère 'caractère' (0x'valeur') incorrect


Le compilateur a détecté un caractère incorrect dans le fichier d'entrée.

La valeur hexadécimale de ce caractère est affichée.

Ceci peut également être causé par des paramètres superflus transmis à une macro de fonction.

3.1.2.303 E2207: Conversion implicite de 'type1' en 'type2' non


autorisée
Lorsqu'une fonction membre d'une classe est appelée avec un pointeur sur une classe dérivée, la valeur du pointeur doit être
implicitement convertie pour pointer sur la classe de base appropriée.

Dans ce cas, une telle conversion implicite est interdite.

3.1.2.304 E2208: Impossible d'accéder à une portée inactive


Vous avez essayé d'évaluer ou d'inspecter une variable locale sur une fonction qui n'est actuellement pas active. (ce message
est généré par le débogueur intégré lors de l'évaluation d'une expression).

3.1.2.305 E2209: Impossible d'ouvrir le fichier include 'nomfichier'


Le compilateur n'a pas trouvé le fichier indiqué.

Cause possible

• Le fichier indiqué n'existe pas.


• Un fichier #include s'est inclus lui-même.
• FILES n'est pas défini dans le fichier CONFIG.SYS de votre répertoire racine.
Solutions
• Vérifiez que le fichier indiqué existe.
• Définissez FILES = 20 dans CONFIG.SYS.

3.1.2.306 E2210: Le membre de référence 'membre' n'est pas


initialisé
Les références doivent toujours être initialisées, dans le constructeur de la classe. 3
Un membre de classe de type référence doit avoir un initialisateur dans tous les constructeurs de cette classe.

Ceci signifie que vous ne pouvez pas compter sur le compilateur pour générer des constructeurs pour une telle classe car il ne
sait pas comment initialiser les références.

331
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.307 E2212: La fonction a été définie inline après avoir été


utilisée comme extern
Les fonctions ne peuvent passer à l'état inline (en ligne) après avoir été utilisées.

Avancez la définition inline dans le fichier ou supprimez-la entièrement.

Le compilateur a détecté quelque chose ressemblant à ceci :


myex();
twoex() { myex(); }
inline myex() { return 2; } // erreur
et a déjà utilisé la fonction comme extern avant de voir qu'elle était inline. Ceci serait correct :
myex();
inline myex() { return 2; }
twoex() { myex(); }
ou, encore mieux :
inline myex();
inline myex() { return 2; }
twoex() { myex(); }

3.1.2.308 E2211: L'assemblage en ligne n'est pas autorisé dans les


fonctions inline et template
Le compilateur ne gère pas les instructions inline d'assembleur dans une fonction en ligne ou modèle C++.

Supprimez le code inline assembleur ou, dans le cas d'une fonction en ligne, transformez-la en macro et supprimez la classe de
stockage en ligne.

3.1.2.309 F1001: Erreur du générateur de code interne


Une erreur s'est produite dans la logique interne du générateur de code. Contactez le Support technique CodeGear.

3.1.2.310 E2413: Déclaration de modèle incorrecte


Après le déclarateur d'un membre modèle, un point-virgule, une initialisation ou un corps étaient attendus, mais un autre token,
illégal, a été détecté. Ce message s'affiche lorsqu'un membre modèle est déclaré en dehors du modèle mais que la syntaxe était
erronée.

3
3.1.2.311 E2070: Utilisation incorrecte de l'espace de nommage
'identificateur'
Un identificateur d'espace de nommage (namespace) a été utilisé de façon incorrecte, par exemple dans une expression.

332
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.312 E2214: Impossible d'avoir des 'données fonction/statique


non inline' dans une classe locale
Tous les membres de classes déclarées locales auprès d'une fonction doivent être entièrement définis dans la définition de la
classe.

Ceci signifie que les classes locales ne peuvent pas contenir de données membre statiques et que toutes leurs fonctions
membre doivent avoir un corps défini dans la définition de la classe.

3.1.2.313 E2215: Spécification de lien non autorisée


Les spécifications de lien telles que extern "C" ne sont autorisées qu'au niveau du fichier.

Déplacez cette déclaration de fonction au niveau du fichier.

3.1.2.314 E2216: Impossible de créer turboc.$ln


Le compilateur ne peut pas créer le fichier temporaire TURBOC.$LN car il est incapable d'accéder au disque, ou le disque est
plein.

3.1.2.315 E2218: Les modèles ne peuvent être déclarés qu'au niveau


d'un espace de nommage ou d'une classe
Les modèles ne peuvent pas être déclarés à l'intérieur d'une classe ou d'une fonction. Ils sont uniquement autorisés dans la
portée globale ou au niveau du fichier.

Par exemple :
void func()
{
template <class T> myClass { // Erreur
T i;
};
}

3.1.2.316 E2217: Les données locales dépassent la limite de taille du


segment
Les variables locales dans la fonction en cours occupent plus de 64 Ko.
3

3.1.2.317 E2219: Nombre incorrect d'arguments dans l'appel de la


macro 'macro'
Votre fichier source a appelé la macro nommée avec un nombre incorrect d'arguments.

333
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.318 E2220: Séparateur d'arguments de macro incorrect


Dans une définition de macro, les arguments doivent être séparés par une virgule.

Le compilateur a détecté un autre caractère après un nom d'argument.

Ceci est correct :


#define tri_add(a, b, c) ((a) + (b) + (c))
Ceci ne l'est pas :
#define tri_add(a b. c) ((a) + (b) + (c))

3.1.2.319 E2221: Erreur de syntaxe dans l'argument de macro


Un argument dans une définition de macro doit être un identificateur.

Le compilateur a détecté autre chose qu'un caractère identificateur alors qu'un argument était attendu.

3.1.2.320 E2222: Développement de macro trop long


Une macro ne peut pas être développée à plus de 4 096 caractères.

3.1.2.321 E2223: Trop de séparateurs décimaux


Le compilateur a détecté une constante à virgule flottante avec plusieurs séparateurs décimaux.

3.1.2.322 E2224: Trop d'exposants


Le compilateur a détecté plusieurs exposants dans une constante à virgule flottante.

3.1.2.323 E2225: Trop d'initialiseurs


Le compilateur a détecté plus d'initialisateurs que permis par la déclaration initialisée.

3.1.2.324 E2226: Paramètre supplémentaire dans l'appel


Un appel à une fonction, via un pointeur défini avec un prototype, comporte trop d'arguments.
3

3.1.2.325 E2227: Paramètre supplémentaire dans l'appel de fonction


Un appel à la fonction nommée (définie avec un prototype) comporte trop d'arguments.

334
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.326 E2228: Trop de messages d'erreur ou d'avertissement


Le nombre d'erreurs ou d'avertissements dépasse la limite autorisée.

3.1.2.327 E2233: Impossible d'initialiser un membre de classe ici


Les membres des structures, des unions et des classes C++ ne peuvent pas posséder d'initialisateurs.

L'ensemble d'une structure ou d'une union peut être initialisé à l'aide d'initialisateurs placés entre accolades.

Une classe C++ ne peut être initialisée que par un constructeur.

3.1.2.328 E2232: Membre 'membre' constante/référence dans la


classe sans constructeur
Une classe contenant des membres constants ou des membres référence (ou les deux) doit avoir au moins un constructeur
défini par l'utilisateur.

Dans le cas contraire, il est impossible d'initialiser les membres.

3.1.2.329 E2229: Le membre 'membre' a le même nom que sa classe


Une donnée membre statique, un énumérateur, un membre d'une union anonyme ou un type imbriqué ne peut pas avoir le
même nom que sa classe.

Seule une fonction membre ou un membre non statique peut avoir le même nom que sa classe.

3.1.2.330 E2234: Référence mémoire attendue


L'assembleur intégré requiert une référence mémoire.

Vous avez sans doute oublié de placer des crochets autour d'un opérande de registre d'index.

3.1.2.331 E2231: Le membre 'membre' ne peut pas être utilisé sans


objet
Ce message signifie que vous avez écrit class::member, où 'member' est un membre ordinaire (non statique) et qu'il n'existe
aucune classe à associer à ce membre. 3
Par exemple, il est possible d'écrire :
obj.class::member
mais pas ceci :
class::member

335
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.332 E2235: Une fonction membre doit être appelée ou son


adresse prise
Une référence à une fonction membre doit être appelée, ou son adresse doit être prise avec l'opérateur "&".

Dans ce cas, une fonction membre a été utilisée dans un contexte illégal.

Par exemple :
classe A
{
typedef int (A::* infptr)(void);
public:
A();
int myex(void);
int three;
} a;
A::A()
{
infptr one = myex; //incorrect - appeler myex ou prendre l'adresse ?
infptr two = &A::myex; //correct
three = (a.*one)() + (a.*two)();
}

3.1.2.333 O2237: Les programmes DPMI doivent utiliser le modèle de


mémoire large
Le compilateur ne génère plus cette erreur.

3.1.2.334 E2238: Plusieurs déclarations pour 'identificateur'


Cet identificateur a été incorrectement déclaré plusieurs fois.

Le problème peut être provoqué par des déclarations conflictuelles, comme :

• int a; double a;
• une fonction déclarée de deux façons différentes, ou
• un libellé répété dans la même fonction, ou
• une déclaration répétée ailleurs que dans une fonction extern ou une variable simple.
Ceci peut également se produire si vous incluez deux fois le même fichier d'en-tête. Par exemple, avec :
//a.h
struct A { int a; };
//b.h
#include "a.h"
3 //myprog.cpp
#include "a.h"
#include "b.h"
myprog.cpp aura deux déclarations pour struct A. Pour empêcher ceci, écrivez le fichier d'en-tête a.h de la façon suivante :
//a.h
#ifndef __A_H
#define __A_H
struct A { int a; };
#endif

336
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

Ceci vous permettra d'inclure a.h sans risque plusieurs fois dans le même fichier source.

3.1.2.335 E2239: 'identificateur' doit être une fonction membre


La plupart des fonctions opérateur C++ peuvent être des fonctions membre ou non membre, mais celles-ci doivent être des
membres de classes :

• opérateur =
• opérateur ->
• opérateur ( )
• conversions de types
Cette fonction opérateur n'est pas une fonction membre alors qu'elle devrait l'être.

3.1.2.336 E2240: Conversion de pointeur near non autorisée


Un pointeur near ne peut pas être converti en pointeur far dans la zone d'évaluation d'expression lorsque aucun programme
n'est exécuté. Ceci s'explique par le fait que la conversion a besoin de la valeur en cours de DS dans le programme utilisateur,
alors que celui-ci n'existe pas.

3.1.2.337 E2243: Un tableau alloué avec 'new' ne peut pas avoir


d'initialisateur
Lorsque vous initialisez un vecteur (un tableau) de classes, vous devez utiliser le constructeur qui n'a pas d'arguments.

Il s'agit du constructeur par défaut, ce qui signifie que vous ne pouvez pas transmettre des arguments au constructeur lorsque
vous initialisez ce vecteur.

3.1.2.338 E2244: 'new' et 'delete' ne sont pas gérés


Le débogueur intégré ne gère pas l'évaluation des opérateurs new et delete.

3.1.2.339 E2245: Impossible d'allouer une référence


Vous avez tenté de créer une référence à l'aide de l'opérateur new.

Ceci n'est pas autorisé car les références ne sont pas des objets et ne peuvent pas être créées avec new.

3
3.1.2.340 E2309: Assembleur Inline non autorisé
Votre fichier source contient des instructions inline d'assembleur et vous le compilez depuis l'EDI.

Vous devez utiliser la commande BCC pour compiler ce source depuis la ligne de commande DOS.

337
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.341 E2250: Aucune classe de base à initialiser


Ce constructeur de classe C++ tente d'appeler implicitement un constructeur de classe de base, mais cette classe a été
déclarée sans classe de base.

Vérifiez vos déclarations.

3.1.2.342 E2254: : attendu après private/protected/private


Lorsqu'ils sont utilisés en début de section private, protected ou public d'une classe C++, les mots réservés "private", "protected"
et "public" doivent être suivis du signe deux points.

3.1.2.343 E2255: Utiliser :: pour prendre l'adresse d'une fonction


membre
Si f est une fonction membre de la classe c, prenez son adresse avec la syntaxe
&c::f
Notez l'utilisation du nom de type de la classe (non pas le nom d'un objet) et le "::" séparant le nom de la classe et le nom de la
fonction.

(Les pointeurs de fonction membre ne sont pas de vrais types de pointeurs et ne font pas référence à une instance particulière
d'une classe).

3.1.2.344 E2256: Pas de : qui suit le ?


Les opérateurs point d'interrogation (?) et deux points (:) ne correspondent pas dans cette expression.

Le caractère ":" a peut-être été oublié, ou des parenthèses sont mal imbriquées ou manquantes.

3.1.2.345 E2257: , attendue


Une virgule était attendue dans une liste de déclarations, d'initialisations ou de paramètres.

Ce problème vient en général d'un élément de syntaxe manquant en amont du fichier ou dans l'un des en-têtes inclus.

3.1.2.346 E2258: Une déclaration était attendue


3
Une déclaration était attendue ici et aucune n'a été détectée.

Vérifiez qu'il ne manque pas de délimiteur tel qu'une virgule, un point-virgule, une parenthèse fermante ou une accolade
fermante.

338
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.347 E2259: Valeur par défaut manquante


Lorsqu'une fonction C++ déclare un paramètre avec une valeur par défaut, tous les paramètres suivants doivent avoir une valeur
par défaut.

Dans cette déclaration, un paramètre avec une valeur par défaut était suivi d'un paramètre sans valeur par défaut.

3.1.2.348 E2260: Une valeur par défaut manque après le paramètre


'paramètre'
Tous les paramètres suivant le premier paramètre avec une valeur par défaut doivent également avoir une valeur par défaut.

3.1.2.349 E2263: La gestion des exceptions n'est pas activée


Un bloc 'try' a été détecté alors que la gestion des exceptions est désactivée.

3.1.2.350 E2264: Expression attendue


Une expression était attendue ici, mais le symbole en cours ne peut servir de début à une expression.

Ce message peut se produire si l'expression de contrôle d'un if ou d'un while est attendue ou si une variable est initialisée.

Ce message est en général causé par un symbole manquant ou en trop.

3.1.2.351 E2266: Aucun nom de fichier donné


La ligne de commande ne contenait aucun nom de fichier. Vous devez spécifier un nom de fichier source.

3.1.2.352 E2265: Aucun signe de fin dans le nom de fichier


Le nom de fichier inclus dans une instruction #include ne comporte pas de guillemet ou de crochet fermant.

3.1.2.353 E2271: Il manque un libellé à l'instruction goto


Le mot clé goto doit être suivi d'un identificateur.

3
3.1.2.354 E2272: Identificateur attendu
Un identificateur était attendu ici, mais aucun n'a été détecté.

En C, un identificateur est attendu dans les situations suivantes :

• dans une liste de paramètres dans un en-tête de fonction de style ancien ;


• après les mots réservés struct ou union lorsque les accolades sont omises ;

339
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

• comme nom de membre dans une structure ou une union (à l'exception des champs de bits de largeur 0).
En C++, un identificateur est attendu dans les situations suivantes :
• dans une liste de classes de base desquelles une autre classe est dérivée, suivant un double deux-points (::) ;
• après le mot réservé "operator" lorsque aucun symbole d'opérateur n'est présent.

3.1.2.355 E2275: Accolade ouvrante attendue


Une accolade gauche était attendue en début de bloc ou d'initialisation.

3.1.2.356 E2276: ( attendue


Une parenthèse gauche était attendue avant la liste des paramètres.

3.1.2.357 E2274: < attendu


Le mot clé template n'est pas suivi de "<".

Chaque déclaration de modèle doit inclure des paramètres formels placés entre "< >", immédiatement après le mot clé template.

3.1.2.358 E2277: Lvalue nécessaire


La partie de gauche d'un opérateur d'affectation doit être une expression adressable.

Les expressions adressables comprennent notamment :

• les variables numériques ou pointeurs ;


• les références de champs de structure ou indirection par pointeur ;
• les éléments de tableau indicés.

3.1.2.359 E2278: Les classes de base multiples ne sont pas gérées


pour les classes Delphi
Les classes Delphi ne peuvent pas avoir plusieurs classes de base.

Exemple :
struct__declspec(delphiclass) base1 {};
struct__declspec(delphiclass) base2 {};
structderived : base1, base2 {}; // Erreur
3
3.1.2.360 E2280: Identificateur de membre attendu
Le nom d'une structure ou d'un membre de classe C++ était attendu ici, mais aucun n'a été détecté. La partie droite d'un
opérateur point (.) ou flèche (->) doit être le nom d'un membre dans la structure ou la classe à gauche de l'opérateur.

340
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.361 E2279: Impossible de trouver le constructeur par défaut


pour initialiser le membre 'identificateur'
Lorsque ceci se produit :

1. Une classe C++ 'classe1' contient un membre de 'classe2,'


and
2. Vous souhaitez construire un objet de type 'classe1' (mais pas depuis un autre objet de type 'classe1'). Il doit exister un
constructeur classe2::classe2() pour que le membre puisse être construit.
Ce constructeur sans paramètre est appelé constructeur par défaut.
Le compilateur fournit automatiquement un constructeur par défaut sauf si vous avez défini un constructeur pour la classe
'classe2'.
Dans ce cas, le compilateur ne fournit pas automatiquement le constructeur par défaut (c'est à vous de le faire).

3.1.2.362 E2310: Seules les fonctions membre peuvent être 'const'


ou 'volatile'
Un autre élément qu'une fonction membre de classe a été déclaré const ou volatile.

3.1.2.363 E2311: La fonction non-virtuelle 'fonction' est déclarée


pure
Seules les fonctions virtuelles peuvent être déclarées pure, car les classes dérivées doivent pouvoir les outrepasser.

3.1.2.364 E2283: Utilisez . ou -> pour appeler 'fonction'


Vous avez tenté d'appeler une fonction membre sans fournir d'objet. C'est nécessaire pour appeler une fonction membre.
class X {
member func() {}
};
X x;
X*xp = new X;
X.memberfunc();
Xp-> memberfunc();

3.1.2.365 E2284: Utilisez . ou -> pour appeler 'membre', ou & pour


prendre son adresse 3

Une référence à un membre de classe non statique sans objet a été détectée.

Un tel membre ne peut pas être utilisé sans objet, ou son adresse doit être prise à l'aide de l'opérateur &.

341
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.366 E2285: Impossible de trouver une correspondance pour


le(s) 'argument(s)'
Aucune fonction C++ n'a été détectée avec les paramètres correspondant aux arguments fournis. Vérifiez les paramètres
transmis à la fonction ou surchargez la fonction pour les paramètres en cours de transmission.

3.1.2.367 E2286: Résolution de fonction surchargée non gérée


Dans une évaluation d'expression du débogueur intégré, la résolution de fonctions ou d'opérateurs surchargés n'est pas gérée, y
compris pour prendre une adresse.

3.1.2.368 E2287: Nom manquant dans le paramètre 'numéro'


Dans un en-tête de définition de fonction, ce paramètre ne contenait qu'un 'numéro' de spécificateur de type, mais aucun nom de
paramètre.

Ceci n'est pas autorisé en C.

Cela est autorisé en C++, mais il n'existe aucun moyen de faire référence au paramètre dans la fonction.

3.1.2.369 E2288: Pointeur sur structure nécessaire du côté gauche


de -> ou ->*
Seul un pointeur peut apparaître à gauche de la flèche (->) en C ou en C++.

En C++, un opérateur -> est autorisé.

3.1.2.370 E2290: ] manquant dans 'code'


Cette erreur est générée dans les cas suivants :

• Votre fichier source a déclaré un tableau dans lequel les limites ne comportent pas de crochet fermant.
• Le spécificateur de tableau dans un opérateur n'a pas de crochet fermant.
• L'opérateur [ ] a été déclaré comme opérateur [.
• Un crochet fermant manque dans une expression d'indice.
Ajoutez le crochet ou corrigez la déclaration.

3 Recherchez les opérateurs manquants ou en trop, ou les parenthèses en nombre impair.

3.1.2.371 E2291: Accolade attendue


Une accolade fermante était attendue à la fin d'un bloc ou d'une initialisation.

342
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.372 E2292: La fonction doit renvoyer une valeur


Votre fichier source a déclaré la fonction en cours comme renvoyant un type autre que int ou void, mais le compilateur a
détecté un retour sans valeur. Ceci signifie généralement qu'une erreur s'est produite.

Les fonctions déclarées comme renvoyant int sont exemptes car les anciennes versions de C ne géraient pas les types de
retour de fonction void.

3.1.2.373 E2293: ) attendue


Une parenthèse fermante était attendue en fin de liste de paramètres.

3.1.2.374 E2294: Structure nécessaire sur le côté gauche de . ou .*


La partie gauche d'un opérateur point (.) (ou point-étoile en C++, .*) doit être de type structure. Ce n'est pas le cas ici.

Cette erreur peut se produire lorsque vous créez une instance d'une classe à l'aide de parenthèses vides puis tentez d'accéder à
un membre de cet 'objet'.

3.1.2.375 E2312: 'constructeur' n'est pas une classe de base non


ambiguë de 'classe'
Un constructeur de classe C++ tente d'appeler ce constructeur de classe de base.

Cette erreur peut se produire également si vous tentez de modifier les droits d'accès de 'class::constructor.'

Vérifiez vos déclarations.

3.1.2.376 E2313: Expression constante nécessaire


Les tableaux doivent être déclarés avec une taille constante.

Cette erreur est généralement causée par une faute de frappe dans une constante #define.

3.1.2.377 E2296: Modèles non gérés


Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande H2ASH. Consultez le fichier "tsm_util.txt" pour
de plus amples informations.
3

3.1.2.378 E2314: Appel d'une non fonction


Le nom appelé n'est pas déclaré comme fonction.

Cette erreur est généralement causée par une déclaration de fonction incorrecte ou par une faute de frappe dans le nom de la
fonction.

343
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.379 E2321: La déclaration ne spécifie pas un repère ou un


identificateur
Cette déclaration ne déclare rien.

Ceci peut indiquer un struct ou un union sans repère ou sans variable dans la déclaration. C++ exige que quelque chose soit
déclaré.

Par exemple :
struct
{
int a
};
//ni repère, ni identificateur

3.1.2.380 E2297: 'this' ne peut être utilisé que dans une fonction
membre
En C++, "this" est un mot réservé qui ne peut être utilisé que dans les fonctions membre de classe.

3.1.2.381 E2316: 'identificateur' n'est pas un membre de 'structure'


Vous tentez de référencer 'identificateur' comme un membre de 'structure', à tort.

Vérifiez vos déclarations.

3.1.2.382 E2317: 'identificateur' n'est pas un paramètre


Dans la section de déclaration des paramètres d'une définition de fonction de style ancien, 'identificateur' est déclaré mais pas
listé comme paramètre. Supprimez la déclaration ou ajoutez 'identificateur' comme paramètre.

3.1.2.383 E2319: 'identificateur' n'est pas une classe de base


publique de 'type de classe'
L'opérande de droite d'un opérateur ".*", "->*" ou "::" n'était pas un pointeur vers un membre d'une classe qui soit identique au
(ou une classe de base non ambiguë du) type de classe de l'opérande de gauche.

3 3.1.2.384 E2320: Expression de type scalaire attendue


Les opérateurs "!", "++" et "--" exigent une expression de type scalaire.

Seuls ces types sont autorisés :

• char
• short
• int

344
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

• long
• enum
• float
• double
• long double
• pointer

3.1.2.385 E2302: Pas d'informations de type


Le débogueur intégré n'a pas d'information de type pour cette variable. Vérifiez que vous avez compilé le module avec les
informations de débogage. Si oui, il se peut que le module ait été compilé par un autre compilateur ou assembleur.

3.1.2.386 E2303: Nom de type attendu


L'une des erreurs ci-dessous s'est produite :

• Lors de la déclaration d'une variable de niveau fichier ou d'un champ struct, ni un nom de type, ni une classe de stockage
n'ont été fournis.
• Lors de la déclaration d'un typedef, aucun type n'a été fourni pour le nom.
• Lors de la déclaration d'un destructeur pour une classe C++, le nom du destructeur n'était pas un nom de type (il doit être
identique au nom de sa classe).
• Lors de la spécification d'un nom de classe de base C++, ce nom n'était pas un nom de classe.

3.1.2.387 E2304: La variable 'variable' Constant/Reference doit être


initialisée
Cet objet C++ est déclaré en tant que constante ou référence, mais n'est pas initialisé.

Il doit l'être au moment de la déclaration.

3.1.2.388 E2305: Impossible de trouver 'class::class' ('class' &) pour


copier un vecteur OU Impossible de trouver
'class'::operator=('class'&) pour copier un vecteur
Lorsque la classe C++ 'classe1' contient un vecteur (un tableau) de classe 'classe2' et que vous souhaitez générer un objet de
type 'classe1' à partir d'un autre objet de type 'classe 1', vous devez utiliser ce constructeur :
classe2::classe2(classe2&) 3
pour que les éléments du vecteur puissent être générés.

Le constructeur, appelé constructeur de copie, n'accepte qu'un paramètre (une référence à sa classe).

En règle générale, le compilateur fournit automatiquement un constructeur de copie.

Cependant, si vous avez défini un constructeur pour 'classe2' ayant un paramètre de type 'classe2&' et d'autres paramètres avec
des valeurs par défaut, le constructeur de copie ne peut exister, ni être créé par le compilateur.

345
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

Ceci car ces deux instructions ne peuvent pas être différenciées :


classe2::classe2(classe2&)
classe2::classe2(classe2&, int = 1)
Vous devez redéfinir ce constructeur de telle façon que tous les paramètres n'aient pas de valeur par défaut.

Vous pouvez alors définir un constructeur de référence ou laisser le compilateur en créer un.

Message "Impossible de trouver class::operator= ..."

Lorsqu'une classe C++ 'classe1' contient un vecteur (un tableau) de classe 'classe2' et que vous souhaitez copier une classe de
type 'classe1', vous devez utiliser cet opérateur d'affectation :
classe2::classe2(classe2&)
pour que les éléments du vecteur puissent être copiés.

En règle générale, le compilateur fournit automatiquement cet opérateur.

Cependant, si vous avez défini un opérateur= pour la 'classe2' qui n'accepte pas de paramètre de type 'classe2&,' le compilateur
ne le fournira pas automatiquement ; c'est vous qui devez le fournir.

3.1.2.389 E2306: Les classes de base virtuelles ne sont pas gérées


par les classes Delphi
Les classes de style Delphi ne peuvent pas être virtuellement dérivées, y compris depuis d'autres classes de style Delphi.

Exemple :
struct __declspec(delphiclass) base {};
struct derived : virtual base {}; // Erreur

3.1.2.390 E2308: L'instruction 'do' doit avoir un 'while'


Votre fichier source contient une instruction do sans mot-clé while de fin.

3.1.2.391 E2322: Format numérique incorrect


Le compilateur a détecté une virgule décimale dans un nombre hexadécimal.

3.1.2.392 E2324: Constante numérique trop grande


Les chaînes et les séquences d'échappement plus grandes que 77 (en hexadécimal ou en octal) ne peuvent être générées.

Des constantes caractères de deux octets peuvent être spécifiées en utilisant une seconde barre oblique inverse. Par exemple,
3
\\
représente une constante de deux octets.

Un littéral numérique suivant une séquence d'échappement doit être réparti ainsi :
printf("\x0A" "12345");
Ceci affiche un retour chariot suivi de 12345.

346
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.393 E2282: Nom d'espace de nommage attendu


Le nom d'un symbole d'espace de nommage était attendu.

3.1.2.394 E2334: Le membre de l'espace de nommage 'identificateur'


a été déclaré en dehors de son espace de nommage
Les membres d'espace de nommage (namespace) doivent être déclarés dans leur espace de nommage. Vous ne pouvez utiliser
qu'une qualification explicite pour définir un membre d'espace de nommage (par exemple, pour donner un corps à une fonction
déclarée dans un espace de nommage). La déclaration elle-même doit être à l'intérieur de l'espace de nommage.

3.1.2.395 E2325: Chiffre octal incorrect


Le compilateur a détecté une constante octale contenant un chiffre non octal (8 ou 9).

3.1.2.396 E2329: Combinaison incorrecte d'instruction et


d'opérandes
L'assembleur intégré n'accepte pas cette combinaison d'opérandes.

Causes possibles

• Il y a trop (ou trop peu) d'opérandes pour cette instruction assembleur.


• Le nombre d'opérandes est correct, mais leur type ou leur ordre ne correspond pas à l'instruction.

3.1.2.397 E2327: Les opérateurs ne doivent pas avoir de valeurs


d'argument par défaut
Il est illégal pour les opérateurs surchargés d'avoir des valeurs d'arguments par défaut.

3.1.2.398 E2330: Un opérateur doit être déclaré comme une fonction


Un opérateur surchargé a été déclaré avec autre chose qu'un type de fonction.

Par exemple :
classe A 3
{
opérateur A& +; ..notez les parenthèses manquantes
};
Dans cet exemple, l'opérateur de fonction '()' est manquant, aussi l'opérateur n'a-t-il pas de type de fonction et génère cette
erreur.

347
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.399 E2333: Le membre de classe 'membre' a été déclaré en


dehors de sa classe
Les fonctions membre de classe C++ ne peuvent être déclarées que dans la déclaration de classe.

A la différences des fonctions non membre, elles ne peuvent être pas déclarées plusieurs fois, ni à un autre endroit.

3.1.2.400 E2335: 'fonction' surchargée ambiguë dans ce contexte


Le seul moment où un nom de fonction surchargée peut être utilisé ou affecté sans appeler la fonction est lorsqu'il est affecté
l'adresse de la fonction surchargée à une variable ou à un paramètre du type approprié de pointeur de fonction.

Dans ce cas, un nom de fonction surchargée a été utilisé dans un autre contexte. Le code ci-dessous, par exemple, générera
cette erreur :
class A {
A(){myex;} //appel de la fonction
void myex(int) {} //ou lecture de l'adresse ?
void myex(float){}
};

3.1.2.401 E2339: Impossible de surcharger 'main'


main ne peut pas être surchargée.

3.1.2.402 E2336: Le pointeur sur la fonction surchargée 'fonction' ne


correspond pas à 'type'
Une variable ou un paramètre reçoit (ou est initialisé avec) l'adresse d'une fonction surchargée.

Cependant, le type de la variable ou du paramètre ne correspond à aucune fonction surchargée ayant le nom spécifié.

3.1.2.403 E2337: Seule une fonction d'un ensemble de fonctions


surchargées peut être "C"
Les fonctions C++ sont par défaut surchargées, et le compilateur affecte un nouveau nom à chaque fonction.

Si vous souhaitez passer outre l'affectation de ce nom par le compilateur en déclarant la fonction extern "C", vous ne pouvez le
faire que pour une fonction d'un ensemble de fonctions de même nom.
3 Dans le cas contraire, le lieur trouverait plusieurs fonctions globales de même nom.

3.1.2.404 E2338: Les overlays ne sont supportés que dans les


modèles mémoire medium, large et huge
Le compilateur ne génère plus cette erreur.

348
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.405 E2340: Non concordance de type dans le paramètre


'nombre'
La fonction appelée, via un pointeur de fonction, a été déclarée avec un prototype.

Cependant, le numéro de paramètre indiqué (en comptant de gauche à droite à partir de 1) n'a pas pu être converti dans le type
du paramètre déclaré.

Lorsque vous compilez des programmes C++, ce message est toujours précédé d'un autre expliquant la raison exacte de cette
non concordance de types.

Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'", mais la non concordance peut avoir de
nombreuses autres causes.

3.1.2.406 E2341: Non concordance de type dans le paramètre


'numéro' dans l'appel à 'fonction'
Votre fichier source a déclaré cette fonction avec un prototype et le numéro de paramètre indiqué (en comptant de gauche à
droite à partir de 1) n'a pas pu être converti dans le type du paramètre déclaré.

Lorsque vous compilez des programmes C++, ce message est toujours précédé d'un autre expliquant la raison exacte de cette
non concordance de types.

Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'", mais la non concordance peut avoir de
nombreuses autres causes.

3.1.2.407 E2342: Non concordance de type dans le paramètre


'paramètre'
La fonction appelée, via un pointeur fonction, a été déclarée dans votre fichier source avec un prototype.

Cependant, le paramètre indiqué n'a pas pu être converti dans le type du paramètre déclaré.

Lorsque vous compilez des programmes C++, ce message est toujours précédé d'un autre expliquant la raison exacte de cette
non concordance de types.

Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'", mais la non concordance peut avoir de
nombreuses autres causes.

3.1.2.408 E2343: Non concordance de type dans le paramètre


'paramètre' dans l'appel à 'fonction' 3

Votre fichier source a déclaré cette fonction avec un prototype, et le paramètre indiqué n'a pas pu être converti dans le type du
paramètre déclaré.

Lorsque vous compilez des programmes C++, ce message est toujours précédé d'un autre expliquant la raison exacte de cette
non concordance de types.

Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'", mais la non concordance peut avoir de

349
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

nombreuses autres causes.

3.1.2.409 E2345: L'accès peut seulement être changé en public ou


protected
Une classe dérivée C++ peut modifier les droits d'accès d'un membre de classe de base, mais uniquement en public ou
protected.

Un membre de classe de base ne peut être private.

3.1.2.410 E2349: Conversion de pointeur non portable


Une conversion implicite entre un pointeur et un type intégral est requise, mais les types ne sont pas de la même taille. Vous
devez utiliser un transtypage explicite (cast).

Cette conversion n'est peut-être pas logique, aussi devez-vous vérifier que c'est bien ce que vous souhaitez.

3.1.2.411 E2350: Impossible de définir un pointeur ou une référence


sur une référence
Il est illégal d'avoir un pointeur sur une référence ou une référence sur une référence.

3.1.2.412 E2352: Impossible de créer une instance de la classe


abstraite 'classe'
Les classes abstraites (celles qui contiennent des fonctions virtuelles pures) ne peuvent être utilisées directement, mais
uniquement en dérivé.

Lorsque vous dérivez une classe de base abstraite, avec l'intention de créer des instances de cette classe dérivée, vous devez
outrepasser chaque fonction virtuelle pure de la classe de base de la façon exacte dont elle est déclarée.

Par exemple :
class A {
public:
virtual myex( int ) = 0;
virtual twoex( const int ) const = 0;
};
class B : public A {
public:
myex( int );
3 twoex( const int );
};
B b; // erreur
L'erreur se produit car vous n'avez pas redéfini la fonction virtuelle dans laquelle twoex peut agir sur les objets const de la
classe. Nous avons créé une nouvelle fonction qui agit sur les objets autres que const. Ceci se compilerait sans erreur :
class A {
public:
virtual myex( int ) = 0;
virtual twoex( const int ) const = 0;

350
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

};
class B : public A {
public:
myex( int );
twoex( const int ) const;
};
B b; // ok

3.1.2.413 E2354: Deux opérandes doivent être évalués de même type


Les types d'expressions des deux côtés du signe deux-points dans l'opérateur d'expression conditionnelle (?:) doivent être
identiques, à l'exception des conversions habituelles.

Voici quelques exemples de conversions habituelles :

• char en int
• float en double
• de void* en un pointeur précis
Dans cette expression, les deux côtés s'évaluent en des types différents qui ne sont pas automatiquement convertis.
Ceci peut être une erreur, ou vous devez simplement transtyper un type en un autre.
Lorsque vous compilez des programmes C++, ce message est toujours précédé d'un autre expliquant la raison exacte de cette
non concordance de types.
Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'", mais la non concordance peut avoir de
nombreuses autres causes.

3.1.2.414 E2355: Fonction modèle récursive : 'x' a instancié 'y'


Le compilateur a détecté une instance récursive de fonction modèle. Par exemple :
template<class T> void f(T x)
{
f((T*)0); // fonction modèle récursive
}
void main()
{
f(0);
}
Le compilateur affiche un message pour chaque instance imbriquée de l'instanciation récursive, ce qui facilite la recherche de la
récursivité. Pour corriger un modèle récursif, changez les dépendances ou fournissez une version spécialisée qui arrêtera la
récursivité. Par exemple, l'ajout de la définition de fonction suivante au code ci-dessus supprimera la récursivité infinie :
void f(int **)
{
}

3.1.2.415 E2356: Non concordance de type dans la redéclaration de 3


'identificateur'
Votre fichier source a redéclaré une variable avec un type différent de son type d'origine.

Cause possible

Ceci peut se produire si une fonction est appelée puis déclarée pour renvoyer autre chose qu'un entier.

351
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

Solutions

Vous devez déclarer la fonction avant son premier appel.

3.1.2.416 E2357: Référence initialisée avec 'type1', nécessite lvalue


de type 'type2'
Une variable de référence non déclarée constante doit être initialisée avec une lvalue du type approprié.

Dans ce cas, l'initialisateur n'était pas une lvalue ou son type ne correspondait pas à la référence initialisée.

3.1.2.417 E2358: Le membre référence 'membre' a besoin d'un


temporaire pour l'initialisation
Vous avez fourni une valeur initiale pour un type de référence qui n'était pas une lvalue du type référencé.

Ceci force le compilateur à créer un temporaire pour l'initialisation.

Etant donné qu'il n'existe aucun endroit spécifique pour stocker ce temporaire, l'initialisation est illégale.

3.1.2.418 E2360: Combinaison de registre incorrecte (ex : [BP+BX])


L'assembleur intégré a détecté une combinaison illégale de registres dans une instruction.

Voici les seules combinaisons autorisées :

• [BX]
• [BP]
• [SI]
• [DI]
• [BX+SI]
• [BX+DI]
• [BP+SI]
• [BP+DI]
Les autres combinaisons de registres d'index ne sont pas autorisées.

3.1.2.419 E2361: 'spécificateur' a déjà été inclus


3 Ce spécificateur de type se trouve plusieurs fois dans cette déclaration.

Supprimez ou modifiez l'une des occurrences.

3.1.2.420 E2362: Le nombre de répétitions a besoin d'une lvalue


L'expression précédant la virgule dans la fenêtre de suivi ou d'évaluation doit être une région de stockage accessible. Ces
expressions, par exemple, ne sont pas correctes :

352
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

i++,10d
x = y, 10m

3.1.2.421 E2363: Tentative de renvoyer une référence à la variable


locale 'identificateur'
Cette fonction C++ renvoie un type référence et vous tentez de renvoyer une référence à une variable locale (auto).

Ceci n'est pas autorisé car la variable référencée disparaît lorsque la fonction se termine.

Vous pouvez renvoyer une référence à une variable statique ou globale ou modifier la fonction de façon à ce qu'elle renvoie une
valeur.

3.1.2.422 E2364: Tentative de renvoyer une référence à un objet


local
Vous avez tenté de renvoyer une référence à un objet temporaire dans une fonction qui renvoie un type référence. Ceci peut
être le fait d'un constructeur ou d'un appel à une fonction.

Cet objet disparaîtra lorsque la fonction renverra son résultat, ce qui rendra la référence illégale.

3.1.2.423 E2365: Un pointeur membre est nécessaire à droite de .*


ou ->*
La partie droite d'un opérateur C++ point-étoile (.*) ou flèche-étoile (->*) doit être déclarée comme pointeur sur un membre de la
classe spécifiée par la partie gauche de cet opérateur.

Dans ce cas, la partie droite n'est pas un pointeur de membre.

3.1.2.424 E2366: Impossible d'hériter une classe non-RTTI depuis la


base RTTI (E2367) OU Impossible d'hériter une classe RTTI depuis la
base non-RTTI
Lorsque des fonctions virtuelles sont présentes, l'attribut RTTI de toutes les classes de base doit être identique à celui de la
classe dérivée.

3.1.2.425 E2368: RTTI non disponible pour une évaluation


d'expression 3

Les expressions nécessitant RTTI ne sont pas gérées par l'évaluateur d'expressions dans le débogueur intégré. Ce message
d'erreur n'est affiché que par l'évaluateur d'expressions (en cas d'inspection, d'évaluation ou de suivi), jamais par le compilateur.

353
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.426 E2371: sizeof ne peut pas être appliqué à un champ de bits


sizeof renvoie la taille d'un objet données en octets, ce qui ne s'applique pas à un champ bit.

3.1.2.427 E2372: sizeof ne peut pas être appliqué à une fonction


sizeof ne peut s'appliquer qu'aux objets données, mais pas aux fonctions.

Vous pouvez demander la taille d'un pointeur sur une fonction.

3.1.2.428 E2373: Un champ de bits ne peut pas être statique


Seules les données membre de classe C++ standard peuvent être déclarées comme statiques. Les champs bit ne le peuvent
pas.

3.1.2.429 E2374: La fonction 'fonction' ne peut pas être statique


Seules les fonctions membre ordinaires et les opérateurs new et delete peuvent être déclarés statiques.

Les constructeurs, les destructeurs et les autres opérateurs ne peuvent être statiques.

3.1.2.430 Débordement de pile


Cette erreur est signalée lorsque vous compilez une fonction en activant l'option de test de dépassement de la pile, mais qu'il n'y
a pas assez d'espace dans la pile pour allouer les variables locales de la fonction.

Cette erreur peut également être causée par les actions suivantes :

• une récursivité infinie, ou


• une procédure en langage assembleur qui ne conserve pas le projet de pile
• un tableau important dans une fonction

3.1.2.431 E2376: ( manquante dans l'instruction


Dans une instruction do, for, if, switch ou while, le compilateur n'a pas trouvé de parenthèse manquante après le mot-clé while
ou l'expression de test.

3
3.1.2.432 E2377: ) manquante dans l'instruction
Dans une instruction do, for, if, switch ou while, le compilateur n'a pas trouvé de parenthèse droite après le mot-clé while ou
l'expression de test.

354
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.433 E2378: ; manquant dans l'instruction do-while ou for


Dans une instruction do ou for, le compilateur n'a pas trouvé de point-virgule après la parenthèse droite.

3.1.2.434 E2379: ; manquante dans l'instruction


Le compilateur a détecté une instruction non suivie d'un point-virgule.

3.1.2.435 E2380: Constante chaîne ou caractère non terminée


Le compilateur n'a pas trouvé de guillemet fermant après le début d'une constante chaîne ou caractère.

3.1.2.436 E2381: Taille de la structure trop grande


Votre fichier source a déclaré une structure de taille supérieure à 64 Ko.

3.1.2.437 E2382: Les effets de bord ne sont pas autorisés


Les effets de bord tels que les affectations, "++" ou "--" ne sont pas autorisés dans la fenêtre de suivi du débogueur. Une erreur
fréquente consiste à utiliser "x = y" (non autorisé) à la place de "x == y" pour tester l'égalité de x et de y.

3.1.2.438 E2383: L'expression de sélection switch doit être de type


entier
L'expression de sélection entre parenthèses dans une instruction switch doit s'évaluer comme un type entier (char, short,
int, long, enum).

Vous devez pouvoir utiliser un transtypage explicite pour satisfaire à cette obligation.

3.1.2.439 E2433: Spécialisation après la première utilisation du


modèle
Une règle ANSI C++ exige qu'une spécialisation de modèle de fonction soit déclarée avant sa première utilisation. Ce message
d'erreur ne s'affiche que lorsque l'option de conformité ANSI (-A) est activée.
3

3.1.2.440 E2384: Impossible d'appeler une fonction membre de


classe near avec un pointeur de type 'type'
ou E2385 Ne peut pas appeler la fonction 'fonction' membre de classe near avec un pointeur de type 'type'

Les fonctions membre de classe near ne peuvent pas être appelées à l'aide d'un pointeur de membre.

355
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

Ceci vaut également pour les appels utilisant des pointeurs sur des membres.

(Notez bien que les classes sont near par défaut dans les modèles de mémoire tiny, small et medium.)

Modifiez le pointeur en near ou déclarez la classe comme far.

3.1.2.441 E2390: Non concordance de type dans le paramètre


'numéro' du nom de classe modèle 'modèle'
La valeur d'argument de modèle fournie pour le paramètre indiqué ne correspondait pas au type de paramètre formel du modèle.

Lorsque vous compilez des programmes C++, ce message est toujours précédé d'un autre expliquant la raison exacte de cette
non concordance de types.

Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'", mais la non concordance peut avoir de
nombreuses autres causes.

3.1.2.442 E2391: Non concordance de type dans le paramètre


'paramètre' du nom de classe modèle 'modèle'
La valeur d'argument de modèle fournie pour le paramètre indiqué ne correspondait pas au type de paramètre formel du modèle.

Lorsque vous compilez des programmes C++, ce message est toujours précédé d'un autre expliquant la raison exacte de cette
non concordance de types.

Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'", mais la non concordance peut avoir de
nombreuses autres causes.

3.1.2.443 E2394: Trop peu d'arguments passés au modèle 'modèle'


Un nom de classe modèle n'a pas de valeurs pour certains de ses paramètres formels.

3.1.2.444 E2395: Trop d'arguments passés au modèle 'modèle'


Ce nom de classe modèle contient trop de valeurs pour ses paramètres formels.

3.1.2.445 E2396: L'argument du modèle doit être une expression


constante
3 Un argument de classe modèle non typé doit être une expression constante du type approprié.

Ceci inclut notamment les expressions constantes entières et les adresses d'objets ou de fonctions comportant des membres ou
des liens externes.

3.1.2.446 E2401: Liste des arguments de modèles incorrecte


Cette erreur indique une liste d'arguments de modèles illégale.

356
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

Dans une déclaration de modèle, le mot-clé template doit être suivi d'une liste d'arguments formels placés entre les délimiteurs
< et >.

3.1.2.447 E2400: L'argument de modèle non typé doit être de type


scalaire
Un argument de modèle formel non typé doit être de type scalaire ; il peut être de type entier, énumération ou pointeur.

3.1.2.448 E2415: Les fonctions modèle doivent avoir seulement des


'arguments de type'
Une fonction modèle a été déclarée avec un argument non typé.

Ce n'est pas autorisé avec une fonction modèle car il n'y a aucun moyen de spécifier la valeur lorsque la fonction est appelée.

3.1.2.449 E2425: 'membre' n'est pas un membre de type modèle


correct
Le membre d'un modèle avec des arguments réels dépendant des arguments formels d'un modèle englobant a été détecté
comme n'étant pas membre d'un modèle spécifié dans une instance précise.

3.1.2.450 E2428: Les modèles doivent être des classes ou des


fonctions
La déclaration dans une déclaration de modèle doit spécifier un type de classe ou une fonction.

3.1.2.451 E2432: Le qualificateur 'template' doit nommer une classe


modèle ou une instance de fonction
Lorsque vous définissez un membre de classe modèle, les arguments réels dans le nom de la classe modèle utilisés comme
opérande gauche pour l'opérateur "::" doivent correspondre aux arguments formels de la classe modèle.

3.1.2.452 E2442: Deux points consécutifs


Etant donné que les points de suspension contiennent trois points (...) et qu'un point décimal ou un opérateur de sélection de 3
membre utilise un point (.), deux points consécutifs ne peuvent être valides dans un programme C.

3.1.2.453 E2443: La classe de base 'classe' est initialisée plus d'une


fois
Dans un constructeur de classe C++, la liste des initialisations suivant l'en-tête de constructeur comporte plusieurs fois la classe

357
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

de base 'classe'.

3.1.2.454 E2444: Le membre 'membre' est initialisé plus d'une fois


Dans un constructeur de classe C++, la liste des initialisations suivant l'en-tête du constructeur comporte plusieurs fois le même
nom de membre.

3.1.2.455 E2445: La variable 'identificateur' est initialisée plus d'une


fois
Cette variable a plusieurs initialisations. Il est possible de déclarer plusieurs fois une variable de niveau fichier, mais elle ne peut
avoir qu'une initialisation (même si deux sont identiques).

3.1.2.456 E2446: La définition de fonction ne peut pas être une


déclaration typedef
En C ANSI, un corps de fonction ne peut être défini par un typedef avec un type de fonction.

Redéfinissez le corps de la fonction.

3.1.2.457 E2132: Les modèles et les opérateurs surchargés ne


peuvent pas avoir de lien C
Vous avez tenté d'utiliser une spécification de lien avec un modèle ou un opérateur surchargé. La cause la plus probable de ce
message d'erreur est que vous avez encapsulé la déclaration dans une spécification de lien extern "C".

3.1.2.458 E2447: 'identificateur' doit être un repère d'énumération


précédemment défini
Cette déclaration tente de référencer 'identificateur' comme repère d'un type enum, mais il n'a pas été déclaré de la sorte.

Corrigez son nom ou déplacez les déclarations.

3.1.2.459 E2448: Etiquette non définie 'identificateur'


3 Le label nommé a un goto dans la fonction, mais aucune définition de label.

3.1.2.460 E2449: La taille de 'identificateur' est inconnue ou zéro


Cet identificateur a été utilisé dans un contexte où sa taille était requise.

Un repère struct n'a peut-être été que déclaré (struct n'étant pas encore défini), ou un tableau extern a été déclaré sans taille.

358
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

Il n'est, dans ce cas, pas permis de référencer un tel élément (comme sizeof) ou de déréférencer un pointeur sur ce type.

Restructurez votre déclaration de telle façon que la taille de 'identificateur' soit disponible.

3.1.2.461 E2450: Structure 'structure' non définie


La structure nommée a été utilisée dans le fichier source, probablement sur un pointeur vers une structure, mais n'avait aucune
définition dans le fichier source.

Ceci est probablement le fait d'un nom de structure mal orthographié ou d'une déclaration manquante.

3.1.2.462 E2451: Symbole 'identificateur' non défini


L'identificateur spécifié n'a aucune déclaration.

Causes possibles

• La déclaration de l'identificateur est en commentaire.


• Faute de frappe à cet endroit ou dans la déclaration.
• Erreur dans la déclaration de l'identificateur.
• Le fichier d'en-tête dans lequel l'identificateur est déclaré n'a pas été inclus en utilisant #include
Ces outils peuvent vous aider à repérer le problème :
GREP ( see page 184)

3.1.2.463 E2453: La taille du type 'identificateur' est inconnue ou


égale à zéro
Ce type a été utilisé dans un contexte où sa taille est requise.

Par exemple, un repère struct n'a peut-être été que déclaré (struct n'étant pas encore défini).

Il n'est, dans ce cas, pas permis de référencer un tel élément (comme sizeof) ou de déréférencer un pointeur sur ce type.

Restructurez vos déclarations de telle façon que la taille de ce type soit disponible.

3.1.2.464 E2452: La taille du type est inconnue ou zéro


Ce message d'erreur indique qu'un tableau de dimension non spécifiée imbriqué dans une autre structure est initialisé alors que
l'option -A (ANSI) est activée. Par exemple :
struct
{ 3
char a[]; //Taille de 'a' inconnue ou nulle
}
b = { "bonjour" }; //Taille du type
//inconnue ou nulle

3.1.2.465 E2454: Une union ne peut pas être un type de base


Une union ne peut être utilisée comme type de base pour un autre type de classe.

359
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.466 E2455: Une union ne peut pas avoir un type de base


En général, une classe C++ peut être de type union, mais une telle classe ne peut être dérivée d'une autre classe.

3.1.2.467 E2456: Le membre de l'union 'membre' est de classe type


avec 'constructeur' (ou destructeur ou opérateur =)
Une union ne peut contenir de membres de classe type avec des constructeurs définis par l'utilisateur, des destructeurs ou
l'opérateur =.

3.1.2.468 E2461: '%s' nécessite une initialisation/finalisation


d'exécution
Ce message s'affiche lorsqu'une variable globale déclarée comme __thread (fonctionnalité réservée à Win32) ou qu'un membre
données statiques d'une classe modèle est initialisé avec une valeur non constante.

Ce message s'affiche également lorsqu'une variable globale déclarée comme __thread (fonctionnalité réservée à Win32) ou
qu'un membre données statiques d'une classe modèle est de type classe avec un constructeur ou un destructeur.

3.1.2.469 E2464: 'virtual' ne peut être utilisé qu'avec des fonctions


membre
Des données membre ont été déclarées avec le spécificateur virtual.

Seules les fonctions membre peuvent l'être.

Par exemple :
class myclass
{
public:
virtual int a; //erreur
};

3.1.2.470 E2465: Les unions ne peuvent pas avoir de fonctions


membre virtuelles
Une union ne peut avoir de fonctions virtuelles comme membres.
3
3.1.2.471 E2466: void & n'est pas un type correct
Une référence se rapporte toujours à un objet, mais un objet ne peut être de type void.

Donc, le type void n'est pas autorisé.

360
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.472 E2467: Une fonction Void ne peut pas renvoyer une valeur
Une fonction avec un type de retour void contient une instruction de retour qui renvoie une valeur ; par exemple, un entier.

Par défaut, ce message est affiché.

3.1.2.473 E2468: Une valeur de type void n'est pas autorisée


Une valeur de type void n'est en fait pas une valeur, aussi ne peut-elle apparaître dans un contexte où une valeur réelle est
requise.

Les contextes requérant une valeur sont notamment :

• la partie droite d'une affectation ;


• un argument de fonction ;
• l'expression de contrôle d'une instruction if, for ou while.

3.1.2.474 E2469: Impossible d'utiliser le modèle mémoire tiny ou


huge avec Windows
Le compilateur ne génère plus cette erreur.

3.1.2.475 E2006: Les programmes protégés par CodeGuard doivent


utiliser le modèle de mémoire large et être prévus pour Windows
Le compilateur ne génère plus cette erreur.

3.1.2.476 E2269: La fonction 'fonction' n'est pas disponible


Vous avez tenté d'appeler une fonction connue de l'évaluateur mais absente du programme en cours de débogage. Il peut s'agir,
par exemple, d'une fonction en ligne.

3.1.2.477 E2124: Appel de fonction incorrect


Un appel de fonction demandé a échoué car la fonction n'est pas disponible dans le programme ou un paramètre ne peut pas
être évalué, etc. Ce message est affiché par l'évaluateur.
3

3.1.2.478 E2213: 'expression' incorrecte dans la redéfinition de


portée
L'évaluateur affiche ce message en cas d'erreur de redéfinition de portée dans une expression que vous suivez ou inspectez.
Vous pouvez spécifier une table de symboles, une unité de compilation, un nom de fichier source, etc. comme portée de

361
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

l'expression, et le message s'affichera si le compilateur ne peut pas accéder à cet élément.

3.1.2.479 E2236: 'identificateur' manquant dans la redéfinition de


portée
La syntaxe d'une redéfinition de portée est incomplète. Ce message est affiché par l'évaluateur.

3.1.2.480 Fonction virtuelle pure appelée


Ceci est une erreur d'exécution. Cette erreur est générée si le corps d'une fonction virtuelle pure n'a jamais été générée et que,
pour une raison quelconque, le compilateur a essayé de l'appeler.

3.1.2.481 E2095: Littéral chaîne non autorisé dans ce contexte


Ce message d'erreur est affiché par l'évaluateur lorsqu'une chaîne littérale apparaît dans un contexte autre qu'un appel de
fonction.

3.1.2.482 Fin anattendue pendant la compilation [Module


Seg#:offset] OU Fin inattendue pendant la liaison [Module
Seg#:offset]
Si l'une de ces erreurs se produit, elle indique un échec catastrophique des outils CodeGear. Vous devez contacter CodeGear
pour signaler le problème et trouver une possibilité de contournement pour votre cas particulier. En isolant le cas de test le plus
rapidement possible, vous augmenterez les chances de CodeGear ou de vous-même de trouver un palliatif au problème.

D'une manière générale, les échecs du compilateur peuvent être palliés en déplaçant le code source en cours de compilation.
Les cas simples peuvent être un changement de l'ordre des déclarations de variable ou des fonctions dans le module source. Le
déplacement de la portée et du stockage des variables aide également dans de nombreux cas.

Pour les échecs du lieur, vous pouvez réduire la quantité d'informations de débogage avec lesquelles travaille le lieur. Essayez
de compiler un ou deux modules seulement avec les informations de débogage au lieu du projet entier.

De même, la commutation de l'ordre dans lequel les modules objet sont transmis au lieur peut pallier le problème. L'EDI
transmet les objets au lieur dans l'ordre dans lequel ils sont listés dans l'arborescence du projet. Essayez de déplacer vers le
haut ou vers le bas un source dans la liste.

3.1.2.483 E2012: Impossible de prendre l'adresse de 'main'


3
En C++, il est illégal de prendre l'adresse de la fonction main.

3.1.2.484 E2016: Redéfinition ambiguë du membre de base virtuel


'fonction_de_base': 'fonction_dérivée'
Une fonction virtuelle dans une classe de base virtuelle a été redéfinie avec deux ou plusieurs fonctions différentes dans des

362
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

chemins différents de la hiérarchie d'héritage. Par exemple,


struct VB
{
virtual f();
};
struct A:virtual VB
{
virtual f();
};
//{
struct B:virtual VB
virtual f();
}

3.1.2.485 E2021: Un tableau doit avoir au moins un élément


En langage ANSI C et C++, un tableau doit être défini avec au moins un élément (les objets de taille nulle sont interdits).

L'astuce souvent utilisée consiste à déclarer un élément de tableau d'une structure comme ayant une taille nulle, puis à allouer
l'espace nécessaire avec malloc.

Sachez que, même si vous avez recours à cette astuce, vous devez déclarer l'élément de tableau comme comportant au moins
un élément si vous compilez en mode ANSI strict.

Les déclarations (par opposition aux définitions) de tableaux de taille inconnue sont autorisées.

Exemple
char ray[]; /* définition de taille inconnue -- ILLEGAL */
char ray[0]; /* définition de taille 0 -- ILLEGAL */
extern char ray[]; /* déclaration de taille inconnue -- OK */

3.1.2.486 E2023: Tableau de références non autorisé


Il est illégal d'avoir un tableau de références, car les pointeurs sur références ne sont pas autorisés et les noms de tableaux sont
convertis en pointeurs.

3.1.2.487 E2032: Utilisation incorrecte d'un pointeur de clôture


(closure)
Une variable pointeur closure est utilisée de façon incorrecte. L'utilisation des variables closure est limitée. Par exemple, vous
pouvez assigner une fonction à une variable closure et exécuter cette fonction via la variable closure, mais vous ne pouvez pas
utiliser une variable closure comme une variable pointeur.

3.1.2.488 E2040: Terminaison de déclaration incorrecte 3


Une déclaration a un symbole de terminaison en trop ou incorrect, tel qu'un point-virgule placé après le corps de la fonction.

Une fonction membre C++ déclarée dans une classe avec un point-virgule entre l'en-tête et l'accolade ouvrante génère
également cette erreur.

363
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.489 E2047: Syntaxe de la directive 'directive' incorrecte


Une définition de macro commence ou se termine par l'opérateur ##, ou contient l'opérateur # non suivi par un nom d'argument
de macro.

Exemple :
Syntaxe incorrecte de la directive ifdef
Notez qu'une directive #ifdef doit contenir un seul identificateur (et rien d'autre) dans le corps de la directive.

Autre exemple :
Syntaxe incorrecte de la directive undef
Une directive #undef doit également contenir un seul identificateur dans le corps de la directive.

3.1.2.490 E2049: Le type de classe 'type' ne peut pas être marqué


comme __declspec(delphireturn)
Les classes marquées comme delphireturn sont des classes spéciales que le compilateur doit reconnaître par le nom. Ces
classes sont prédéfinies dans les en-têtes.

Certaines classes delphireturn sont des Variant, AnsiString et Currency.

Vous ne pouvez pas marquer comme delphireturn des classes définies par l'utilisateur.

3.1.2.491 E2052: Conflits de la fonction dynamique 'fonction' avec la


classe de base 'classe'
Certains des modificateurs de cette fonction dynamique sont en conflit avec la définition de la même fonction dans la classe de
base. Les deux fonctions doivent avoir les mêmes modificateurs. Les modificateurs suivants (entre autres) peuvent être à
l'origine de ces conflits :

• __export
• __import
• declspec(naked)
• declspec(package)
• __fastcall

3.1.2.492 E2057: Spécification d'exception non autorisée ici


3
Les déclarations de type de pointeur de fonction ne peuvent pas contenir des spécifications d'exceptions.

3.1.2.493 E2058: La variable de gestion des exceptions ne peut pas


être utilisée ici
Vous avez tenté d'utiliser l'une des valeurs de gestion des exceptions qui sont réservées à des structures précises de gestion

364
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

des exceptions, telles que GetExceptionCode().

3.1.2.494 E2065: L'utilisation du symbole d'espace de nommage


'symbole' crée un conflit avec un intrinsèque du même nom
Si vous définissez une fonction dans un espace de nommage dont le nom peut être remplacé par un appel à un intrinsèque
quand -Oi est activé, vous ne pouvez pas avoir une déclaration "using" qui fait référence à ce membre.

Par exemple, des appels à "strcmp" sont remplacés par l'intrinsèque "__strcmp__" quand -Oi est activé. Cela signifie que la
déclaration "using N::strcmp;" devient "using N::__strcmp__", puisque le remplacement de token intervient avant que l'analyseur
du compilateur ne puisse voir les tokens.

Dans ce cas, une erreur s'affiche car le compilateur ne sait pas comment traiter "N::__strcmp__".

3.1.2.495 E2067: Le type renvoyé par 'main' doit être int


En C++, la fonction main comporte certaines restrictions, l'une d'elles étant qu'elle ne peut pas être déclarée avec un type de
retour autre que int.

3.1.2.496 E2073: Rien n'est autorisé après l'option pragma pop


L'option #pragma pop ne peut être suivie que de commentaires, de blancs ou d'une fin de ligne.

3.1.2.497 E2091: Les fonctions ne peuvent pas renvoyer des


tableaux ou des fonctions
Une fonction a été définie comme renvoyant un tableau ou une fonction. Vérifiez si la valeur de retour souhaitée est un pointeur
sur un tableau ou une fonction (peut-être le symbole * a-t-il été oublié) ou si la définition de la fonction contenait une demande
d'un type de données incorrect.

3.1.2.498 E2093: Opérateur 'opérateur' non implémenté dans le type


'type' pour les arguments du même type
L'opérateur que vous appelez n'est pas défini dans cette classe. Quand vous avez une expression x + x, où x est de type classe
X, l'opérateur + doit être défini dans la classe X et doit être accessible.

3
3.1.2.499 E2094: Opérateur 'opérateur' non implémenté dans le type
'type' pour les arguments de type 'type'
L'opérateur que vous appelez n'est pas défini dans cette classe. Quand vous avez une expression x + x, où x est de type classe
X, l'opérateur + doit être défini dans la classe X et doit être accessible.

365
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.500 E2097: Instanciation explicite uniquement autorisée dans


les fichiers ou les espaces de nommage
L'opérateur d'instanciation explicite "template" ne peut être utilisé qu'à un niveau global ou dans un espace de nommage. Il ne
peut par exemple pas être utilisé pour qualifier une classe locale ou un membre de classe.

3.1.2.501 E2098: Un déclarateur de spécialisation explicite


"template<>" est maintenant nécessaire
Quand vous spécialisez une fonction, par exemple en fournissant la définition de "foo<int>" pour que foo appelle l'argument "int",
vous devez désormais commencer la déclaration par un opérateur de spécialisation explicite.

3.1.2.502 E2099: Spécialisation explicite uniquement autorisée dans


les fichiers ou les espaces de nommage
L'opérateur de spécialisation explicite template<> ne peut être utilisé qu'à un niveau global ou dans un espace de nommage. Il
ne peut par exemple pas être utilisé pour qualifier une classe locale ou un membre de classe.

3.1.2.503 E2101: Le mot clé 'export' doit précéder une déclaration de


modèle
Dans une déclaration de modèle, le mot clé 'export' ne peut se trouver qu'avant le mot clé "template". Il ne peut pas être utilisé
ailleurs.

3.1.2.504 E2103: Une instanciation explicite doit être utilisée avec


une classe ou une fonction modèle
L'opérateur d'instanciation explicite "template" ne peut être utilisé que pour faire référence à des modèles. Il ne peut pas être
utilisé avec autre chose que des modèles.

3.1.2.505 E2106: Une spécialisation explicite doit être utilisée avec


une classe ou une fonction modèle
3
L'opérateur de spécialisation explicite template<> ne peut être utilisé qu'en face d'une classe ou d'une fonction modèle. S'il est
utilisé avec une classe normale, il ne signifie rien et génère donc une erreur.

3.1.2.506 E2112: Directive d'unité inconnue : 'directive'


Vous ne pouvez pas utiliser ce nom comme une directive unit. A la place, utilisez l'une des directives unit suivantes : weak,
smart_init ou deny.

366
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.507 E2118: Les champs de bits doivent être de type entier


En C++, les champs de bits doivent être de type entier. Ceci inclut les énumérations.

3.1.2.508 E2120: Impossible d'appeler 'main' depuis le programme


C++ n'autorise pas les appels récursifs de main( ).

3.1.2.509 E2125: Le compilateur n'a pas pu générer de constructeur


de copie pour la classe 'classe' OU Le compilateur n'a pas pu
générer de constructeur par défaut pour la classe 'classe' OU Le
compilateur n'a pas pu générer d'opérateur = pour la classe 'classe'
Le compilateur doit parfois générer une fonction membre pour l'utilisateur.

Lorsque cela n'est pas possible à cause des règles du langage, le compilateur affiche l'un de ces messages d'erreur.

3.1.2.510 E2130: Définition de propriété circulaire


Indique qu'une définition de propriété dépend (directement ou non) d'elle-même.

Exemple :
struct pbase
{
int __property ip1 = {read = ip2, write = ip2};
int __property ip2 = {read = ip1, write = ip1};
};
L'exemple de code ci-dessus entraînera l'affichage de ce message d'erreur en cas d'utilisation de ip1 ou de ip2.

3.1.2.511 E2131: Les objets de type 'type' ne peuvent pas être


initialisés avec des { }
Les structures C ordinaires peuvent être initialisées avec un ensemble de valeurs placées entre accolades.

Les classes C++ ne peuvent être initialisées avec des constructeurs que si la classe a des constructeurs, des membres privés,
des fonctions ou des classes de base qui sont virtuelles.
3
3.1.2.512 E2148: La valeur de l'argument par défaut a été redéclarée
pour le paramètre 'paramètre'
Lorsqu'un paramètre d'une fonction C++ est déclaré comme ayant une valeur par défaut, cette valeur ne peut être modifiée,
redéclarée ou omise dans une autre déclaration de cette fonction.

367
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.513 E2149: La valeur de l'argument par défaut a été redéclarée


Lorsqu'un paramètre d'une fonction C++ est déclaré comme ayant une valeur par défaut, cette valeur ne peut être modifiée,
redéclarée ou omise dans une autre déclaration de cette fonction.

3.1.2.514 E2151: Mauvaise correspondance de type dans la valeur


par défaut pour le paramètre 'paramètre'
La valeur par défaut du paramètre n'a pas pu être convertie en type du paramètre.

Ce message est affiché lorsque le paramètre n'a pas de nom.

Lorsque vous compilez des programmes C++, ce message est toujours précédé d'un autre expliquant la raison exacte de cette
non concordance de types.

Cet autre message est généralement "Impossible de convertir 'type1' en 'type2'", mais la non concordance peut avoir de
nombreuses autres causes.

3.1.2.515 E2157: La suppression d'un objet nécessite exactement


une conversion en opérateur de pointeur
Si une personne utilise l'opérateur 'delete' sur un objet (pas un pointeur sur un objet, mais l'objet lui-même), le standard exige de
définir exactement une "conversion en opérateur de pointeur" qui produira le pointeur libéré. Par exemple :
char *a = new char[10];
class foo {
public:
operator char *() { return a; }
};

int main() {
delete[] x;
}
Comme 'x' n'est pas un pointeur, mais un objet, le compilateur supprimera 'a', car c'est ce que l'opérateur de conversion de
pointeur de l'objet offre. Vous ne pouvez pas avoir plusieurs conversions en opérateur de pointeur, car le compilateur ne saurait
pas laquelle appeler.

3.1.2.516 E2173: Le gestionnaire dupliqué pour 'type1' avait déjà


'type2'
3 Vous ne pouvez pas spécifier deux gestionnaires pour un même type.

3.1.2.517 E2174: Le gestionnaire spécifié doit être le dernier


Dans une liste de gestionnaires catch, si le gestionnaire spécifié est présent, il doit être le dernier de la liste.

368
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.518 E2177: Redéclaration de #pragma package avec différents


arguments
Vous pouvez avoir plusieurs instructions de paquet #pragma dans un fichier source tant qu'elles ont les mêmes arguments.
Cette erreur se produit si le compilateur rencontre plusieurs paquets #pragma comportant chacun des arguments différents.

3.1.2.519 E2178: Conflit de nom VIRDEF pour 'fonction'


Le compilateur doit tronquer les noms substantypés à une certaine longueur en raison de la limite imposée par le lieur. Cette
opération peut (c'est très rare) affecter deux noms au même lieur. Si ces deux noms sont des noms VIRDEF, le compilateur
affiche ce message d'erreur. La meilleure solution consiste à changer le nom de 'fonction' pour éviter le conflit.

3.1.2.520 E2180: Numéro dispid déjà utilisé par l'identificateur


Les dispid doivent être uniques ; le compilateur vérifie que c'est bien le cas.

Exemple :
struct__declspec(delphiclass) clxclass
{
__automated:
int __fastcall foo1(void) __dispid(42);// OK
int __fastcall foo2(void) __dispid(42);// Erreur
};

3.1.2.521 E2181: Impossible de redéfinir une fonction


'dynamique/virtuelle' avec une fonction 'dynamique/virtuelle'
Lorsque vous déclarez une fonction dynamique, vous ne pouvez pas redéfinir cette fonction dans une classe dérivée avec une
fonction virtuelle de même nom et de même type. De même, quand la fonction est déclarée virtuelle, vous ne pouvez pas la
redéfinir avec une fonction dynamique dans une classe dérivée.

3.1.2.522 E2202: Goto est interdit dans un gestionnaire d'exception


Il est interdit de passer à un bloc try ou à un gestionnaire d'exception associé à un bloc try.

3.1.2.523 E2205: Type 'type' incorrect dans la section __automated


3
Seuls certains types sont autorisés dans les sections __automated.

Exemple :
struct__declspec(delphiclass) clxclass
{
__automated:
int__fastcall fooInt(int);// OK
long__fastcall fooLong(long);// Erreur : long illégal
};

369
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.524 E2242: Le spécificateur a besoin d'un type de classe de


style Delphi
Les spécificateurs de stockage stored, default et nodefault ne sont autorisés que dans les déclarations de propriétés des types
de classes de style Delphi.

Exemple :
struct regclass
{
int __property ip1 = { stored = false }; // Erreur
int __property ip2 = { default = 42 }; // Erreur
int __property ip3 = { nodefault }; // Erreur
};
struct __declspec(delphiclass) clxclass
{
int __property ip1 = { stored = false }; // OK
int __property ip2 = { default = 42 }; // OK
int __property ip3 = { nodefault }; // OK
};

3.1.2.525 E2247: 'membre' n'est pas accessible


Vous tentez de référencer le membre de classe C++ 'membre', mais il est privé ou protégé et ne peut être référencé depuis cette
fonction.

Ceci se produit parfois lorsque vous tentez d'appeler une fonction membre surchargée accessible (ou un constructeur), alors
que les arguments correspondent à une fonction inaccessible.

La résolution surchargée est toujours vérifiée avant l'accessibilité.

Si cela pose problème, tentez un transtypage explicite d'un ou de plusieurs paramètres pour sélectionner la fonction accessible
désirée.

Les constructeurs de classes de base virtuelles doivent être accessibles dans la portée de la classe la plus dérivée. Ceci
s'explique par le fait que C++ construit toujours les classes de base virtuelles en premier, quelle que soit leur place dans la
hiérarchie. Par exemple :
class A {
public:
A();
};
class B : private virtual A {};
class C : private B {
public:
C();
};
C::C() {} // erreur, A::A() n'est pas inaccessible

3 Etant donné que A est privé pour B, qui est privé pour C, le constructeur de A est inaccessible à C. Cependant, le constructeur
de C doit pouvoir appeler les constructeurs de sa classe de base virtuelle, A. Si B hérite publiquement de A, l'exemple ci-dessus
se compilera.

370
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.526 E2248: Impossible de trouver un constructeur par défaut


pour initialiser un élément de tableau de type 'classe'
Lorsque vous déclarez un tableau d'une classe ayant des constructeurs, vous devez initialiser explicitement chaque élément du
tableau, ou la classe doit posséder un constructeur par défaut.

Le compilateur définira un constructeur par défaut pour une classe si vous n'en définissez aucun.

3.1.2.527 E2251: Impossible de trouver un constructeur par défaut


pour initialiser la classe de base 'classe'
Lorsque la classe dérivée C++ 'classe2' est construite, chaque classe de base 'classe1' doit d'abord être construite.

Si le constructeur pour 'classe2' ne spécifie aucun constructeur pour 'classe1' (dans l'en-tête de 'classe2'), il doit exister un
constructeur classe1::classe1() pour la classe de base.

Ce constructeur sans paramètre est appelé constructeur par défaut.

Le compilateur fournit automatiquement un constructeur par défaut sauf si vous avez défini un constructeur pour 'classe1'.

Dans ce cas, le compilateur ne fournit pas automatiquement le constructeur par défaut ; c'est à vous de le faire.
class Base {
public:
Base(int) {}
};
class Derived = public Base {
Derived():Base(1) {}
}
// doit appeler explicitement le constructeur de base ou fournir
// un constructeur par défaut dans Base.
Les membres de classes avec un constructeur doivent être initialisés dans la liste des initialisateurs de la classe, par exemple :
class A {
public
A( int );
};
class B {
public:
A a;
B() : a( 3 ) {}; //ok
};

3.1.2.528 E2252: 'catch' attendu


Dans un programme C++, un bloc 'try' doit être suivi d'au moins un bloc 'catch'.
3

3.1.2.529 E2253: La convention d'appel doit être attribuée au type de


fonction, non au closure
La convention d'appel n'est pas à la bonne place dans la déclaration de closure. Par exemple,
int __fastcall (__closure * x)()

371
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

compilera, mais
int (__fastcall __closure * x)()
ne se compilera pas.

3.1.2.530 E2261: L'utilisation d'un dispid avec une propriété


nécessite un getter ou un setter
Cette propriété a besoin d'un getter ou d'un setter.

3.1.2.531 E2262: '__except' ou '__finally' attendu après '__try'


En C, un bloc '__try' doit être suivi d'un bloc gestionnaire '__except' ou '__finally'.

3.1.2.532 E2270: > attendu


Le caractère ">" de fermeture n'a pas été détecté dans un nouveau transtypage (par exemple, dynamic_cast).

3.1.2.533 E2273: 'main' ne peut pas être déclaré comme statique ou


en ligne
Vous ne pouvez pas déclarer main comme statique ni en ligne. Par exemple, vous ne pouvez pas utiliser static int main() ni
inline int main().

3.1.2.534 E2281: Identificateur1 nécessite la définition de


Identificateur2 comme type pointeur
Pour utiliser Identificateur1, une définition de Identificateur2 doit être présente (un type).

Voici un exemple où __classid est le premier identificateur et TClass (qui se trouve dans clx.h) le second :
// #include <clx/clx.h> missing
struct __declspec(delphiclass)bar
{
virtual int barbara(void);
};
void *foo(void)
{
return classid(bar); // Erreur
3 }

3.1.2.535 E2289: Les sections __published ou __automated ne sont


gérées que par les classes Delphi
Le compilateur doit générer un type spécial de vtable pour les classes contenant des sections __published et __automated. Ces
sections ne sont donc gérées que par les classes de style Delphi.

372
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

Exemple :
structregclass
{
int mem;
__published:// Erreur : pas une classe de style Delphi
int __property ip = { read = mem, write = mem };
};
struct__declspec(delphiclass) clxclass
{
int mem;
__published:// OK
int __property ip = { read = mem, write = mem };
};

3.1.2.536 E2298: Impossible de créer 'fonction' à partir de la fonction


modèle 'modèle'
Un appel à une fonction modèle a été détecté, mais aucune fonction modèle correspondante ne peut être générée à partir du
modèle de la fonction.

3.1.2.537 E2301: Impossible d'utiliser des modèles dans les


arguments closure ; utilisez un typedef
Lorsque vous déclarez un type closure, les arguments transmis à ce closure doivent être de type simple. Les modèles ne sont
pas acceptés. Pour transmettre à un closure une référence à un objet de type modèle, vous devez déclarer un typedef, qui
compte comme un nom de type simple.

Exemple :
typedef my_class<int> mci;
typedef void (__closure * func) (const mci& object);

3.1.2.538 E2307: Le type 'type' n'est pas une classe définie avec des
fonctions virtuelles
Un dynamic_cast a été utilisé avec un pointeur sur un type classe qui est indéfini ou ne possède pas de fonctions membre
virtuelles.

3.1.2.539 E2315: 'Membre' n'est pas un membre de 'classe', car le


type n'est pas encore défini
Le membre est en train d'être référencé alors que la classe n'a pas encore été entièrement définie. Cela peut arriver si vous 3
déclarez d'avance la classe X, déclarez une variable pointeur sur X, et référencez un membre via ce pointeur ; par exemple :
class X;
X * oneX;
int test() { return oneX->i; }

373
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.540 E2318: 'type' n'est pas un type de classe polymorphe


Cette erreur est générée si l'option -RT du compilateur (pour les informations d'exécution) est désactivée et si :

dynamic_cast a été utilisé avec un pointeur sur une classe

ou

vous avez tenté de supprimer un pointeur sur un objet d'une classe possédant un destructeur virtuel.

3.1.2.541 E2323: Suffixe numérique incorrect


Un littéral numérique est suivi d'un suffixe non reconnu par le compilateur.

Exemple :
int i = 1234i15; // Erreur : suffixe "i15" erroné
int j = 1234i16; // OK

3.1.2.542 E2326: Utilisez __declspec(spec1[, spec2]) pour combiner


plusieurs __declspecs
Si vous utilisez plusieurs modificateurs __declspec, le compilateur générera une erreur s'ils ne sont pas combinés en un seul
__declspec. Par exemple :
int __declspec(__import) __declspec(delphiclass) X
générera une erreur. Utilisez à la place :
int __declspec(__import, delphiclass) X

3.1.2.543 E2328: Les classes avec des propriétés ne peuvent pas


être copiées par valeur
Cette erreur se produit si vous essayez d'utiliser l'opérateur d'affectation par défaut. Par exemple, le code suivant génère cette
erreur avec deux libellés sur une fiche :
*Label1->Font = *Label2->Font;

3.1.2.544 E2331: Nombre de contextes d'option admissibles dépassé


Vous avez entremêlé trop de changements d'options de code source (en utilisant l'option #pragma) entre les déclarations de
modèles. Par exemple :
3 #pragma option -x
template<class T> class foo1 { };
#pragma option -a3
template<class T> class foo2 { };
#pragma option -b
template<class T> class foo3 { };
#pragma option -k-
Vous devez séparer le code source entre fichiers plus petits.

374
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.545 E2332: La variable 'variable' a été optimisée et n'est pas


disponible
Vous avez tenté d'inspecter, de surveiller ou d'accéder d'une autre façon à une variable que l'optimisateur a supprimée.

Cette variable ne se voit jamais affecter de valeur et n'a aucun emplacement de pile.

3.1.2.546 E2476: Impossible de surcharger 'fonction'


Vous ne pouvez pas surcharger la fonction spécifiée. Cette erreur s'affiche si vous avez essayé de déclarer une fonction avec le
même nom qu'une autre fonction, mais la redéclaration est illégale. Par exemple, si les deux fonctions disposent du type de
liaison 'extern "C"', seule une fonction 'extern "C"' peut recevoir un nom.

3.1.2.547 E2346: Le spécificateur d'accès 'x' de la propriété


'propriété' doit être une fonction membre
Seules les fonctions membre ou les données membre sont autorisées dans les spécifications d'accès des propriétés.

Exemple :
int GlobalGetter(void)
{
return 0;
}
struct pbase
{
intMemberGetter(void) {return 1;}
int __property ip1 = { read = GlobalGetter }; // Erreur
int __property ip2 = { read = MemberGetter }; // OK
};

3.1.2.548 E2347: Non concordance de paramètre dans le


spécificateur d'accès 'spécificateur' de la propriété 'propriété'
Les paramètres de la fonction membre utilisés pour accéder à une propriété ne correspondent pas aux paramètres attendus.

Exemple :
structpbase
{
voidSetter1(void){}
voidSetter2(int){}
int __property ip1 = { write = Setter1 }; // Erreur
int __property ip2 = { write = Setter2 }; // OK 3
};

3.1.2.549 E2348: Spécificateur de stockage non autorisé pour les


propriétés de tableau
Les propriétés de tableaux ne peuvent avoir de spécification de stockage.

375
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

Exemple :
struct pbase
{
int __property ap[char *] =
{ stored = false }; // Erreur
};

3.1.2.550 E2351: Membres de données statiques non autorisés dans


les sections __published ou __automated
Seules les données membre non statiques et les fonctions membre sont autorisées dans les sections __published ou
__automated.

Exemple :
struct__declspec(delphiclass) clxclass
{
__published:
static intstaticDataMember;// Erreur
};

3.1.2.551 E2353: La classe 'classe' est abstraite car 'membre = 0'


Ce message s'affiche immédiatement après le message "Impossible de créer une instance de la classe abstraite 'classe'". Il
vous permet de comprendre pourquoi une classe précise est considérée comme abstraite par le compilateur.

Considérez l'exemple suivant de tentative illégale d'instanciation d'une classe abstraite :


struct VB
{
virtualvoid f() = 0;
virtualvoid g() = 0;
virtualvoid h() = 0;
};
struct D1 : virtual VB
{
void f();
};
struct D2 : virtual VB
{
void h();
};
struct DD : D1, D2
{
}
v; // erreur : 'DD' est une classe abstraite
Le code ci-dessus générerait les deux messages d'erreur suivants :
Error TEST.CPP 21: Impossible de créer une instance de la classe abstraite 'DD'
Error TEST.CPP 21: La classe 'DD' est abstraite à cause de 'VB::g() = 0'
3

3.1.2.552 E2359: Le membre référence 'membre' a été initialisé avec


un paramètre non-référence
Tentative de lier un membre référence à un paramètre constructeur. Etant donné que le paramètre cessera d'exister lorsque le
constructeur retournera à son appelant, ce code ne fonctionnera jamais correctement.

376
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.553 E2369: Impossible d'utiliser le résultat d'une affectation de


propriété comme une rvalue
Le résultat de l'affectation d'une propriété est une lvalue. Cela implique par exemple que les affectations de propriétés en chaîne
ne sont pas autorisées ; par exemple, x = y = 5, où x et y sont toutes deux des propriétés. Certaines affectations de propriétés
imbriquées peuvent également produire des erreurs ; par exemple, x != ( y = z ), où y est une propriété.

3.1.2.554 E2370: Nom de type simple attendu


Pour garantir l'interopérabilité entre Delphi et C++, il existe des restrictions sur les noms de type mentionnés dans les listes de
paramètres des types closure publiés. Les types de paramètres doivent être des noms de type simple avec un modificateur
const et une notation de pointeur ou de référence facultatifs.

Ainsi, lorsque vous déclarez un type closure, les arguments transmis à ce closure doivent être de type simple. Par exemple, les
modèles ne sont pas acceptés. Pour transmettre à un closure une référence à un objet de type modèle, vous devez déclarer un
typedef, qui compte comme un nom de type simple.

Exemple :
struct __declspec(delphiclass) foo
{
typedef void __fastcall (__closure *foo1)(SomeTemplateType<int> *);
typedef SomeTemplateType<int> SimpleTypeName;
typedef void __fastcall (__closure *foo2)(SimpleTypeName *);
published:
__property foo1 prop1; // Erreur
__property foo2 prop2; // OK
};

3.1.2.555 E2398: L'argument 'argument' de la fonction modèle n'est


pas utilisé dans les types d'argument
L'argument spécifié n'a pas été utilisé dans la liste d'arguments de la fonction.

La liste d'arguments d'une fonction modèle doit utiliser tous les arguments formels du modèle, sans quoi il est impossible de
générer une instance de fonction modèle basée sur les types d'arguments réels.

3.1.2.556 E2419: Erreur pendant l'instanciation du modèle 'modèle'


Une erreur s'est produite pendant l'instanciation d'un modèle particulier. Ce message suit toujours un autre message d'erreur qui
indique ce qui ne va pas réellement. Ce message est affiché pour aider à repérer l'instanciation du modèle qui a causé le
problème. 3

3.1.2.557 E2424: Classe modèle imbriquée trop profondément :


'class'
Le compilateur impose une certaine limite sur le niveau d'imbrication des classes modèle. Cette limite n'est en général dépassée
que par une dépendance récursive de classe modèle.

377
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

Lorsque ceci se produit, le compilateur affiche ce message d'erreur pour toutes les classes modèle imbriquées. Ceci facilite en
général la recherche de la récursivité.

Ce message d'erreur est toujours suivi de l'erreur fatale "Out of memory" (mémoire saturée).

3.1.2.558 E2457: Les classes de style Delphi doivent être prises par
référence
Un objet de style Delphi ne peut être intercepté que par pointeur.

Exemple :
void foo(TObject *p)
{
try
{
throw(p);
}
catch (TObject o) // Erreur
{
}
catch (TObject *op) // OK
{
}
}

3.1.2.559 E2458: Les classes Delphi doivent être dérivées de classes


Delphi
Vous ne pouvez pas dériver une classe Delphi d'une classe non Delphi.

Exemple :
struct base// la base n'est pas une classe de style Delphi
{
intbasemem;
};
struct __declspec(delphiclass) derived : base // ou
{
intderivedmem;
};

3.1.2.560 E2459: Les classes de style Delphi doivent être construites


en utilisant l'opérateur new
Les classes de style Delphi ne peuvent pas être définies statiquement. Elles doivent être construites sur le tas.
3 Exemple :
voidfoo(void)
{
Tobject o1; // Erreur;
Tobject *o2 = new TObject();
}

378
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.561 E2460: Les classes de style Delphi nécessitent que la


gestion d'exception soit activée
Si vous utilisez des classes Delphi dans votre programme, vous ne pouvez pas désactiver la gestion d'exceptions (option -x-
du compilateur) lorsque vous compilez votre source.

3.1.2.562 E2463: 'base' est une classe de base virtuelle indirecte de


'classe'
Vous ne pouvez pas créer un pointeur sur un membre C++ d'une classe de base virtuelle.

Vous avez tenté de créer un tel pointeur (soit directement, soit par transtypage) et d'accéder à un membre inaccessible de l'une
de vos classes de base.

3.1.2.563 Affectation de pointeur Null


Lorsqu'un programme de modèle mémoire de taille petite ou moyenne se termine, une vérification est effectuée pour déterminer
si le contenu des premiers octets dans le segment de données du programme a changé. Ces octets ne devraient jamais être
modifiés par un programme qui s'exécute. S'ils ont été modifiés, ce message s'affiche pour vous informer que (probablement)
une valeur a été stockée dans un pointeur non initialisé.

Le programme peut sembler fonctionner correctement dans tous les autres cas ; toutefois, il s'agit d'une erreur importante qui
devrait être corrigée immédiatement. Un échec à corriger un pointeur non initialisé peut conduire à un comportement
imprévisible (y compris le verrouillage de l'ordinateur dans les modèles mémoire large, compact et huge).

Vous pouvez utiliser le débogueur intégré pour repérer les pointeurs null.

3.1.2.564 E2268: Appel à une fonction 'fonction' non définie


Votre fichier source a déclaré la fonction en cours comme renvoyant un autre type que void en C++ (ou int en C), mais le
compilateur a détecté un retour sans valeur. Toutes les fonctions int sont exemptes en C car, dans les anciennes versions de
C, il n'existait pas de type void pour indiquer qu'une fonction ne renvoyait rien.

3.1.2.565 E2375: Débordement de pile assembleur


L'assembleur n'a plus de mémoire disponible pendant la compilation. Analysez la portion de code repérée par le message
d'erreur pour vérifier qu'elle utilise correctement la mémoire.
3

3.1.2.566 Initialisation d'une énumération avec un type


Vous tentez d'initialiser une variable enum avec un type différent. Par exemple,
enum count { zero, one, two } x = 2;
affichera cet avertissement, car 2 est de type int et non de type enum count. Nous vous conseillons d'utiliser l'identificateur enum
à la place d'un entier littéral lorsque vous affectez à ou initialisez des types enum.

379
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

Il s'agit d'une erreur mais elle est réduite en avertissement pour que les programmes existants puissent s'exécuter.

3.1.2.567 <nom> n'est pas un identificateur correct


L'identificateur est incorrect. Vérifiez que le premier caractère est une lettre ou un caractère de soulignement (_). Les caractères
suivants doivent être des lettres, des chiffres ou des caractères de soulignement, et l'identificateur ne doit contenir aucun espace.

3.1.2.568 Exemple pour les messages d'erreur d'"utilisation


temporaire..."
Dans cet exemple, la fonction f requiert une référence à un entier (int), et c est un caractère (char) :
f(int&);
char c;
f(c);
Au lieu d'appeler f avec l'adresse de c, le compilateur génère le code équivalent au code source C++ :
int X = c, f(X);

3.1.2.569 Application en cours d'exécution


L'application que vous tentez d'exécuter est déjà en cours d'exécution.

Pour Windows, assurez-vous que la boucle des messages du programme s'est correctement terminée.
PostQuitMessage(0);

3.1.2.570 Formats en virgule flottante Printf/Scanf non liés


Les formats en virgule flottante contiennent des informations de formatage qui sont utilisées pour manipuler des nombres en
virgule flottante dans certaines fonctions de la bibliothèque d'exécution, telles que scanf() et atof(). Généralement, vous devez
éviter la liaison des formats en virgule flottante (qui prennent environ 1K) s'ils ne sont pas requis par votre application. Toutefois,
vous devez explicitement lier les formats en virgule flottante pour les programmes qui manipulent des champs d'une manière
limitée et spécifique.

Reportez-vous à la liste suivante des causes potentielles (listées de la plus courante à la moins courante) pour déterminer
comment résoudre cette erreur :

• CAUSE : Virgule flottante initialisée à Aucune. Vous initialisez l'option virgule flottante à Aucune alors qu'elle devrait être
initialisée à Rapide ou Normale.
• CORRECTION : Initialisez Virgule flottante à Rapide ou Normale.
• CAUSE : Soit le compilateur sur-optimise, soit les formats en virgule flottante n'ont pas vraiment besoin d'être liés. Vous avez
3 besoin des formats en virgule flottante si votre programme manipule des flottants d'une manière limitée et spécifique. Sous
certaines conditions, le compilateur ignorera l'utilisation des virgules flottantes dans scanf(). Par exemple, cela se produit
lorsque vous essayez de lire dans une variable flottante des données faisant partie d'un tableau contenu dans une structure.
• CORRECTION : Ajoutez le code suivant à un module source :
extern _floatconvert;
#pragma extref _floatconvert
CAUSE : Vous avez oublié de mettre l'opérateur adresse & dans l'expression de la variable scanf. Par exemple :
float foo;

380
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

scanf("%f", foo);
CORRECTION : Modifiez le code pour que l'opérateur & soit utilisé si c'est nécessaire. Par exemple, modifiez le code ci-dessus
comme suit :
float foo;
scanf("%f", &foo);

3.1.2.571 W8000: Les opérateurs ambigus requièrent des


parenthèses
(Option de ligne de commande affichant cet avertissement : -wamb)

Cet avertissement s'affiche lorsque deux opérateurs de décalage (shift), relationnels ou booléens binaires sont utilisés sans
parenthèses.

Cet avertissement est également affiché si un opérateur d'addition ou de soustraction apparaît sans parenthèses avec un
opérateur de décalage.

3.1.2.572 W8060: Affectation peut-être incorrecte


(Option de la ligne de commande pour supprimer l'avertissement : -w-pia)

Cet avertissement est généré lorsque le compilateur rencontre un opérateur d'affectation comme opérateur principal d'une
expression conditionnelle (faisant partie d'une instruction 'if', 'while' ou 'do-while').

Il s'agit en général d'une faute de frappe dans l'opérateur d'égalité.

Pour supprimer cet avertissement, placez l'affectation entre parenthèses et comparez l'ensemble à zéro de façon explicite.

Par exemple, ce code


if (a = b) ...
doit être réécrit ainsi :
if ((a = b) != 0) ...

3.1.2.573 W8002: Redémarrage de la compilation avec l'assembleur


(Option de la ligne de commande pour supprimer l'avertissement : -w-asc)

Le compilateur a détecté un asm sans instruction inline ou #pragma correspondante.

La compilation redémarre en utilisant les fonctionnalités du langage assembleur.

Par défaut = Activé.

3
3.1.2.574 W8003: Instruction assembleur inconnue
(Option de la ligne de commande pour supprimer l'avertissement : -w-asm)

Le compilateur a détecté une instruction assembleur en ligne avec un opcode non autorisé ou un token inconnu. Vérifiez
l'orthographe de l'opcode ou du token.
Remarque : Vous obtenez un message d'erreur distinct de l'assembleur si vous saisissez un code source assembleur interdit.

381
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

Par défaut, cet avertissement est désactivé.

3.1.2.575 W8052: Initialisation de base sans nom de classe


maintenant obsolète
(Option de la ligne de commande pour supprimer l'avertissement : -w-obi)

Les précédentes versions de C++ vous permettaient d'initialiser une classe de base en faisant suivre l'en-tête du constructeur
par une liste de paramètres du constructeur de classe de base.

Nous vous recommandons désormais d'inclure le nom de la classe de base.

Ceci facilite la lecture du code. C'est de plus nécessaire lorsque vous avez plusieurs classes de base.

Ancienne méthode
derived::derived(int i) : (i, 10) { ... }
Nouvelle méthode
derived::derived(int i) : base(i, 10) { ... }

3.1.2.576 E2117: Les champs de bits doivent être des entiers signés
ou non signés
(Option de ligne de commande affichant cet avertissement : -wbbf)

En C ANSI, les champs de bits ne peuvent pas être de type char signé ou char non signé.

Lorsque vous ne compilez pas en ANSI strict, le compilateur autorise ces constructions mais affiche cet avertissement.

3.1.2.577 W8064: Appel à une fonction sans prototype


(Option de la ligne de commande pour supprimer l'avertissement : -w-pro)

Ce message s'affiche si l'avertissement "Prototypes requis" est activé et que vous appelez une fonction sans fournir de prototype
au préalable.

3.1.2.578 W8065: Appel à la fonction 'fonction' sans prototype


Ce message s'affiche si l'avertissement "Prototypes requis" est activé et que vous appelez une fonction sans fournir au préalable
un prototype pour cette fonction.

3
3.1.2.579 W8009: La constante est longue
(Option de ligne de commande affichant cet avertissement : -wcln)

Le compilateur a détecté l'une des situations suivantes :

• une constante décimale est supérieure à 32 767, ou


• une constante octale, hexadécimale ou décimale est supérieure à 65 535 et n'est pas suivie de la lettre l ou L.

382
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

La constante est considérée comme un entier long.

3.1.2.580 W8008: La condition est toujours vraie OU W8008 La


condition est toujours fausse
(Option de la ligne de commande pour supprimer l'avertissement : -w-ccc)

Lorsque le compilateur rencontre une comparaison constante qui (en raison de la nature de la valeur comparée) est toujours
true ou false, il affiche cet avertissement et évalue la condition lors de la compilation.

Par exemple :
void proc(unsigned x){
if (x >= 0) /* toujours 'true' */
{
...
}
}

3.1.2.581 W8012: Comparaison de valeurs signées et non signées


(Option de la ligne de commande pour supprimer l'avertissement : -w-csu)

Etant donné que les limites des types signés et non signés sont différentes, le résultat d'une comparaison ordonnée d'une valeur
non signée avec une valeur signée peut être inattendu.

Exemple :
#pragma warn +csu
boolfoo(unsigned u, int i)
{
return u < i;
}

3.1.2.582 W8010: Caractère de continuation \ trouvé dans un


commentaire //
(Option de la ligne de commande pour supprimer l'avertissement : -w-com)

Cet avertissement s'affiche lorsqu'un commentaire C++ // se poursuit à la ligne suivante avec le caractère barre oblique inversée
(\).

Le but de ce message est de vous prévenir au cas où des lignes contenant du code source seraient à tort intégrées à un
commentaire car le commentaire se termine par une barre oblique inversée.

Si cet avertissement s'affiche, vérifiez que la ligne suivant le commentaire // est bien une ligne de commentaire. Si ce n'est pas
le cas, supprimez la barre oblique inversée ou placez un autre caractère après ce symbole. S'il s'agit d'un commentaire, il
semble préférable de commencer aussi la ligne de commentaire suivante par //. 3
Cet avertissement peut être désactivé à l'aide de l'instruction #pragma warn -com.

3.1.2.583 W8080: 'identificateur' est déclaré mais jamais utilisé


(Option de ligne de commande affichant cet avertissement : -wuse)

383
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

L'identificateur spécifié n'a jamais été utilisé. Ce message peut se produire en cas de variables locales ou statiques. Il s'affiche
lorsque le fichier source déclare la variable locale ou statique nommée comme faisant partie du bloc qui se termine, alors que la
variable n'a jamais été utilisée.

Dans le cas de variables locales, cet avertissement se produit lorsque le compilateur rencontre l'accolade fermante de
l'instruction composée ou de la fonction. Dans le cas de variables statiques, cet avertissement se produit lorsque le compilateur
rencontre la fin du fichier source.

Par exemple :
// Il est nécessaire de compiler avec -w pour que cet avertissement s'affiche.
#pragma option -w
int foo()
{
int x;
return 0;
}

3.1.2.584 W8014: Déclaration ignorée


(Option de la ligne de commande pour supprimer l'avertissement : -w-dig)

Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande H2ASH. Consultez le fichier "tsm_util.txt" pour
de plus amples informations.

Par défaut = Activé.

3.1.2.585 W8068: Constante hors limites dans la comparaison


(Option de la ligne de commande pour supprimer l'avertissement : -w-rng)

Votre fichier source inclut une comparaison comportant une sous-expression constante qui est en dehors de la plage autorisée
par le type de l'autre sous-expression.

Par exemple, il est inutile de comparer une valeur non signée avec -1.

Pour obtenir une constante non signée supérieure à 32 767 (décimal), vous devez :

• convertir la constante en non signé -- par exemple, (non signé) 65535, ou


• ajouter la lettre "u" ou "U" à la constante -- par exemple, 65535u.
Même si ce message s'affiche, le compilateur génère le code permettant d'effectuer la comparaison.
Même si ce code renvoie toujours le même résultat (par exemple, en comparant une expression char avec 4000), le code
effectue le test.

3.1.2.586 W8016: Taille de tableau ignorée pour 'delete'


3 (Option de la ligne de commande pour supprimer l'avertissement : -w-dsz)

L'EDI de C++ affiche cet avertissement lorsque vous avez spécifié la taille d'un tableau lors de sa suppression.

Avec les nouvelles spécifications de C++, vous n'avez plus besoin de le faire. Le compilateur ignore cette construction.

Cet avertissement permet aux anciens codes de se compiler.

384
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.587 W8082: Division par zéro


(Option de la ligne de commande pour supprimer l'avertissement : -w-zdi)

Une expression de division ou de reste a un zéro littéral comme diviseur.

3.1.2.588 W8018: Affectation de 'type' à 'énumération'


(Option de la ligne de commande pour supprimer l'avertissement : -w-eas)

Affectation d'une valeur entière à un type enum.

Ceci est une erreur dans C++, mais elle est réduite à un avertissement pour permettre aux programmes existants de s'exécuter.

3.1.2.589 W8006: Initialisation de 'identificateur' avec 'identificateur'


(Option de la ligne de commande pour supprimer l'avertissement : -w-bei)

Vous tentez d'initialiser une variable enum avec un type différent.

Par exemple, l'initialisation suivante affichera cet avertissement car 2 est de type int et non de type enum count :
enum count zero, one, two x = 2;
Nous vous conseillons d'utiliser l'identificateur enum à la place d'un entier littéral lorsque vous affectez à ou initialisez des types
enum.

Il s'agit d'une erreur mais elle est réduite en avertissement pour que les programmes existants puissent s'exécuter.

3.1.2.590 W8001: & superflu avec une fonction


(Option de ligne de commande affichant cet avertissement : -wamp)

L'opérateur adresse de (&) n'est pas nécessaire avec un nom de fonction ; ces opérateurs ne sont pas pris en compte.

3.1.2.591 W8020: 'identificateur' est déclaré à la fois externe et


statique
(Option de la ligne de commande pour supprimer l'avertissement : -w-ext)

Cet identificateur est apparu dans une déclaration qui l'a marqué implicitement ou explicitement comme global ou externe, ainsi
que dans une déclaration statique.
3
L'identificateur est considéré comme statique.

Vérifiez toutes les déclarations pour cet identificateur.

385
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.592 W8007: La valeur hexadécimale contient plus de trois


chiffres
(Option de ligne de commande supprimant cet avertissement : -w-big)

Dans les anciennes versions de C, une séquence d'échappement hexadécimale pouvait contenir plus de trois chiffres.

Le standard ANSI autorise un nombre quelconque de chiffres, à la condition que la valeur tienne dans un octet.

Cet avertissement s'affiche lorsque vous avez une séquence d'échappement hexadécimale longue avec des zéros de début
(\x00045, par exemple).

Les anciennes versions de C interprètent cette chaîne différemment.

3.1.2.593 W8024: La classe de base 'classe1' est aussi une classe de


base de 'classe2'
(Option de la ligne de commande pour supprimer l'avertissement : -w-ibc)

Une classe hérite directement et indirectement de la même classe de base. Il est recommandé d'éviter ce genre de
programmation pour des raisons de portabilité.

3.1.2.594 W8022: 'fonction1' cache la fonction virtuelle 'fonction2'


(Option de la ligne de commande pour supprimer l'avertissement : -w-hid)

Une fonction virtuelle dans une classe de base est généralement redéfinie par une déclaration dans une classe dérivée.

Dans ce cas, une déclaration de même nom mais de types d'arguments différents rend les fonctions virtuelles inaccessibles aux
autres classes dérivées.

3.1.2.595 W8023: La variable tableau 'identificateur' est near


(Option de la ligne de commande pour supprimer l'avertissement : -w-ias)

Lorsque vous activez l'option Far Data Threshold, le compilateur définit automatiquement comme far toutes les variables
globales de taille supérieure au seuil.

Si la variable est un tableau initialisé avec une taille non spécifiée, sa taille totale n'est pas connue lorsque le compilateur doit
décider s'il doit en faire une variable near ou far, aussi le compilateur la définit-il comme near.

Le compilateur affiche cet avertissement si le nombre d'initialisateurs fournis pour le tableau fait en sorte que la taille totale de la
3 variable dépasse le seuil de taille des données.

Si le fait que le compilateur rende la variable near pose des problèmes, définissez explicitement la variable en question comme
far.

Pour ce faire, insérez le mot clé "far" immédiatement à gauche du nom de la variable dans sa définition.

386
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.596 W8061: L'initialisation est partiellement entre accolades


(Option de ligne de commande affichant cet avertissement : -wpin)

Lorsque des structures sont initialisées, les accolades peuvent être utilisées pour marquer l'initialisation de chaque membre de
la structure. Si un membre est un tableau ou une structure, utilisez des paires d'accolades imbriquées. Ceci garantit que le
compilateur placera les bonnes valeurs dans les membres appropriés. Lorsque des accolades facultatives sont omises, le
compilateur affiche cet avertissement.

3.1.2.597 W8038: Le membre constante 'identificateur' n'est pas


initialisé
(Option de la ligne de commande pour supprimer l'avertissement : -w-nci)

Cette classe C++ contient un membre constant 'membre' qui n'a pas d'initialisation.

Notez que les membres constants ne peuvent être qu'initialisés ; ils ne peuvent être la destination d'une affectation.

3.1.2.598 W8071: La conversion peut perdre des chiffres significatifs


(Option de ligne de commande affichant cet avertissement : -wsig)

Pour un opérateur d'affectation ou dans d'autres circonstances, votre fichier source requiert une conversion d'un type de
données intégral vers un autre type de données intégral plus petit.

Etant donné que les variables de type de données intégral n'ont pas la même taille, ce type de conversion peut influer sur le
fonctionnement de votre programme.

3.1.2.599 W8043: Définition de macro ignorée


(Option de la ligne de commande pour supprimer l'avertissement : -w-nma)

Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande H2ASH. Consultez le fichier "tsm_util.txt" pour
de plus amples informations.

3.1.2.600 W8017: La redéfinition de 'x' n'est pas identique


(Option de la ligne de commande pour supprimer l'avertissement : -w-dup)

Votre fichier source a redéfini la macro 'ident' avec du texte qui n'était pas exactement celui de la première définition de la macro.
3
Le nouveau texte remplace l'ancien.

3.1.2.601 W8079: Mélange de pointeurs de plusieurs types 'char'


(Option de ligne de commande affichant cet avertissement : -wucp)

Vous avez converti un pointeur char signé en un pointeur char non signé, ou vice versa, sans utiliser de transtypage explicite.

387
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

Ceci n'est pas grave, bien qu'incorrect.

3.1.2.602 W8067: Instructions de retour avec et sans valeur utilisées


(Option de la ligne de commande pour supprimer l'avertissement : -w-ret)

La fonction en cours a des instructions de retour avec et sans valeurs.

Cette situation est autorisée en langage C, mais génère presque toujours une erreur.

Il est possible qu'une instruction de retour ait été omise à la fin de la fonction.

3.1.2.603 W8048: Utilisez un nom qualifié pour accéder au type


membre 'identificateur'
(Option de la ligne de commande pour supprimer l'avertissement : -w-nst)

Dans les anciennes spécifications de C++, les noms de typedef et de repères déclarés dans des classes étaient directement
visibles dans la portée globale.

Dans les nouvelles spécifications de C++, ces noms doivent être précédés de classe::qualificateur s'ils doivent être utilisés en
dehors de la portée de leur classe.

Le compilateur affiche cet avertissement lorsqu'un nom est défini de façon unique dans une seule classe. Le compilateur
autorise cette utilisation sans classe::. Cela permet aux anciennes versions de code de se compiler.

3.1.2.604 W8039: Liste d'initialiseurs de constructeurs ignorée


(Option de la ligne de commande pour supprimer l'avertissement : -w-ncl)

Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande H2ASH. Consultez le fichier "tsm_util.txt" pour
de plus amples informations.

3.1.2.605 W8040: Corps de fonction ignoré


(Option de la ligne de commande pour supprimer l'avertissement : -w-nfd)

Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande H2ASH. Consultez le fichier "tsm_util.txt" pour
de plus amples informations.

3.1.2.606 W8042: Initialiseur pour l'objet 'x' ignoré


3
(Option de la ligne de commande pour supprimer l'avertissement : -w-nin)

Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande H2ASH. Consultez le fichier "tsm_util.txt" pour
de plus amples informations.

388
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.607 W8044: Directive #undef ignorée


(Option de la ligne de commande pour supprimer l'avertissement : -w-nmu)

Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande H2ASH. Consultez le fichier "tsm_util.txt" pour
de plus amples informations.

3.1.2.608 W8037: Fonction non const 'fonction' appelée pour un


objet const
(Option de ligne de commande supprimant cet avertissement : -w-ncf)

Une fonction membre non constante a été appelée pour un objet const.

(Ceci est une erreur réduite en avertissement pour permettre aux programmes existants de s'exécuter.)

3.1.2.609 W8051: Fonction non volatile 'fonction' appelée pour un


objet volatile
(Option de la ligne de commande pour supprimer l'avertissement : -w-nvf)

En C++, une fonction membre de classe a été appelée pour un objet volatile du type de la classe, mais la fonction n'a pas été
déclarée avec volatile après l'en-tête de fonction. Seule une fonction membre volatile peut être appelée pour un objet volatile.

Par exemple, si vous avez :


class c
{
public:
f() volatile;
g();
};
volatile c vcvar;
il est possible d'appeler vcvar.f(), mais pas d'appeler vcvar.g().

3.1.2.610 W8019: Le code n'a pas d'effet


(Option de la ligne de commande pour supprimer l'avertissement : -w-eff)

Cet avertissement s'affiche lorsque le compilateur rencontre une instruction comportant des opérateurs sans effet.

Par exemple, l'instruction


a + b; 3
n'a aucun effet sur les deux variables.

Cette opération n'est pas nécessaire et indique probablement un bogue.

389
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.611 W8057: Paramètre 'paramètre' jamais utilisé


(Option de la ligne de commande pour supprimer l'avertissement : -w-par)

Le paramètre nommé, déclaré dans la fonction, n'a jamais été utilisé dans le corps de la fonction.

Ceci est peut-être une erreur, souvent causée par une faute de frappe dans le nom du paramètre.

Cet avertissement s'affiche également si l'identificateur est redéclaré comme une variable automatique (locale) dans le corps de
la fonction.

Le paramètre est masqué par la variable automatique et reste inutilisé.

3.1.2.612 W8070: La fonction doit renvoyer une valeur


(Option de la ligne de commande pour supprimer l'avertissement : -w-rvl)

Cette fonction a été déclarée (peut-être implicitement) pour renvoyer une valeur.

Le compilateur a détecté une instruction de retour sans valeur de retour, ou a atteint la fin de la fonction sans rencontrer
d'instruction de retour.

Renvoyez une valeur ou modifiez la déclaration de la fonction pour renvoyer void.

3.1.2.613 W8047: Déclaration de la fonction statique function


ignorée
(Option de la ligne de commande pour supprimer l'avertissement : -w-nsf)

Une erreur s'est produite lors de l'utilisation de l'utilitaire de ligne de commande H2ASH. Consultez le fichier "tsm_util.txt" pour
de plus amples informations.

3.1.2.614 W8041: Valeur non signée rendue négative


(Option de la ligne de commande pour supprimer l'avertissement : -w-ngu)

Il est normalement inutile de rendre négative une valeur non signée car le résultat sera toujours non signé.

Exemple :
#pragma warn +ngu
unsignedfoo(unsigned u)
{
return-u;
3 }

3.1.2.615 W8054: Ce style de définition de fonction est maintenant


obsolète
(Option de ligne de commande supprimant cet avertissement : -w-ofp)

En C++, cette ancienne définition de fonction C est illégale :

390
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

int func(p1, p2) int p1, p2; { /* ... */ }


Il se peut que cette définition soit refusée par les autres compilateurs C++.

3.1.2.616 W8025: Pragma mal formé


(Option de la ligne de commande pour supprimer l'avertissement : -w-ill)

Un pragma ne correspond pas à l'un des pragmas attendus par le compilateur.

3.1.2.617 W8063: Opérateur de préfixe surchargé 'opérateur' utilisé


comme un opérateur de suffixe
(Option de la ligne de commande pour supprimer l'avertissement : -w-pre)

La spécification C++ vous permet de surcharger les versions à préfixe et à suffixe des opérateurs "++" et "--".

Lorsque l'opérateur de préfixe est surchargé, mais est utilisé dans un contexte de suffixe, le compilateur utilise l'opérateur de
préfixe et affiche cet avertissement.

Cet avertissement permet aux anciens codes de se compiler.

3.1.2.618 W8015: Déclarez 'type' avant de l'utiliser dans le prototype


(Option de la ligne de commande pour supprimer l'avertissement : -w-dpu)

Lorsqu'un prototype de fonction fait référence à un type structure non déclaré, la déclaration dans le prototype est différente de
la déclaration en dehors du prototype.

Par exemple,
int func(struct s *ps); struct s /* ... */ ;
Etant donné qu'il n'existe pas de "struct s" dans la portée du prototype de func, le type de paramètre ps est un pointeur sur des
struct s indéfinis, et n'est pas le même que les "struct s" déclarés plus loin.

Ceci générera plus tard des avertissements et des messages d'erreur à propos de types incompatibles, ce qui serait
incompréhensible sans cet avertissement.

Pour corriger le problème, vous pouvez déplacer la déclaration de "struct s" avant les prototypes y faisant référence ou ajouter la
déclaration de type incomplète "struct s" avant les prototypes y faisant référence.

Si le paramètre de la fonction est une struct plutôt qu'un pointeur sur une struct, la déclaration incomplète n'est pas suffisante.

Vous devez alors placer la déclaration struct avant le prototype.

3
3.1.2.619 W8069: Conversion de pointeur non portable
(Option de la ligne de commande pour supprimer l'avertissement : -w-rpt)

Une valeur entière différente de zéro est utilisée dans un contexte où un pointeur ou une valeur entière est requis ; la taille du
type entier et du pointeur est la même.

Utilisez un transtypage explicite si vous devez absolument effectuer cette tâche.

391
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.620 W8066: Code inatteignable


(Option de la ligne de commande pour supprimer l'avertissement : -w-rch)

Une instruction break, continue, goto ou return n'était pas suivie d'un libellé ou de la fin d'une boucle ou d'une fonction.

Le compilateur vérifie les boucles while, do et for avec une condition de test constante et tente de détecter celles qui sont
erronées.

3.1.2.621 W8029: Un temporaire a été utilisé pour le paramètre '???'


(Option de la ligne de commande pour supprimer l'avertissement : -w-lvc)

En C++, une variable ou un paramètre de type référence doit se voir affecter une référence à un objet du même type. Si les
types ne sont pas identiques, la valeur est affectée à un temporaire du bon type, et l'adresse du temporaire est affectée à la
variable ou au paramètre de référence.

Cet avertissement signifie que la variable ou le paramètre de référence ne désigne pas ce qui était prévu, mais une variable
temporaire autrement inutilisée.

Dans l'exemple ci-dessous, la fonction f requiert une référence à un entier (int), et c est un caractère (char) :
f(int &amp);
char c;
f(c);
Au lieu d'appeler f avec l'adresse de c, le compilateur génère le code équivalent au code source C++ :
int X = c, f(X);

3.1.2.622 W8031: Temporaire utilisé pour le paramètre 'paramètre'


OU W8029 Temporaire utilisé pour le paramètre 'numéro' OU W8030
Temporaire utilisé pour le paramètre 'paramètre' dans l'appel à
'fonction' OU W8032 Temporaire utilisé pour le paramètre 'numéro'
dans l'appel à 'fonction'
(Option de la ligne de commande pour supprimer l'avertissement : -w-lvc)

En C++, une variable ou un paramètre de type référence doit se voir affecter une référence à un objet du même type.

Si les types ne sont pas identiques, la valeur est affectée à un temporaire du bon type, et l'adresse du temporaire est affectée à
la variable ou au paramètre de référence.

Cet avertissement signifie que la variable ou le paramètre de référence ne désigne pas ce qui était prévu, mais une variable
3 temporaire autrement inutilisée.

3.1.2.623 W8032: Un temporaire a été utilisé pour le paramètre 2


dans l'appel à '???'
(Option de la ligne de commande pour supprimer l'avertissement : -w-lvc)

392
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

En C++, une variable ou un paramètre de type référence doit se voir affecter une référence à un objet du même type. Si les
types ne sont pas identiques, la valeur est affectée à un temporaire du bon type, et l'adresse du temporaire est affectée à la
variable ou au paramètre de référence.

Cet avertissement signifie que la variable ou le paramètre de référence ne désigne pas ce qui était prévu, mais une variable
temporaire autrement inutilisée.

Dans l'exemple ci-dessous, la fonction f requiert une référence à un entier (int), et c est un caractère (char) :
f(int &amp);
char c;
f(c);
Au lieu d'appeler f avec l'adresse de c, le compilateur génère le code équivalent au code source C++ :
int X = c, f(X);

3.1.2.624 W8028: Variable temporaire utilisée pour initialiser


'identificateur'
(Option de la ligne de commande pour supprimer l'avertissement : -w-lin)

En C++, une variable ou un paramètre de type référence doit se voir affecter une référence à un objet du même type.

Si les types ne sont pas identiques, la valeur est affectée à un temporaire du bon type, et l'adresse du temporaire est affectée à
la variable ou au paramètre de référence.

Cet avertissement signifie que la variable ou le paramètre de référence ne désigne pas ce qui était prévu, mais une variable
temporaire autrement inutilisée.

Exemple

Dans cet exemple, la fonction f requiert une référence à un entier (int), et c est un caractère (char) :
f(int&);
char c;
f(c);
Au lieu d'appeler f avec l'adresse de c, le compilateur génère le code équivalent au code source C++ :
int X = c, f(X);

3.1.2.625 W8074: Structure transmise par valeur


(Option de ligne de commande affichant cet avertissement : -wstv)

Cet avertissement est généré dès qu'une structure est transmise par une valeur comme argument.

Une erreur de programmation fréquente consiste à laisser un opérateur "adresse de" (&) en dehors d'une structure lors de sa
transmission comme argument.

Etant donné que les structures peuvent être transmises par valeur, cette omission est acceptable. 3
Cet avertissement attire simplement votre attention sur cette erreur.

3.1.2.626 W8011: Comparaison de pointeur non portable


(Option de la ligne de commande pour supprimer l'avertissement : -w-cpt)

393
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

Votre fichier source a comparé un pointeur avec un non pointeur autre que la constante 0.

Il est recommandé d'utiliser un transtypage pour supprimer cet avertissement si la comparaison est correcte.

3.1.2.627 W8075: Conversion de pointeur suspecte


(Option de la ligne de commande pour supprimer l'avertissement : -w-sus)

Le compilateur a détecté une conversion de pointeur à cause de laquelle le pointeur pointe sur un type différent.

Utilisez un transtypage pour supprimer cet avertissement si la conversion est correcte.

Cet avertissement est en général affiché lorsque le compilateur C convertit un pointeur de fonction d'un type en un autre (le
compilateur C++ génère une erreur lorsque vous lui demandez d'effectuer cette conversion). Ce message peut être supprimé en
faisant un transtypage. En voici une occurrence fréquente pour les programmeurs sous Windows :
#define STRICT
#include <windows.h>
LPARAM _export WndProc( HWND , UINT , WPARAM , LPARAM );
test() {
WNDCLASS wc;
wc.lpfnWndProc = WndProc; //avertissement
}
Il est supprimé par affectation à lpfnWndProc :
wc.lpfnWndProc = ( WNDPROC ) WndProc;

3.1.2.628 W8059: La taille de la structure a changé


(Option de la ligne de commande pour supprimer l'avertissement : -w-pck)

Ce message d'avertissement s'affiche lorsque l'alignement de la structure est modifié après l'inclusion d'un fichier.

Ce message vous prévient si un fichier inclus change la compression d'une structure mais ne restaure pas, au final, le paramètre
d'origine. Si ceci est voulu, vous pouvez spécifier la directive #pragma nopackwarning en fin de fichier inclus pour désactiver cet
avertissement pour ce fichier précis.

L'avertissement peut être également désactivé avec #pragma warn -pck.

3.1.2.629 8045: Pas de déclaration pour la fonction 'fonction'


(Option de ligne de commande affichant cet avertissement : -wnod)

Ce message s'affiche si vous appelez une fonction sans l'avoir déclarée.

En C, vous pouvez déclarer une fonction sans présenter de prototype :


int func();
3
En C++, chaque déclaration de fonction est également un prototype ; l'exemple ci-dessus est équivalent à
int func(void);
La déclaration peut être de style classique ou moderne (prototype).

394
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.630 W8073: Structure 'structure' non définie


(Option de la ligne de commande pour afficher l'avertissement = -wstu)

Votre fichier source a utilisé la structure nommée dans une ligne avant celle où l'erreur est signalée (probablement sur un
pointeur vers une structure), mais n'avait aucune définition pour la structure.

Ceci est probablement le fait d'un nom de structure mal orthographié ou d'une déclaration manquante.

3.1.2.631 W8013: Utilisation possible de 'identificateur' avant sa


définition
(Option de ligne de commande affichant cet avertissement : -wdef)

Votre fichier source a utilisé la variable 'identificateur' dans une expression avant qu'une valeur ne lui ait été affectée.

Le compilateur utilise une analyse simple du programme pour reconnaître cette erreur.

Si l'utilisation d'une variable se produit physiquement avant toute affectation, cet avertissement est généré.

Bien sûr, le déroulement du programme peut affecter la valeur avant que le programme ne l'utilise.

3.1.2.632 W8004: 'identificateur' a une valeur qui n'est jamais utilisée


(Option de la ligne de commande pour supprimer l'avertissement : -w-aus)

La variable apparaît dans une affectation mais n'est pas utilisée dans la fonction qui vient de se terminer.

Cet avertissement ne s'affiche que lorsque le compilateur rencontre l'accolade de fin.

Le commutateur #pragma warn -aus a une granularité de niveau fonction. Vous ne pouvez pas désactiver cet avertissement
pour des variables individuelles dans une fonction ; il est activé ou désactivé pour la fonction entière.

3.1.2.633 W8081: Les fonctions void ne peuvent pas renvoyer de


valeur
(Option de la ligne de commande pour supprimer l'avertissement : -w-voi)

Votre fichier source a déclaré la fonction en cours comme retournant void, mais le compilateur a détecté une instruction de
retour avec une valeur. La valeur de cette instruction sera ignorée.

Exemple :
// Cela DOIT figurer dans un fichier "C". Cela constituerait une erreur dans un fichier "C++" 3
void foo()
{
return 0; // Impossible de renvoyer une valeur à partir d'une fonction void
}

395
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.634 W8078: L'expression throw viole la spécification


d'exception
(Option de la ligne de commande pour supprimer l'avertissement : -w-thr)

Cet avertissement s'affiche lorsque vous ajoutez une spécification d'exception à une définition de fonction et que vous
déclenchez un type dans le corps de la fonction qui n'est pas mentionné dans la spécification d'exception.

Le programme suivant génère cet avertissement :


int foo() throw(char*) // Je promets de ne déclencher que char*s
{
throw 5; // Mince, j'ai déclenché un entier
return 0;
}

3.1.2.635 W8021: Le gestionnaire de 'type1' est caché par le


gestionnaire précédent de 'type2'
(Option de la ligne de commande pour supprimer l'avertissement : -w-hch)

Cet avertissement s'affiche lorsqu'un gestionnaire pour un type 'D' dérivé du type 'B' est spécifié après un gestionnaire pour 'B',
car le gestionnaire pour 'D' ne sera jamais appelé.

3.1.2.636 W8056: Débordement arithmétique d'entiers


Le compilateur a détecté une condition de débordement dans une expression de calcul sur des entiers.

Par exemple :
int X = 0xFFFF * 0xFFFF;

3.1.2.637 W8035: Message défini par l'utilisateur


Le message d'erreur pour lequel vous avez demandé de l'aide est un avertissement défini par l'utilisateur.

En code C++, les messages définis par l'utilisateur sont introduits à l'aide de la syntaxe #pragma du compilateur de messages.
Remarque : En plus des messages que vous introduisez avec #pragma, des avertissements définis par l'utilisateur peuvent
être générés par des bibliothèques d'autres fournisseurs. Contactez ces fournisseurs pour obtenir de l'aide sur l'un de leurs
messages.

3 3.1.2.638 W8049: Utilisez '> >' pour les modèles imbriqués au lieu de
'>>'
(Option de la ligne de commande pour supprimer l'avertissement : -w-ntd)

Un espace est nécessaire pour séparer le ">" fermant dans un nom de modèle imbriqué, mais comme il est fréquemment oublié,
le compilateur accepte un ">>" avec cet avertissement.

396
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.639 W8026: Les fonctions avec des spécifications d'exception


ne sont pas développées en ligne
Egalement :Les fonctions prenant des arguments classe par valeur ne sont pas développées en ligne

(Option de la ligne de commande pour supprimer l'avertissement : -w-inl)

Les spécifications d'exceptions ne sont pas développées en ligne : vérifiez si votre code en ligne contient des spécifications
d'exceptions.

Les fonctions acceptant des arguments "classe par valeur" ne sont pas développées en ligne : lorsque la gestion des exceptions
est activée, les fonctions acceptant des arguments de classe par valeur ne peuvent pas être développées en ligne.
Remarque : Les fonctions acceptant des paramètres de classe par référence ne sont pas concernées par cette restriction.

3.1.2.640 W8058: Impossible de créer un en-tête précompilé : 'raison'


(Option de la ligne de commande pour supprimer l'avertissement : -w-pch)

Cet avertissement s'affiche lorsque les en-têtes précompilés sont activés mais que le compilateur n'a pas pu en générer un pour
l'une des raisons suivantes :

RaisonExplication

Echec d'écriture. Le compilateur n'a pas pu écrire le fichier d'en-tête précompilé. Cela se produit lorsque vous spécifiez un
emplacement invalide pour la mise en cache des en-têtes précompilés ou si le disque est plein.

Code de l'en-tête. L'un des en-têtes contenait un corps de fonction non inline.

données initialisées dans l'en-tête. L'un des en-têtes contenait une définition de variable globale (en C, une variable globale
avec un initialisateur ; en C++, toute variable non déclarée comme 'extern').

en-tête incomplet. L'en-tête précompilé s'est terminé au milieu d'une déclaration, par exemple dans une définition de classe (ceci
se produit s'il manque une accolade fermante dans un fichier d'en-tête).

3.1.2.641 W8046: Option pragma pop sans option push


correspondante
Le compilateur a rencontré une option #pragma pop avant une précédente option #pragma push ou, dans le cas d'une
imbrication, il y a plus d'occurrences d'options #pragma pop que d'options #pragma push.

3.1.2.642 W8050: Aucun fichier OBJ présent. Désactivation de


3
l'option des types externes.
(Option de la ligne de commande pour supprimer l'avertissement : -w-nto)

Un fichier d'en-tête précompilé fait référence à un fichier de types d'objet, mais ce fichier est introuvable. Cette erreur n'est pas
fatale mais augmente la taille de vos fichiers objets de façon indue.

397
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++

3.1.2.643 W8027: Les fonctions contenant 'instruction' ne sont pas


développées en ligne
(Option de la ligne de commande pour supprimer l'avertissement : -w-inl)

où :

'instruction' peut être un de ces éléments :

• Variables statiques
• Initialiseurs d'agrégation
• Certaines instructions de retour
• Destructeurs locaux
• Certaines instructions if
• Classes locales
• Instructions de retour manquantes
• Mots réservés non autorisés listés "Mots réservés" ci-après.
Mots réservés
Les fonctions contenant l'un de ces mots réservés ne peuvent pas être développées en ligne, même si elles sont spécifiées
comme telles :
asmexcept
breakfinally
casefor
continuegoto
defaultswitch
dowhile
La fonction reste valide, mais sera traitée comme une fonction statique ordinaire (non globale).
Une copie de la fonction apparaîtra dans chaque unité de compilation où elle est appelée.
Description
Si une fonction en ligne devient trop complexe, le compilateur ne peut plus la développer en ligne. Mais, puisque cette fonction
est complexe, la développer en ligne n'apporterait vraisemblablement pas d'amélioration significative des performances.
Destructeurs locaux
Vous avez créé une fonction en ligne pour laquelle le compilateur désactive la mise en ligne. Vous pouvez ignorer cet
avertissement ; la fonction sera générée hors ligne.

3 3.1.2.644 W8036: Mot clé non ANSI utilisé : 'mot clé'


(Option de ligne de commande affichant cet avertissement : -wnak)

Un mot clé non ANSI (tel que '__fastcall') a été utilisé alors que vous aviez demandé une conformité ANSI stricte à l'aide de
l'option -A.

398
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs

3.1.2.645 W8053: 'identificateur' obsolète


(Option de la ligne de commande pour supprimer l'avertissement : -w-obs)

Cet avertissement s'affiche si vous utilisez une fonction de lien "C" spécifiée. Il vous prévient si des fonctions sont "obsolètes".

Voici un exemple de son utilisation :


#ifdef __cplusplus
extern "C" {
#endif
void my_func(void);
#ifdef __cplusplus
}
#endif
#pragma obsolete my_func
main()
{
my_func(); // Génère un avertissement de fonction obsolète
}

3.1.2.646 W8103: Le chemin 'chemin' et le nom de fichier


'nomfichier' dépassent la taille maximale 'n'
(Option de ligne de commande affichant cet avertissement : -wstv)

Lors de la recherche des fichiers d'inclusion, le compilateur C++ a rencontré un fichier dont le chemin et le nom de fichier
contiennent un nombre de caractères supérieur au nombre de caractères maximal de Windows. Renommez les chemins et les
noms de fichiers que vous pouvez, et raccourcissez leurs noms si possible.

3.1.2.647 W8062: Options et avertissements précédents non


restaurés
Le compilateur n'a pas rencontré une option #pragma pop après une précédente option #pragma push ou, lors d'une imbrication,
il y a plus d'occurrences d'options #pragma push que d'options #pragma pop.

3.1.2.648 W8055: Débordement possible dans une opération shift


Le compilateur a détecté des cas où le nombre de bits décalés est supérieur au nombre de bits de la variable affecté. Par
exemple :
char c; c >> 16;

3
3.1.2.649 W8072: Arithmétique de pointeur suspecte
Ce message indique un effet non prévu d'un calcul sur pointeur (ou d'un indice de tableau) détecté dans une expression.

Exemple :
#pragma warn +spa
intarray[10];
intfoo(__int64 index)

399
Exemples C++ RAD Studio 3.1 Référence C++

{
returnarray[index];
}
La valeur de l'indice est codée sur 64 bits alors que l'adresse du tableau l'est sur 32.

3.1.2.650 W8033: La conversion en 'type' échouera pour les


membres de la base virtuelle 'classe'
(Option de la ligne de commande pour supprimer l'avertissement : -w-mpc)

Cet avertissement ne s'affiche que si l'option -Vv est utilisée.

Cet avertissement peut s'afficher lorsqu'un pointeur de membre d'un type est transtypé en un pointeur de membre d'un autre
type et que la classe du pointeur de membre converti a des bases virtuelles.

Si cet avertissement s'affiche, cela signifie que, à l'exécution, si la conversion du pointeur de membre ne peut s'effectuer, le
résultat du transtypage sera un pointeur de membre NULL.

3.1.2.651 W8034: Précision maximum utilisée pour le type pointeur


membre 'type'
(Option de la ligne de commande pour supprimer l'avertissement : -w-mpd)

Lors de la déclaration d'un type de pointeur de membre, sa classe n'a pas été entièrement définie et l'option -Vmd a été utilisée,
le compilateur doit utiliser la représentation la plus générique (et la moins efficace) pour ce type de pointeur de membre. Ceci
peut entraîner la création d'un code moins efficace (et rendre le type de pointeur de membre plus volumineux que nécessaire) et
générer des problèmes de compilation séparée ; voir l'option -Vm du compilateur pour plus de détails.

3.1.3 Exemples C++


Cette section contient des exemples C++.

Rubriques
Nom Description
Exemple Remove et MessageDlg ( see page 400) Le code suivant ajoute un nouvel objet à une liste d'un objet liste, puis le retire :

3.1.3.1 Exemple Remove et MessageDlg


Le code suivant ajoute un nouvel objet à une liste d'un objet liste, puis le retire :
3
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TList *pList = new TList();
AnsiString TheObject = "C'est un objet."
try
{
pList->Add(TheObject); // ajoute l'instance de AnsiString à la liste
MessageDlg("La liste possède " + IntToStr(pList->Count) + "objets",
mtInformation, TMsgDlgButtons() << mbOK, 0);
pList->Remove(TheObject);

400
3.1 Référence C++ RAD Studio Guide du langage C++

MessageDlg("La liste possède " + IntToStr(pList->Count) + "objets",


mtInformation, TMsgDlgButtons() << mbOK, 0);

}
__finally
{
delete pList;
}
}

3.1.4 Guide du langage C++


Cette section traite du langage C++.

Rubriques
Nom Description
Spécificités du C++ ( see page 401) Cette section traite des spécificités du C++.
Liste alphabétique des mots clés ( see page 519) Cette section présente la liste alphabétique des mots clés.
Mots clés par catégorie ( see page 583) Cette section présente la liste thématique des mots clés.
Structure du langage ( see page 590) Les rubriques de cette section fournissent une définition formelle du langage C++
et de son implémentation dans le compilateur CodeGear C++. Elles décrivent les
méthodes de combinaisons autorisées des divers tokens lexicaux en vue de
former des expressions, des instructions et d'autres unités significatives.
Eléments lexicaux ( see page 666) Cette section traite des éléments lexicaux.
Le préprocesseur ( see page 692) Cette section traite du préprocesseur.

3.1.4.1 Spécificités du C++


Cette section traite des spécificités du C++.

Rubriques
Nom Description
Classes ( see page 402) Cette section traite des classes.
Présentation des templates de classes ( see page 428) Cette section présente les templates de classes.
Commutateurs du compilateur relatifs aux templates ( see page 430) Cette section traite des commutateurs du compilateur relatifs aux templates.
Constructeurs et destructeurs ( see page 432) Cette section traite des constructeurs et destructeurs.
Espaces de nommage C++ ( see page 443) Cette section contient les rubriques relatives aux espaces de nommage C++.
Portée en C++ ( see page 447) Cette section traite des portées C++.
Exportation et importation de templates ( see page 450) Cette section traite de l'exportation et de l'importation des templates.
Présentation des templates de fonctions ( see page 450) Cette section présente les templates de fonctions.
Opérateurs new et delete ( see page 452) Cette section traite des opérateurs new et delete.
Présentation du nouveau style de transtypage ( see page 455) Cette section présente le nouveau style de transtypage.
Présentation de la surcharge des opérateurs ( see page 456) Cette section présente la surcharge des opérateurs.
Présentation de la surcharge des fonctions opérateurs ( see page 459) Cette section présente la surcharge des fonctions opérateurs.
Classes polymorphes ( see page 463) Cette section traite des classes polymorphes.
Référencement ( see page 469) Cette section traite de l'opérateur typeid. 3
Identification de type à l'exécution (RTTI) ( see page 471) Cette section traite de l'identification des types au moment de l'exécution
(Run-Time Type Identification, RTTI).
Opérateur de résolution de portée ( see page 472) Cette section traite de l'opérateur de résolution de portée.

401
Guide du langage C++ RAD Studio 3.1 Référence C++

Compilateur C++ plus strict (C++Builder 2007) ( see page 473) Pour une meilleure conformité aux règles du standard C++ ANSI, le compilateur
C++ livré avec C++Builder 2007 est plus strict que les versions précédentes. Le
code qui ne générait pas d'erreurs dans les versions précédentes de C++Builder
peut provoquer des erreurs de compilation avec C++Builder 2007.
Cette section répertorie certaines zones où le compilateur est plus strict. Chaque
cas est illustré par un exemple présentant le problème et montrant comment
mettre à jour le code afin d'obtenir une compilation correcte avec C++Builder
2007. Notez qu'il existe souvent plusieurs façons de mettre à jour le code
incorrect. La méthode adéquate dépend... suite ( see page 473)
Templates ( see page 479) Cette section traite des templates.
Fonctionnalités C++0x (C++Builder 2009) ( see page 480) C++Builder 2009 implémente un certain nombre des nouvelles fonctionnalités
proposées dans le standard C++0x. Cette section liste et décrit ces
fonctionnalités C++0x. Vous pouvez visualiser le "Working Paper draft" qui a été
utilisé comme guide de l'implémentation de ces fonctionnalités à l'adresse Draft
Working Paper. Vous pouvez visualiser un résumé des "working group papers" à
l'adresse Summary of Working Group Papers.
Unicode pour C++ ( see page 513) Cette section contient les rubriques des fonctionnalités associées à Unicode pour
C++.

3.1.4.1.1 Classes
Cette section traite des classes.

Rubriques
Nom Description
Classes C++ ( see page 403) Les classes C++ sont des extensions aux types prédéfinis. Chaque type de
classe représente un ensemble unique d'objets et les opérations (méthodes) et
conversions disponibles pour créer, manipuler et détruire ces objets. Il est
possible de déclarer des classes dérivées qui héritent des membres d'une ou de
plusieurs classes de base (classes parent).
Dans C++, les structures et les unions sont considérées comme des classes
avec certaines valeurs d'accès par défaut.
Une syntaxe simplifiée pour les déclarations de classe est :
clé-classe <type-info> nom-classe
<: liste-bases> { <liste-membres> };
clé-classe est class, struct ou union.
Type-info (facultatif), indique une... suite ( see page 403)
Amies de classes ( see page 404) Cette section traite des amies des classes.
Liste des membres de classe ( see page 406) La liste-membres optionnelle est une séquence incluant notamment, mais pas
uniquement, ce qui suit:

• Déclarations de données (de tout type, y compris les


énumérations, les champs de bits et autres classes)
• Déclarations de types imbriqués
• Définitions de types imbriqués
• Déclarations de templates
• Définitions de templates
• Déclarations de fonctions
• Définitions de fonctions
• Constructeurs
3
• Un destructeur
Les membres d'une classe peuvent optionnellement avoir
des spécificateurs de classe de stockage et des
modificateurs d'accès. Les objets ainsi définis sont dits
membres de classe. Les spécificateurs de stockage de
classe auto, extern et register ne sont pas autorisés.
Toutefois, il est possible de... suite ( see page 406)
Fonctions inline ( see page 407) Cette section traite des fonctions inline.

402
3.1 Référence C++ RAD Studio Guide du langage C++

Portée du nom de classe ( see page 409) La portée du nom de classe est locale. Certaines conditions spéciales sont
requises lorsque le nom de classe apparaît plusieurs fois dans la même portée.
La portée du nom de classe commence avec la déclaration et se termine avec le
bloc qui la contient. Un nom de classe cache une classe, un objet, un
énumérateur ou une fonction ayant le même nom dans la portée. Si un nom de
classe est déclaré dans une portée contenant la déclaration d'un objet, d'une
fonction ou d'un énumérateur de même nom, il n'est possible de faire référence à
la classe qu'en utilisant le... suite ( see page 409)
Mot clé this ( see page 410) Cette section traite du mot clé this.
Noms de classes ( see page 411) nom-classe est un identificateur unique dans sa portée. Avec les structures, les
classes et les unions, il est possible d'omettre le nom de la classe. Pour plus
d'informations sur les structures sans sélecteur, voir Structures sans sélecteur et
typedef.
Portée des membres ( see page 412) Cette section traite de la portée des membres.
Objets de classes ( see page 418) Les objets de classes peuvent être assignés (sauf si la copie a été limitée),
transmis comme arguments aux fonctions, renvoyés par les fonctions (avec
quelques exceptions), etc. D'autres opérations sur les objets et membres des
classes peuvent être définies par l'utilisateur de diverses façons, y compris la
définition de fonctions membre et amie et la redéfinition des fonctions et des
opérateurs standard lorsqu'ils sont utilisés avec des objets d'une certaine classe.
Les fonctions et opérateurs redéfinis sont dits surchargés. Les opérateurs et les
fonctions qui sont limités aux objets d'une certaine classe (ou d'un groupe de
classes) sont dits fonctions... suite ( see page 418)
Classes de base virtuelles ( see page 419) Cette section traite des classes de base virtuelles.
Types de classes ( see page 420) La déclaration crée un nom de classe de type unique, nom-classe. Ceci permet
de déclarer ensuite des objets de classes (ou instances) du même type, et des
objets dérivés de ce type (comme des pointeurs, des références et des tableaux
de nom-classe, etc.) :
Fonctions membres ( see page 421) Les fonctions déclarées sans le spécificateur friend sont dites fonctions
membres d'une classe. Celles déclarées avec friend sont dites fonctions amies.
Les fonctions membres sont souvent référencées comme les méthodes dans la
documentation de Delphi.
Le même nom est utilisable pour plusieurs fonctions, à condition qu'elles diffèrent
quant au type ou au nombre d'arguments.
Déclarations de classes VCL ( see page 422) Syntaxe
Méthodes de classe ( see page 422) Dans C++Builder, une méthode de classe est une méthode qui peut être
invoquée sur un nom de classe, ainsi que sur une instance de cette classe. En
revanche, les méthodes d'objet peuvent être invoquées seulement sur les objets
-- instances d'une classe.
Propriétés statiques ( see page 427) Les propriétés statiques ont été implémentées dans C++Builder 2009 pour
améliorer la compatibilité avec le langage Delphi

3.1.4.1.1.1 Classes C++


Les classes C++ sont des extensions aux types prédéfinis. Chaque type de classe représente un ensemble unique d'objets et
les opérations (méthodes) et conversions disponibles pour créer, manipuler et détruire ces objets. Il est possible de déclarer des
classes dérivées qui héritent des membres d'une ou de plusieurs classes de base (classes parent).

Dans C++, les structures et les unions sont considérées comme des classes avec certaines valeurs d'accès par défaut.

Une syntaxe simplifiée pour les déclarations de classe est :

clé-classe <type-info> nom-classe

<: liste-bases> { <liste-membres> };

clé-classe est class, struct ou union. 3


Type-info (facultatif), indique une demande d'informations de type à l'exécution, relatives à la classe. Vous pouvez soit compiler
avec l'option de compilation –RT, soit utiliser le mot clé __rtti.

liste-bases (facultatif) énumère la classe de base ou les classes à partir desquelles nom-classe obtient par héritage les objets et
méthodes. Si des classes de base sont spécifiées, la classe nom-classe est appelée classe dérivée. liste-bases possède des
spécificateurs d'accès par défaut et de redéfinition facultatifs qui peuvent modifier les principes d'accès de la classe dérivée aux
membres des classes de base.

403
Guide du langage C++ RAD Studio 3.1 Référence C++

liste-membres (facultatif) déclare les membres de la classe (données et fonctions) de nom-classe avec les spécificateurs d'accès
par défaut et de redéfinition dont peut dépendre l'accès aux membres par les fonctions.

Voir aussi
Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.2 Amies de classes


Cette section traite des amies des classes.

Rubriques
Nom Description
Amies de classes ( see page 404) Une friend F de la classe X est une fonction ou une classe qui, bien que n'étant
pas fonction membre de X, dispose des droits d'accès complets aux membres
privés et protégés de X. Mais en ce qui concerne la portée, les déclarations et les
définitions, F est une fonction normale.
Puisque F n'est pas un membre de X, elle n'est pas dans la portée de X et ne
peut être appelée via les opérateurs de sélection x.F et xptr>F (x étant un objet
de X et xptr un pointeur sur un objet de X).
Si le spécificateur friend est... suite ( see page 404)

3.1.4.1.1.2.1 Amies de classes


Une friend F de la classe X est une fonction ou une classe qui, bien que n'étant pas fonction membre de X, dispose des droits
d'accès complets aux membres privés et protégés de X. Mais en ce qui concerne la portée, les déclarations et les définitions, F
3 est une fonction normale.

Puisque F n'est pas un membre de X, elle n'est pas dans la portée de X et ne peut être appelée via les opérateurs de sélection
x.F et xptr>F (x étant un objet de X et xptr un pointeur sur un objet de X).

Si le spécificateur friend est utilisé dans une déclaration ou une définition de fonction à l'intérieur de la classe X, la fonction
devient une amie de X.

Les fonctions friend définies dans une classe suivent les mêmes règles inline que les fonctions membres (voir Fonctions Inline).
Les fonctions friend ne sont pas affectées par leur position dans la classe, ni par les spécificateurs d'accès. Par exemple :

404
3.1 Référence C++ RAD Studio Guide du langage C++

class X {
int i; // private par rapport à X
friend void friend_func(X*, int);
/* friend_func n'est pas private bien qu'elle soit déclarée dans la partie private */
public:
void member_func(int);
};
/* définitions; remarquez que les deux fonctions ont un accès private à int i */
void friend_func(X* xptr, int a) { xptr–>i = a; }
void X::member_func(int a) { i = a; }
X xobj;
/* remarquez la différence au niveau des appels de fonction */
friend_func(&xobj, 6);
xobj.member_func(6);
Vous pouvez faire de toutes les fonctions de la classe Y des amies de la classe X à l'aide d'une seule déclaration :
class Y; // déclaration incomplète
class X {
friend Y;
int i;
void member_funcX();
};
class Y; { // complète la déclaration
void friend_X1(X&);
void friend_X2(X*);
.
.
.
};
Les fonctions déclarées dans Y sont des amies de X, bien qu'aucun spécificateur friend ne leur soit associé. Elles ont accès aux
membres privés de X, comme i et member_funcX.

Il est possible pour une fonction membre spécifique de la classe X d'être une amie de la classe Y :
class X {
.
.
.
void member_funcX();
}
class Y {
int i;
friend void X::member_funcX();
.
.
.
};
L'amitié d'une classe n'est pas transitive : X amie de Y et Y amie de Z n'impliquent pas X amie de Z. L'amitié n'est pas héritée.

Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)


3
Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

405
Guide du langage C++ RAD Studio 3.1 Référence C++

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes

3.1.4.1.1.3 Liste des membres de classe


La liste-membres optionnelle est une séquence incluant notamment, mais pas uniquement, ce qui suit:

• Déclarations de données (de tout type, y compris les énumérations, les champs de bits et autres classes)
• Déclarations de types imbriqués
• Définitions de types imbriqués
• Déclarations de templates
• Définitions de templates
• Déclarations de fonctions
• Définitions de fonctions
• Constructeurs
• Un destructeur
Les membres d'une classe peuvent optionnellement avoir des spécificateurs de classe de stockage et des modificateurs
d'accès. Les objets ainsi définis sont dits membres de classe. Les spécificateurs de stockage de classe auto, extern et
register ne sont pas autorisés. Toutefois, il est possible de déclarer des membres avec le spécificateur de classe de
stockage static.
Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Fonctions membres ( see page 421)


3 Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

406
3.1 Référence C++ RAD Studio Guide du langage C++

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.4 Fonctions inline


Cette section traite des fonctions inline.

Rubriques
Nom Description
Fonctions inline ( see page 407) Vous pouvez déclarer des fonctions membres dans leur classe et les définir
ailleurs. Vous pouvez aussi les déclarer et les définir dans leur classe : ces
fonctions sont dites inline.
Le compilateur peut parfois réduire le temps d'appel d'une fonction en
remplaçant l'appel directement par le code compilé du corps de la fonction. Ce
processus, dit de développement inline d'un corps de fonction, n'affecte pas la
portée du nom ni les arguments de la fonction. Les développements inline ne
sont pas toujours réalisables. Le spécificateur inline indique au compilateur que
vous souhaitez un développement inline.
Remarque: Le compilateur peut ignorer les... suite ( see page 407)

3.1.4.1.1.4.1 Fonctions inline


Vous pouvez déclarer des fonctions membres dans leur classe et les définir ailleurs. Vous pouvez aussi les déclarer et les définir
dans leur classe : ces fonctions sont dites inline.

Le compilateur peut parfois réduire le temps d'appel d'une fonction en remplaçant l'appel directement par le code compilé du
corps de la fonction. Ce processus, dit de développement inline d'un corps de fonction, n'affecte pas la portée du nom ni les
arguments de la fonction. Les développements inline ne sont pas toujours réalisables. Le spécificateur inline indique au
compilateur que vous souhaitez un développement inline.

Remarque: Le compilateur peut ignorer les demandes de développement inline.

Les demandes explicites et implicites inline sont plutôt réservées à des petites fonctions, fréquemment utilisées, comme, par
exemple, les fonctions opérateur qui implémentent des opérateurs de surcharge. La déclaration de classe de func :
int i; // int global
class X {
public:
char* func(void) { return i; } // inline par défaut
char* i;
};
est l'équivalent de :
inline char* X::func(void) { return i; }
func est définie "hors" de la classe avec un spécificateur inline explicite. La valeur i renvoyée par func est char* i de la classe X
(voir Portée des membres).

Fonctions inline et exceptions

Une fonction inline avec spécification d'exception ne sera jamais développée en ligne par le compilateur. Par exemple, 3
inline void f1() throw(int)
{
// Avertissement : Les fonctions avec spécification d'exception ne sont pas développées
}
Les restrictions restantes ne s'appliquent que lorsque l'élimination des destructeurs est activée.

Remarque: Les destructeurs sont appelés par défaut. Voir Initialisation des options de gestion des exceptions pour de plus

407
Guide du langage C++ RAD Studio 3.1 Référence C++

amples informations sur les options de gestion des exceptions.

Une fonction inline qui accepte au moins un paramètre du type "classe avec un destructeur" ne sera pas développée inline.
Remarquez que cette restriction ne s'applique qu'aux classes transmises par référence. Exemple :
struct foo {
foo();
~foo();
};
inline void f2(foo& x)
{
// pas d'avertissement, f2() peut être développé inline
}
inline void f3(foo x)
{
// Avertissement : Les fonctions acceptant le ou les arguments classe-par-valeur
// ne sont pas développées inline dans la fonction f3(foo)
}
Une fonction inline qui renvoie par valeur une classe contenant un destructeur ne sera pas développée inline chaque fois que
des variables ou des objets temporaires devront être détruits dans l'expression renvoyée :
struct foo {
foo();
~foo();
};
inline foo f4()
{
return foo();
// pas d'avertissement, f4() peut être développée inline
}
inline foo f5()
{
foo X;
return foo(); // L'object X doit être détruit
// Avertissement : Les fonctions contenant les instructions
// renvoyées ne sont pas développées inline dans la fonction f5()
}
inline foo f6()
{
return ( foo(), foo() ); // provisoire dans la valeur renvoyée
// Avertissement: les fonctions contenant les instructions
// renvoyées ne sont pas développées inline dans la fonction f6()
}
Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)


3 Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline

Portée des membres ( see page 416)

408
3.1 Référence C++ RAD Studio Guide du langage C++

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.5 Portée du nom de classe


La portée du nom de classe est locale. Certaines conditions spéciales sont requises lorsque le nom de classe apparaît plusieurs
fois dans la même portée. La portée du nom de classe commence avec la déclaration et se termine avec le bloc qui la contient.
Un nom de classe cache une classe, un objet, un énumérateur ou une fonction ayant le même nom dans la portée. Si un nom de
classe est déclaré dans une portée contenant la déclaration d'un objet, d'une fonction ou d'un énumérateur de même nom, il
n'est possible de faire référence à la classe qu'en utilisant le spécificateur de type composé. Ceci signifie que le mot clé de
classe, class, struct ou union, doit être utilisé avec le nom. Par exemple,
struct S { ... };
int S(struct S *Sptr);
void func(void) {
S t; // déclaration ILLEGALE : pas de classe clé et pas de fonction S dans la portée
struct S s; // OK : élaboré avec classe clé
S(&s); // OK : il s'agit d'un appel de fonction
}
C++ admet aussi une déclaration de classe incomplète :
class X; // pas de membres pour le moment
Les déclarations incomplètes permettent certaines références aux noms de classe X (généralement des références à des
pointeurs sur des objets classe) avant que les classes ne soient totalement définies. Voir Déclarations des membres d'une
structure pour de plus amples informations. Naturellement, vous devez faire une déclaration complète avec les membres pour
pouvoir déclarer et utiliser les objets de cette classe.

Voir aussi la syntaxe des déclarations incomplètes des classes VCL.

Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410) 3


Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

409
Guide du langage C++ RAD Studio 3.1 Référence C++

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.6 Mot clé this


Cette section traite du mot clé this.

Rubriques
Nom Description
Membres statiques ( see page 410) Le spécificateur de classe de stockage static est utilisable dans les déclarations
de classe des données et fonctions membres. Ces dernières sont dites membres
statiques et ont des caractéristiques distinctes de celles des membres non
statiques. Avec des membres non statiques, il “existe” une copie distincte pour
chaque instance de la classe ; avec les membres statiques, une seule copie
suffit, accessible sans référence à un objet précis de la classe. Si x est un
membre statique de la classe X, il peut être référencé comme X::x (même si les
objets de la classe X n'ont pas encore été créés). Il... suite ( see page 410)

3.1.4.1.1.6.1 Membres statiques


Le spécificateur de classe de stockage static est utilisable dans les déclarations de classe des données et fonctions membres.
Ces dernières sont dites membres statiques et ont des caractéristiques distinctes de celles des membres non statiques. Avec
des membres non statiques, il “existe” une copie distincte pour chaque instance de la classe ; avec les membres statiques, une
seule copie suffit, accessible sans référence à un objet précis de la classe. Si x est un membre statique de la classe X, il peut
être référencé comme X::x (même si les objets de la classe X n'ont pas encore été créés). Il est possible aussi d'accéder à x en
utilisant les opérateurs standard d'accès aux membres : par exemple, y.x et yptr->x où y est un objet de la classe X et yptr un
pointeur sur un objet de la classe X, bien que les expressions y et yptr ne soient pas évaluées. En particulier, une fonction
membre statique peut être appelée avec ou sans la syntaxe spéciale de fonction membre :
class X {
int member_int;
public:
static void func(int i, X* ptr);
};
void g(void)
{
X obj;
func(1, &obj); // erreur à moins qu'une func() globale
// soit définie quelque part
X::func(1, &obj); // appelle la fonction statique func() de X
// OK pour les fonctions statiques uniquement
obj.func(1, &obj); // idem (OK pour fonctions statiques et
// non statiques)
}
Puisqu'il est possible d'appeler une fonction membre statique sans aucun objet précis en vue, celle-ci n'a aucun pointeur this. Il
en résulte qu'une fonction membre statique ne peut accéder à des membres non statiques sans spécification explicite d'un objet
avec . ou ->. Par exemple, avec les déclarations de l'exemple précédent, func pourrait être définie comme suit :
void X::func(int i, X* ptr)
{
3 member_int = i; // à quel objet se réfère member_int
// ? Erreur
ptr->member_int = i; // OK: maintenant nous savons !
}
A l'exception des fonctions inline, les fonctions membres statiques de classes globales ont une liaison externe. Elles ne peuvent
pas être des fonctions virtuelles. Il est impossible d'avoir une fonction membre statique et non statique ayant le même nom et les
mêmes types d'arguments.

La déclaration d'un membre statique de données dans la déclaration de sa classe n'est pas une définition ; il faut fournir une

410
3.1 Référence C++ RAD Studio Guide du langage C++

définition pour allouer de la mémoire et donner une valeur d'initialisation.

Les membres statiques d'une classe déclarée locale par rapport à une certaine fonction n'ont pas de liaison et ne peuvent pas
être initialisés. Ceux d'une classe globale sont initialisables, comme des objets globaux ordinaires, mais uniquement dans la
portée fichier. Les membres statiques imbriqués à n'importe quel niveau suivent les règles d'accès aux membres de classe, sauf
qu'il est possible de les initialiser.
class X {
static int x;
static const int size = 5;
class inner {
static float f;
void func(void); // déclaration imbriquée
};
public:
char array[size];
};
int X::x = 1;
float X::inner::f = 3.14; // initialisation imbriquée statique
void X::inner::func(void) { /* définit la fonction imbriquée */ }
La principale utilité des membres statiques est qu'ils permettent de suivre des données communes à tous les objets d'une
classe, comme le nombre d'objets créés, ou la dernière ressource utilisée parmi l'ensemble de celles que partagent tous les
objets. Les membres statiques servent aussi à :

• Réduire le nombre des noms globaux visibles


• Mettre en évidence les objets statiques qui appartiennent logiquement à une classe
• Permettre un contrôle d'accès à leurs noms.
Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413) 3


Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.7 Noms de classes


nom-classe est un identificateur unique dans sa portée. Avec les structures, les classes et les unions, il est possible d'omettre le

411
Guide du langage C++ RAD Studio 3.1 Référence C++

nom de la classe. Pour plus d'informations sur les structures sans sélecteur, voir Structures sans sélecteur et typedef.

Voir aussi
Classes C++ ( see page 403)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

Noms de classes VCL

3.1.4.1.1.8 Portée des membres


Cette section traite de la portée des membres.

Rubriques
Nom Description
Accès aux classes de base et dérivées ( see page 413) Lorsque vous déclarez une classe dérivée D, vous énumérez les classes de
base B1, B2, ... dans une liste-bases dont le délimiteur est une virgule :
Contrôle d'accès aux membres ( see page 415) Les membres d'une classe acquièrent leurs attributs d'accès soit par défaut
(selon la clé de classe et le lieu de la déclaration) ou grâce à l'un des trois
spécificateurs d'accès : public, private et protected. La signification de ces
attributs est la suivante :

• public : Membre pouvant être utilisé par toutes les


fonctions.
• private : Le membre n'est utilisable que par des fonctions
membres et amies de la classe dans laquelle il est
déclaré.

3 • protected : même chose que private. En outre, le


membre n'est utilisable que par des fonctions membres et
amies des classes dérivées de la... suite ( see page 415)
Portée des membres ( see page 416) L'expression X::func() de l'exemple illustré dans Fonctions et exceptions inline
utilise le nom de classe X avec le modificateur d'accès de portée pour indiquer
que func, bien que définie "hors" de la classe, est en réalité une fonction membre
de X et qu'elle existe dans la portée de X. L'influence de X s'étend au corps de la
définition. Ceci explique pourquoi la valeur i renvoyée par func se réfère à X::i, la
valeur char* i de X, et non pas à la valeur globale int i. Sans le modificateur X::,
la fonction func représenterait une fonction ordinaire de type... suite ( see page
416)

412
3.1 Référence C++ RAD Studio Guide du langage C++

Types imbriqués ( see page 417) Les balises ou les noms typedef déclarés dans une classe appartiennent
lexicalement à la portée de cette classe. Pour accéder à ces noms, vous devez
en général utiliser la notation xxx::yyy, sauf si vous êtes dans la portée de la
classe appropriée.
Une classe déclarée dans une autre classe est appelée classe imbriquée. Son
nom est local à la classe qui la contient ; la classe imbriquée se trouve dans la
portée de la classe qui la contient. Il s'agit d'une imbrication purement lexicale.
La classe imbriquée ne bénéficie d'aucun privilège supplémentaire pour accéder
aux membres de la classe qui... suite ( see page 417)

3.1.4.1.1.8.1 Accès aux classes de base et dérivées


Lorsque vous déclarez une classe dérivée D, vous énumérez les classes de base B1, B2, ... dans une liste-bases dont le
délimiteur est une virgule :
clé-classe D : liste-bases { <liste-membres> }
D hérite de tous les membres de ces classes de base. Les membres des classes de base redéfinies sont obtenus par héritage
et sont accessibles via une redéfinition de portée. D ne peut utiliser que des membres public ou protected de ses classes de
base. Mais quels vont être les attributs d'accès des membres dérivés tels que les voit D ? D souhaitera, par exemple, utiliser un
membre public d'une classe de base, mais le rendre private dans la mesure où des fonctions extérieures sont impliquées. La
solution consiste à appliquer des spécificateurs d'accès dans la liste-bases.

Remarque: Puisqu'une classe de base peut être elle-même une classe dérivée, la question de l'attribut d'accès est récursive :
vous revenez en arrière jusqu'à ce que vous parveniez à la première des classes de base, celle qui n'a hérité d'aucune autre.

Lorsque vous déclarez D, vous pouvez utiliser le spécificateur d'accès public, protected ou private devant chaque classe de la
liste-bases :
class D : public B1, private B2, ... {
.
.
.
}
Ces modificateurs ne changent pas les attributs d'accès des membres de base tels qu'ils sont perçus par la classe de base,
même s'ils peuvent modifier ceux des membres de base tels que les voit la classe dérivée.

La valeur par défaut est private si D est une déclaration class, et public si D est une déclaration struct.

Remarque: Les unions ne peuvent contenir aucune classe de base ni être utilisées comme classes de base.

La classe dérivée hérite des attributs d'accès d'une classe de base selon les principes suivants :

• Classe de base public : les membres à accès public de la classe de base sont des membres public de la classe dérivée.
Les membres à accès protected de la classe de base sont des membres protected de la classe dérivée. Les membres à
accès private de la classe de base restent private pour la classe de base.
• Classe de base protected : les membres à accès public et protected de la classe de base sont des membres protected de
la classe dérivée. Les membres à accès private de la classe de base restent private pour cette classe.
• Classe de base private : les membres à accès public et protected de la classe de base sont des membres private de la
classe dérivée. Les membres à accès private de la classe de base restent private pour cette classe.
Vous remarquerez que les membres private d'une classe de base sont, et restent, inaccessibles aux fonctions membres de la
classe dérivée, à moins que vous ne déclariez explicitement un spécificateur friend dans la classe de base pour autoriser 3
l'accès. Par exemple,
/* la classe X est dérivée de la classe A */
class X : A { // la valeur par défaut pour classe est private A
.
.
.
}
/* la classe Y est dérivée (héritage multiple) de B et de C
B devient par défaut private B */

413
Guide du langage C++ RAD Studio 3.1 Référence C++

class Y : B, public C { // remplacement de la valeur par défaut pour C


.
.
.
}
/* struct S est dérivée de D */
struct S : D { // la valeur implicite pour struct est public D
.
.
.
}
/* struct T est dérivée (héritage multiple) de D et E
E devient par défaut public E */
struct T : private D, E { // remplacement de la valeur implicite pour D
// E est public par défaut
.
.
.
}
Les effets dus aux spécificateurs d'accès dans la liste de base sont adaptables à l'aide d'un nom-qualifié dans les déclarations
public ou protected de la classe dérivée. Par exemple :
class B {
int a; // private par défaut
public:
int b, c;
int Bfunc(void);
};
class X : private B { // a, b, c, Bfunc sont désormais private dans X
int a; // private par défaut, NOTE : a ne l'est pas
// accessible dans X
public:
B::c; // c était private, il est devenu public
int e;
int Xfunc(void);
};
int Efunc(X& x); // externe à B et X
La fonction Efunc() ne peut utiliser que les noms publics c, e et Xfunc().

La fonction Xfunc() de X, et dérivée de private B, a accès :

• à c "devenu public"
• aux membres "private-pour-X" à partir de B : b et Bfunc()
• aux membres private et public de X : d, e et Xfunc()
Cependant, Xfunc() ne peut pas accéder au membre "private-pour-B", a.
Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)


3
Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

414
3.1 Référence C++ RAD Studio Guide du langage C++

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.8.2 Contrôle d'accès aux membres


Les membres d'une classe acquièrent leurs attributs d'accès soit par défaut (selon la clé de classe et le lieu de la déclaration) ou
grâce à l'un des trois spécificateurs d'accès : public, private et protected. La signification de ces attributs est la suivante :

• public : Membre pouvant être utilisé par toutes les fonctions.


• private : Le membre n'est utilisable que par des fonctions membres et amies de la classe dans laquelle il est déclaré.
• protected : même chose que private. En outre, le membre n'est utilisable que par des fonctions membres et amies des
classes dérivées de la classe déclarée, et uniquement dans les objets de type dérivé. Les classes dérivées sont expliquées
dans Accès aux classes de base et dérivées.
Remarque: Les déclarations de fonctions amies ne sont pas affectées par les spécificateurs d'accès. Voir Amies de classes
pour plus d'informations.
Les membres d'une classe sont à accès private par défaut, de sorte que vous devez explicitement mentionner les
spécificateurs public ou protected pour changer cette valeur.
Les membres d'une structure struct sont à accès public par défaut, mais vous pouvez redéfinir l'accès à la structure en
appliquant le spécificateur private ou protected.
Les membres d'une union sont public par défaut, et ne sont pas modifiables. De ce fait, les trois spécificateurs d'accès sont
illégaux dans les membres d'une union.
Un modificateur d'accès implicite ou de redéfinition reste applicable pour toutes les déclarations de membres le suivant, tant
qu'un autre modificateur n'apparaît pas. Par exemple,
class X {
int i; // X::i est private par défaut
char ch; // de même pour X::ch
public:
int j; // les deux suivants sont public
int k;
protected:
int l; // X::l est protected
};
struct Y {
int i; // Y::i est public par défaut
private:
int j; // Y::j est private
public: 3
int k; // Y::k est public
};
union Z {
int i; // public par défaut ; pas d'autre choix
double d;
};
Remarque: Les spécificateurs d'accès peuvent être répertoriés et groupés dans l'ordre voulu. Vous pourrez éviter la saisie en
déclarant tous les membres à accès privé ensemble, etc.

415
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.8.3 Portée des membres


L'expression X::func() de l'exemple illustré dans Fonctions et exceptions inline utilise le nom de classe X avec le modificateur
d'accès de portée pour indiquer que func, bien que définie "hors" de la classe, est en réalité une fonction membre de X et qu'elle
existe dans la portée de X. L'influence de X s'étend au corps de la définition. Ceci explique pourquoi la valeur i renvoyée par
func se réfère à X::i, la valeur char* i de X, et non pas à la valeur globale int i. Sans le modificateur X::, la fonction func
représenterait une fonction ordinaire de type non classe, renvoyant la valeur globale int i.

Toutes les fonctions membres figurent donc dans la portée de leur classe, même si elles sont définies à l'extérieur de cette
classe.

Les données membres d'une classe X peuvent être référencées à l'aide des opérateurs de sélection . et -> (comme avec les
structures C). Il est également possible d'appeler les fonctions membres avec ces opérateurs (Voir le mot clé this). Par
exemple :
class X {
public:
int i;
char name[20];
X *ptr1;
3 X *ptr2;
void Xfunc(char*data, X* left, X* right); // définition ailleurs
};
void f(void);
{
X x1, x2, *xptr=&x1;
x1.i = 0;
x2.i = x1.i;
xptr–>i = 1;
x1.Xfunc("stan", &x2, xptr);

416
3.1 Référence C++ RAD Studio Guide du langage C++

}
Si m est un membre ou un membre de base de la classe X, l'expression X::m est dite nom qualifié ; elle est du même type que
m, et est une lvalue uniquement si m est une lvalue. Un point déterminant est que, même si le nom de classe X est caché par un
nom non-type, le nom qualifié X::m accédera au membre de classe adéquat, c'est-à-dire m.

Les membres de classe ne peuvent pas être ajoutés à une classe dans une autre section de votre programme. La classe X ne
peut pas contenir des objets de la classe X, mais uniquement des pointeurs ou des références à des objets de la classe X
(remarquez la similitude avec les types d'union et de structure du C).

Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.8.4 Types imbriqués


Les balises ou les noms typedef déclarés dans une classe appartiennent lexicalement à la portée de cette classe. Pour accéder
à ces noms, vous devez en général utiliser la notation xxx::yyy, sauf si vous êtes dans la portée de la classe appropriée.

Une classe déclarée dans une autre classe est appelée classe imbriquée. Son nom est local à la classe qui la contient ; la
classe imbriquée se trouve dans la portée de la classe qui la contient. Il s'agit d'une imbrication purement lexicale. La classe
imbriquée ne bénéficie d'aucun privilège supplémentaire pour accéder aux membres de la classe qui la contient (et vice-versa).

Vous pouvez imbriquer les classes de cette manière à un niveau arbitraire, dans la limite de la place disponible en mémoire. Les
classes imbriquées peuvent être déclarées dans une classe et être définies plus tard. Par exemple, 3
struct outer
{
typedef int t; // 'outer::t' est un nom typedef
struct inner // 'outer::inner' est une classe
{
static int x;
};
static int x;
int f();

417
Guide du langage C++ RAD Studio 3.1 Référence C++

class deep; // déclaration imbriquée


};
int outer::x; // définit donnée membre statique
int outer::f() {
t x; // 't' directement visible ici
return x;
}
int outer::inner::x; // définit donnée membre statique
outer::t x; // doit utiliser 'outer::t' ici
class outer::deep { }; // définit la classe imbriquée ici
En Borland C++ 2.0, toute balise ou tout nom typedef déclaré à l'intérieur d'une classe appartient en réalité à la portée globale
(fichier). Par exemple :
struct foo
{
enum bar { x }; // règles 2.0 : 'bar' appartient à la portée de fichier
// règles 2.1 : 'bar' appartient à la portée 'foo'
};
bar x;
Le fragment précédent se compile sans erreur. Comme le code est illicite avec la version 2.1, un avertissement est émis :
Avertissement : Utiliser le nom qualifié pour accéder au type imbriqué 'foo::bar'
Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)


3
3.1.4.1.1.9 Objets de classes
Les objets de classes peuvent être assignés (sauf si la copie a été limitée), transmis comme arguments aux fonctions, renvoyés
par les fonctions (avec quelques exceptions), etc. D'autres opérations sur les objets et membres des classes peuvent être
définies par l'utilisateur de diverses façons, y compris la définition de fonctions membre et amie et la redéfinition des fonctions et
des opérateurs standard lorsqu'ils sont utilisés avec des objets d'une certaine classe.

Les fonctions et opérateurs redéfinis sont dits surchargés. Les opérateurs et les fonctions qui sont limités aux objets d'une

418
3.1 Référence C++ RAD Studio Guide du langage C++

certaine classe (ou d'un groupe de classes) sont dits fonctions membres de cette classe. C++ offre ce mécanisme de surcharge
qui permet d'appeler par le même nom une fonction ou un opérateur effectuant différentes tâches, selon le type ou le nombre
d'arguments ou d'opérandes.

Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.10 Classes de base virtuelles


Cette section traite des classes de base virtuelles.

Rubriques
Nom Description
Classes de base virtuelles ( see page 419) Une classe virtual est une classe de base transmise à plus d'une classe dérivée,
ce qui peut arriver avec l'héritage multiple.
Une classe de base ne peut être spécifiée qu'une seule fois dans une classe
dérivée :

3.1.4.1.1.10.1 Classes de base virtuelles


Une classe virtual est une classe de base transmise à plus d'une classe dérivée, ce qui peut arriver avec l'héritage multiple.

Une classe de base ne peut être spécifiée qu'une seule fois dans une classe dérivée :
class B { ... };
class D : B; B { ... }; //ILLEGAL
3
Toutefois, la transmission indirecte de la classe de base dans la classe dérivée est possible plusieurs fois :
class X : public B { ... };
class Y : public B { ... };
class Z : public X, public Y { ... }; //OK
Dans ce cas, chaque objet de la classe Z aura deux sous-objets de la classe B.

Si cela pose problème, vous pouvez ajouter le mot clé virtual à un spécificateur de classe de base. Par exemple,

419
Guide du langage C++ RAD Studio 3.1 Référence C++

class X : virtual public B { ... };


class Y : virtual public B { ... };
class Z : public X, public Y { ... };
B est maintenant une classe de base virtuelle et la classe Z ne possède qu'un sous-objet de la classe B.

Constructeurs pour les classes de base virtuelles

Les constructeurs des classes de base virtuelles sont appelés avant toutes les autres classes de base non virtuelles.

Si la hiérarchie contient plusieurs classes de base virtuelles, leurs constructeurs sont appelés dans l'ordre des déclarations des
classes.

Toute base non virtuelle est ensuite construite avant que le constructeur de classe dérivée ne soit appelé.

Si une classe virtuelle dérive d'une classe de base non virtuelle, celle-ci apparaît en premier, afin que la construction de la
classe de base virtuelle soit correcte. Par exemple, ce code
class X : public Y, virtual public Z
X one;
produit l'ordre suivant :
Z(); // initialisation de classe de base virtuelle
Y(); // classe de base non virtuelle
X(); // classe dérivée
Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles


3
Amies de classes ( see page 404)

3.1.4.1.1.11 Types de classes


La déclaration crée un nom de classe de type unique, nom-classe. Ceci permet de déclarer ensuite des objets de classes (ou
instances) du même type, et des objets dérivés de ce type (comme des pointeurs, des références et des tableaux de
nom-classe, etc.) :

420
3.1 Référence C++ RAD Studio Guide du langage C++

class X { ... };
X x, &xr, *xptr, xarray[10];
/* quatre objets : type X, référence à X, pointeur sur X et tableau de X*/
struct Y { ... };
Y y, &yr, *yptr, yarray[10];
// en C on aurait
// struct Y y, *yptr, yarray[10];
union Z { ... };
Z z, &zr, *zptr, zarray[10];
// en C on aurait
// union Z z, *zptr, zarray[10];
Remarquez la différence entre les déclarations d'union et de structure en C et C++ : si les mots clés struct et union sont
essentiels en C, en C++ ils ne sont nécessaires que lorsque les noms de classes Y et Z sont cachés (voir Portée du nom de
classe)

Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Portée du nom de classe ( see page 409)

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.12 Fonctions membres


Les fonctions déclarées sans le spécificateur friend sont dites fonctions membres d'une classe. Celles déclarées avec friend
sont dites fonctions amies.

Les fonctions membres sont souvent référencées comme les méthodes dans la documentation de Delphi.

Le même nom est utilisable pour plusieurs fonctions, à condition qu'elles diffèrent quant au type ou au nombre d'arguments.
3
Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

421
Guide du langage C++ RAD Studio 3.1 Référence C++

Objets de classes ( see page 418)

Liste des membres de classe ( see page 406)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.13 Déclarations de classes VCL


Syntaxe
__declspec(<modificateur-decl>)
Description

L'argument modificateur-decl peut être delphiclass ou pascalimplementation. Ces arguments doivent être utilisés seulement
avec les classes dérivées des classes VCL.

• Vous devez utiliser __declspec(delphiclass) pour n'importe quelle déclaration avancée (forward) de classes qui sont
directement ou indirectement dérivées de TObject.
• Utilisez le modificateur __declspec(pascalimplementation) pour indiquer qu'une classe a été implémentée dans le langage
Delphi. Ce modificateur apparaît dans les fichiers d'en-tête de portabilité Delphi d'extension .hpp.
Remarque: Un autre argument, delphireturn
, est utilisé pour marquer les classes C++ pour une gestion compatible VCL des appels de fonctions comme les paramètres et
les valeurs renvoyées. L'argument delphiclass est utilisé pour créer des classes ayant la compatibilité VCL suivante :
• RTTI compatible VCL
• Comportement du destructeur/constructeur compatible VCL
• Gestion des exceptions compatible VCL
Une classe compatible VCL possède les restrictions suivantes :
• Classe de base non virtuelle ou héritage multiple autorisé.
• Elle doit être allouée dynamiquement en utilisant l'opérateur global new.
• Les constructeurs de copie et d'affectation doivent être explicitement définis. Le compilateur ne fournit pas automatiquement
ces constructeurs pour les classes dérivées VCL.
3 • Elle doit hériter publiquement d'une autre classe VCL.
Voir aussi
Noms de classes VCL

3.1.4.1.1.14 Méthodes de classe


Dans C++Builder, une méthode de classe est une méthode qui peut être invoquée sur un nom de classe, ainsi que sur une

422
3.1 Référence C++ RAD Studio Guide du langage C++

instance de cette classe. En revanche, les méthodes d'objet peuvent être invoquées seulement sur les objets -- instances d'une
classe.

Comment les méthodes de classe fonctionnent dans Delphi


Le langage Delphi (Pascal Objet) supporte les méthodes de classe et une métaclasse comme décrit dans la section Méthodes
de classe de la rubrique d'aide Delphi Méthodes.

En voici un exemple :
TTest = class;

// Déclaration du type métaclasse


TTestClass = class of TTest;

TTest = class
public
// Méthodes de classe
class function add(I, J: Integer): Integer;
class function GetClsName: string;

// Méthode de classe virtuelle


class function GetClsNameVirt: string; virtual;

// Getter et setter de classe


class function GetCount: Integer;
class procedure SetCount(I: Integer);

// Getter et setter de classe virtuelle


class function GetStrProp: string; virtual;
class procedure SetStrProp(N: string); virtual;

// Classe statique
class function GetStaticCount: Integer; static;
class procedure SetStaticCount(I: Integer); static;

// Propriétés de classe
property Count: Integer read GetCount write SetCount; // Non-virtuel
property StrProp: string read GetStrProp write SetStrProp; // getters/setters virtuels
end;

// Fonction qui prend une référence de classe


function RegisterTestType(Cls: TTestClass): boolean;
Méthodes de classe en tant que méthodes statiques avec un paramètre TMetaClass* explicite
Avant C++Builder 2009, les méthodes de classe étaient représentées comme des méthodes statiques avec un paramètre
métaclasse explicite. Une métaclasse est représentée par un pointeur sur une instance de TMetaClass ou un TClass. Cette
métaclasse ou référence de classe est obtenue avec l'extension __classid qui renvoie une instance de TMetaClass* pour un
nom de classe.

Voici un exemple de cet usage, tentant de définir les mêmes méthodes et propriétés que dans l'exemple Delphi ci-dessus. Notez
que certaines fonctionnalités de méthodes de classe Delphi ne peuvent pas être réalisées correctement à l'aide de cette
approche de métaclasse.
// Tous les types métaclasse sont TMetaClass* en C++ 3
typedef TMetaClass* TTestClass;

class DELPHICLASS TTest;


class PASCALIMPLEMENTATION TTest : public System::TObject
{
typedef System::TObject inherited;
public:
// Méthodes de classe exposées comme des méthodes statiques avec
// la référence de classe 'cachée' explicite comme premier paramètre.

423
Guide du langage C++ RAD Studio 3.1 Référence C++

static int __fastcall add(TMetaClass* vmt, int I, int J);


static UnicodeString __fastcall GetClsName(TMetaClass* vmt);

// Les méthodes de classe virtuelles seraient exposées comme des méthodes virtuelles
simples
// avec la référence de classe cachée explicite comme premier paramètre.
// Cela signifie que sur l'appel de cette méthode depuis C++, il y aurait
// deux paramètres 'cachés' passés--qui ne devraient pas fonctionner.
virtual UnicodeString __fastcall GetClsNameVirt(TMetaClass* vmt);

// Les méthodes non virtuelles peuvent fonctionner. Ces deux méthodes


// sont généralement surchargées avec le premier paramètre TMetaClass*
// codé en dur dans __classid(TTest).
static int __fastcall GetCount(TMetaClass* vmt);
static void __fastcall SetCount(TMetaClass* vmt, int I);

// Vous pouvez surcharger ces setters et getters virtuels, mais étant donné
// que l'appel est incorrect, le programme échoue
// lors de l'accès à la propriété liée à ces méthodes.
virtual UnicodeString __fastcall GetStrProp(TMetaClass* vmt);
virtual void __fastcall SetStrProp(TMetaClass* vmt, UnicodeString N);

// La méthode statique de classe Delphi serait statique C++ simple.


static int __fastcall GetStaticCount();
static void __fastcall SetStaticCount(int I);

// Bien que le compilateur permet ces déclarations,


// car TMetaClass* est requis, vous obtiendrez une erreur
// du compilateur C++ sur la tentative d'accès à ces
propriétés.
__property int Count = {read=GetCount, write=SetCount, nodefault};
__property UnicodeString StrProp = {read=GetStrProp, write=SetStrProp};};

extern PACKAGE bool __fastcall RegisterTestType(TMetaClass* Cls);


Il existe plusieurs limitations avec cette façon d'exposer les méthodes de classe en utilisant un paramètre TMetaClass* explicite :

• Le code C++ ne peut pas invoquer correctement les méthodes de classe virtuelles. Les appels C++ devraient passer deux
paramètres cachés : le pointeur à l'instance de l'objet et le paramètre TMetaClass* explicite. Toutefois, la fonction attend
seulement un paramètre TMetaClass*.
• Même dans les cas où l'appel à une méthode de classe virtuelle réussit, le code C++ doit avoir une instance de l'objet pour
invoquer la méthode, mais une méthode de classe adéquate devrait être invocable sans nécessiter une instance d'objet.
• Le code C++ ne peut pas accéder convenablement aux propriétés dont les getters ou setters sont des méthodes de classe,
car il n'existe aucun moyen de fournir le paramètre TMetaClass* qui doit être explicite.
Méthodes de classe utilisant le mot clé __classmethod
C++Builder 2009 introduit les méthodes de classe qui retirent les limitations listées ci-dessus et fournissent une syntaxe plus
simple et plus intuitive pour les méthodes de classe. Les méthodes de classe sont maintenant déclarées avec le nouveau mot
clé __classmethod.

Voici comment le code ci-dessus est écrit avec la syntaxe __classmethod :


// Les références de classe utilisent toujours TMetaClass*.
3 typedef TMetaClass* TTestClass;

class DELPHICLASS TTest;


class PASCALIMPLEMENTATION TTest : public System::TObject
{
typedef System::TObject inherited;

public:
// Le paramètre TMetaClass* est maintenant caché.
// Le mot clé __classmethod marque les méthodes comme des méthodes de classe.
__classmethod int __fastcall add(int I, int J);

424
3.1 Référence C++ RAD Studio Guide du langage C++

__classmethod UnicodeString __fastcall GetClsName();

// Les méthodes virtuelles peuvent être utilisées.


__classmethod virtual UnicodeString __fastcall GetClsNameVirt();

// Les méthodes peuvent accéder aux propriétés de classe


__classmethod int __fastcall GetCount();
__classmethod void __fastcall SetCount(int I);
__classmethod virtual UnicodeString __fastcall GetStrProp();
__classmethod virtual void __fastcall SetStrProp(UnicodeString N);

// Les méthodes statiques de classe sont toujours mappées en méthodes statiques C++.
static int __fastcall GetstaticCount();
static void __fastcall SetstaticCount(int I);

// Propriétés de classe
__property int Count = {read=GetCount, write=SetCount, nodefault};
__property UnicodeString StrProp = {read=GetStrProp, write=SetStrProp};
};
C++Builder ne fournit pas un moyen de déclarer une reférence de classe autrement que par TMetaClass*. Les méthodes de
classe sont invoquées avec un nom de type ou avec une instance d'un objet. Les méthodes de classes virtuelles sont invoquées
de la même façon que les méthodes virtuelles régulières, sauf qu'au lieu d'effectuer un push du pointeur this, le pointeur
métaclasse est le paramètre caché.

Cette implémentation fournit deux capacités :

• Les méthodes de classe peuvent être virtuelles.


• Les propriétés de classe peuvent être définies.

Répartition dynamique des méthodes de classes virtuelles


Si une méthode de classe est définie avec __classmethod pour une classe dérivée d'une autre classe, vous ne pouvez pas
invoquer dynamiquement la méthode virtuelle de la classe dérivée en utilisant un nom de classe. Toutefois, vous pouvez
invoquer la méthode adéquate en utilisant une instance.

Le mécanisme "virtuel" des méthodes de classes est analogue au mécanisme "virtuel" des méthodes régulières. Pour les
méthodes régulières, vous obtenez seulement le polymorphisme lors de l'utilisation d'un pointeur ou d'une référence, car la
vtable est alors déterminée à l'exécution. Avec une instance de valeur, vous n'obtenez pas le polymorphisme car la vtable est
déterminée à la compilation.

De même, pour les méthodes de classe, vous obtenez le polymorphisme avec une instance mais pas avec un type. Pour illustrer
cela :
class TBase {
virtual __classmethod void cfunc();
virtual void vfunc();
};

class TDerived: TBase {


virtual __classmethod void cfunc();
virtual void vfunc(); 3
};

// Méthodes virtuelles régulières


TDerived d;
d.vfunc(); // appelle TDerived::vfunc;

TBase* bp = new TDerived();


bp->vfunc(); // appelle TDerived::vfunc;

TBase& br = TDerived();

425
Guide du langage C++ RAD Studio 3.1 Référence C++

br.vfunc(); // appelle TDerived::vfunc;

TBase b;
b.vfunc(); // appelle TBase::vfunc
// Méthodes virtuelles de classe
TBase* b = new TDerived();
b->cfunc(); // appelle version dans TDerived--dynamic
TDerived::cfunc(); // appelle version dans TDerived--temps de compilation--non dynamique
__classid(TDerived)->cfunc(); // erreur du compilateur

Mise à jour de votre code afin d'utiliser __classmethod


Si vous avez du code C++ qui implémente des méthodes de classe en utilisant les méthodes de classe d'ancien style avec un
paramètre Metaclass *, vous pouvez mettre à jour votre code afin d'utiliser la syntaxe __classmethod. Puisque le paramètre
TMetaClass* est maintenant caché, la signature et le substantypage de telles méthodes de classe sont différents. Le tableau
suivant illustre comment mettre à jour les constructions C++ communes en utilisant les méthodes de classe. Il utilise la méthode
add(int i, int j) et la propriété Count de l'exemple de code __classmethod ci-dessus pour illustrer les modifications que vous
devriez faire.

Objet du code Code "class static" d'ancien style Code mis à jour avec __classmethod
Déclaration de fonction class TTest : public System::TObject { public: class TTest : public System::TObject { public:
static int __fastcall add(TMetaClass* vmt, int I, int __classmethod int __fastcall add(int I, int J); };
J); };
Utilisation du __classid TTest::add(__classid(TTest), 10, 20); TTest::add(10, 20);
Utilisation du __classid TTestDerived::add(__classid(TTestDerived), 10, TTestDerived::add(10, 20);
dérivé 20);
Utilisation d'une TTest* p = new TTest(); ... TTest* p = new TTest(); ... p->add(10, 20);
instance de classe TTest::add(p->ClassType(), 10, 20);
Utilisation d'une TTest* p = new TTestDerived(); ... TTest* p = new TTestDerived(); ... p->add(10,
instance dérivée TTest::add(p->ClassType(), 10, 20); 20);
Utilisation d'une TTest* p = new TTest(); ... p->Count = 20; TTest::Count = 20; // Utilisation du nom de
propriété de classe classe // Utilisation d'une instance TTest* p =
new TTest(); ... p->Count = 20;

Voir aussi
Classes C++ ( see page 403)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Liste des membres de classe ( see page 406)

Fonctions membres ( see page 421)


3
Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

426
3.1 Référence C++ RAD Studio Guide du langage C++

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et classes dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.1.15 Propriétés statiques


Les propriétés statiques ont été implémentées dans C++Builder 2009 pour améliorer la compatibilité avec le langage Delphi

Déclaration des fonctions de classe comme statiques


Si les fonctions d'accès aux propriétés (getters et setters) sont déclarées comme statiques, vous pouvez utiliser la propriété
directement depuis la classe sans spécifier un objet. Par exemple :
class TMyClass : TComponent {
static int x;
static int GetX() { return x; }
static void SetX( int i ) { x = i; }

__property int X = { read = GetX, write = SetX }


};

TMyClass::X = 5;
int y = TMyClass::X;
Delphi permet également les méthodes statiques simples comme les getters (lecture) et les setters (écriture) de propriétés.
Notez que ces méthodes statiques ne sont pas des méthodes de classe ; il n'y a pas de paramètre caché. Par exemple :
class TTest{
static int __fastcall GetCount();
static void __fastcall SetCount(int I);
public:
__property int Count = {read=GetCount, write=SetCount};
};
Dans ce cas, vous pouvez alors utiliser les propriétés comme ceci :
int c = TTest::Count;
TTest t;
int i = t.Count;
Le compilateur C++ supporte déjà les propriétés statiques qui sont mappées en variable de membre. Par exemple :
class TEncoding {
static int Prop;
public:
__property int Count = { read=Prop };
};
int f(TEncoding& t) {
return t.Count;
}
Voir aussi
Classes C++ ( see page 403) 3
Méthodes de classe (2009)

Noms de classes ( see page 411)

Types de classes ( see page 420)

Portée du nom de classe ( see page 409)

Liste des membres de classe ( see page 406)

427
Guide du langage C++ RAD Studio 3.1 Référence C++

Fonctions membres ( see page 421)

Mot clé This ( see page 573)

Membres statiques ( see page 410)

Fonctions inline ( see page 407)

Portée des membres ( see page 416)

Types imbriqués ( see page 417)

Contrôle d'accès aux membres ( see page 415)

Accès aux classes de base et classes dérivées ( see page 413)

Classes de base virtuelles ( see page 419)

Amies de classes ( see page 404)

3.1.4.1.2 Présentation des templates de classes


Cette section présente les templates de classes.

Rubriques
Nom Description
Utilisation des crochets angulaires dans les templates ( see page 428) Faites attention à l'utilisation du crochet angulaire de droite pendant
l'instanciation :
Arguments des templates ( see page 428) Plusieurs arguments sont autorisés en tant que parties de la déclaration de la
classe template. Outre des types de données, ces arguments peuvent également
représenter des valeurs :
Templates de classes ( see page 429) Le template d'une classe (également appelé classe générique ou générateur de
classe) permet de définir le modèle des définitions de la classe. Prenons
l'exemple d'une classe vectorielle (un tableau unidimensionnel). Qu'il s'agisse
d'un vecteur d'entiers ou de tout autre type, les opérations de base effectuées
sur le type sont identiques (insertion, suppression, index, etc.). En considérant le
type d'élément comme paramètre de la classe, le système génère, à la volée, les
définitions de classe à type fiable.
Comme avec les templates de fonction, une spécialisation explicite de la classe
template peut permettre de remplacer la définition automatique d'un type
donné :... suite ( see page 429)
Suppression des pointeurs dans les templates ( see page 429) Une autre méthode consiste à inclure les objets réels, en rendant les pointeurs
inutiles. Cela permet également de réduire le nombre d'appels de fonctions
virtual requis car le compilateur connaît les types réels des objets. Cette
méthode présente un avantage supplémentaire si les fonctions virtual sont
suffisamment courtes pour être effectivement inline. Il est difficile de mettre en
ligne des fonctions virtual en les appelant avec les pointeurs car le compilateur
ne connaît pas le type réel des objets pointés.
Utilisation des listes génériques à type fiable dans les templates ( see page En général, si vous avez besoin d'écrire un grand nombre d'expressions
430) identiques, pensez aux templates. Avec la définition de classe ci-dessous (classe
de liste générique),

3.1.4.1.2.1 Utilisation des crochets angulaires dans les templates


Faites attention à l'utilisation du crochet angulaire de droite pendant l'instanciation :
3
Buffer<char, (x > 100 ? 1024 : 64)> buf;
Dans l'exemple précédent, si l'on enlève les parenthèses au deuxième argument, le > entre x et 100 referme prématurément la
liste d'arguments template.

3.1.4.1.2.2 Arguments des templates


Plusieurs arguments sont autorisés en tant que parties de la déclaration de la classe template. Outre des types de données, ces

428
3.1 Référence C++ RAD Studio Guide du langage C++

arguments peuvent également représenter des valeurs :


template<class T, int size = 64> class Buffer { ... };
A la fois les arguments qui ne représentent pas des types (comme size) et les arguments qui en représentent peuvent avoir des
valeurs implicites. La valeur d'un argument d'un template qui ne représente pas un type doit être une expression constante :
const int N = 128;
int i = 256;
Buffer<int, 2*N> b1;// OK
Buffer<float, i> b2;// Erreur : i n'est pas une constante
Comme chaque instanciation d'une classe template est en fait une classe, elle reçoit sa propre copie de membres statiques. De
même, les fonctions template obtiennent leurs propres copies de variables locales statiques.

3.1.4.1.2.3 Templates de classes


Le template d'une classe (également appelé classe générique ou générateur de classe) permet de définir le modèle des
définitions de la classe. Prenons l'exemple d'une classe vectorielle (un tableau unidimensionnel). Qu'il s'agisse d'un vecteur
d'entiers ou de tout autre type, les opérations de base effectuées sur le type sont identiques (insertion, suppression, index, etc.).
En considérant le type d'élément comme paramètre de la classe, le système génère, à la volée, les définitions de classe à type
fiable.

Comme avec les templates de fonction, une spécialisation explicite de la classe template peut permettre de remplacer la
définition automatique d'un type donné :
class Vector<char *> { ... };
Le symbole Vector doit toujours être accompagné d'un type de données entre crochets angulaires. Il ne doit pas apparaître seul,
sauf éventuellement dans la définition du template initial.

Voir aussi
Exportation et importation de templates ( see page 450)

Suppression des pointeurs dans les templates ( see page 429)

Arguments des templates ( see page 428)

3.1.4.1.2.4 Suppression des pointeurs dans les templates


Une autre méthode consiste à inclure les objets réels, en rendant les pointeurs inutiles. Cela permet également de réduire le
nombre d'appels de fonctions virtual requis car le compilateur connaît les types réels des objets. Cette méthode présente un
avantage supplémentaire si les fonctions virtual sont suffisamment courtes pour être effectivement inline. Il est difficile de mettre
en ligne des fonctions virtual en les appelant avec les pointeurs car le compilateur ne connaît pas le type réel des objets
pointés.
template <class T> aBase {
.
.
.
private:
T buffer; 3
};
class anObject : public aSubject, public aBase<aFilebuf> {
.
.
.
};
Toutes les fonctions de aBase peuvent directement appeler des fonctions définies dans aFilebuf sans passer par un pointeur. En
outre, si toute fonction aFilebuf peut être mise en ligne, vous allez améliorer la vitesse d'exécution.

429
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.1.2.5 Utilisation des listes génériques à type fiable dans les templates
En général, si vous avez besoin d'écrire un grand nombre d'expressions identiques, pensez aux templates. Avec la définition de
classe ci-dessous (classe de liste générique),
class GList
{
public:
void insert( void * );
void *peek();
.
.
.
};
Les types de listes ne sont pas fiables et les définitions de classe doivent être répétées pour les solutions standard. Comme les
types des expressions insérées ne sont pas contrôlées, vous ne pouvez pas savoir ce que vous allez obtenir. Pour résoudre ce
problème, vous pouvez écrire une classe "en boucle" :
class FooList : public GList {
public:
void insert( Foo *f ) { GList::insert( f ); }
Foo *peek() { return (Foo *)GList::peek(); }
.
.
.
};
Le type sera fiable. insert prend uniquement des arguments du type pointeur sur Foo ou objet dérivé de Foo. Le conteneur
sous-jacent contiendra donc uniquement des pointeurs désignant quelque chose de type Foo. Cela signifie que le transtypage
FooList::peek() est toujours fiable et que vous avez généré une vraie FooList. Pour procéder de même pour une BarList,
BazList, etc., vous devez répéter les définitions de classe séparément. Pour résoudre le problème des définitions de classe
répétées et pour que le type soit fiable, utilisez encore les templates. Voir l'exemple de classe de liste générique à type fiable. La
STL (Standard Template Library) C++ propose un riche ensemble de classes collection à type fiable.

En utilisant des templates, vous pouvez construire toutes les listes à type fiable que vous souhaitez avec une simple déclaration.
En outre, ces conversions de type ne génèrent pas de code ; aucun temps d'exécution n'est donc imposé par la fiabilité du type.

3.1.4.1.3 Commutateurs du compilateur relatifs aux templates


Cette section traite des commutateurs du compilateur relatifs aux templates.

Rubriques
Nom Description
Commutateurs du compilateur relatifs aux templates ( see page 431) La famille -Jg des commutateurs contrôle la manière dont les instances de
templates sont générées par le compilateur. Chaque instance de template que le
compilateur rencontre sera affectée par la valeur du commutateur à l'endroit où
la première occurrence de cette instance est vue par le compilateur.
Dans les fonctions template, le commutateur s'applique à toutes les instances de
la fonction. Dans les classes template, il s'applique à toutes les fonctions
membres et aux données membres statiques de la classe template. Dans tous
3 les cas, ce commutateur est valable uniquement pour les instances de templates
générées par le compilateur et... suite ( see page 431)

430
3.1 Référence C++ RAD Studio Guide du langage C++

Sémantique de génération des templates ( see page 431) Le compilateur C++ génère les méthodes suivantes pour les instances de
templates :

• Les méthodes effectivement utilisées


• Les méthodes virtuelles d'une instance
• Toutes les méthodes de classes explicitement instanciées
L'avantage de ce nouveau comportement aboutit à des
fichiers objets, bibliothèques et exécutables sensiblement
moins volumineux, suivant l'intensité de l'utilisation des
templates.
Vous pouvez, si vous le souhaitez, utiliser le commutateur
'-Ja' pour générer toutes les méthodes.
Vous pouvez aussi imposer la génération de toutes les
méthodes hors ligne d'une instance de template à l'aide
de la syntaxe d'instanciation de template explicite définie
par la norme ISO/ANSI C++ Standard. La syntaxe est :...
suite ( see page 431)

3.1.4.1.3.1 Commutateurs du compilateur relatifs aux templates


La famille -Jg des commutateurs contrôle la manière dont les instances de templates sont générées par le compilateur. Chaque
instance de template que le compilateur rencontre sera affectée par la valeur du commutateur à l'endroit où la première
occurrence de cette instance est vue par le compilateur.

Dans les fonctions template, le commutateur s'applique à toutes les instances de la fonction. Dans les classes template, il
s'applique à toutes les fonctions membres et aux données membres statiques de la classe template. Dans tous les cas, ce
commutateur est valable uniquement pour les instances de templates générées par le compilateur et jamais pour les instances
définies par le programmeur. Cependant, vous pouvez utiliser ce commutateur pour indiquer au compilateur les instances qui
sont définies par le programmeur de manière à ce qu'elles ne soient pas générées à partir du template.

3.1.4.1.3.2 Sémantique de génération des templates


Le compilateur C++ génère les méthodes suivantes pour les instances de templates :

• Les méthodes effectivement utilisées


• Les méthodes virtuelles d'une instance
• Toutes les méthodes de classes explicitement instanciées
L'avantage de ce nouveau comportement aboutit à des fichiers objets, bibliothèques et exécutables sensiblement moins
volumineux, suivant l'intensité de l'utilisation des templates.
Vous pouvez, si vous le souhaitez, utiliser le commutateur '-Ja' pour générer toutes les méthodes.
Vous pouvez aussi imposer la génération de toutes les méthodes hors ligne d'une instance de template à l'aide de la syntaxe
d'instanciation de template explicite définie par la norme ISO/ANSI C++ Standard. La syntaxe est :
template class nomclasse<paramètre template>;
L'exemple STL suivant amène le compilateur à générer toutes les méthodes hors ligne de la classe "list<char>", que le code 3
utilisateur y fasse ou non référence :
template class list<char>
Vous pouvez aussi instancier explicitement une seule méthode ou une donnée membre statique unique d'une classe template,
auquel cas la méthode est générée par le fichier .OBJ même si elle n'est pas utilisée :
template void nomclasse <paramètre template>:: nomméthode ();

431
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.1.4 Constructeurs et destructeurs


Cette section traite des constructeurs et destructeurs.

Rubriques
Nom Description
Introduction aux constructeurs et destructeurs ( see page 432) Il existe plusieurs fonctions membres spéciales qui permettent de créer,
initialiser, copier et détruire les objets d'une classe. Les constructeurs et les
destructeurs sont les plus importantes. Ils possèdent la plupart des
caractéristiques des fonctions membres classiques (ils sont déclarés et définis
dans la classe, ou déclarés dans la classe et définis en dehors), mais aussi
certaines particularités :

• Ils n'ont pas de valeur renvoyée (pas même void).


• Ils ne peuvent pas être hérités, bien qu'une classe dérivée
puisse appeler le constructeur et le destructeur de la
classe de base.
• Le constructeur, comme la plupart des fonctions C++,
peut avoir... suite ( see page 432)
Constructeurs ( see page 433) Cette section traite des constructeurs.
Destructeurs ( see page 439) Cette section traite des destructeurs.

3.1.4.1.4.1 Introduction aux constructeurs et destructeurs


Il existe plusieurs fonctions membres spéciales qui permettent de créer, initialiser, copier et détruire les objets d'une classe. Les
constructeurs et les destructeurs sont les plus importantes. Ils possèdent la plupart des caractéristiques des fonctions membres
classiques (ils sont déclarés et définis dans la classe, ou déclarés dans la classe et définis en dehors), mais aussi certaines
particularités :

• Ils n'ont pas de valeur renvoyée (pas même void).


• Ils ne peuvent pas être hérités, bien qu'une classe dérivée puisse appeler le constructeur et le destructeur de la classe de
base.
• Le constructeur, comme la plupart des fonctions C++, peut avoir des arguments par défaut ou utiliser une liste de valeurs
d'initialisation membre.
• Les destructeurs peuvent être virtual mais pas les constructeurs. (Voir Destructeurs virtuels.)
• Vous ne pouvez pas manipuler leurs adresses.
int main (void)
{
.
.
.
void *ptr = base::base; // illégal
.
.
.
}
3 • Les constructeurs et destructeurs peuvent être générés automatiquement par le compilateur s'ils n'ont pas été définis par le
programmeur. Ils sont aussi appelés en de nombreuses occasions sans que vous l'ayez demandé. Tout constructeur ou
destructeur généré par le compilateur est à accès public.
• Vous ne pouvez appeler un constructeur comme vous appelez une fonction standard. Vous pouvez appeler un destructeur si
vous donnez son nom qualifié complet.
{
.
.
.

432
3.1 Référence C++ RAD Studio Guide du langage C++

X *p;
.
.
.
p–>X::~X(); // appel du destructeur légal
X::X(); // appel du destructeur illégal
.
.
.
}
• Le compilateur appelle automatiquement les constructeurs et les destructeurs lors de la définition et de la suppression des
objets.
• Les constructeurs et destructeurs peuvent effectuer des appels implicites à l'opérateur new et à l'opérateur delete si une
allocation d'espace mémoire est requise pour un objet.
• Un objet muni d'un constructeur ou d'un destructeur ne peut pas être utilisé en tant que membre d'une union.
• Si aucun constructeur n'a été défini dans une classe X pour accepter un type donné, aucune tentative ne sera faite pour
trouver un autre constructeur ou une autre fonction qui convertisse la valeur affectée en un type acceptable pour un
constructeur de la classe X. Notez que cette règle ne s'applique qu'aux constructeurs à un paramètre et sans valeur
d'initialisation qui utilise la syntaxe “=”.
class X { /* ... */ X(int); };
class Y { /* ... */ Y(X); };
Y a = 1; // illégal: Y(X(1)) pas tenté
Si une class X possède un ou plusieurs constructeurs, l'un d'entre eux est appelé à chaque création d'une instance x de la
class X. Le constructeur crée l'objet x et l'initialise. Le destructeur inverse le processus en détruisant les objets classes créés
par le constructeur.

Les constructeurs sont également appelés lorsque des objets locaux ou temporaires sont créés dans une classe ; les
destructeurs sont appelés lorsque ces objets sortent de la portée.

3.1.4.1.4.2 Constructeurs
Cette section traite des constructeurs.

Rubriques
Nom Description
Initialisation de classe ( see page 434) Un objet de classe avec des membres public et aucun constructeur ni classe de
base (généralement une structure), peut être initialisé avec une liste de valeurs
d'initialisation. Si une classe a un constructeur, ses objets doivent être initialisés
ou posséder un constructeur implicite. Ce dernier est utilisé pour des objets non
initialisés explicitement par le programmeur.
Les objets des classes avec constructeurs peuvent être initialisés avec une liste
d'expressions mise entre parenthèses. La liste sert de liste d'arguments au
constructeur. Il est aussi possible d'utiliser un signe égal suivi d'une valeur
unique. Cette dernière peut être du même type que... suite ( see page 434)
Constructeur implicite ( see page 436) Le constructeur implicite de la class X est un constructeur qui n'accepte aucun
argument et dont la notation est généralement X::X(). S'il n'existe aucun
constructeur défini par l'utilisateur pour une classe, le compilateur génère un
constructeur implicite. Dans une déclaration comme X x, le constructeur implicite
crée l'objet x.
Comme toutes les fonctions, les constructeurs ont des arguments implicites. Par
exemple, le constructeur 3
Constructeurs ( see page 436) Les constructeurs se distinguent de toutes les autres fonctions membres en
ayant le même nom de la classe à laquelle ils appartiennent. Lorsqu'un objet de
classe est créé ou copié, le constructeur est appelé implicitement.
Les constructeurs des variables globales sont appelés avant la fonction main.
Les constructeurs des variables globales sont aussi appelés avant les fonctions
#pragma startup.
Des objets locaux sont créés dès lors que la portée de la variable devient active.
Un constructeur est également appelé lorsqu'un objet temporaire de la classe est
créé.

433
Guide du langage C++ RAD Studio 3.1 Référence C++

Ordre d'appel des constructeurs ( see page 437) Lorsqu'une classe a une ou plusieurs classes de base, les constructeurs des
classes de base sont appelés avant celui de la classe dérivée. Ils sont en outre
appelés dans l'ordre de leur déclaration.
Par exemple, dans la définition,
Surcharge des constructeurs ( see page 438) Il est possible de surcharger les constructeurs, ce qui permet de créer des objets
dépendant des valeurs utilisées pour l'initialisation.
Constructeur de copie ( see page 438) Un constructeur de copie de class X est un constructeur que l'on peut appeler
avec un argument unique de type X, comme suit :

3.1.4.1.4.2.1 Initialisation de classe


Un objet de classe avec des membres public et aucun constructeur ni classe de base (généralement une structure), peut être
initialisé avec une liste de valeurs d'initialisation. Si une classe a un constructeur, ses objets doivent être initialisés ou posséder
un constructeur implicite. Ce dernier est utilisé pour des objets non initialisés explicitement par le programmeur.

Les objets des classes avec constructeurs peuvent être initialisés avec une liste d'expressions mise entre parenthèses. La liste
sert de liste d'arguments au constructeur. Il est aussi possible d'utiliser un signe égal suivi d'une valeur unique. Cette dernière
peut être du même type que le premier argument accepté par un constructeur de cette classe, auquel cas soit il n'existe pas
d'autre argument, soit les arguments restants ont des valeurs implicites. La valeur unique peut aussi être un objet du même type
que la classe. Dans le premier cas, le constructeur correspondant est appelé pour créer l'objet. Dans le deuxième cas, le
constructeur copie est appelé pour initialiser l'objet.
class X
{
int i;
public:
X(); // corps de fonction omis pour plus de clarté
X(int x);
X(const X&);
};
void main()
{
X one; // le constructeur implicite est appelé
X two(1); // le constructeur X::X(int) est utilisé
X three = 1; // appelle X::X(int)
X four = one; // appelle X::X(const X&) pour copie
X five(two); // appelle X::X(const X&)
}
Le constructeur peut affecter des valeurs à ses membres de deux manières :

1. soit en acceptant les valeurs comme paramètres, et en effectuant des affectations aux variables membres dans le corps de la
fonction du constructeur :
class X
{
int a, b;
public:
X(int i, int j) { a = i; b = j }
};
2. soit en utilisant une liste de valeurs d'initialisation avant le corps de la fonction :
class X
3 {
int a, b, &c; // Notez la variable référence.
public:
X(int i, int j) : a(i), b(j), c(a) {}
};
La liste de valeurs d'initialisation est le seul endroit où référencer une variable référence.

Dans les deux cas, une initialisation de X x(1, 2) affecte la valeur 1 à x::a et 2 à x::b. La deuxième méthode (liste de valeurs
d'initialisation) permet de transmettre des valeurs aux constructeurs des classes de base.

434
3.1 Référence C++ RAD Studio Guide du langage C++

Remarque: Les constructeurs des classes de base doivent être déclarés public

ou protected pour être appelés depuis une classe dérivée.


class base1
{
int x;
public:
base1(int i) { x = i; }
};
class base2
{
int x;
public:
base2(int i) : x(i) {}
};
class top : public base1, public base2
{
int a, b;
public:
top(int i, int j) : base1(i*5), base2(j+i), a(i) { b = j;}
};
Avec cette hiérarchie de classe, une déclaration de type top one(1, 2) aboutit à l'initialisation de base1 à la valeur 5, et de base2
à la valeur 3. Il est possible de combiner les méthodes d'initialisation.

Comme nous venons de le voir, les classes de base sont initialisées dans l'ordre des déclarations. Les membres sont ensuite
initialisés, également dans l'ordre des déclarations, et indépendamment de la liste des valeurs d'initialisation.
class X
{
int a, b;
public:
X(int i, j) : a(i), b(a+j) {}
};
Avec cette classe, la déclaration X x(1,1) entraîne l'affectation de 1 à x::a et de 2 à x::b.

Les constructeurs des classes de base sont appelés avant la construction des membres des classes dérivées. Si les valeurs de
la classe dérivée sont modifiées, elles ne se répercutent pas sur la création de la classe de base.
class base
{
int x;
public:
base(int i) : x(i) {}
};
class derived : base
{
int a;
public:
derived(int i) : a(i*10), base(a) { } // Attention! Base recevra
// une ’a’ non initialisée
};
Avec cette définition de classe, un appel de la classe derived d(1) ne donnera pas la valeur 10 pour le membre x de la classe de
base. La valeur transmise au constructeur de la classe de base restera non définie. 3
Si vous voulez inclure une liste de valeurs d'initialisation dans un constructeur qui n'est pas inline, ne la placez pas dans la
définition de classe. Placez-la à l'endroit où la fonction est définie.
derived::derived(int i) : a(i)
{
.
.
.
}

435
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
Appel des destructeurs ( see page 441)

Atexit ( see page 443)

Exit et les destructeurs ( see page 440)

Abort et les destructeurs ( see page 442)

Destructeurs virtuels ( see page 441)

3.1.4.1.4.2.2 Constructeur implicite


Le constructeur implicite de la class X est un constructeur qui n'accepte aucun argument et dont la notation est généralement
X::X(). S'il n'existe aucun constructeur défini par l'utilisateur pour une classe, le compilateur génère un constructeur implicite.
Dans une déclaration comme X x, le constructeur implicite crée l'objet x.

Comme toutes les fonctions, les constructeurs ont des arguments implicites. Par exemple, le constructeur
X::X(int, int = 0)
peut prendre un ou deux arguments. Lorsqu'il est écrit avec un seul argument, le deuxième est supposé être un int nul. De
même, le constructeur
X::X(int = 5, int = 6)
pourrait prendre un ou deux arguments, ou aucun, avec des valeurs par défaut appropriées. Cependant, le constructeur implicite
X::X() n'accepte aucun argument et ne doit pas être confondu avec par exemple X::X(int = 0) qui peut être appelé sans
argument comme un constructeur implicite, ou peut prendre un argument.

Evitez toute ambiguïté lors de l'appel des constructeurs. Dans le cas suivant, les deux constructeurs implicites sont ambigus :
class X
{
public:
X();
X(int i = 0);
};
int main()
{
X one(10); // OK; utilise X::X(int)
X two; // Illégal; ambiguïté: l'appel est-il X::X()
// ou X::X(int = 0)
return 0;
}
Voir aussi
Constructeurs ( see page 436)

3.1.4.1.4.2.3 Constructeurs
Les constructeurs se distinguent de toutes les autres fonctions membres en ayant le même nom de la classe à laquelle ils
3 appartiennent. Lorsqu'un objet de classe est créé ou copié, le constructeur est appelé implicitement.

Les constructeurs des variables globales sont appelés avant la fonction main. Les constructeurs des variables globales sont
aussi appelés avant les fonctions #pragma startup.

Des objets locaux sont créés dès lors que la portée de la variable devient active. Un constructeur est également appelé
lorsqu'un objet temporaire de la classe est créé.
class X {
public:

436
3.1 Référence C++ RAD Studio Guide du langage C++

X(); // constructeur classe X


};
Un constructeur de class X ne peut pas prendre X comme argument :
class X {
public:
X(X); // illégal
};
Les paramètres associés à un constructeur peuvent être de n'importe quel type, sauf celui de la classe dont il est membre. Si le
constructeur accepte une référence à sa propre classe comme paramètre, il est dit constructeur copie. Un constructeur qui
n'accepte aucun paramètre est appelé constructeur implicite.

3.1.4.1.4.2.4 Ordre d'appel des constructeurs


Lorsqu'une classe a une ou plusieurs classes de base, les constructeurs des classes de base sont appelés avant celui de la
classe dérivée. Ils sont en outre appelés dans l'ordre de leur déclaration.

Par exemple, dans la définition,


class Y {...}
class X : public Y {...}
X one;
les constructeurs sont appelés dans l'ordre suivant :
Y(); // constructeur de la classe de base
X(); // constructeur de la classe dérivée
Dans le cas ou il y a plusieurs classes de base,
class X : public Y, public Z
X one;
les constructeurs sont appelés dans l'ordre de déclaration :
Y(); // les constructeurs des classes de base en premier
Z();
X();
Les constructeurs des classes de base virtuelles sont appelés avant toutes les autres classes de base non virtuelles. Si la
hiérarchie contient plusieurs classes de base virtuelles, leurs constructeurs sont appelés dans l'ordre des déclarations des
classes. Toute base non virtuelle est ensuite construite avant que le constructeur de classe dérivée ne soit appelé.

Si une classe virtuelle dérive d'une classe de base non virtuelle, celle-ci apparaît en premier, afin que la construction de la
classe de base virtuelle soit correcte. Par exemple, le code :
class X : public Y, virtual public Z
X one;
produit l'ordre suivant :
Z(); // initialisation de classe de base virtuelle
Y(); // classe de base non virtuelle
X(); // classe dérivée
Voici un exemple plus complexe : 3
class base;
class base2;
class level1 : public base2, virtual public base;
class level2 : public base2, virtual public base;
class toplevel : public level1, virtual public level2;
toplevel view;
L'ordre de construction de view sera le suivant :

437
Guide du langage C++ RAD Studio 3.1 Référence C++

base(); // classe de base virtuelle la plus haute dans


// la hiérarchie ; base est construite une seule fois
base2(); // base non virtuelle de base virtuelle level2
// doit être appelée pour construire level2
level2(); // classe de base virtuelle
base2(); // base non virtuelle de level1
level1(); // autre base non virtuelle
toplevel();
Lorsqu'une hiérarchie de classe contient plusieurs instances d'une classe de base virtuelle, la classe de base n'est construite
qu'une fois. Cependant, s'il existe plusieurs instances virtuelles et non virtuelles de la classe de base, le constructeur est appelé
une seule fois pour toutes les instances virtuelles, et une autre fois pour chaque occurrence non virtuelle de la classe de base.

Les constructeurs appliqués à des éléments de tableau sont appelés dans l'ordre croissant des indices.

Voir aussi
Initialisation de classe ( see page 434)

Appel des destructeurs ( see page 441)

Atexit ( see page 443)

Exit et les destructeurs ( see page 440)

Abort et les destructeurs ( see page 442)

Destructeurs virtuels ( see page 441)

3.1.4.1.4.2.5 Surcharge des constructeurs


Il est possible de surcharger les constructeurs, ce qui permet de créer des objets dépendant des valeurs utilisées pour
l'initialisation.
class X {
int integer_part;
double double_part;
public:
X(int i) { integer_part = i; }
X(double d) { double_part = d; }
};
int main()
{
X one(10); // appelle X::X(int) et fixe integer_part à 10
X one(3.14); // appelle X::X(double) en configurant double_part à 3.14
return 0;
}
Voir aussi
Initialisation de classe ( see page 434)

Appel des destructeurs ( see page 441)

Atexit ( see page 443)

3 Exit et les destructeurs ( see page 440)

Abort et les destructeurs ( see page 442)

Destructeurs virtuels ( see page 441)

3.1.4.1.4.2.6 Constructeur de copie


Un constructeur de copie de class X est un constructeur que l'on peut appeler avec un argument unique de type X, comme suit :

438
3.1 Référence C++ RAD Studio Guide du langage C++

X::X(X&)
ou
X::X(const X&)
ou
X::X(const X&, int = 0)
Les arguments implicites sont également autorisés dans un constructeur de copie. Les constructeurs copie sont appelés lors de
l'initialisation d'un objet classe, plus précisément lorsque vous déclarez l'initialisation par un autre objet classe :
X x1;
X x2 = x1;
X x3(x1);
Le compilateur génère un constructeur de copie pour class X, s'il en faut un, et si aucun n'est défini dans la class X. Le
constructeur de copie généré par le compilateur permet de commencer en toute sécurité la programmation avec des types de
données simples. Vous devez faire votre propre définition du constructeur de copie uniquement si votre programme crée des
types complexes d'agrégat, comme class, struct et les tableaux. Le constructeur de copie est également appelé lorsque un
argument d'une classe est transmis par valeur à une fonction.

Voir aussi la discussion sur l'affectation de classe membre par membre. Nous vous conseillons de définir le constructeur de
copie si vous devez surcharger l'opérateur d'affectation.

Voir aussi
Constructeur implicite ( see page 436)

Initialisation de classe ( see page 434)

Appel des destructeurs ( see page 441)

Atexit ( see page 443)

Exit et les destructeurs ( see page 440)

Abort et les destructeurs ( see page 442)

Destructeurs virtuels ( see page 441)

Exemple de surcharge des opérateurs ( see page 456)

3.1.4.1.4.3 Destructeurs
Cette section traite des destructeurs.

Rubriques
Nom Description
Destructeurs ( see page 440) Le destructeur d'une classe est appelé pour libérer les membres d'un objet avant
que celui-ci ne soit détruit. Le destructeur est une fonction membre portant le
même nom que la classe, mais précédé du signe tilde (~). Un destructeur
n'accepte pas de paramètres, pas plus qu'il n'a un type ou une valeur déclarée.
Exit et les destructeurs ( see page 440) Lorsque vous appelez exit dans un programme, les destructeurs ne sont appelés
pour aucune variable locale dans la portée en cours. Les variables globales sont 3
pour leur part détruites normalement.

439
Guide du langage C++ RAD Studio 3.1 Référence C++

Appel des destructeurs ( see page 441) Un destructeur est implicitement appelé lorsqu'une variable sort de la portée
déclarée. Les destructeurs de variables locales sont appelés lorsque le bloc où
elles sont déclarées n'est plus actif. Dans le cas de variables globales, les
destructeurs sont appelés dans le cadre de la procédure de sortie, après la
fonction main.
Lorsque des pointeurs sur des objets sortent des limites de la portée, un
destructeur n'est pas implicitement appelé. Il faut donc appeler l'opérateur delete
pour détruire l'objet.
Les destructeurs sont appelés dans l'ordre exactement inverse de celui des
constructeurs correspondants (voir Ordre d'appel des constructeurs).
Destructeurs virtuels ( see page 441) Il est possible de déclarer un destructeur virtual. Ceci autorise un pointeur sur un
objet d'une classe de base à appeler le destructeur adéquat dans le cas où ce
pointeur se réfère en réalité à un objet d'une classe dérivée. Le destructeur d'une
classe dérivée d'une classe munie d'un destructeur virtual est lui-même virtual.
Abort et les destructeurs ( see page 442) Si vous appelez abort n'importe où dans un programme, aucun destructeur n'est
appelé, pas même pour les variables globales.
Il est possible d'appeler un destructeur explicitement, ceci de deux façons :
indirectement par un appel à delete, ou directement en utilisant le nom qualifié
entier du destructeur. L'opérateur delete peut servir à détruire des objets qui ont
été alloués à l'aide de new. Les appels explicites au destructeur ne sont
nécessaires que pour des objets qui ont reçu une adresse spécifique par le biais
d'appels à new.
Atexit, #pragma Exit et les destructeurs ( see page 443) Tous les objets globaux sont actifs tant que le code au niveau des procédures de
sortie n'est pas exécuté. Les variables locales, y compris celles déclarées dans
main, sont détruites dès qu'elles sortent de la portée. L'ordre d'exécution à la fin
d'un programme est, dans ce cas, le suivant :

• Les fonctions atexit() sont exécutées dans l'ordre où elles


ont été entrées.
• Les fonctions de sortie #pragma exit sont exécutées
dans l'ordre de leurs codes de priorité.
• Les destructeurs des variables globales sont appelés.

3.1.4.1.4.3.1 Destructeurs
Le destructeur d'une classe est appelé pour libérer les membres d'un objet avant que celui-ci ne soit détruit. Le destructeur est
une fonction membre portant le même nom que la classe, mais précédé du signe tilde (~). Un destructeur n'accepte pas de
paramètres, pas plus qu'il n'a un type ou une valeur déclarée.
#include <stdlib.h>
class X
{
public:
~X(){}; // destructeur pour la classe X
};
Si un destructeur n'est pas explicitement défini pour une classe, le compilateur en génère un.

Voir aussi
Initialisation de classe ( see page 434)

Appel des destructeurs ( see page 441)

Atexit ( see page 443)


3 Exit et les destructeurs ( see page 440)

Abort et les destructeurs ( see page 442)

Destructeurs virtuels ( see page 441)

3.1.4.1.4.3.2 Exit et les destructeurs


Lorsque vous appelez exit dans un programme, les destructeurs ne sont appelés pour aucune variable locale dans la portée en

440
3.1 Référence C++ RAD Studio Guide du langage C++

cours. Les variables globales sont pour leur part détruites normalement.

Voir aussi
Initialisation de classe ( see page 434)

Appel des destructeurs ( see page 441)

Atexit ( see page 443)

Abort et les destructeurs ( see page 442)

Destructeurs virtuels ( see page 441)

3.1.4.1.4.3.3 Appel des destructeurs


Un destructeur est implicitement appelé lorsqu'une variable sort de la portée déclarée. Les destructeurs de variables locales sont
appelés lorsque le bloc où elles sont déclarées n'est plus actif. Dans le cas de variables globales, les destructeurs sont appelés
dans le cadre de la procédure de sortie, après la fonction main.

Lorsque des pointeurs sur des objets sortent des limites de la portée, un destructeur n'est pas implicitement appelé. Il faut donc
appeler l'opérateur delete pour détruire l'objet.

Les destructeurs sont appelés dans l'ordre exactement inverse de celui des constructeurs correspondants (voir Ordre d'appel
des constructeurs).

Voir aussi
Initialisation de classe ( see page 434)

Atexit ( see page 443)

Exit et les destructeurs ( see page 440)

Abort et les destructeurs ( see page 442)

Destructeurs virtuels ( see page 441)

3.1.4.1.4.3.4 Destructeurs virtuels


Il est possible de déclarer un destructeur virtual. Ceci autorise un pointeur sur un objet d'une classe de base à appeler le
destructeur adéquat dans le cas où ce pointeur se réfère en réalité à un objet d'une classe dérivée. Le destructeur d'une classe
dérivée d'une classe munie d'un destructeur virtual est lui-même virtual.
/* Comment les destructeurs virtuels affectent l'ordre d'appel des destructeurs.
Sans destructeur virtuel dans la classe de base, le destructeur de classe dérivé
ne sera pas appelé. */
#include <iostream>
class color {
public:
virtual ~color() { // destructeur virtuel
std::cout << "color dtor\n";
}
};
class red : public color { 3
public:
~red() { // Ce destructeur est aussi virtuel
std::cout << "red dtor\n";
}
};
class brightred : public red {
public:
~brightred() { // Ce destructeur est aussi virtuel
std::cout << "brightred dtor\n";

441
Guide du langage C++ RAD Studio 3.1 Référence C++

}
};
int main()
{
color *palette[3];
palette[0] = new red;
palette[1] = new brightred;
palette[2] = new color;
// Les destructeurs de red et color sont appelés
delete palette[0];
std::cout << std::endl;
// Les destructeurs de brightred, red, et color sont appelés
delete palette[1];
std::cout << std::endl;
// Le destructeur de color est appelé
delete palette[2];
return 0;
}
Sortie du programme :
red dtor
color dtor
brightred dtor
red dtor
color dtor
color dtor
Si aucun destructeur n'est déclaré virtuel, delete palette[0], delete palette[1] et delete palette[2] n'appelleront tous que le
destructeur de la classe color. Cela détruira de manière incorrecte les deux premiers éléments, qui sont en fait du type red et
brightred.

Voir aussi
Initialisation de classe ( see page 434)

Appel des destructeurs ( see page 441)

Atexit ( see page 443)

Exit et les destructeurs ( see page 440)

Abort et les destructeurs ( see page 442)

3.1.4.1.4.3.5 Abort et les destructeurs


Si vous appelez abort n'importe où dans un programme, aucun destructeur n'est appelé, pas même pour les variables globales.

Il est possible d'appeler un destructeur explicitement, ceci de deux façons : indirectement par un appel à delete, ou directement
en utilisant le nom qualifié entier du destructeur. L'opérateur delete peut servir à détruire des objets qui ont été alloués à l'aide
de new. Les appels explicites au destructeur ne sont nécessaires que pour des objets qui ont reçu une adresse spécifique par le
biais d'appels à new.
#include <stdlib.h>
class X {
3 public:
.
.
.
~X(){};
.
.
.
};
void* operator new(size_t size, void *ptr)

442
3.1 Référence C++ RAD Studio Guide du langage C++

{
return ptr;
}
char buffer[sizeof(X)];
void main()
{
X* pointer = new X;
X* exact_pointer;
exact_pointer = new(&buffer) X; // pointeur initialisé à
// l'adresse du tampon
.
.
.
delete pointer; // delete est utilisé pour détruire le pointeur
exact_pointer–>X::~X(); // appel direct pour désallouer
}
Voir aussi
Initialisation de classe ( see page 434)

Appel des destructeurs ( see page 441)

Atexit ( see page 443)

Exit et les destructeurs ( see page 440)

Destructeurs virtuels ( see page 441)

3.1.4.1.4.3.6 Atexit, #pragma Exit et les destructeurs


Tous les objets globaux sont actifs tant que le code au niveau des procédures de sortie n'est pas exécuté. Les variables locales,
y compris celles déclarées dans main, sont détruites dès qu'elles sortent de la portée. L'ordre d'exécution à la fin d'un
programme est, dans ce cas, le suivant :

• Les fonctions atexit() sont exécutées dans l'ordre où elles ont été entrées.
• Les fonctions de sortie #pragma exit sont exécutées dans l'ordre de leurs codes de priorité.
• Les destructeurs des variables globales sont appelés.
Voir aussi
Initialisation de classe ( see page 434)

Appel des destructeurs ( see page 441)

Exit et les destructeurs ( see page 440)

Abort et les destructeurs ( see page 442)

Destructeurs virtuels ( see page 441)

3.1.4.1.5 Espaces de nommage C++


Cette section contient les rubriques relatives aux espaces de nommage C++. 3
Rubriques
Nom Description
Déclaration d'un espace de nommage ( see page 444) La déclaration d'un espace de nommage original doit utiliser un identificateur qui
n'a pas été préalablement utilisé comme identificateur global.

443
Guide du langage C++ RAD Studio 3.1 Référence C++

Accès aux éléments d'un espace de nommage ( see page 445) Il y a trois manières d'accéder aux éléments d'un espace de nommage : par
qualification explicite de l'accès, en utilisant la déclaration ou la directive using.
N'oubliez pas qu'indépendamment des espaces de nommage ajoutés à la portée
locale, les identificateurs de portée globale (la portée globale n'étant qu'un autre
espace de nommage) sont toujours accessibles en utilisant l'opérateur de
résolution de portée ::.

• Qualification d'accès explicite ( see page 446)


• Directive using ( see page 446)
• Using (déclaration) ( see page 577)
Accès aux espaces de nommage dans les classes
Il n'est pas possible d'utiliser la directive using dans une
classe. Cependant, la déclaration using est permise.
Espaces de nommage anonymes ( see page 445) La grammaire C++ permet de définir des espaces de nommage anonymes. Pour
ce faire, il suffit d'utiliser le mot clé namespace sans identificateur avant
l'accolade fermante.
Définition d'un espace de nommage ( see page 445) La grammaire de la définition d'un espace de nommage est :
Qualification d'accès explicite ( see page 446) Il est possible de qualifier explicitement chaque membre d'un espace de
nommage. Pour ce faire, utilisez l'identificateur de l'espace de nommage avec
l'opérateur de résolution de portée :: suivi du nom du membre. Par exemple,
pour accéder à un membre spécifique de l'espace de nommage ALPHA, il suffit
d'écrire :
Extension d'un espace de nommage ( see page 446) Les espaces de nommage sont discontinus et ouverts à des développements
supplémentaires. Si vous redéclarez un espace de nommage, vous étendez
l'espace de nommage d'origine en lui ajoutant de nouvelles déclarations. Toute
extension faite à un espace de nommage après une déclaration using ne sera
pas connue à l'endroit où la déclaration using a lieu. Cependant, toute version
surchargée de fonctions doit être comprise dans l'espace de nommage avant de
déclarer la fonction comme utilisée.
Alias d'un espace de nommage ( see page 446) Il est possible d'utiliser un autre nom pour désigner l'identificateur de l'espace de
nommage. Un tel alias est utile pour désigner un identificateur d'espace de
nommage long.
Directive using ( see page 446) Si vous voulez utiliser certains (ou tous les) membres d'un espace de nommage,
C++ propose un moyen simple d'accéder à tout l'espace de nommage. La
directive using a pour conséquence que tous les identificateurs d'un espace de
nommage se trouvent dans la portée du point où l'instruction contenant la
directive using est exécutée. La directive using utilise la grammaire suivante.
Directive-using :
using namespace :: opt spécificateur-nom-imbriqué opt
nom-espace_de_nommage;
La directive using est transitive. Lorsque vous appliquez la directive using à un
espace de nommage contenant lui-même des directives using, vous avez
également accès à ces espaces de nommage. Si, par... suite ( see page 446)

3.1.4.1.5.1 Déclaration d'un espace de nommage


La déclaration d'un espace de nommage original doit utiliser un identificateur qui n'a pas été préalablement utilisé comme
identificateur global.
namespace alpha { /* ALPHA est l'identificateur de l'espace de nommage. */
/* déclarations du programme */
long double LD;
float f(float y) { return y; }
}
3
Un identificateur d'espace de nommage doit être connu dans toutes les unités de traduction où vous avez l'intention d'accéder à
ses éléments.

Voir aussi
Alias d'un espace de nommage ( see page 446)

444
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.1.5.2 Accès aux éléments d'un espace de nommage


Il y a trois manières d'accéder aux éléments d'un espace de nommage : par qualification explicite de l'accès, en utilisant la
déclaration ou la directive using. N'oubliez pas qu'indépendamment des espaces de nommage ajoutés à la portée locale, les
identificateurs de portée globale (la portée globale n'étant qu'un autre espace de nommage) sont toujours accessibles en
utilisant l'opérateur de résolution de portée ::.

• Qualification d'accès explicite ( see page 446)


• Directive using ( see page 446)
• Using (déclaration) ( see page 577)
Accès aux espaces de nommage dans les classes
Il n'est pas possible d'utiliser la directive using dans une classe. Cependant, la déclaration using est permise.
Voir aussi
Directive using ( see page 446)

Using (déclaration) ( see page 577)

3.1.4.1.5.3 Espaces de nommage anonymes


La grammaire C++ permet de définir des espaces de nommage anonymes. Pour ce faire, il suffit d'utiliser le mot clé namespace
sans identificateur avant l'accolade fermante.
namespace { // espace de nommage anonyme
// Déclarations
}
Tous les espaces de nommage anonymes dans la portée globale (c'est-à-dire les espaces de nommage anonymes non
imbriqués) de la même unité de traduction partagent le même espace de nommage. Il est possible de cette manière de faire des
déclarations statiques sans utiliser le mot clé static.

Chaque identificateur inclus dans un espace de nommage est unique dans l'unité de traduction dans laquelle l'espace de
nommage anonyme est défini.

3.1.4.1.5.4 Définition d'un espace de nommage


La grammaire de la définition d'un espace de nommage est :
nom-espacedenommage-origine:
identificateur
définition-espacedenommage:
définition-espacedenommage-origine
définition-espacedenommage-extension
définition-espacedenommage-sansnom
Il y a deux manières de définir un espace de nommage avec le mot clé namespace :
définition-espacedenommage-origine:
namespace identificateur { corps-espacedenommage } 3
définition-espacedenommage-extension:
namespace nom-espacedenommage-origine { corps-espacedenommage }
définition-espacedenommage-sansnom:
namespace { corps-espacedenommage }
Le corps est une séquence optionnelle de déclarations. Sa grammaire est
corps-espacedenommage:
séquence-déclaration opt

445
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
Déclaration d'un espace de nommage ( see page 444)

Extension d'un espace de nommage ( see page 446)

3.1.4.1.5.5 Qualification d'accès explicite


Il est possible de qualifier explicitement chaque membre d'un espace de nommage. Pour ce faire, utilisez l'identificateur de
l'espace de nommage avec l'opérateur de résolution de portée :: suivi du nom du membre. Par exemple, pour accéder à un
membre spécifique de l'espace de nommage ALPHA, il suffit d'écrire :
ALPHA::LD; // Accès à une variable
ALPHA::f; // Accès à une fonction
La qualification explicite d'accès peut toujours être utilisée pour résoudre des ambiguïtés. Indépendamment de l'espace de
nommage utilisé dans votre sous-système (sauf l'espace de nommage anonyme), il est possible d'appliquer l'opérateur de
résolution de portée :: pour accéder aux identificateurs de tout espace de nommage (y compris un espace de nommage utilisé
dans la portée locale) ou de l'espace de nommage global. Il est donc possible, avec une qualification adéquate, d'accéder à tout
identificateur de l'application.

Nouveau style de transtypage

Cette section présente différentes méthodes de transtypage. Les méthodes présentées ici augmentent le nombre des
expressions de transtypage (qui sont disponibles) du langage C.

Les types ne peuvent être définis lors d'un transtypage.

3.1.4.1.5.6 Extension d'un espace de nommage


Les espaces de nommage sont discontinus et ouverts à des développements supplémentaires. Si vous redéclarez un espace de
nommage, vous étendez l'espace de nommage d'origine en lui ajoutant de nouvelles déclarations. Toute extension faite à un
espace de nommage après une déclaration using ne sera pas connue à l'endroit où la déclaration using a lieu. Cependant, toute
version surchargée de fonctions doit être comprise dans l'espace de nommage avant de déclarer la fonction comme utilisée.

3.1.4.1.5.7 Alias d'un espace de nommage


Il est possible d'utiliser un autre nom pour désigner l'identificateur de l'espace de nommage. Un tel alias est utile pour désigner
un identificateur d'espace de nommage long.
namespace BORLAND_SOFTWARE_CORPORATION {
/* corps de l'espace de nommage */
namespace NESTED_BORLAND_SOFTWARE_CORPORATION {
/* corps de l'espace de nommage */
}
}
// Alias de l'espace de nommage
namespace BI = BORLAND_SOFTWARE_CORPORATION;
// Utilisation de qualificateur d'accès pour donner un alias à un espace de nommage imbriqué.
namespace NBI = BORLAND_SOFTWARE_CORPORATION::NESTED_BORLAND_SOFTWARE_CORPORATION;
3
3.1.4.1.5.8 Directive using
Si vous voulez utiliser certains (ou tous les) membres d'un espace de nommage, C++ propose un moyen simple d'accéder à tout
l'espace de nommage. La directive using a pour conséquence que tous les identificateurs d'un espace de nommage se trouvent
dans la portée du point où l'instruction contenant la directive using est exécutée. La directive using utilise la grammaire suivante.

Directive-using :

446
3.1 Référence C++ RAD Studio Guide du langage C++

using namespace :: opt spécificateur-nom-imbriqué opt nom-espace_de_nommage;

La directive using est transitive. Lorsque vous appliquez la directive using à un espace de nommage contenant lui-même des
directives using, vous avez également accès à ces espaces de nommage. Si, par exemple, vous appliquez la directive using
dans votre programme, vous obtenez également les espaces de nommage qux, foo et bar.
namespace qux {
using namespace foo; // Cela a été défini préalablement
using namespace bar; // Cela a également été défini préalablement
}
La directive using n'ajoute aucun identificateur à la portée locale. Donc, un identificateur défini dans plusieurs espaces de
nommage ne pose pas de problème sauf si vous l'utilisez. Les déclarations de portée locale ont la priorité en masquant toutes
les autres déclarations similaires.

Avertissement: N'utilisez pas de directive using

dans les fichiers en-tête. Vous risqueriez de rompre les espaces de nommage dans le code client.

Voir aussi
Accès aux éléments d'un espace de nommage ( see page 445)

Using (déclaration) ( see page 577)

3.1.4.1.6 Portée en C++


Cette section traite des portées C++.

Rubriques
Nom Description
Portée en C++ ( see page 448) Les règles lexicales de portée pour C++, à part la portée de classe, sont
identiques aux règles générales de C, à la différence que C++ autorise les
déclarations de données et de fonctions chaque fois qu'une instruction apparaît.
Cette souplesse supplémentaire demande toutefois que vous accordiez une
attention particulière à l'interprétation de phrases comme “portée extérieure” et
“point de déclaration”.
Résumé des règles de portée en C++ ( see page 448) Les règles suivantes s'appliquent à tous les noms, y compris les noms typedef
et les noms de classes, à condition que C++ accepte ces noms dans le contexte
en question :

• Le nom lui-même est testé afin de lever toute ambiguïté


éventuelle. Si aucune ambiguïté n'est détectée, la
séquence d'accès est initiée.
• S'il n'y a pas d'erreurs de contrôle d'accès, le type de
l'objet, de la fonction, de la classe, de typedef, etc. est
testé.
• Si le nom est utilisé hors d'une fonction ou d'une classe,
ou préfixé par l'opérateur unaire de résolution de portée ::,
et si le nom n'est... suite ( see page 448)

447
Guide du langage C++ RAD Studio 3.1 Référence C++

Portée de classe ( see page 449) Le nom M d'un membre de classe X a la portée classe "locale pour X" ; il n'est
utilisable que dans les situations suivantes :

• Dans les fonctions membre de X ;


• Dans des expressions comme x.M, où x est un objet de X
;
• Dans des expressions comme xptr->M, où xptr est un
pointeur sur un objet de X ;
• Dans des expressions comme X::M ou D::M, où D est une
classe dérivée de X ;
• Dans les références aval au sein de la classe dont il est
membre.
Les noms des fonctions déclarées comme amies de X, ne
sont pas des membres de... suite ( see page 449)
Masquage ( see page 449) Un nom peut être caché par une déclaration explicite du même nom dans un bloc
englobé ou dans une classe. Un membre de classe caché reste accessible à
l'aide du modificateur de portée avec un nom de classe : X::M. Un nom caché de
portée globale pour un fichier peut être référencé avec l'opérateur unaire ::, par
exemple ::g. Le nom X d'une classe peut être caché par le nom d'un objet, d'une
fonction ou d'un énumérateur déclaré dans la portée de X, indépendamment de
l'ordre dans lequel les noms sont déclarés. Cependant, le nom X caché de la
classe reste... suite ( see page 449)

3.1.4.1.6.1 Portée en C++


Les règles lexicales de portée pour C++, à part la portée de classe, sont identiques aux règles générales de C, à la différence
que C++ autorise les déclarations de données et de fonctions chaque fois qu'une instruction apparaît. Cette souplesse
supplémentaire demande toutefois que vous accordiez une attention particulière à l'interprétation de phrases comme “portée
extérieure” et “point de déclaration”.

Voir aussi
Portée de classe ( see page 449)

Masquage ( see page 449)

Résumé des règles de portée en C++ ( see page 448)

3.1.4.1.6.2 Résumé des règles de portée en C++


Les règles suivantes s'appliquent à tous les noms, y compris les noms typedef et les noms de classes, à condition que C++
accepte ces noms dans le contexte en question :

• Le nom lui-même est testé afin de lever toute ambiguïté éventuelle. Si aucune ambiguïté n'est détectée, la séquence d'accès
est initiée.
• S'il n'y a pas d'erreurs de contrôle d'accès, le type de l'objet, de la fonction, de la classe, de typedef, etc. est testé.
• Si le nom est utilisé hors d'une fonction ou d'une classe, ou préfixé par l'opérateur unaire de résolution de portée ::, et si le
nom n'est pas qualifié par l'opérateur binaire :: ou par les opérateurs de sélection de membres . et ->, il doit être un objet
3 global, une fonction ou un énumérateur.
• Si le nom apparaît sous une des formes X::n, x.n (où x est un objet de X ou une référence à X), ou ptr->n (où ptr est un
pointeur sur X), n est le nom d'un membre de X ou le membre d'une classe dont est dérivé X.
• Tout nom, non encore décrit, utilisé dans une fonction membre statique doit être déclaré dans le bloc où il apparaît ou dans
un bloc englobant, ou être un nom global. La déclaration d'un nom local n cache des déclarations de n dans des blocs
englobant et des déclarations globales de n. Les noms figurant dans des portées différentes ne sont pas surchargés.
• Tout nom, non encore décrit, utilisé dans une fonction membre non statique de classe X doit être déclaré dans le bloc où il
apparaît ou dans un bloc englobant, être membre de la classe X ou d'une classe de base de X, ou être un nom global. La

448
3.1 Référence C++ RAD Studio Guide du langage C++

déclaration d'un nom local n cache des déclarations de n dans des blocs englobant, des membres de la classe de la fonction,
et des déclarations globales de n. La déclaration d'un nom de membre cache des déclarations de même nom dans des
classes de base.
• Le nom d'un argument dans une définition de fonction est dans la portée du bloc de définition principale de la fonction. Le
nom d'un argument de fonction dans une déclaration de fonction de référence n'a pas de portée. La portée d'un argument
implicite est déterminée par le point de déclaration de cet argument, mais il n'a pas accès aux variables locales ou aux
membres de classe non statiques. Les arguments implicites sont évalués à chaque point d'appel.
• Une valeur d'initialisation de constructeur est évaluée dans la portée du bloc de définition principale de son constructeur, de
sorte qu'elle peut se référer aux noms d'arguments du constructeur.
Voir aussi
Portée en C++ ( see page 448)

Portée de classe ( see page 449)

Masquage ( see page 449)

3.1.4.1.6.3 Portée de classe


Le nom M d'un membre de classe X a la portée classe "locale pour X" ; il n'est utilisable que dans les situations suivantes :

• Dans les fonctions membre de X ;


• Dans des expressions comme x.M, où x est un objet de X ;
• Dans des expressions comme xptr->M, où xptr est un pointeur sur un objet de X ;
• Dans des expressions comme X::M ou D::M, où D est une classe dérivée de X ;
• Dans les références aval au sein de la classe dont il est membre.
Les noms des fonctions déclarées comme amies de X, ne sont pas des membres de X; leur nom définit une portée extérieure.
Voir aussi
Portée en C++ ( see page 448)

Masquage ( see page 449)

Résumé des règles de portée en C++ ( see page 448)

3.1.4.1.6.4 Masquage
Un nom peut être caché par une déclaration explicite du même nom dans un bloc englobé ou dans une classe. Un membre de
classe caché reste accessible à l'aide du modificateur de portée avec un nom de classe : X::M. Un nom caché de portée globale
pour un fichier peut être référencé avec l'opérateur unaire ::, par exemple ::g. Le nom X d'une classe peut être caché par le nom
d'un objet, d'une fonction ou d'un énumérateur déclaré dans la portée de X, indépendamment de l'ordre dans lequel les noms
sont déclarés. Cependant, le nom X caché de la classe reste accessible, il suffit de préfixer X au mot clé adéquat : class, struct
ou union.

Le point de déclaration d'un nom x figure immédiatement après sa déclaration complète, mais avant la valeur d'initialisation, s'il y
a lieu.
3
Voir aussi
Portée en C++ ( see page 448)

Portée de classe ( see page 449)

Résumé des règles de portée en C++ ( see page 448)

449
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.1.7 Exportation et importation de templates


Cette section traite de l'exportation et de l'importation des templates.

Rubriques
Nom Description
Exportation et importation de templates ( see page 450) La déclaration d'une fonction ou d'une classe template doit être suffisamment
flexible pour être utilisée dans une DLL (bibliothèque liée dynamiquement et
partagée) ou un fichier exécutable. La même déclaration de template doit être
disponible en importation comme en exportation ou sans modificateur. Pour être
complètement flexible, les déclarations de template du fichier en-tête ne doivent
pas utiliser les modificateurs __export et __import. Cela permet d'appliquer le
modificateur approprié au point d'instanciation selon la manière dont
l'instanciation va être utilisée.
Les étapes suivantes illustrent la manière d'exporter et d'importer des templates.
Le code source est organisé en trois fichiers.... suite ( see page 450)

3.1.4.1.7.1 Exportation et importation de templates


La déclaration d'une fonction ou d'une classe template doit être suffisamment flexible pour être utilisée dans une DLL
(bibliothèque liée dynamiquement et partagée) ou un fichier exécutable. La même déclaration de template doit être disponible en
importation comme en exportation ou sans modificateur. Pour être complètement flexible, les déclarations de template du fichier
en-tête ne doivent pas utiliser les modificateurs __export et __import. Cela permet d'appliquer le modificateur approprié au
point d'instanciation selon la manière dont l'instanciation va être utilisée.

Les étapes suivantes illustrent la manière d'exporter et d'importer des templates. Le code source est organisé en trois fichiers.
En utilisant le fichier en-tête, du code est généré dans la bibliothèque liée dynamiquement (DLL).

1. Déclarations de templates exportables/importables


Le fichier en-tête contient toutes les déclarations de classes et de fonctions template. Une version d'exportation/importation du
template peut être instanciée en définissant la macro appropriée au moment de la compilation.
2. Compilation de templates exportables
Ecrivez le code source d'une bibliothèque liée dynamiquement. Une fois compilée, la bibliothèque a du code d'export réutilisable
pour les templates.
3. Utilisation d'ImportTemplates
Il est maintenant possible d'écrire un appel de fonction utilisant des templates. Ce fichier exécutable est lié à la DLL. Seuls les
objets non déclarés dans le fichier en-tête qui sont instanciés dans la fonction main provoquent la génération d'un code
nouveau par le compilateur. Le code des objets nouvellement instanciés est écrit dans le fichier main.obj.

3.1.4.1.8 Présentation des templates de fonctions


Cette section présente les templates de fonctions.

Rubriques
Nom Description
Templates de fonctions ( see page 451) Considérons une fonction max(x,y) qui renvoie le plus grand de ses deux
3 arguments. x et y peuvent être de n'importe quel type et peuvent être ordonnés.
Néanmoins, comme C++ est un langage fortement typé, les types des
paramètres x et y doivent être déclarés au moment de la compilation. Si vous
n'utilisez pas de template, vous devrez avoir recours à de nombreuses versions
surchargées de max, une pour chaque type de données devant être supporté,
même si le code est identique pour chaque version. Les versions comparent les
arguments et renvoient le plus grand.
Pour contourner ce problème, vous pouvez... suite ( see page 451)
Fonctions template implicites et explicites ( see page 451) Pendant une résolution de surcharge (en suivant les étapes d'une recherche de
correspondance parfaite), le compilateur ignore les fonctions template générées
implicitement par le compilateur.

450
3.1 Référence C++ RAD Studio Guide du langage C++

Surcharge d'une fonction template ( see page 452) L'exemple précédent est appelé template de fonction (ou fonction générique).
L'instanciation spécifique d'un template de fonction est appelée fonction
template. L'instanciation d'une fonction template se produit lorsque vous prenez
l'adresse de la fonction, ou lorsque vous appelez la fonction par le biais de types
de données définis (non génériques). Pour remplacer la fonction template d'un
type spécifique par une fonction non template :

3.1.4.1.8.1 Templates de fonctions


Considérons une fonction max(x,y) qui renvoie le plus grand de ses deux arguments. x et y peuvent être de n'importe quel type
et peuvent être ordonnés. Néanmoins, comme C++ est un langage fortement typé, les types des paramètres x et y doivent être
déclarés au moment de la compilation. Si vous n'utilisez pas de template, vous devrez avoir recours à de nombreuses versions
surchargées de max, une pour chaque type de données devant être supporté, même si le code est identique pour chaque
version. Les versions comparent les arguments et renvoient le plus grand.

Pour contourner ce problème, vous pouvez utiliser la macro :


#define max(x,y) ((x > y) ? x : y)
Néanmoins, en utilisant #define, vous contournez le mécanisme de contrôle de type qui est en fait une amélioration du C++ par
rapport au C. En fait, ce cas d'utilisation de macros dans C++, est presque obsolète. Le but de max(x,y) est de comparer des
types compatibles. Malheureusement, la macro permet de comparer un int et un struct qui sont incompatibles.

En outre, avec les macros, vous risquez d'effectuer des substitutions à des endroits indésirables. En revanche, si vous utilisez
un template, vous pouvez définir une structure pour une famille de fonctions surchargées associées, en laissant le type de
données lui-même être un paramètre :
template <class T> T max(T x, T y){
return (x > y) ? x : y;
};
Le type de données est représenté par l'argument du template : <class T>. Lorsqu'il est utilisé dans une application, le
compilateur génère la fonction appropriée suivant le type de données utilisé dans l'appel :
int i;
Myclass a, b;
int j = max(i,0); // les arguments sont des entiers
Myclass m = max(a,b); // les arguments sont de type Myclass
Vous pouvez utiliser tout type de données (pas uniquement une classe) pour <class T>. Le compilateur prend soin d'appeler
l'operator>() approprié. Vous pouvez donc utiliser max avec les arguments du type pour lequel operator>() est défini.

Voir aussi
Exportation et importation de templates ( see page 450)

Fonctions template implicites et explicites ( see page 451)

3.1.4.1.8.2 Fonctions template implicites et explicites


Pendant une résolution de surcharge (en suivant les étapes d'une recherche de correspondance parfaite), le compilateur ignore
les fonctions template générées implicitement par le compilateur.
template<class T> T max(T a, T b){ 3
return (a > b) ? a : b;
}
void f(int i, char c)
{
max(i, i); // Appelle max(int ,int )
max(c, c); // Appelle max(char,char)
max(i, c); // Pas de correspondance pour max(int,char)
max(c, i); // Pas de correspondance pour max(char,int)
}

451
Guide du langage C++ RAD Studio 3.1 Référence C++

Ce code génère les messages d'erreur suivants :


Impossible de trouver la correspondance pour 'max(int,char)' dans la fonction f(int,char)
Impossible de trouver la correspondance pour 'max(char,int)' dans la fonction f(int,char)
Si l'utilisateur déclare explicitement une fonction, cette fonction participera totalement dans la résolution de surcharge. Voir
l'exemple de fonction explicite.

Lors de la recherche de paramètres de fonction template avec correspondance exacte, les conversions triviales sont
considérées comme des correspondances exactes. Voir l'exemple des conversions triviales.

Les fonctions template avec pointeur de classe dérivée ou arguments de référence sont autorisés de façon qu'elles
correspondent à leurs classes de base publiques. Voir l'exemple de référencement de classe de base.

3.1.4.1.8.3 Surcharge d'une fonction template


L'exemple précédent est appelé template de fonction (ou fonction générique). L'instanciation spécifique d'un template de
fonction est appelée fonction template. L'instanciation d'une fonction template se produit lorsque vous prenez l'adresse de la
fonction, ou lorsque vous appelez la fonction par le biais de types de données définis (non génériques). Pour remplacer la
fonction template d'un type spécifique par une fonction non template :
#include <string.h>
char *max(char *x, char *y){
return(strcmp(x,y) > 0) ? x : y;
}
Si vous appelez la fonction avec des arguments chaîne, elle sera exécutée à la place de la fonction template automatique. Dans
ce cas, vous évitez une comparaison inutile entre deux pointeurs en appelant la fonction.

Seuls les arguments triviaux sont convertis à partir de fonctions template générées par le compilateur.

Les types d'arguments d'une fonction template doivent utiliser tous les arguments formels du template. Si ce n'est pas le cas, il
est impossible d'obtenir les valeurs réelles des arguments template non utilisés en appelant la fonction.

3.1.4.1.9 Opérateurs new et delete


Cette section traite des opérateurs new et delete.

Rubriques
Nom Description
Gestion des erreurs pour l'opérateur new ( see page 453) Par défaut, new déclenche l'exception bad_alloc lorsqu'une requête d'allocation
mémoire n'est pas satisfaite.
Vous pouvez définir une fonction qui peut être appelée si l'opérateur new
échoue. Pour transmettre à l'opérateur new la fonction new-handler, utilisez
set_new_handler et donnez un pointeur sur new-handler. Si vous voulez que
new renvoie null en cas d'échec, utilisez set_new_handler(0).
Syntaxe des arguments de l'opérateur new ( see page 453) La syntaxe de new_args pour operator new( ) peut être utilisée seulement si
vous avez surchargé l'opérateur d'allocation avec les arguments appropriés.
Vous pouvez utiliser la syntaxe new_args lorsque vous voulez utiliser et réutiliser
un espace mémoire initialisé une fois au début de votre programme.
Lorsque vous surchargez operator new( ) pour spécifier l'emplacement de
l'allocation, vous êtes responsable de l'effacement de cette allocation. Comme
3 vous appelez votre version de l'opérateur d'allocation, vous ne pouvez utiliser
::operator delete( ) pour l'effacement.
Pour libérer la mémoire, effectuez un appel explicite au destructeur. Cette
méthode pour libérer la mémoire ne devrait être... suite ( see page 453)

452
3.1 Référence C++ RAD Studio Guide du langage C++

Surcharge de l'opérateur delete ( see page 454) Les opérateurs globaux ::operator delete() et ::operator delete[]() ne peuvent
pas être surchargés. Cependant, vous pouvez surcharger la version par défaut
de chacun de ces opérateurs dans votre propre implémentation. Une seule
instance de la fonction globale delete peut exister dans le programme.
L'opérateur delete défini par l'utilisateur doit avoir un type de retour void et void*
comme premier argument ; le second, facultatif, est de type size_t. Une classe T
peut définir au plus une version de chaque T::operator delete[]() et T::operator
delete(). Pour surcharger des opérateurs delete, utilisez les prototypes suivants.

• void operator delete(void... suite ( see page 454)


Surcharge de l'opérateur new ( see page 454) Les opérateurs globaux ::operator new() et ::operator new[]() peuvent être
surchargés. Chaque instance surchargée doit avoir une signature unique. C'est
pourquoi plusieurs instances d'un opérateur global d'allocation peuvent coexister
dans un programme.
Les opérateurs d'allocation de mémoire non spécifique aux classes peuvent
également être surchargés. L'opérateur new peut être implémenté pour fournir
d'autres routines de gestion de la mémoire de stockage libre (tas) ou pour
accepter des arguments supplémentaires. L'opérateur new défini par le
programmeur doit renvoyer void* et doit avoir size_t pour premier argument.
Pour surcharger des opérateurs new, utilisez les prototypes suivants :

• void * operator new(size_t... suite ( see page 454)


Opérateur delete avec les tableaux ( see page 454) Les tableaux sont supprimés par l'opérateur delete[](). Vous devez utiliser la
syntaxe delete [] expr lors de la suppression d'un tableau :
Opérateur new ( see page 455) Par défaut, s'il n'existe pas de version surchargée de new, une demande
d'allocation de mémoire dynamique utilise la version globale de new, ::operator
new(). Une demande d'allocation pour les tableaux appelle ::operator new[]().
Lorsqu'il est utilisé avec des objets classes de type name, vous pouvez définir un
opérateur spécifique name::operator new() ou name::operator new[]().
Lorsque new est appliqué aux objets classe name, il appelle l'opérateur
approprié name::operator new s'il est présent. Sinon, c'est l'opérateur global
::operator new qui est utilisé.
Seule la fonction operator new() autorise une valeur d'initialisation facultative.
La version d'allocation de... suite ( see page 455)
Opérateur new avec les tableaux ( see page 455) Lorsque vous utilisez la fiche tableau de operator new[](), le pointeur renvoyé
pointe le premier élément du tableau. Lorsque vous créez des tableaux
multidimensionnels avec new, toutes les tailles doivent être spécifiées (bien que
la première dimension ne soit pas nécessairement une constante) :

3.1.4.1.9.1 Gestion des erreurs pour l'opérateur new


Par défaut, new déclenche l'exception bad_alloc lorsqu'une requête d'allocation mémoire n'est pas satisfaite.

Vous pouvez définir une fonction qui peut être appelée si l'opérateur new échoue. Pour transmettre à l'opérateur new la fonction
new-handler, utilisez set_new_handler et donnez un pointeur sur new-handler. Si vous voulez que new renvoie null en cas
d'échec, utilisez set_new_handler(0).

Voir aussi
Le mot clé new ( see page 561)

3.1.4.1.9.2 Syntaxe des arguments de l'opérateur new


La syntaxe de new_args pour operator new( ) peut être utilisée seulement si vous avez surchargé l'opérateur d'allocation avec
les arguments appropriés. Vous pouvez utiliser la syntaxe new_args lorsque vous voulez utiliser et réutiliser un espace mémoire
initialisé une fois au début de votre programme. 3
Lorsque vous surchargez operator new( ) pour spécifier l'emplacement de l'allocation, vous êtes responsable de l'effacement de
cette allocation. Comme vous appelez votre version de l'opérateur d'allocation, vous ne pouvez utiliser ::operator delete( ) pour
l'effacement.

Pour libérer la mémoire, effectuez un appel explicite au destructeur. Cette méthode pour libérer la mémoire ne devrait être
utilisée que dans les situations particulières et avec précaution. Si un appel explicite au destructeur est effectué avant qu'un
objet construit sur la pile ait été en dehors de la portée, le destructeur sera rappelé lorsque le cadre de pile sera libéré.

453
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
Le mot clé new ( see page 561)

3.1.4.1.9.3 Surcharge de l'opérateur delete


Les opérateurs globaux ::operator delete() et ::operator delete[]() ne peuvent pas être surchargés. Cependant, vous pouvez
surcharger la version par défaut de chacun de ces opérateurs dans votre propre implémentation. Une seule instance de la
fonction globale delete peut exister dans le programme.

L'opérateur delete défini par l'utilisateur doit avoir un type de retour void et void* comme premier argument ; le second,
facultatif, est de type size_t. Une classe T peut définir au plus une version de chaque T::operator delete[]() et T::operator
delete(). Pour surcharger des opérateurs delete, utilisez les prototypes suivants.

• void operator delete(void *Type_ptr, [size_t Type_size]); // Pour non-tableaux


• void operator delete[](size_t Type_ptr, [size_t Type_size]); // Pour tableaux
Voir aussi
Le mot clé delete ( see page 552)

3.1.4.1.9.4 Surcharge de l'opérateur new


Les opérateurs globaux ::operator new() et ::operator new[]() peuvent être surchargés. Chaque instance surchargée doit avoir
une signature unique. C'est pourquoi plusieurs instances d'un opérateur global d'allocation peuvent coexister dans un
programme.

Les opérateurs d'allocation de mémoire non spécifique aux classes peuvent également être surchargés. L'opérateur new peut
être implémenté pour fournir d'autres routines de gestion de la mémoire de stockage libre (tas) ou pour accepter des arguments
supplémentaires. L'opérateur new défini par le programmeur doit renvoyer void* et doit avoir size_t pour premier argument.
Pour surcharger des opérateurs new, utilisez les prototypes suivants :

• void * operator new(size_t Type_size); // Pour non-tableaux


• void * operator new[](size_t Type_size); // Pour tableaux
Le compilateur fournit Type_size à l'opérateur new. Tous les types de données peuvent être remplacés par Type_size, sauf : les
noms de fonctions (bien qu'un pointeur de fonction soit accepté), déclarations de classes, déclarations d'énumérations, const
et volatile.
Voir aussi
Le mot clé new ( see page 561)

3.1.4.1.9.5 Opérateur delete avec les tableaux


Les tableaux sont supprimés par l'opérateur delete[](). Vous devez utiliser la syntaxe delete [] expr lors de la suppression d'un
tableau :
char * p;
3 void func()
{
p = new char[10]; // alloue 10 caractères
delete[] p; // supprime 10 caractères
}
La mention de la dimension du tableau dans l'expression delete était obligatoire pour les anciens compilateurs C++. Pour gérer
le code pré-existant, le compilateur émet un avertissement et ignore toute taille spécifiée. Si vous aviez dans l'exemple
précédent delete[10] p, vous obtiendriez à la compilation :

454
3.1 Référence C++ RAD Studio Guide du langage C++

Avertissement : Taille de tableau pour 'delete' ignorée dans fonction func()


Voir aussi
Le mot clé delete ( see page 552)

3.1.4.1.9.6 Opérateur new


Par défaut, s'il n'existe pas de version surchargée de new, une demande d'allocation de mémoire dynamique utilise la version
globale de new, ::operator new(). Une demande d'allocation pour les tableaux appelle ::operator new[](). Lorsqu'il est utilisé
avec des objets classes de type name, vous pouvez définir un opérateur spécifique name::operator new() ou name::operator
new[](). Lorsque new est appliqué aux objets classe name, il appelle l'opérateur approprié name::operator new s'il est présent.
Sinon, c'est l'opérateur global ::operator new qui est utilisé.

Seule la fonction operator new() autorise une valeur d'initialisation facultative. La version d'allocation de tableau, operator
new[](), n'accepte pas de valeurs d'initialisation. En l'absence de valeurs explicites, l'objet créé par new contient des données
non prévisibles. L'objet alloué par new, lorsqu'il ne s'agit pas d'un tableau, peut être initialisé à l'aide d'une expression entre
parenthèses :
int_ptr = new int(3);
Les tableaux de classes avec constructeurs sont initialisés avec le constructeur par défaut (voir plus loin dans ce même
chapitre). L'opérateur new défini par le programmeur avec une initialisation personnalisée joue un rôle important, au niveau des
constructeurs C++, pour les objets de type classe.

Voir aussi
Surcharge de l'opérateur new ( see page 454)

Le mot clé new ( see page 561)

3.1.4.1.9.7 Opérateur new avec les tableaux


Lorsque vous utilisez la fiche tableau de operator new[](), le pointeur renvoyé pointe le premier élément du tableau. Lorsque
vous créez des tableaux multidimensionnels avec new, toutes les tailles doivent être spécifiées (bien que la première dimension
ne soit pas nécessairement une constante) :
mat_ptr = new int[3][10][12]; // OK
mat_ptr = new int[n][10][12]; // OK
mat_ptr = new int[3][][12]; // illégal
mat_ptr = new int[][10][12]; // illégal
Bien que la première dimension puisse être une variable, toutes les suivantes doivent être des constantes.

Voir aussi
Le mot clé new ( see page 561)

3.1.4.1.10 Présentation du nouveau style de transtypage


Cette section présente le nouveau style de transtypage. 3
Rubriques
Nom Description
Nouveau style de transtypage ( see page 456) Cette section présente différentes méthodes de transtypage. Les méthodes
présentées ici augmentent le nombre des expressions de transtypage (qui sont
disponibles) du langage C.
Les types ne peuvent être définis lors d'un transtypage.

455
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.1.10.1 Nouveau style de transtypage


Cette section présente différentes méthodes de transtypage. Les méthodes présentées ici augmentent le nombre des
expressions de transtypage (qui sont disponibles) du langage C.

Les types ne peuvent être définis lors d'un transtypage.

Voir aussi
Const_cast (opérateur de transtypage) ( see page 545)

Dynamic_cast (opérateur de transtypage) ( see page 553)

Reinterpret_cast (opérateur de transtypage) ( see page 567)

static_cast (opérateur de transtypage) ( see page 570)

3.1.4.1.11 Présentation de la surcharge des opérateurs


Cette section présente la surcharge des opérateurs.

Rubriques
Nom Description
Comment construire une classe de vecteurs complexes ( see page 456) Cette section traite de la façon de construire une classe de vecteurs complexes.
Surcharge des opérateurs ( see page 458) C++ permet de redéfinir l'action de la plupart des opérateurs afin qu'ils exécutent
des fonctions spécifiées lorsqu'ils sont utilisés avec les objets d'une classe
particulière. Comme avec les fonctions surchargées de C++ en général, le
compilateur fait la distinction entre les différentes fonctions en considérant le
contexte de l'appel : le nombre et le type des arguments ou des opérandes.
Tous les opérateurs peuvent être surchargés, à l'exception de :

3.1.4.1.11.1 Comment construire une classe de vecteurs complexes


Cette section traite de la façon de construire une classe de vecteurs complexes.

Rubriques
Nom Description
Exemple de surcharge des opérateurs ( see page 456) L'exemple suivant étend la classe complex pour créer des vecteurs de type
complexe. La plupart des opérateurs les plus utiles sont surchargés pour pouvoir
donner aux opérations mathématiques personnalisées une syntaxe logique.
Voici certaines des solutions illustrées dans cet exemple :

• Le constructeur par défaut est défini. Le constructeur par


défaut n'est fourni par le compilateur que si vous ne l'avez
pas défini, lui ni un autre constructeur.
• Le constructeur copie est défini explicitement. En règle
générale, le compilateur fournit un constructeur si vous
n'en avez défini aucun. Nous vous conseillons de définir
le constructeur copie si vous devez surcharger
l'opérateur... suite ( see page 456)
3
3.1.4.1.11.1.1 Exemple de surcharge des opérateurs
L'exemple suivant étend la classe complex pour créer des vecteurs de type complexe. La plupart des opérateurs les plus utiles
sont surchargés pour pouvoir donner aux opérations mathématiques personnalisées une syntaxe logique.

Voici certaines des solutions illustrées dans cet exemple :

• Le constructeur par défaut est défini. Le constructeur par défaut n'est fourni par le compilateur que si vous ne l'avez pas
défini, lui ni un autre constructeur.

456
3.1 Référence C++ RAD Studio Guide du langage C++

• Le constructeur copie est défini explicitement. En règle générale, le compilateur fournit un constructeur si vous n'en avez
défini aucun. Nous vous conseillons de définir le constructeur copie si vous devez surcharger l'opérateur d'affectation.
• L'opérateur d'affectation est surchargé. Si vous ne le surchargez pas, le compilateur appelle un opérateur d'affectation
lorsque c'est nécessaire. En surchargeant l'affectation de types cvector, vous spécifiez précisément les actions à
entreprendre. Notez que les classes dérivées ne peuvent pas hériter de l'opérateur d'affectation.
• L'opérateur d'accès est défini comme une fonction membre (nécessaire en cas de surcharge) qui n'a qu'un seul argument. La
version const garantit que l'argument de l'appelant ne sera pas modifié (très utile lors d'une copie ou d'une affectation). Cet
opérateur doit contrôler que la valeur d'index reste dans la fourchette de valeurs (c'est le bon emplacement pour implémenter
la gestion des exceptions).
• L'opérateur d'addition est défini comme une fonction membre. Il n'autorise l'addition que pour les types cvector. L'addition doit
toujours vérifier que les tailles des opérandes sont compatibles.
• L'opérateur de multiplication est déclaré comme friend. Cela permet de définir l'ordre des opérandes. Si vous tentez
d'inverser l'ordre des opérandes, une erreur de compilation se produit.
• L'opérateur d'insertion de flux est surchargé pour afficher un cvector. Les grands objets qui ne s'affichent pas correctement
dans un écran de taille limitée nécessitent une stratégie d'affichage différente.
Exemple de source
/* COMMENT ETENDRE LA CLASSE complex ET SURCHARGER LES OPERATEURS REQUIS */ */
complexcomplexcomplex
#include <complex> // Cela inclut iostream
using namespace std;
// VECTEURS COMPLEXES
template <class T>
class cvector {
int size;
complex<T> *data;
public:
cvector() { size = 0; data = NULL; };
cvector(int i = 5) : size(i) { // TAILLE DU VECTEUR PAR DEFAUT.
data = new complex<T>[size];
for (int j = 0; j < size; j++)
data[j] = j + (0.1 * j); // INITIALISATION ARBITRAIRE.
};
/* CETTE VERSION EST APPELEE DANS main() */
complex<T>& operator [](int i) { return data[i]; };
/* CETTE VERSION EST APPELEE DANS L'OPERATEUR D'AFFECTATION ET COPIE LE CONSTRUCTEUR */
const complex<T>& operator [](int i) const { return data[i]; };
cvector operator +(cvector& A) { // OPERATEUR D'ADDITION
cvector result(A.size); // NE MODIFIE PAS L'ORIGINAL
for (int i = 0; i < size; i++)
result[i] = data[i] + A.data[i];
return result;
};
/* LA MULTIPLICATION scalar * vector N'ETANT PAS COMMUTATIVE, L'ORDRE
DES ELEMENTS DOIT ETRE SPECIFIE. LA FONCTION OPERATEUR AMIE REND FIABLE
LE PROCEDE DE MULTIPLICATION. */
friend cvector operator *(T scalar, cvector& A) {
cvector result(A.size); // NE MODIFIE PAS L'ORIGINAL
for (int i = 0; i < A.size; i++)
result.data[i] = scalar * A.data[i];
return result;
} 3
/* L'OPERATEUR D'INSERTION DE FLUX */
friend ostream& operator <<(ostream& out_data, cvector& C) {
for (int i = 0; i < C.size; i++)
out_data << "[" << i << "]=" << C.data[i] << " ";
cout << endl;
return out_data;
};
cvector( const cvector &C ) { // CONSTRUCTEUR DE COPIE
size = C.size;

457
Guide du langage C++ RAD Studio 3.1 Référence C++

data = new complex<T>[size];


for (int i = 0; i < size; i++)
data[i] = C[i];
}
cvector& operator =(const cvector &C) { // OPERATEUR D'AFFECTATION.
if (this == &C) return *this;
delete[] data;
size = C.size;
data = new complex<T>[size];
for (int i = 0; i < size; i++)
data[i] = C[i];
return *this;
};
virtual ~cvector() { delete[] data; }; // DESTRUCTEUR
};
int main(void) { /* QUELQUES OPERATIONS AVEC LES VECTEURS complex. */
cvector<float> cvector1(4), cvector2(4), result(4);
// CREE DES VALEURS complex ET LES AFFECTE AUX VECTEURS complex
cvector1[3] = complex<float>(3.3, 102.8);
cout << "Voici cvector1 :" << endl;
cout << cvector1;
cvector2[3] = complex<float>(33.3, 81);
cout << "Voici cvector2 :" << endl;
cout << cvector2;
result = cvector1 + cvector2;
cout << "Résultat de l'addition des vecteurs :" << endl;
cout << result;
result = 10 * cvector2;
cout << "Résultat de 10 * cvector2 :" << endl;
cout << result;
return 0;
}
Sortie
Voici cvector1 :
[0]=(0, 0) [1]=(1.1, 0) [2]=(2.2, 0) [3]=(3.3, 102.8)
Voici cvector2 :
[0]=(0, 0) [1]=(1.1, 0) [2]=(2.2, 0) [3]=(33.3, 81)
Résultat de l'addition des vecteurs :
[0]=(0, 0) [1]=(2.2, 0) [2]=(4.4, 0) [3]=(36.6, 183.8)
Résultat de 10 * cvector2 :
[0]=(0, 0) [1]=(11, 0) [2]=(22, 0) [3]=(333, 810)

3.1.4.1.11.2 Surcharge des opérateurs


C++ permet de redéfinir l'action de la plupart des opérateurs afin qu'ils exécutent des fonctions spécifiées lorsqu'ils sont utilisés
avec les objets d'une classe particulière. Comme avec les fonctions surchargées de C++ en général, le compilateur fait la
distinction entre les différentes fonctions en considérant le contexte de l'appel : le nombre et le type des arguments ou des
opérandes.

Tous les opérateurs peuvent être surchargés, à l'exception de :


. .* :: ?:

3 Les symboles du préprocesseur suivants ne peuvent être surchargés.


# ##
Les opérateurs =, [ ], ( ), et -> ne peuvent être surchargés qu'en tant que fonctions membres non statiques. Ils ne peuvent pas
être surchargés pour les types enum. Si vous tentez de surcharger la version globale de ces opérateurs, une erreur se produit à
la compilation.

Le mot clé operator suivi du symbole d'opérateur est appelé nom de fonction opérateur. Il est utilisé comme un nom de fonction
normal lorsque vous définissez la nouvelle action (surchargée) de l'opérateur.

458
3.1 Référence C++ RAD Studio Guide du langage C++

Un opérateur de fonction appelé avec des arguments se comporte comme un opérateur appliqué aux opérandes d'une
expression. La fonction opérateur ne modifie pas le nombre des arguments ni les règles de priorité et d'associativité qui
s'appliquent aux opérateurs normaux.

Voir aussi
Exemple de surcharge des opérateurs ( see page 456)

Opérateurs surchargés et héritage ( see page 462)

Surcharge des opérateurs binaires ( see page 460)

Surcharge des fonctions opérateurs ( see page 461)

Surcharge de l'opérateur d'affectation = ( see page 459)

Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)

Surcharge de l'opérateur d'appel de fonction ( ) ( see page 461)

Surcharge de l'opérateur d'accès [ ] ( see page 462)

3.1.4.1.12 Présentation de la surcharge des fonctions opérateurs


Cette section présente la surcharge des fonctions opérateurs.

Rubriques
Nom Description
Surcharge de l'opérateur d'affectation = ( see page 459) L'opérateur d'affectation =() ne peut être surchargé que par déclaration d'une
fonction membre non statique. Par exemple,
Surcharge des opérateurs binaires ( see page 460) Vous pouvez surcharger un opérateur binaire en déclarant une fonction membre
non statique acceptant un argument, ou en déclarant une fonction non membre
(généralement friend) prenant deux arguments. Si @ représente un opérateur
binaire, x@y est interprétable soit comme x.operator@(y) soit comme
operator@(x,y), selon les déclarations. Si les deux formes ont été déclarées, il y
a mise en correspondance avec l'argument standard pour résoudre l'ambiguïté.
Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460) Syntaxe
Surcharge de l'opérateur d'appel de fonction ( ) ( see page 461) Syntaxe
Surcharge des fonctions opérateurs ( see page 461) Les fonctions opérateurs peuvent être appelées directement, bien qu'en général
elles le soient indirectement par le biais de l'opérateur de surcharge :
Opérateurs surchargés et héritage ( see page 462) A l'exception de la fonction d'affectation operator=( ), toutes les fonctions à
opérateurs surchargés d'une classe X sont transmises par héritage aux classes
dérivées de X, avec les règles de résolution standard pour les fonctions
surchargées. Si X est une classe de base pour Y, une fonction à opérateur
surchargé pour X peut éventuellement être surchargée pour Y.
Surcharge de l'opérateur d'accès [ ] ( see page 462) Syntaxe
Surcharge des opérateurs unaires ( see page 463) Vous pouvez surcharger un opérateur unaire préfixe ou suffixe en déclarant une
fonction membre non statique n'acceptant aucun argument, ou en déclarant une
fonction non membre prenant un argument. Si @ représente un opérateur
unaire, @x et x@ peuvent tous les deux être interprétés comme x.operator@ ()
ou operator@(x), selon les déclarations. Si les deux formes ont été déclarées, il y
a mise en correspondance avec l'argument standard pour résoudre l'ambiguïté.

• Pour les versions inférieures à C++ 2.0, une surcharge de


l'opérateur ++ ou – est utilisée comme suffixe ou préfixe 3
de l'opérateur.
• En C++ 2.1, lorsqu'un operator++ ou operator--... suite (
see page 463)

3.1.4.1.12.1 Surcharge de l'opérateur d'affectation =


L'opérateur d'affectation =() ne peut être surchargé que par déclaration d'une fonction membre non statique. Par exemple,

459
Guide du langage C++ RAD Studio 3.1 Référence C++

class String {
.
.
.
String& operator = (String& str);
.
.
.
String (String&);
~String();
}
Ce code, avec les définitions adaptées de String::operator=(), permet des affectations str1 = str2, comme dans tous les autres
langages. Contrairement aux autres fonctions opérateur, la fonction opérateur d'affectation ne peut pas se transmettre aux
classes dérivées. Si pour une classe X le programme n'a pas défini d'opérateur =, celui-ci sera défini par défaut comme
l'affectation membre par membre des membres de la classe X :
X& X::operator = (const X& source)
{
// affectation au niveau des membres
}
Voir aussi
Exemple de surcharge des opérateurs ( see page 456)

Opérateurs surchargés et héritage ( see page 462)

Surcharge des opérateurs binaires ( see page 460)

Surcharge des fonctions opérateurs ( see page 461)

Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)

Surcharge de l'opérateur d'appel de fonction ( ) ( see page 461)

Surcharge de l'opérateur d'accès [ ] ( see page 462)

3.1.4.1.12.2 Surcharge des opérateurs binaires


Vous pouvez surcharger un opérateur binaire en déclarant une fonction membre non statique acceptant un argument, ou en
déclarant une fonction non membre (généralement friend) prenant deux arguments. Si @ représente un opérateur binaire, x@y
est interprétable soit comme x.operator@(y) soit comme operator@(x,y), selon les déclarations. Si les deux formes ont été
déclarées, il y a mise en correspondance avec l'argument standard pour résoudre l'ambiguïté.

Voir aussi
Exemple de surcharge des opérateurs ( see page 456)

Opérateurs surchargés et héritage ( see page 462)

Surcharge des fonctions opérateurs ( see page 461)

Surcharge de l'opérateur d'affectation = ( see page 459)

3 Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)

Surcharge de l'opérateur d'appel de fonction ( ) ( see page 461)

Surcharge de l'opérateur d'accès [ ] ( see page 462)

3.1.4.1.12.3 Surcharge de l'opérateur d'accès aux membres de classe ->


Syntaxe

460
3.1 Référence C++ RAD Studio Guide du langage C++

expression-postfixée -> expression-primaire


Description

L'expression x->m, où x est un objet de class X, est interprété comme (x.operator->())->m, de sorte que la fonction operator->()
doit renvoyer soit un pointeur sur un objet de la classe, soit un objet d'une classe pour laquelle operator-> est défini.

La fonction operator->() ne peut être surchargée que dans une fonction membre non statique.

Voir aussi
Exemple de surcharge des opérateurs ( see page 456)

Opérateurs surchargés et héritage ( see page 462)

Surcharge des opérateurs binaires ( see page 460)

Surcharge des fonctions opérateurs ( see page 461)

Surcharge de l'opérateur d'affectation = ( see page 459)

Surcharge de l'opérateur d'appel de fonction ( ) ( see page 461)

Surcharge de l'opérateur d'accès [ ] ( see page 462)

3.1.4.1.12.4 Surcharge de l'opérateur d'appel de fonction ( )


Syntaxe
expression-postfixée ( <liste-expressions> )
Description

Dans son utilisation normale comme appel de fonction, expression-postfixée doit être un nom de fonction ou un pointeur ou une
référence de fonction. Si expression-postfixée est utilisé pour appeler une fonction membre, ce doit être un nom de fonction
membre de classe ou une expression pointeur de membre utilisée pour sélectionner une fonction membre de classe. Dans les
deux cas, expression-postfixée est suivie par une liste facultative d'expressions.

L'appel de X(arg1, arg2), où X est un objet de la classe X, est interprété comme X.operator()(arg1, arg2).

L'opérateur d'appel de fonction, operator()(), ne peut être surchargé que dans une fonction membre non-statique.

Voir aussi
Exemple de surcharge des opérateurs ( see page 456)

Opérateurs surchargés et héritage ( see page 462)

Surcharge des opérateurs binaires ( see page 460)

Surcharge des fonctions opérateurs ( see page 461)

Surcharge de l'opérateur d'affectation = ( see page 459)

Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)

Surcharge de l'opérateur d'accès [ ] ( see page 462) 3

3.1.4.1.12.5 Surcharge des fonctions opérateurs


Les fonctions opérateurs peuvent être appelées directement, bien qu'en général elles le soient indirectement par le biais de
l'opérateur de surcharge :
c3 = c1.operator + (c2); // même chose que c3 = c1 + c2
Excepté new et delete, qui ont leurs propres règles, une fonction opérateur doit être une fonction membre non statique, ou avoir

461
Guide du langage C++ RAD Studio 3.1 Référence C++

au moins un argument du type classe. Les fonctions opérateurs =, ( ), [ ] et -> doivent être des fonctions membres non statiques.

Les énumérations peuvent être des opérateurs surchargés. Toutefois, les fonctions opérateurs =, ( ), [ ] et -> ne peuvent être
surchargés pour des énumérations.

Voir aussi
Exemple de surcharge des opérateurs ( see page 456)

Opérateurs surchargés et héritage ( see page 462)

Surcharge des opérateurs binaires ( see page 460)

Surcharge de l'opérateur d'affectation = ( see page 459)

Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)

Surcharge de l'opérateur d'appel de fonction ( ) ( see page 461)

Surcharge de l'opérateur d'accès [ ] ( see page 462)

3.1.4.1.12.6 Opérateurs surchargés et héritage


A l'exception de la fonction d'affectation operator=( ), toutes les fonctions à opérateurs surchargés d'une classe X sont
transmises par héritage aux classes dérivées de X, avec les règles de résolution standard pour les fonctions surchargées. Si X
est une classe de base pour Y, une fonction à opérateur surchargé pour X peut éventuellement être surchargée pour Y.

Voir aussi
Exemple de surcharge des opérateurs ( see page 456)

Surcharge des opérateurs binaires ( see page 460)

Surcharge des fonctions opérateurs ( see page 461)

Surcharge de l'opérateur d'affectation = ( see page 459)

Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)

Surcharge de l'opérateur d'appel de fonction ( ) ( see page 461)

Surcharge de l'opérateur d'accès [ ] ( see page 462)

3.1.4.1.12.7 Surcharge de l'opérateur d'accès [ ]


Syntaxe
expression-postfixée [ expression ]
Description

La fonction opérateur correspondante est operator[]() ; elle peut être définie par le programmeur pour une classe X (et toutes ses
classes dérivées) en terme de fonction membre non statique. L'expression X[y], où X est un objet de la classe X, est interprétée
comme x.operator[](y).
3
La fonction operator[]() ne peut être surchargée que dans une fonction membre non statique.

Voir aussi
Exemple de surcharge des opérateurs ( see page 456)

Opérateurs surchargés et héritage ( see page 462)

Surcharge des opérateurs binaires ( see page 460)

Surcharge des fonctions opérateurs ( see page 461)

462
3.1 Référence C++ RAD Studio Guide du langage C++

Surcharge de l'opérateur d'affectation = ( see page 459)

Surcharge de l'opérateur d'appel de fonction ( ) ( see page 461)

Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)

3.1.4.1.12.8 Surcharge des opérateurs unaires


Vous pouvez surcharger un opérateur unaire préfixe ou suffixe en déclarant une fonction membre non statique n'acceptant
aucun argument, ou en déclarant une fonction non membre prenant un argument. Si @ représente un opérateur unaire, @x et
x@ peuvent tous les deux être interprétés comme x.operator@ () ou operator@(x), selon les déclarations. Si les deux formes ont
été déclarées, il y a mise en correspondance avec l'argument standard pour résoudre l'ambiguïté.

• Pour les versions inférieures à C++ 2.0, une surcharge de l'opérateur ++ ou – est utilisée comme suffixe ou préfixe de
l'opérateur.
• En C++ 2.1, lorsqu'un operator++ ou operator-- est déclaré fonction membre sans paramètres, ou fonction non membre avec
un seul paramètre, il surcharge uniquement l'opérateur préfixe ++ ou --. Vous ne pouvez surcharger un opérateur suffixe ++
ou -- qu'en le définissant comme fonction membre prenant un paramètre int ou comme fonction non membre avec une classe
et un paramètre int.
Lorsque seule la version préfixe d'un opérateur ++ ou - - est surchargée et que l'opérateur est appliqué à un objet de classe
comme opérateur suffixe, le compilateur émet un avertissement. Puis, il appelle l'opérateur préfixe en permettant au code 2.0
de compiler. L'exemple précédent émet les avertissements suivants :
Avertissement : Opérateur préfixe surchargé 'operator ++' utilisé comme opérateur suffixe dans
la fonction func()
Avertissement : Opérateur préfixe surchargé 'operator --' utilisé comme opérateur suffixe dans
la fonction func()
Voir aussi
Exemple de surcharge des opérateurs ( see page 456)

Opérateurs surchargés et héritage ( see page 462)

Surcharge des opérateurs binaires ( see page 460)

Surcharge des fonctions opérateurs ( see page 461)

Surcharge de l'opérateur d'affectation = ( see page 459)

Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)

Surcharge de l'opérateur d'appel de fonction ( ) ( see page 461)

Surcharge de l'opérateur d'accès [ ] ( see page 462)

3.1.4.1.13 Classes polymorphes


Cette section traite des classes polymorphes.

Rubriques
Nom Description 3
Classes abstraites ( see page 464) Cette section traite des classes abstraites.
Classes polymorphes ( see page 465) Les classes polymorphes sont celles dont l'implémentation sert différentes
configurations tout en produisant une même interface. Une classe est
polymorphe lorsqu'elle déclare une fonction virtuelle (ou virtuelle pure) au moins,
ou lorsqu'elle en hérite. Les seuls types qui supportent le polymorphisme sont
class et struct.
Fonctions virtuelles ( see page 465) Cette section traite des fonctions virtuelles.

463
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.1.13.1 Classes abstraites


Cette section traite des classes abstraites.

Rubriques
Nom Description
Classes abstraites ( see page 464) Une classe abstraite est une classe ayant au moins une fonction virtual pure.
Une fonction virtual est spécifiée comme étant pure en lui attribuant la valeur
zéro.
Une classe abstraite n'est utilisable que comme classe de base pour d'autres
classes. Aucun objet de classe abstraite ne peut être créé. Une classe abstraite
ne s'utilise pas comme type d'argument ni comme type de renvoi de fonction.
Cependant, vous pouvez déclarer des pointeurs sur une classe abstraite. Des
références à une classe abstraite sont également permises, à condition qu'un
objet temporaire ne soit pas requis lors de l'initialisation. Par exemple,

3.1.4.1.13.1.1 Classes abstraites


Une classe abstraite est une classe ayant au moins une fonction virtual pure. Une fonction virtual est spécifiée comme étant
pure en lui attribuant la valeur zéro.

Une classe abstraite n'est utilisable que comme classe de base pour d'autres classes. Aucun objet de classe abstraite ne peut
être créé. Une classe abstraite ne s'utilise pas comme type d'argument ni comme type de renvoi de fonction. Cependant, vous
pouvez déclarer des pointeurs sur une classe abstraite. Des références à une classe abstraite sont également permises, à
condition qu'un objet temporaire ne soit pas requis lors de l'initialisation. Par exemple,
class shape { // classe abstraite
point center;
.
.
.
public:
where() { return center; }
move(point p) { center = p; draw(); }
virtual void rotate(int) = 0; // fonction virtuelle pure
virtual void draw() = 0; // fonction virtuelle pure
virtual void hilite() = 0; // fonction virtuelle pure
.
.
.
}
shape x;// ERREUR : essai de création d'un objet d'une classe abstraite
shape* sptr;// pointeur sur classe abstraite : OK
shape f();// ERREUR : une classe abstraite ne peut pas être renvoyée comme type
int g(shape s);// ERREUR : une classe abstraite ne peut être le type d'un argument d'une
fonction
shape& h(shape&);// référence à une classe abstraite comme valeur
// de renvoi ou argument de fonction : OK
Supposons que D soit une classe dérivée avec la classe abstraite B comme classe de base immédiate. Pour chaque fonction
virtuelle pure pvf dans B, D doit soit contenir une définition pour pvf, soit déclarer pvf comme étant pure.

Par exemple, l'utilisation de la classe shape déjà citée :


3
class circle : public shape {// circle dérivé de la classe abstraite
int radius;// private
public:
void rotate(int) { }// fonction virtuelle définie : pas d'action
// pour faire pivoter le cercle
void draw(); // circle::draw doit être définie quelque part
}
Les fonctions membres peuvent être appelées depuis un constructeur de classe abstraite, mais l'appel d'une fonction virtuelle
pure, directement ou indirectement, depuis ce constructeur entraîne une erreur au moment de l'exécution

464
3.1 Référence C++ RAD Studio Guide du langage C++

Voir aussi
Classes polymorphes ( see page 465)

Fonctions virtuelles ( see page 467)

Fonctions dynamiques ( see page 465)

3.1.4.1.13.2 Classes polymorphes


Les classes polymorphes sont celles dont l'implémentation sert différentes configurations tout en produisant une même interface.
Une classe est polymorphe lorsqu'elle déclare une fonction virtuelle (ou virtuelle pure) au moins, ou lorsqu'elle en hérite. Les
seuls types qui supportent le polymorphisme sont class et struct.

Voir aussi
Fonctions virtuelles ( see page 467)

Fonctions dynamiques ( see page 465)

Classes abstraites ( see page 464)

3.1.4.1.13.3 Fonctions virtuelles


Cette section traite des fonctions virtuelles.

Rubriques
Nom Description
Fonctions dynamiques ( see page 465) Les fonctions dynamic sont autorisées pour les classes dérivées de TObject.
Les fonctions dynamiques s'apparentent aux fonctions virtuelles sauf dans leur
stockage dans les tables virtuelles. Les fonctions virtuelles occupent un
emplacement dans la table virtuelle, dans l'objet dans lequel elles sont définies et
dans la table virtuelle de chaque descendant de cet objet. Les fonctions
dynamiques occupent un emplacement dans chaque objet qui les définit, pas
dans les descendants. En d'autres termes, les fonctions dynamiques sont des
fonctions virtuelles stockées dans des tables virtuelles éparses. Si vous appelez
une fonction dynamique qui n'est pas définie dans votre objet, les... suite ( see
page 465)
Fonctions virtuelles ( see page 467) Les fonctions virtual permettent aux classes dérivées de mettre en place
différentes versions d'une fonction de classe de base. Vous pouvez utiliser le mot
clé virtual pour déclarer une fonction virtual dans une classe de base : en
déclarant le prototype de fonction de manière habituelle et en préfixant la
déclaration du mot clé virtual. Pour déclarer une fonction pure (qui déclare
automatiquement une classe abstraite), vous devez préfixer le prototype du mot
clé virtual, et définir la fonction égale à zéro.

3.1.4.1.13.3.1 Fonctions dynamiques


Les fonctions dynamic sont autorisées pour les classes dérivées de TObject. Les fonctions dynamiques s'apparentent aux
fonctions virtuelles sauf dans leur stockage dans les tables virtuelles. Les fonctions virtuelles occupent un emplacement dans la
table virtuelle, dans l'objet dans lequel elles sont définies et dans la table virtuelle de chaque descendant de cet objet. Les
fonctions dynamiques occupent un emplacement dans chaque objet qui les définit, pas dans les descendants. En d'autres
termes, les fonctions dynamiques sont des fonctions virtuelles stockées dans des tables virtuelles éparses. Si vous appelez une 3
fonction dynamique qui n'est pas définie dans votre objet, les tables virtuelles de ses ancêtres sont parcourues jusqu'à ce que la
fonction soit trouvée.

En conséquence, les fonctions dynamiques réduisent la taille de vos tables virtuelles au prix d'un délai à l'exécution
correspondant à la recherche de l'adresse des fonctions.

Comme les fonctions dynamiques ne sont disponibles que dans les classes dérivées à partir de TObject, vous obtenez un
message d'erreur si vous les utilisez dans une classe normale. Par exemple :

465
Guide du langage C++ RAD Studio 3.1 Référence C++

class dynfunc {
int __declspec(dynamic) bar() { return 5; }
};
donne un message d'erreur syntaxique spécifiant que la classe de stockage 'dynamic' n'est pas autorisée. Mais le code suivant
se compile.
#include <clxvcl.h>
#include <stdio.h>
class __declspec(delphiclass) func1 : public TObject {
public:
func1() {}
int virtual virtbar() { return 5; }
int __declspec(dynamic) dynbar() { return 5; }
};
class __declspec(delphiclass) func2 : public func1 {
public:
func2() {}
};
class __declspec(delphiclass) func3 : public func2 {
public:
func3() {}
int virtbar() { return 10; }
int dynbar() { return 10; }
};
int main()
{
func3 * Func3 = new func3;
func1 * Func1 = Func3;
printf("func3->dynbar: %d\n", Func3->dynbar());
printf("func3->virtbar: %d\n", Func3->virtbar());
printf("func1->dynbar: %d\n", Func1->dynbar());
printf("func1->virtbar: %d\n", Func1->virtbar());
delete Func3;
func2 * Func2 = new func2;
printf("func2->dynbar: %d\n", Func2->dynbar());
printf("func2->virtbar: %d\n", Func2->virtbar());
delete Func2;
return 0;
}
L'attribut dynamic est hérité

Puisque les fonctions dynamiques sont comme les fonctions virtuelles, l'attribut dynamic est automatiquement hérité. Vous
pouvez vérifier cela en exécutant l'exemple précédent. Lorsque vous générez une sortie assembleur avec "bcc32 -S", vous
pouvez examiner les tables virtuelles de func1, func2 et func3, et constater que func2 n'a pas d'entrée pour dynbar, mais qu'elle
en a une pour virtbar. Vous pouvez cependant appeler dynbar dans l'objet func2 :

Sortie :
func3->dynbar: 10
func3->virtbar: 10
func1->dynbar: 10
func1->virtbar: 10
func2->dynbar: 5
func2->virtbar: 5
3
Les fonctions dynamiques ne peuvent pas devenir virtuelles (et vice-versa)

Vous ne pouvez pas redéclarer une fonction virtuelle en dynamique, de même que vous ne pouvez pas redéclarer une fonction
dynamique en virtuelle. L'exemple suivant génère des messages d'erreur :
#include <clxvcl.h>
#include <stdio.h>
class __declspec(delphiclass) foo1 : public TObject {
public:

466
3.1 Référence C++ RAD Studio Guide du langage C++

foo1() {}
int virtual virtbar() { return 5; }
int __declspec(dynamic) dynbar() { return 5; }
};
class __declspec(delphiclass) foo2 : public foo1 {
public:
foo2() {}
int __declspec(dynamic) virtbar() { return 10; }
int virtual dynbar() { return 10; }
};
Erreur : Impossible de remplacer une fonction virtuelle par une fonction dynamique
Erreur : Impossible de remplacer une fonction dynamique par une fonction virtuelle
Voir aussi
Classes polymorphes ( see page 465)

Fonctions virtuelles ( see page 467)

Fonctions dynamiques

Classes abstraites ( see page 464)

3.1.4.1.13.3.2 Fonctions virtuelles


Les fonctions virtual permettent aux classes dérivées de mettre en place différentes versions d'une fonction de classe de base.
Vous pouvez utiliser le mot clé virtual pour déclarer une fonction virtual dans une classe de base : en déclarant le prototype de
fonction de manière habituelle et en préfixant la déclaration du mot clé virtual. Pour déclarer une fonction pure (qui déclare
automatiquement une classe abstraite), vous devez préfixer le prototype du mot clé virtual, et définir la fonction égale à zéro.
virtual int funct1(void); // déclaration de fonction virtuelle
virtual int funct2(void) = 0; // déclaration de fonction pure
Une déclaration de fonction ne peut pas fournir à la fois une définition et un spécificateur pur.

Exemple :
struct C {
virtual void f() { } = 0; // incorrect
};
La seule syntaxe légale permettant de fournir un corps est :
struct TheClass
{
virtual void funct3(void) = 0;
};
virtual void TheClass::funct3(void)
{
// Il y a du code ici
};
Remarque: Voir Classes abstraites pour de plus amples informations sur les fonctions virtuelles pures.

Lorsque vous définissez des fonctions virtual, gardez à l'esprit les indications suivantes :

• Elles ne peuvent être que des fonctions membres. 3


• Elles peuvent être déclarées comme friend d'une autre classe.
• Elles ne peuvent pas être un membre statique.
Vous n'avez pas à redéfinir une fonction virtual dans une classe dérivée. Vous pouvez fournir une définition dans la classe de
base de façon que tous les appels accèdent à la fonction de base.
Pour redéfinir une fonction virtual dans une classe dérivée, le nombre et le type d'arguments doivent être identiques dans la
déclaration de la classe de base et dans celle de la classe dérivée. Les fonctions virtual redéfinies dont seul le type des
valeurs renvoyées est différent sont traitées plus loin. Une fonction redéfinie remplace la fonction de la classe de base.

467
Guide du langage C++ RAD Studio 3.1 Référence C++

Vous pouvez aussi déclarer les fonctions int Base::Fun(int) et int Derived::Fun(int) même quand elles ne sont pas virtual. Dans
ce cas, on dit que int Derived::Fun(int) cache toutes les autres versions de Fun(int) existant dans n'importe quelle classe de
base. En outre, si une classe dérivée définit d'autres versions de Fun() (c'est-à-dire des versions de Fun() portant des
signatures différentes), celles-ci sont dites surchargées.
Types de valeurs renvoyées par les fonctions virtuelles
En règle générale, lorsque vous redéfinissez une fonction virtual, vous ne pouvez pas modifier seulement le type de valeur
renvoyée. Lors de la redéfinition d'une fonction virtual, la nouvelle définition (dans certaines classes dérivées) doit
correspondre exactement au type de renvoi et aux paramètres formels de la déclaration initiale. Si deux fonctions portant le
même nom ont des paramètres formels différents, C++ les considère comme différentes et passe outre le mécanisme de
fonction virtual.
En revanche, certaines fonctions virtuelles d'une classe de base ont une version de redéfinition dans une classe dérivée dont le
type des valeurs renvoyées est différent de la fonction redéfinie. Cela est possible uniquement lorsque les deux conditions
suivantes sont respectées :
• La fonction virtual remplacée renvoie un pointeur ou une référence de la classe de base.
• La fonction de redéfinition renvoie un pointeur ou une référence de la classe dérivée.
Supposons une classe de base B contenant une fonction virtual vf, et la classe D dérivée de B contenant une fonction vf du
même type ; si vf est appelée pour un objet d de D, l'appel est D::vf(), même si l'accès se fait par un pointeur ou une
référence à B. Par exemple,
struct X {};// Classe de base
struct Y : X {};// Classe dérivée
struct B {
virtual void vf1();
virtual void vf2();
virtual void vf3();
void f();
virtual X* pf();// Le type renvoyé est un pointeur sur base
// Cela peut être redéfini
};
class D : public B {
public:
virtual void vf1();// Spécificateur virtuel légal mais redondant
void vf2(int);// Pas de spécificateur virtuel, puisqu'une autre liste
// d'arguments est utilisée Cela cache B::vf2()
// char vf3();// Illégal: seul le type de renvoi change
void f();
Y* pf();// La fonction redéfinie diffère seulement
// par le type renvoyé. Elle renvoie un pointeur sur
// la classe dérivée
};
void extf()
{
D d;// Instancie un objet D
B* bp = &d;// Conversion standard de D* vers B*
// Initialise bp avec la table de fonctions fournie
// pour l'objet d. S'il n'existe aucune entrée
// dans la table d pour une fonction a,
// utilisez la fonction dans la table B
bp–>vf1(); // Appelle D::vf1
bp–>vf2(); // Appelle B::vf2 puisque D's vf2 a des arguments différents
bp–>f(); // Appelle B::f (non virtuelle)
3 X* xptr = bp–>pf();// Appelle D::pf() et convertit le résultat
// en un pointeur sur X
D* dptr = &d;
Y* yptr = dptr–>pf();// Appelle D::pf() et initialise yptr
// Aucune autre conversion n'est faite
}
La fonction de redéfinition vf1 dans D est automatiquement virtual. Le spécificateur virtual est utilisable avec une déclaration de
fonction de redéfinition dans la classe dérivée. Si d'autres classes doivent être dérivées de D, le mot clé virtual est obligatoire.
Si aucune autre classe ne doit être dérivée de D, l'emploi de virtual est redondant.

468
3.1 Référence C++ RAD Studio Guide du langage C++

L'interprétation d'un appel de fonction virtual dépend du type de l'objet pour lequel il y a appel ; avec des appels de fonctions
non virtuelles, l'interprétation dépend uniquement du type du pointeur ou de la référence désignant l'objet concerné par l'appel.

Les fonctions virtual exigent le prix de leur polyvalence : chaque objet de la classe dérivée possède un pointeur sur une table de
fonctions pour permettre la sélection de la fonction adéquate au moment de l'exécution (liaison en temps réel)..

Voir aussi
Classes polymorphes ( see page 465)

Fonctions dynamiques ( see page 465)

Classes abstraites ( see page 464)

3.1.4.1.14 Référencement
Cette section traite de l'opérateur typeid.

Rubriques
Nom Description
Arguments de référence ( see page 469) Le déclarateur de référence peut également être utilisé pour déclarer des
paramètres de type référence dans une fonction :
Référencement ( see page 470) En langage de programmation C, les arguments peuvent être passés
uniquement par valeur. En C++, ce passage peut s'effectuer aussi bien par
valeur que par référence. Les types de référence en C++ sont très proches des
types de pointeur. Ils créent des alias pour des objets. Les rubriques suivantes
décrivent le référencement.
Remarque: Le référencement et le déréférencement de pointeurs C++
spécifiques sont présentés dans Opérateurs spécifiques du C++ ( see page
594).
Références simples ( see page 471) Le déclarateur de référence sert à déclarer des références en dehors des
fonctions :

3.1.4.1.14.1 Arguments de référence


Le déclarateur de référence peut également être utilisé pour déclarer des paramètres de type référence dans une fonction :
void func1 (int i);
void func2 (int &ir); // ir est du type "référence à int"
.
.
.
int sum = 3;
func1(sum); // somme transmise par valeur
func2(sum); // somme transmise par référence
L'argument sum transmis par référence est modifiable directement par func2. En revanche, func1 fournit une copie de l'argument
sum (passé par valeur), de sorte que somme elle-même ne peut pas être modifiée par func1.

Lorsqu'un argument réel x est transmis par valeur, l'argument formel correspondant dans la fonction reçoit une copie de x. Toute
modification de cette copie dans le corps de la fonction n'est pas répercutée sur la valeur de x en dehors de la portée de la
fonction. Naturellement, la fonction peut renvoyer une valeur qui sera ultérieurement utilisable pour modifier x, mais elle ne peut
pas directement changer un paramètre passé par valeur. 3
En C, la modification de la valeur d'un paramètre d'une fonction en dehors de la portée de celle-ci suppose que vous
transmettiez l'adresse du paramètre. Celle-ci est transmise par valeur, si bien que la modification du contenu de l'adresse affecte
la valeur du paramètre en dehors de la portée de la fonction.

Même si la fonction n'a pas besoin de changer la valeur d'un paramètre, il demeure utile de transmettre l'adresse (ou une
référence) à une fonction. Cela est notamment le cas si le paramètre est une structure de données ou un objet volumineux. La
transmission d'un objet directement à une fonction nécessite de copier la totalité de l'objet.

469
Guide du langage C++ RAD Studio 3.1 Référence C++

Comparez les trois implémentations de la fonction treble :

Implémentation 1
int treble_1(int n)
{
return 3 * n;
}
.
.
.
int x, i = 4;
x = treble_1(i); // à présent x = 12, i = 4
.
.
.
Implémentation 2
void treble_2(int* np)
{
*np = (*np) * 3;
}
.
.
.
treble_2(&i); // à présent i = 2
Implémentation 3
void treble_3(int& n) // n est un type référence
{
n = n * 3;
}
.
.
.
treble_3(i); // à présent i = 36
La déclaration de l'argument formel type& t établit t comme type de "référence à type". Ainsi, lorsque treble_3 est appelé avec
l'argument réel i, i est utilisé pour initialiser l'argument formel de référence n. n constitue donc un alias de i, de sorte que n = n*3;
affecte aussi 3 * i à i.

Si la valeur d'initialisation est une constante ou un objet d'un autre type que référence, C++ crée un objet provisoire pour lequel
la référence joue le rôle d'alias :
int& ir = 6; /* l'objet int provisoire créé, avec pour alias ir, prend la valeur 6*/
float f;
int& ir2 = f; /* crée un objet int provisoire avec ir2 pour alias ; f est converti
avant affectation */
ir2 = 2.0 // à présent ir2 = 2, mais f ne change pas
La création automatique d'objets temporaires permet la conversion de types références lorsque les arguments réels et formels
ont des types différents mais compatibles pour l'affectation. Lors du passage par valeur, naturellement, quelques problèmes de
conversion se manifestent puisque la copie de l'argument réel peut être physiquement modifiée avant affectation à l'argument
formel.
3
Voir aussi
Référencement ( see page 470)

Références simples ( see page 471)

3.1.4.1.14.2 Référencement
En langage de programmation C, les arguments peuvent être passés uniquement par valeur. En C++, ce passage peut

470
3.1 Référence C++ RAD Studio Guide du langage C++

s'effectuer aussi bien par valeur que par référence. Les types de référence en C++ sont très proches des types de pointeur. Ils
créent des alias pour des objets. Les rubriques suivantes décrivent le référencement.

Remarque: Le référencement et le déréférencement de pointeurs C++ spécifiques sont présentés dans Opérateurs spécifiques
du C++ ( see page 594).

Voir aussi
Références simples ( see page 471)

Arguments de référence ( see page 469)

Opérateurs de référencement / déréférencement ( see page 663)

3.1.4.1.14.3 Références simples


Le déclarateur de référence sert à déclarer des références en dehors des fonctions :
int i = 0;
int &ir = i; // ir est un alias pour i
ir = 2; // même effet que i = 2
Cela crée la lvalue ir comme un alias pour i, à condition que la valeur d'initialisation ait le même type que la référence. Toutes les
opérations sur ir ont exactement les mêmes conséquences que des opérations sur i. Par exemple, ir = 2 affecte la valeur 2 à i, et
&ir renvoie l'adresse de i.

Voir aussi
Référencement ( see page 470)

Arguments de référence ( see page 469)

3.1.4.1.15 Identification de type à l'exécution (RTTI)


Cette section traite de l'identification des types au moment de l'exécution (Run-Time Type Identification, RTTI).

Rubriques
Nom Description
Identification de type à l'exécution (RTTI) ( see page 471) L'ajout de l'identification du type à l'exécution (RTTI) rend possible l'écriture de
code portable pouvant déterminer le véritable type d'un objet de données au
moment de l'exécution, même si ce code ne peut accéder qu'à un pointeur ou
qu'à une référence de l'objet en question. Par exemple, il est désormais possible
de convertir un pointeur sur une classe de base virtuelle en pointeur sur un type
dérivé du véritable objet. Consultez la description de l'opérateur dynamic_cast
qui utilise les informations de type obtenues à l'exécution.
Le mécanisme RTTI permet également de vérifier de quel type est un objet, ou
si... suite ( see page 471)
Opérateur typeid ( see page 472) Cette section traite de l'opérateur typeid.

3.1.4.1.15.1 Identification de type à l'exécution (RTTI)


L'ajout de l'identification du type à l'exécution (RTTI) rend possible l'écriture de code portable pouvant déterminer le véritable
type d'un objet de données au moment de l'exécution, même si ce code ne peut accéder qu'à un pointeur ou qu'à une référence 3
de l'objet en question. Par exemple, il est désormais possible de convertir un pointeur sur une classe de base virtuelle en
pointeur sur un type dérivé du véritable objet. Consultez la description de l'opérateur dynamic_cast qui utilise les informations de
type obtenues à l'exécution.

Le mécanisme RTTI permet également de vérifier de quel type est un objet, ou si deux objets sont du même type. L'opérateur
qui permet cela est typeid : il détermine le véritable type des arguments de l'objet, et renvoie une référence à un objet de type
const type_info, qui décrit ce type.

471
Guide du langage C++ RAD Studio 3.1 Référence C++

Vous pouvez aussi utiliser un nom de type comme argument de typeid, et typeid vous renverra un objet const type_info pour
ce type. La classe type_info contient un operator== et un operator!=, qui serviront à déterminer si deux objets sont du même
type. La classe type_info fournit aussi une fonction membre name qui renvoie un pointeur sur une chaîne de caractères
contenant le nom du type.

Voir aussi
__rtti ( see page 534)

Opérateur typeid ( see page 575)

3.1.4.1.15.2 Opérateur typeid


Cette section traite de l'opérateur typeid.

Rubriques
Nom Description
Identification de type à l'exécution et destructeurs ( see page 472) Si l'option de nettoyage du destructeur est active, un pointeur de classe ayant un
destructeur virtuel ne peut être détruit si la classe n'est pas compilée avec
l'identification de type à l'exécution active. Les options d'identification de type à
l'exécution et de nettoyage du destructeur sont activées par défaut. Elles peuvent
être désactivées à partir de la page C++ de la boîte de dialogue Options du
projet, ou en utilisant les options de ligne de commande -xd- et -RT-.
Exemple

3.1.4.1.15.2.1 Identification de type à l'exécution et destructeurs


Si l'option de nettoyage du destructeur est active, un pointeur de classe ayant un destructeur virtuel ne peut être détruit si la
classe n'est pas compilée avec l'identification de type à l'exécution active. Les options d'identification de type à l'exécution et de
nettoyage du destructeur sont activées par défaut. Elles peuvent être désactivées à partir de la page C++ de la boîte de dialogue
Options du projet, ou en utilisant les options de ligne de commande -xd- et -RT-.

Exemple
class Alpha {
public:
virtual ~Alpha( ) { }
};
void func( Alpha *Aptr ) {
delete Aptr; // Erreur. Alpha n'est pas un type de classe polymorphe
}

3.1.4.1.16 Opérateur de résolution de portée


Cette section traite de l'opérateur de résolution de portée.

Rubriques
Nom Description
Opérateur de résolution de portée :: ( see page 472) L'opérateur d'accès (ou de résolution) de portée :: (deux signes : accolés)
permet d'accéder à un nom global (qui a la durée de vie d'un fichier) même s'il
est caché par une redéclaration locale. Il est possible d'utiliser un identificateur
3 global en le préfixant de l'opérateur de résolution de portée. L'accès à un nom de
membre imbriqué se fait en spécifiant la classe et en utilisant l'opérateur de
résolution de portée. De plus, Alpha::func( ) et Beta::func( ) sont deux fonctions
différentes.

3.1.4.1.16.1 Opérateur de résolution de portée ::


L'opérateur d'accès (ou de résolution) de portée :: (deux signes : accolés) permet d'accéder à un nom global (qui a la durée de
vie d'un fichier) même s'il est caché par une redéclaration locale. Il est possible d'utiliser un identificateur global en le préfixant
de l'opérateur de résolution de portée. L'accès à un nom de membre imbriqué se fait en spécifiant la classe et en utilisant

472
3.1 Référence C++ RAD Studio Guide du langage C++

l'opérateur de résolution de portée. De plus, Alpha::func( ) et Beta::func( ) sont deux fonctions différentes.

3.1.4.1.17 Compilateur C++ plus strict (C++Builder 2007)


Pour une meilleure conformité aux règles du standard C++ ANSI, le compilateur C++ livré avec C++Builder 2007 est plus strict
que les versions précédentes. Le code qui ne générait pas d'erreurs dans les versions précédentes de C++Builder peut
provoquer des erreurs de compilation avec C++Builder 2007.

Cette section répertorie certaines zones où le compilateur est plus strict. Chaque cas est illustré par un exemple présentant le
problème et montrant comment mettre à jour le code afin d'obtenir une compilation correcte avec C++Builder 2007. Notez qu'il
existe souvent plusieurs façons de mettre à jour le code incorrect. La méthode adéquate dépend de l'objectif du code d'origine.

Rubriques
Nom Description
Compilateur C++ plus strict : Liaison des références et des qualificateurs ( see De nombreuses constructions génèrent maintenant des messages d'erreur
page 474) provenant du compilateur CodeGear C++ inclus avec C++Builder 2007 et les
nouvelles releases. Les règles régissant ce comportement sont décrites à la
section 8.5.3 du C++ ANSI standard 2003.
Les règles peuvent être réparties dans les catégories suivantes (avec le
commutateur du compilateur qui outrepasse ce comportement) :

• Liaison d'une lvalue non-const à une référence non-const.


Utilisez le commutateur -Vbr du compilateur pour
autoriser cela.
• Liaison d'un temporaire à une référence non-const.
Utilisez le commutateur -Vbr du compilateur pour
autoriser cela.
• Liaison d'objets const ou volatiles respectivement à des
méthodes non-const ou non-volatiles.... suite ( see page
474)
Compilateur C++ plus strict : Les littéraux chaîne sont maintenant des constantes Les littéraux chaîne sont à présent considérés comme étant par défaut de type
( see page 475) 'const char[]'. Cela, combiné à la liaison de qualification plus stricte des types et
valeurs const, peut générer des messages d'erreur dans du code compilé
auparavant.
Vous pouvez activer le commutateur -Vbs pour rétablir les littéraux chaîne en
non-const. Toutefois, CodeGear recommande plutôt la mise à jour du code.
Sachez que la modification du type des littéraux chaîne peut également changer
la façon dont le compilateur résoud les appels aux méthodes surchargées. Cela
est illustré par l'exemple suivant :
Compilateur C++ plus strict : Modifications des templates ( see page 476) Le compilateur C++ n'autorise plus un template explicite sans le préfixe 'template
<>'. Utilisez le commutateur -Vbe du compilateur pour autoriser cela. Cela est
illustré par l'exemple suivant :
Compilateur C++ plus strict : Résolution des surcharges de fonction ( see page L'une des zones où le compilateur C++Builder 2007 diffère le plus des versions
476) précédentes est la résolution des surcharges, qui inclut la détection des
ambiguïtés. Le compilateur se conforme à présent mieux aux règles de la section
13.3 du standard C++ ANSI 2003. Plusieurs constructions qui étaient auparavant
autorisées peuvent maintenant être signalées comme ambiguës ou sans
correspondance, ce qui nécessite la modification du code afin de clarifier son
objectif.
L'option -Vbo du compilateur rétablit l'ancien comportement, sans imposer le
nouveau comportement plus strict. Toutefois, les changements du compilateur ne
peuvent pas tous être contrôlés par ce commutateur. CodeGear recommande...
suite ( see page 476) 3

473
Guide du langage C++ RAD Studio 3.1 Référence C++

Compilateur C++ plus strict : Initialisation et conversion ( see page 477) Le compilateur se conforme à présent aux règles des sections 8.5.1 et 13.3.1 du
standard C++ ANSI 2003 pour l'initialisation et la conversion :

• L'initialisation directe nécessite maintenant l'initialisation


par un constructeur et ne prend plus une séquence de
conversion utilisateur.
• L'initialisation de la copie pour les objets de même type ou
de type dérivé nécessite maintenant un appel du
constructeur.
• L'initialisation de la copie pour les objets de types
différents ne préfère plus la conversion utilisateur à la
construction. Si le compilateur trouve une conversion
utilisateur appropriée, il continue maintenant à rechercher
(ambiguïté possible) des constructeurs de conversion.
Si... suite ( see page 477)

3.1.4.1.17.1 Compilateur C++ plus strict : Liaison des références et des qualificateurs
De nombreuses constructions génèrent maintenant des messages d'erreur provenant du compilateur CodeGear C++ inclus avec
C++Builder 2007 et les nouvelles releases. Les règles régissant ce comportement sont décrites à la section 8.5.3 du C++ ANSI
standard 2003.

Les règles peuvent être réparties dans les catégories suivantes (avec le commutateur du compilateur qui outrepasse ce
comportement) :

• Liaison d'une lvalue non-const à une référence non-const. Utilisez le commutateur -Vbr du compilateur pour autoriser cela.
• Liaison d'un temporaire à une référence non-const. Utilisez le commutateur -Vbr du compilateur pour autoriser cela.
• Liaison d'objets const ou volatiles respectivement à des méthodes non-const ou non-volatiles. Utilisez le commutateur -Vbn
du compilateur pour autoriser cela.
Les versions précédentes des compilateurs C++ autorisaient les formes diverses de liaison à des paramètres de référence
non-const. Dans l'exemple suivant, par exemple, le transtypage simple du paramètre psize était autorisé :
int takesLongRef(long& l);

int takesUnsignedPtr(unsigned long* psize) {

return takesLongRef((long)*psize);
}
Avec C++Builder2007, le code ci-dessus génère les erreurs suivantes :
Erreur E2357 test.cpp 3: Référence initialisée avec 'long', nécessite lvalue de type 'long'
dans la fonction takesUnsignedPtr(unsigned long *)
Erreur E2342 test.cpp 3: Non concordance de type dans le paramètre 'l' ('long &' voulu, 'long'
obtenu) dans la fonction takesUnsignedPtr(unsigned long *)
Pour y remédier, vous pouvez transtyper psize avant le déréférencement, comme dans :
int takesLongRef(long& l);
int takesUnsignedPtr(unsigned long* psize) { return takesLongRef(*reinterpret_cast
<long*>(psize)); }
3
Prenez conscience des cas impliquant des temporaires d'une façon imprévisible. Par exemple, certains opérateurs binaires
impliquent un temporaire :
enum { zero, one, two } num;
num |= two; // Not allowed
num = num | two; // OK
Un autre cas impliquant des temporaires d'une façon imprévisible est la valeur de retour d'une propriété. L'exemple suivant
illustre un code compilé avec les versions précédentes du compilateur :

474
3.1 Référence C++ RAD Studio Guide du langage C++

#include <vcl.h>

class TTest {
WideString FData ;
public:
__property WideString Data = {read = FData };
};

void Func(WideString& wref);

void test() {
TTest t;
Func(t.Data);
}
Avec C++Builder 2007, le code ci-dessus génère deux erreurs :
Erreur E2357 test.cpp 14: Référence initialisée avec 'const WideString', nécessite lvalue de
type 'WideString' dans la fonction test()
Erreur E2342 test.cpp 14: Non concordance de type dans le paramètre 'wref' ('WideString &'
voulu, 'WideString' obtenu) dans la fonction test()
Vous pouvez corriger cela en changeant la référence en une référence const, comme dans :
void Func(const WideString& wref);

Voici un exemple de tentative de liaison d'un objet const sur une méthode non-const :
struct X {
void foo();
};
const X x;
x.foo(); //erreur
Dialogue Erreur et conciliation : Résolution des problèmes
Le problème des temporaires et références cité ci-dessus est rencontré dans le code généré par les versions précédentes de
l'expert Dialogue Erreur et conciliation.

Pour remédier à cela, recherchez la méthode VarToAnsiStr :


AnsiString VarToAnsiStr (Variant &V TFieldType DataType)
et modifiez-la afin qu'elle prenne un const Variant&, comme dans :
AnsiString VarToAnsiStr (const Variant &V, TFieldType DataType)
Voir aussi
Compilateur C++ plus strict (C++Builder 2007) ( see page 473)

Les littéraux chaîne sont maintenant des constantes ( see page 475)

Modifications des templates ( see page 476)

Résolution des surcharges de fonction ( see page 476)

Initialisation et conversion ( see page 477)


3
3.1.4.1.17.2 Compilateur C++ plus strict : Les littéraux chaîne sont maintenant des
constantes
Les littéraux chaîne sont à présent considérés comme étant par défaut de type 'const char[]'. Cela, combiné à la liaison de
qualification plus stricte des types et valeurs const, peut générer des messages d'erreur dans du code compilé auparavant.

Vous pouvez activer le commutateur -Vbs pour rétablir les littéraux chaîne en non-const. Toutefois, CodeGear recommande
plutôt la mise à jour du code.

475
Guide du langage C++ RAD Studio 3.1 Référence C++

Sachez que la modification du type des littéraux chaîne peut également changer la façon dont le compilateur résoud les appels
aux méthodes surchargées. Cela est illustré par l'exemple suivant :
void foo(char *);
void foo(const char *);
foo("string"); // Le nouveau compilateur choisit foo(const char *)
Avec C++Builder2007, le code ci-dessus génère les erreurs suivantes :

Voir aussi
Liaison des références et des qualificateurs ( see page 474)

Modifications des templates ( see page 476)

Résolution des surcharges de fonction ( see page 476)

Initialisation et conversion ( see page 477)

3.1.4.1.17.3 Compilateur C++ plus strict : Modifications des templates


Le compilateur C++ n'autorise plus un template explicite sans le préfixe 'template <>'. Utilisez le commutateur -Vbe du
compilateur pour autoriser cela. Cela est illustré par l'exemple suivant :
template <class>
class foo {
foo();
};
foo<int>::foo();//Erreur
template<> foo<int>::foo();//OK
De même, le compilateur C++ n'autorise plus une spécialisation de template explicite dans une classe. Utilisez le commutateur
-Vbx du compilateur pour autoriser cela. Par exemple, le code suivant génère une erreur :
struct S {};
struct SP
{
template <typename> void foo(const T &) {}
template <> void foo(const S &) {} // Erreur
};

template <> void SP::foo(const S &) {} //OK


Voir aussi
Compilateur C++ plus strict (C++Builder 2007) ( see page 473)

Liaison des références et des qualificateurs ( see page 474)

Les littéraux chaîne sont maintenant des constantes ( see page 475)

Résolution des surcharges de fonction ( see page 476)

Initialisation et conversion ( see page 477)

3 3.1.4.1.17.4 Compilateur C++ plus strict : Résolution des surcharges de fonction


L'une des zones où le compilateur C++Builder 2007 diffère le plus des versions précédentes est la résolution des surcharges,
qui inclut la détection des ambiguïtés. Le compilateur se conforme à présent mieux aux règles de la section 13.3 du standard
C++ ANSI 2003. Plusieurs constructions qui étaient auparavant autorisées peuvent maintenant être signalées comme ambiguës
ou sans correspondance, ce qui nécessite la modification du code afin de clarifier son objectif.

L'option -Vbo du compilateur rétablit l'ancien comportement, sans imposer le nouveau comportement plus strict. Toutefois, les
changements du compilateur ne peuvent pas tous être contrôlés par ce commutateur. CodeGear recommande ainsi la mise à

476
3.1 Référence C++ RAD Studio Guide du langage C++

jour du code.

Voici un exemple d'une ambiguïté qui était autorisée par le compilateur précédent :
class X{};
void foo(X);
void foo(const X&);
void ambig() {
X x;
foo(x); //erreur-ambiguïté-le compilateur précédent choisissait 'void foo(x)'
}
Ambiguïté std::abs
La fonction abs standard peut également générer un message ambigu lorsqu'elle est invoquée avec un paramètre qui ne
correspond pas exactement aux types attendus par les diverses versions surchargées de abs. En voici un exemple :
#include <limits>bool test(long l) { return std::abs(l)> 0;}
Le code ci-dessus génère une erreur et un avertissement :
Erreur E2015 test.cpp 5: Ambiguïté entre 'std::abs(int) à C:\dev\tp\sc\include\math.h:208' et
'std::abs(long double) à C:\dev\tp\sc\include\math.h:275' dans la fonction test(long)
Avertissement W8057 test.cpp 6: Paramètre 'l' jamais utilisé dans la fonction test(long)
Pour corriger cela, transtypez vers le type de la surcharge que vous voulez invoquer. Par exemple :
#include <limits>bool test(long l) { return std::abs(static_cast<int>(l)) > 0;}
Voir aussi
Compilateur C++ plus strict (C++Builder 2007) ( see page 473)

Liaison des références et des qualificateurs ( see page 474)

Les littéraux chaîne sont maintenant des constantes ( see page 475)

Modifications des templates ( see page 476)

Initialisation et conversion ( see page 477)

3.1.4.1.17.5 Compilateur C++ plus strict : Initialisation et conversion


Le compilateur se conforme à présent aux règles des sections 8.5.1 et 13.3.1 du standard C++ ANSI 2003 pour l'initialisation et
la conversion :

• L'initialisation directe nécessite maintenant l'initialisation par un constructeur et ne prend plus une séquence de conversion
utilisateur.
• L'initialisation de la copie pour les objets de même type ou de type dérivé nécessite maintenant un appel du constructeur.
• L'initialisation de la copie pour les objets de types différents ne préfère plus la conversion utilisateur à la construction. Si le
compilateur trouve une conversion utilisateur appropriée, il continue maintenant à rechercher (ambiguïté possible) des
constructeurs de conversion. Si la fonction de conversion choisie est un constructeur de conversion, l'appel initialise un
temporaire du type destination. Le résultat de l'appel (temporaire pour le cas constructeur) est alors utilisé pour effectuer
l'initialisation directe de l'objet. Utilisez le commutateur -Vbo du compilateur pour revenir au comportement précédent.
• Pour un transtypage explicite, le compilateur effectue maintenant l'initialisation directe sur un temporaire. 3
Cet exemple illustre le nouveau comportement :
// Dans cet exemple, dst est le type destination et src est le type source class A { };
class V { public: V() { }; V( const V & ) { } V( const A & ) { } };G g; V
v;
// initialisation directe
// ==> les constructeurs sont considérés.
V v9(g);
// Ces deux instructions étaient auparavant compilées, mais produisent maintenant l'erreur :
// Erreur E2015: Ambiguïté entre 'V::V(const V &)' et 'V::V(const A &)'

477
Guide du langage C++ RAD Studio 3.1 Référence C++

// transtypages
// (V)g est traité comme V tmp(g) qui est l'initialisation directe de 'tmp'
// ==> les constructeurs sont considérés.
(V)g;
static_cast<V> (g);
// Ces deux instructions étaient auparavant compilées, mais produisent maintenant l'erreur :
// Erreur E2015: Ambiguïté entre 'V::V(const V &)' et 'V::V(const A &)'

// initialisation de la copie avec dst=V src=G


// ==> les séquences de conversion définies par l'utilisateur sont considérées.
V v4 = g;
V v5 = G();
// Ces deux instructions sont maintenant compilées, mais produisaient auparavant l'erreur :
// Erreur E2015: Ambiguïté entre 'V::V(const A &)' et 'V::V(const V &)'

// initialisation de la copie avec dst=V src=V


// ==> les constructeurs de conversion de V sont considérés.
V v6 = (V)g;
V v7 = V(g);
// Ces deux instructions étaient auparavant compilées, mais produisent maintenant l'erreur :
// Erreur E2015: Ambiguïté entre 'V::V(const V &)' et 'V::V(const A &)'
Conversion via des opérateurs définis par l'utilisateur
Le nouveau compilateur C++Builder 2007 signale souvent des ambiguïtés pour les conversions impliquant des opérateurs
définis par l'utilisateur. Voici un exemple :
class AnsiString { public: bool operator ==(const AnsiString& other);
AnsiString(const wchar_t* src); };
class Variant { public: operator AnsiString() const;operator wchar_t*() const;
bool operator ==(const AnsiString& rhs) const { return static_cast<AnsiString>(*this) ==
rhs;}
Les utilisateurs de C++Builder peuvent noter que l'exemple ci-dessus est une version issue des classes AnsiString et Variant de
la VCL. Les versions précédentes du compilateur invoquaient le 'Variant' 'operator AnsiString() const' pour
'static_cast<AnsiString>(*this)', tandis que C++Builder 2007 utilise la 'conversion via un constructeur'. Puisque le Variant peut
être converti en plusieurs types pour lesquels il y a des constructeurs AnsiString, le compilateur génère une erreur d'ambiguïté.

Pour corriger cette erreur d'ambiguïté, vous devez éliminer le transtypage, comme dans :
bool operator ==(const AnsiString& rhs) const
{ return (*this) == rhs;}
Vous pouvez également être explicite sur l'opérateur :
bool operator ==(const AnsiString& rhs) const
{ return this->operator AnsiString() == rhs; }
Variant/OleVariant/AnsiString/WideString/TDateTime
Le problème décrit ci-dessus avec un opérateur de conversion défini par l'utilisateur contre une conversion via un constructeur
peut être rencontré dans plusieurs constructions impliquant les classes VCL Variant, OleVariant, AnsiString, WideString,
TDateTime, Currency, et ainsi de suite.

Le tableau suivant répertorie les constructions générant maintenant des messages d'erreur et la syntaxe mise à jour.
3
Construction précédente Construction mise à jour Notes
AnsiString test(OleVariant v) { AnsiString test(OleVariant v) { AnsiString Ne transtypez pas RHS lors de
AnsiString ret = (AnsiString) v; return ret = /*(AnsiString)*/ v; return ret; } l'invocation d'un opérateur de conversion
ret; } dans une affectation.
WideString test(OleVariant v) { WideString test(OleVariant v) { Utilisez l'initialisation de copie à la place
WideString w(v); return w; } WideString w = v; return w; } du constructeur plus direct.

478
3.1 Référence C++ RAD Studio Guide du langage C++

Les changements du compilateur sous-jacent relatifs aux erreurs décrites ci-dessus est lié à la façon dont le compilateur gère
maintenant l'initialisation et la conversion.

Voir aussi
Compilateur C++ plus strict (C++Builder 2007) ( see page 473)

Liaison des références et des qualificateurs ( see page 474)

Les littéraux chaîne sont maintenant des constantes ( see page 475)

Modifications des templates ( see page 476)

Résolution des surcharges de fonction ( see page 476)

3.1.4.1.18 Templates
Cette section traite des templates.

Rubriques
Nom Description
Analyse du corps de template ( see page 479) Les versions précédentes du compilateur ne vérifiaient pas la syntaxe du corps
d'un template sauf si le template était instancié. Désormais le corps d'un
template est immédiatement analysé dès qu'il est rencontré comme toutes les
autres déclarations.
Utilisation des templates ( see page 480) Les templates, également appelés types paramétrés ou génériques permettent
de construire une famille de fonctions ou de classes associées. Les sections
suivantes vous permettront d'en savoir plus sur le concept de base des
templates :
Exportation et importation de templates ( see page 450)
Analyse du corps de template ( see page 479)
Templates de fonctions ( see page 451)
Templates de classes ( see page 429)
Fonctions de templates implicites et explicites ( see page 451)
Commutateurs du compilateur relatifs aux templates ( see page 431)
Le mot clé template ( see page 573)

3.1.4.1.18.1 Analyse du corps de template


Les versions précédentes du compilateur ne vérifiaient pas la syntaxe du corps d'un template sauf si le template était instancié.
Désormais le corps d'un template est immédiatement analysé dès qu'il est rencontré comme toutes les autres déclarations.
template <class T> class X : T
{
Int j; // Erreur : Nom de type attendu dans template X<T>
};
Supposons que Int n'ait pas été défini jusque là. Cela signifie que Int doit être un membre de l'argument template T. Mais cela
peut n'être qu'une erreur de frappe et devrait être int et non pas Int. Comme le compilateur ne peut deviner la bonne
interprétation, il génère un message d'erreur.

Pour accéder aux types définis dans un argument template, utilisez un typedef pour clarifier vos intentions pour le compilateur :
template <class T> class X : T 3
{
typedef typename T::Int Int;
Int j;
};
Il n'est pas possible d'écrire uniquement
typedef T::Int;
comme dans les versions précédentes du compilateur. Ne pas spécifier le nom de typedef était acceptable, désormais cela

479
Guide du langage C++ RAD Studio 3.1 Référence C++

provoque un message d'erreur.

Tous les autres templates mentionnés à l'intérieur du corps du template sont déclarés ou définis à ce point. Donc, l'exemple
suivant est incorrect et ne passe pas à la compilation :
template <class T> class X
{
void f(NotYetDefindedTemplate<T> x);
};
Toutes les définitions de template doivent se terminer par un point-virgule. Les versions antérieures du compilateur ne
réagissaient pas à l'absence du point-virgule.

Voir aussi
Utilisation des templates ( see page 480)

Templates de fonctions ( see page 451)

Templates de classes ( see page 429)

Commutateurs du compilateur relatifs aux templates ( see page 431)

Sémantique de génération des templates ( see page 431)

Exportation et importation de templates ( see page 450)

3.1.4.1.18.2 Utilisation des templates


Les templates, également appelés types paramétrés ou génériques permettent de construire une famille de fonctions ou de
classes associées. Les sections suivantes vous permettront d'en savoir plus sur le concept de base des templates :

Exportation et importation de templates ( see page 450)

Analyse du corps de template ( see page 479)

Templates de fonctions ( see page 451)

Templates de classes ( see page 429)

Fonctions de templates implicites et explicites ( see page 451)

Commutateurs du compilateur relatifs aux templates ( see page 431)

Le mot clé template ( see page 573)

3.1.4.1.19 Fonctionnalités C++0x (C++Builder 2009)


C++Builder 2009 implémente un certain nombre des nouvelles fonctionnalités proposées dans le standard C++0x. Cette section
liste et décrit ces fonctionnalités C++0x. Vous pouvez visualiser le "Working Paper draft" qui a été utilisé comme guide de
l'implémentation de ces fonctionnalités à l'adresse Draft Working Paper. Vous pouvez visualiser un résumé des "working group
papers" à l'adresse Summary of Working Group Papers.
3 Rubriques
Nom Description
Opérateur alignof (C++0x) ( see page 481) Le standard C++0x inclut l'opérateur et le mot clé alignof, qui indiquent
l'alignement d'un type.
Pour obtenir l'alignement d'un type, utilisez la syntaxe suivante :
Fonctions trait de type (C++0x) ( see page 482) Cette section contient les rubriques d'aide relatives aux fonctions trait de type.

480
3.1 Référence C++ RAD Studio Guide du langage C++

Attributs noreturn et final (C++0x) ( see page 504) Le standard C++0x inclut l'addition d'attributs qui peuvent être appliqués à la
déclaration d'une classe, d'une fonction générale, d'un constructeur, d'un
tableau, et ainsi de suite. C++Builder 2009 implémente deux attributs : noreturn
et final.
Les attributs sont désactivés dans le code par des double crochets, comme
[[noreturn]].
Opérateurs de conversion explicite (C++0x) ( see page 505) C++Builder 2009 inclut le support des opérateurs de conversion explicite, une
des fonctionnalités du standard C++0x.
Vous pouvez maintenant appliquer le spécificateur de fonction explicit dans la
définition d'un opérateur de conversion défini par l'utilisateur. Auparavant, les
constructeurs explicites (y compris les constructeurs de copie) ont été ajoutés au
langage afin d'empêcher les conversions involontaires appelées implicitement
par le compilateur. Des opérateurs de conversion explicite ont maintenant été
ajoutés afin de fournir le même contrôle sur les appels de conversion
involontaire. .
Les fonctions de conversion déclarées en tant que travail explicite dans les
mêmes contextes que les constructeurs explicites... suite ( see page 505)
Templates extern (C++0x) ( see page 506) C++Builder 2009 inclut l'utilisation des templates extern, qui vous permettent de
définir des templates qui ne sont pas instanciés dans une unité de traduction.
L'utilisation des templates extern réduit ainsi à la fois le temps de compilation et
la taille du module compilé. Cette fonctionnalité fait partie du nouveau standard
C++0x.
Déclaration forward des énumérations (C++0x) ( see page 507) C++Builder 2009 introduit la déclaration forward des énumérations. Vous pouvez
déclarer une énumération sans fournir une liste d'énumérateurs. De telles
déclarations ne sont pas des définitions et peuvent seulement être fournies pour
les énumérations avec des types sous-jacents fixes. Une énumération peut
ensuite être redéclarée, avec fourniture possible de la liste des énumérateurs
manquante, mais la redéclaration doit correspondre à la déclaration précédente.
Cette fonctionnalité fait partie des fonctionnalités C++0x ajoutées à C++Builder
2009.
Références rvalue (C++0x) ( see page 507) C++Builder 2009 inclut l'utilisation des références rvalue qui permettent la
création d'une référence aux temporaires. De plus, les références rvalue évitent
la copie inutile et rendent possible les fonctions forward parfaites. Cette
fonctionnalité fait partie du standard C++0x.
Assertions statiques (C++0x) ( see page 510) Le mot clé static_assert est utilisé pour tester les assertions durant la
compilation. C'est l'une des fonctionnalités ajoutées à C++Builder 2009.
Ce mot clé opère d'une façon différente de la macro assert, qui déclenche des
assertions durant l'exécution. Le mot clé static_assert diffère également de la
directive de préprocesseur #error, qui opère durant le prétraitement et émet
simplement un message.
Enumérations fortement typées (C++0x) ( see page 511) C++Builder 2009 introduit les énumérations de portée. En outre, les
énumérations existantes sont étendues avec le type sous-jacent et la portée
explicite. Cette fonctionnalité fait partie des fonctionnalités C++0x ajoutées à
C++Builder 2009.
Les énumérations de portée sont généralement caractérisées comme suit :

• Les énumérateurs sont dans la portée de leur


énumération.
• Les énumérateurs et les énumérations ne sont pas
implicitement convertis en int (comme le font les
énumérations et énumérateurs "ordinaires").
• Les énumérations et les énumérateurs peuvent avoir un
type sous-jacent défini.
Spécificateur de type decltype (C++0x) ( see page 512) Le standard C++0x inclut l'opérateur et le mot clé decltype, qui représentent le
type d'une expression. Cette fonctionnalité fait partie des fonctionnalités C++0x
ajoutées à C++Builder 2009.
Littéraux et types de caractères Unicode (C++0x) ( see page 512) C++Builder 2009 implémente les nouveaux littéraux caractère et types de
caractères pour Unicode. Ces types appartiennent aux fonctionnalités C++0x
3
ajoutées à C++Builder 2009.

3.1.4.1.19.1 Opérateur alignof (C++0x)


Le standard C++0x inclut l'opérateur et le mot clé alignof, qui indiquent l'alignement d'un type.

Pour obtenir l'alignement d'un type, utilisez la syntaxe suivante :


alignof(type);

481
Guide du langage C++ RAD Studio 3.1 Référence C++

Le résultat est une constante entière de type std::size_t. La valeur indique les frontières sur lesquelles les éléments de ce
type sont alignés en mémoire. Par exemple, un alignement de 2 signifie que le type doit commencer sur une adresse mémoire
paire. Une valeur typique pour alignof (double) pourrait être 8.

L'application de alignof à un type référence provoque l'alignement du type référencé. Si vous appliquez alignof sur un type
tableau, vous obtenez l'alignement du type de ses éléments.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Working Draft

Standard for Programming Language C++ (Sec. 5.3.6)

3.1.4.1.19.2 Fonctions trait de type (C++0x)


Cette section contient les rubriques d'aide relatives aux fonctions trait de type.

Rubriques
Nom Description
Présentation des fonctions trait de type (C++0x) ( see page 488) C++Builder 2009 supporte une bibliothèque de fonctions trait de type désignées
pour supporter les techniques de métaprogrammation à la compilation.
Ces fonctions trait de type sont des fonctions de type intrinsèques qui sont
définies d'une manière similaire à typeid, sizeof et decltype. Les fonctions trait
de type acceptent un type à la compilation et délivrent une expression constante
de compilation en tant que résultat, généralement de type bool.
Chaque fonction trait de type est nommée après son trait de type respectif,
préfixé d'un double caractère de soulignement (__), qui marque un nom réservé
à l'implémentation.
Par exemple,... suite ( see page 488)
__alignment_of ( see page 489) Usage : unsigned int __alignment_of( typename T )
Cette fonction n'est pas nécessaire, étant donné que alignof ( see page 537)
est un nouveau mot clé proposé.
__array_extent ( see page 489) Usage : unsigned int __array_extent( typename T, unsigned
intI )
Renvoie : Si T n'est pas un type tableau, ou s'il a un rang inférieur à I, ou si I est
égal à 0 et T a le type "tableau de dimension inconnue de U", puis 0 ; sinon, la
taille de la I'ième dimension de T.
__array_rank ( see page 489) Usage : unsigned int __array_rank( typename T )
Renvoie : Si T nomme un type tableau, un entier représentant le nombre de
dimensions de T ; sinon, 0..
__has_nothrow_assign ( see page 489) Usage : bool __has_nothrow_assign ( typename T )
Renvoie true si et seulement si le compilateur peut prouver que T a un opérateur
d'affectation de copie qu'il ne peut pas déclencher.
True si __has_trivial_assign(T).
Egalement true si l'opérateur d'affectation de copie a une spécification
d'exception vide.
Interaction Ox false si l'affectation de copie est définie comme supprimée.
__has_nothrow_copy_constructor ( see page 489) Usage : bool __has_nothrow_copy_constructor ( typename T )
Renvoie true si et seulement si le compilateur peut prouver que T a un
constructeur de copie qu'il ne peut pas déclencher.
Erreur si T est un type incomplet.
True si __has_trivial_copy_constructor(T).
3 Interaction Ox false si le constructeur de copie est défini comme supprimé.
__has_nothrow_default_constructor ( see page 490) Usage : bool __has_nothrow_default_constructor (typename T )
Renvoie true si et seulement si T peut prouver que T a un constructeur par
défaut qu'il ne peut pas déclencher.
Erreur si T est un type incomplet.
True si __has_trivial_default_constructor(T).
True si le constructeur par défaut a une spécification d'exception vide.
False (mais bien formé) si un type de classe n'a pas de constructeur par défaut.
False si T est un type référence.
Interaction Ox false si le constructeur par défaut est défini comme supprimé.

482
3.1 Référence C++ RAD Studio Guide du langage C++

__has_trivial_assign ( see page 490) Usage : bool __has_trivial_assign (typename T )


Renvoie true si et seulement si T a un opérateur d'affectation de copie trivial.
Erreur si T est un type incomplet.
La définition de la section 20.4.4.3 du "Working Draft notes" indique qu'un type T
a un opérateur d'affectation de copie trivial si T n'est ni const ni un type
référence, et T est un des types suivants :

• un type scalaire (ou array thereof)


• un type classe avec un opérateur d'affectation de copie
trivial
Selon la section 21.8 p11 du "Working Draft", un opérateur
d'affectation de copie pour la classe X est trivial si :... suite
( see page 490)
__has_trivial_copy_constructor ( see page 491) Usage : bool __has_trivial_copy_constructor ( typename T )
Renvoie true si et seulement si T a un constructeur par défaut trivial.
Erreur si T est un type incomplet.
False (mais bien formé) si un type classe n'a pas de constructeur par défaut
La définition (de la section 20.4.4.3 du "Working Draft notes") a un type T ayant
un constructeur de copie trivial s'il est dans la liste :

• un type scalaire (ou array thereof)


• un type référence (ou array thereof)
• un tableau de type classe avec un destructeur trivial
• un type classe avec un constructeur de copie trivial (12.8)
Selon la section... suite ( see page 491)
__has_trivial_default_constructor ( see page 491) Usage : bool __has_trivial_default_constructor (typename T )
Renvoie true si et seulement si T a un constructeur par défaut trivial.
Erreur si T est un type incomplet.
False (mais bien formé) si un type de classe n'a pas de constructeur par défaut.
Selon la définition de la section 20.4.4.3 du "Working Draft notes", un type T a un
opérateur d'affectation de copie trivial s'il est dans la liste :

• un type scalaire (ou array thereof)


• un tableau de type classe avec un constructeur trivial par
défaut
• un type classe avec un constructeur trivial par défaut
False en particulier pour les types référence.... suite ( see
page 491)
__has_trivial_destructor ( see page 492) Usage : bool __has_trivial_destructor (typename T )
Renvoie true si et seulement si T a un destructeur trivial.
Erreur si T est un type incomplet.
Remarque : La définition des notes 20.4.4.3 comporte un type T qui a un
destructeur trivial si T est inclus dans la liste suivante :

• un type scalaire (ou array thereof)


• un type scalaire (ou array thereof)
• un tableau de type classe avec un destructeur trivial
3
• un tableau de type classe avec un destructeur trivial
• un type classe avec un destructeur trivial
Selon la section 12.4, p 3 du "Working Draft", un destructeur
pour la classe X... suite ( see page 492)

483
Guide du langage C++ RAD Studio 3.1 Référence C++

__has_virtual_destructor ( see page 493) Usage : bool __has_virtual_destructor (typename T )


Renvoie true si et seulement si T est un type classe et le destructeur est déclaré
virtuel.
Erreur si T est un type incomplet.
Les classes dérivées ont un destructeur virtuel si le destructeur de la classe de
base est déclaré virtuel, même s'il n'est pas déclaré explicitement comme virtuel
dans la classe dérivée.
__is_abstract ( see page 493) Décrit l'utilisation de la fonction trait de type C++0x __is_abstract.
Usage : bool __is_abstract( typename T )
Renvoie true si et seulement si T a un type de classe abstrait.
Erreur si T est un type incomplet.
Remarque: Une classe abstraite est une classe qui contient ou hérite (sans
redéfinition) au moins une fonction virtuelle pure, selon la section 10.4 du
"Working Draft".
__is_arithmetic ( see page 493) Usage : bool __is_arithmetic ( typename T )
Renvoie __is_integral(T) || __is_floating_point(T).
__is_array ( see page 494) Usage : bool __is_array( typename T )
Renvoie true si et seulement si T est un type tableau.
Remarque: False pour référence vers tableau et pointeur vers tableau dégradé ;
true pour tableau-de dimension inconnue.
__is_base_of ( see page 494) Usage : bool __is_base_of (typename Base, typename Derived
(Typename T)
Renvoie true si et seulement si Base est une classe de base de Derived.
Erreur si Derived est un type incomplet et Base un type-classe.
Remarque : False (mais bien formé) si Base ou Derived est une union ou un type
non-classe, même si l'autre est un type incomplet.
True si une classe du DAG des classes de base pour Derived est Base. Cela
inclut les bases privées, protégées, ambiguës ou virtuelles. Renvoie ainsi
simplement true la première fois que la recherche trouve une correspondance.
__is_class ( see page 494) Usage : bool __is_class(typename T)
Renvoie true si et seulement si T est un type classe, et PAS un type union.
Renvoie true pour les classes déclarées avec la clé-classe "class" ou "struct".
Renvoie false pour référence/pointeur sur type classe.
Renvoie true pour la spécialisation d'un template de classe.
Mal formé si appelé avec le nom d'un template, sans spécifier les paramètres de
template. Un template n'est pas un type ; c'est un générateur de type.
__is_complete_type ( see page 494) Usage : bool __is_complete_type(T)
Renvoie True si et seulement si T est un type complet au point de l'appel de la
fonction.
C'est une fonction de support conçue pour aider les utilisateurs à détecter le
code mal formé, et pas un trait de type distinct requis par le standard. Cette
fonction est typiquement utilisée dans les instructions static_assert, car la
plupart des autres utilisent le risque transgressant l'ODR. Notez que void et les
tableaux de dimension inconnue sont toujours des types incomplets.
__is_compound ( see page 495) Usage : bool __is_compound( typename T )
Renvoie true si et seulement si T est un type composé.
Un type composé est essentiellement un élément de la liste suivante :

• tableau
• fonction
• pointeur
• pointeur-vers-membre
• référence
3
• classe
• union
• énumération
Les types composés sont définis dans la section 3.92 du
"Working Draft".

484
3.1 Référence C++ RAD Studio Guide du langage C++

__is_const ( see page 495) Usage : bool __is_const(typename T)


Renvoie true si et seulement si T est un type const-qualifié.
Remarque : Les références ne sont jamais cv-qualifiés.
Pour les pointeurs, se réfère au type pointeur lui-même, et PAS le type
pointé-vers.
Renvoie true si T est à la fois const et volatile qualifié.
__is_convertible ( see page 495) Usage : bool __is_convertible ( typename From, typename To )
Renvoie true si et seulement si From est implicitement convertible en To.
Erreur si From ou To est un type incomplet.
Remarque : Le test exact décrit dans la section 20.4.4.3 du "Working Draft" est
true si le code suivant est bien formé :
__is_empty ( see page 496) Usage : bool __is_empty( typename T )
Renvoie true si et seulement si T est un type 'vide'.
Erreur si T est un type incomplet.
La définition de __is_empty est donnée dans le tableau de la section 20.4.4.3
du "Working Draft".
Un type T est vide si T :

• est un type classe mais pas un type union.


• n'a pas de données membres non-statisques autres que
les champs-bit de longueur 0
• n'a pas de fonctions membre virtuelles
• n'a pas de classes de base virtuelles
• n'a pas de classe de base non vide.
__is_enum ( see page 496) Usage : bool _is_enum ( typename T )
Renvoie true si et seulement si T est un type enum.
Renvoie true pour les énumérations C++0x fortement typées.
Renvoie false pour référence/pointeur sur type enum.
__is_floating_point ( see page 496) Usage : bool __is_floating_point(typename T)
Renvoie true si et seulement si T est un type virgule flottante (potentiellement
cv-qualifié).
L'ensemble standard des types virgule flottante est :

• floating
• double
• long double
Les types virgule flottante sont définis dans la section 3.9.1 p
7 du "Working Draft".
__is_function ( see page 497) Usage : bool __is_function( typename T )
Renvoie true si et seulement si T est un type fonction.
Renvoie false pour référence/pointeur sur type fonction.
Renvoie true pour la spécialisation d'un template de fonction.
Mal formé si appelé avec le nom d'un template, sans spécifier les paramètres de
template. Un template n'est pas un type ; c'est un générateur de type.
__is_fundamental ( see page 497) Usage : bool __is_fundamental( typename T )
Renvoie true si et seulement si T est un type fondamental.
Les types fondamentaux sont définis dans la section 3.9.1 du "Working Draft".
La définition est essentiellement __is_arithmetic(T) || __is_void(T)
Une alternative est un type composé, comme un pointeur, une référence, une
énumération, une classe ou un tableau. 3
__is_integral ( see page 497) Usage : bool __is_integral(typename T)
Renvoie True si et seulement si T est un type intégral (potentiellement
cv-qualifié).
Les types intégraux sont définis dans la section 3.9.1 page 7 du "Working
Standard".
L'ensemble standard des types intégraux est : bool, char, signed char, unsigned
char, char16_t, char32_t, wchar_t, [unsigned]short, [unsigned] int, [unsigned]
long et [unsigned] long.

485
Guide du langage C++ RAD Studio 3.1 Référence C++

__is_lvalue_expr ( see page 498) Décrit l'utilisation de la fonction trait de type C++0x __is_lvalue_expr.
Usage : bool __is_lvalue_expr( typename T )
Renvoie true si et seulement si T est une expression lvalue.
__is_lvalue_reference ( see page 498) Décrit l'utilisation de la fonction trait de type C++0x __is_lvalue_reference.
Usage : bool __is_lvalue_reference( typename T )
Renvoie true si et seulement si T est un type référence lvalue.
Peut être une référence à un objet ou un type fonction.
__is_member_function_pointer ( see page 498) Usage : bool __is_member_function_pointer( typename T )
Renvoie true si et seulement si T est un type pointeur-vers-fonction-membre.
Renvoie false pour un pointeur-vers-données membres.
Renvoie false pour un pointeur d'objet régulier.
__is_member_object_pointer ( see page 498) Usage : bool __is_member_object_pointer( typename T )
Renvoie true si et seulement si T est un type pointeur-vers-données-membres.
Renvoie false pour un pointeur-vers-fonction-membre.
Renvoie false pour un pointeur d'objet régulier.
__is_member_pointer ( see page 499) Usage : bool __is_member_pointer( typename T )
Renvoie : __is_member_object_pointer(T) ||
__is_member_function_pointer(T).
__is_object ( see page 499) Usage : bool __is_object( typename T)
Renvoie true si et seulement si T est un type objet.
Défini dans la section 3.9 p8 du "Working Draft", essentiellement :
!__is_reference(T) && !__is_function(T) && !__is_void(T).
__is_pod ( see page 499) Usage : bool __is_pod( typename T )
Renvoie true si et seulement si T est un type POD (plain ol' data).
Erreur si T est un type incomplet.
Les types POD sont définis dans la section 3.9 p10 du "Working Draft".
Les classes POD sont définies dans la section 9 p9 du "Working Draft".
Effectively __is_trivial_type(T) && is standard_layout(T)
__is_pointer ( see page 500) Usage : bool__is_pointer( typename T )
Renvoie true si et seulement si T est un type pointeur.
Peut être un pointeur d'objet ou un pointeur de fonction.
False pour pointeur-vers-membre.
__is_polymorphic ( see page 500) Usage : bool __is_polymorphic( typename T )
Renvoie true si et seulement si T est un type classe polymorphique.
Erreur si T est un type incomplet.
Les types polymorphiques sont définis dans la section 10.3 du "Working Draft".
"Une classe qui déclare ou hérite une valeur virtuelle est appelée une classe
polymorphique."
__is_reference ( see page 500) Usage : bool __is_reference( typename T )
Renvoie : __is_lvalue_reference(T) || __is_rvalue_reference(T).
__is_lvalue_expr ( see page 500) Décrit l'utilisation de la fonction trait de type C++0x __is_rvalue_expr.
Usage : bool __is_rvalue_expr( typename T )
Renvoie true si et seulement si T est une expression rvalue.
__is_rvalue_reference ( see page 501) Usage : bool __is_rvalue_reference( typename T )
Renvoie true si et seulement si T est un type référence rvalue.
Peut être une référence à un type fonction ou objet, bien que les rvalues de type
fonction ont peu de sens au-delà de la métaprogrammation dans le système de
types.
__is_same ( see page 501) Usage : bool __is_same( typename T, typename U )
Renvoie true si et seulement si T et U sont de même type, avec des
qualificateurs CV identiques.
Les noms de types lors de l'appel à __is_same peuvent être des alias différents
3 pour le même type, s'ils sont appelés avec des typedefs ou des paramètres de
type template.
Interaction Ox : Les alias de template permettent une autre façon de définir l'alias
du même nom de type.

486
3.1 Référence C++ RAD Studio Guide du langage C++

__is_scalar ( see page 501) Usage : bool __is_scalar( typename T )


Renvoie true si et seulement si T est un type scalaire.
Le type scalaire est défini dans la section 3.9 p10 du "Working Draft",
essentiellement :
__is_arithmetic( T ) || __is_enumeration(T) ||
__is_pointer(T) || __is_member_pointer(T)
Les types scalaires ont une signification intégrée pour operator < ainsi que
operator ==. Par conséquent, __closure n'est pas un type scalaire.
__is_signed ( see page 501) Usage : _bool __is_signed( typename T )
Renvoie true si et seulement si __is_arithmetic(T) et T reconnaissent des
valeurs inférieures à zéro.
__is_standard_layout ( see page 502) Usage : bool __is_standard_layout(typename T)
Renvoie true si et seulement si T est un type implémentation standard.
Erreur si T est un type incomplet.
Les classes d'implémentation standard sont définies dans la section 9, p 6 du
"Working Draft".
Un type implémentation standard est :

• un type scalaire
• un tableau de types implémentation standard
• un type classe d'implémentation standard
Une classe d'implémentation standard est une classe qui :
• n'a pas de données membres non-statiques autres que
les types implémentation standard
• a le même contrôle d'accès pour toutes les données
membres non-statiques (comme public ou privé)
• n'a pas de classes de base autres... suite ( see page
502)
__is_trivial ( see page 502) Usage : bool __is_trivial( typename T )
Renvoie true si et seulement si T est un type trivial.
Erreur si T est un type incomplet.
Les types triviaux sont définis dans la section 3.9 p10 du "Working Draft".
Les classes triviales sont définies dans la section 9 p5 du "Working Draft".
Renvoie true si T est à la fois const et volatile qualifié.
Un type est trivial s'il est :

• un type scalaire
• Un tableau de types triviaux
• un type classe/union où les 4 membres spéciaux sont
triviaux :
• constructeur par défaut
• constructeur de copie
• opérateur d'affectation de copie
• destructeur
Consultez cette... suite ( see page 502)
__is_union ( see page 503) Usage : bool __is_union( typename T ) 3
Renvoie true si et seulement si T est un type union.
Remarque : les unions sont des types classe déclarés dans l'union clé-classe.
Renvoie false pour référence/pointeur sur type union.
__is_unsigned ( see page 503) Usage : bool __is_unsigned
Renvoie true si _is_arithmetic(T) et T ne reconnaissent pas les valeurs
inférieures à zéro
__is_void ( see page 503) Usage : bool __is_void( typename T )
Renvoie True si T est void (potentiellement cv-qualifié). Sinon renvoie False, y
compris pour pointeur ou référence sur void.

487
Guide du langage C++ RAD Studio 3.1 Référence C++

__is_volatile ( see page 504) Usage : bool __is_volatile( typename T )


Renvoie true si et seulement si T est un type volatile-qualifié.
Remarque : Les références ne sont jamais cv-qualifiées.
Pour les pointeurs, se réfère au type pointeur lui-même, et PAS le type
pointé-vers.
Renvoie true si T est à la fois const et volatile qualifié.

3.1.4.1.19.2.1 Présentation des fonctions trait de type (C++0x)


C++Builder 2009 supporte une bibliothèque de fonctions trait de type désignées pour supporter les techniques de
métaprogrammation à la compilation.

Ces fonctions trait de type sont des fonctions de type intrinsèques qui sont définies d'une manière similaire à typeid, sizeof et
decltype. Les fonctions trait de type acceptent un type à la compilation et délivrent une expression constante de compilation en
tant que résultat, généralement de type bool.

Chaque fonction trait de type est nommée après son trait de type respectif, préfixé d'un double caractère de soulignement (__),
qui marque un nom réservé à l'implémentation.

Par exemple, le code suivant illustre une fonction trait de type qui est évaluée à True si T est un type union, ou False sinon :
bool __is_union(typename T)
Le mot clé typename indique ici une fonction qui prend un type plutôt qu'une valeur en argument, à des fins d'illustration
uniquement.

Différences entre les fonctions trait de type et les autres fonctions intrinsèques
Les fonctions trait de type acceptent seulement les types nommés, et pas les expressions arbitraires (qui sont acceptées par
typeid, sizeof et decltype). Vous pouvez spécifier plusieurs arguments avec une fonction trait de type, mais une liste séparée
par des virgules est interprétée comme une application de l'opérateur virgule par typeid, sizeof et decltype.

De même, toute tentative de référencer le type d'un champ de bits (comme à travers decltype) produit le type de stockage
sous-jacent pour le champ de bits, et c'est ce qui est testé dans les fonctions trait de type.

Fonctions trait de type et types incomplets


La plupart des fonctions trait de type ne fonctionnent pas avec les types incomplets. Par exemple, après qu'une classe ait été
déclarée forward, le type peut être identifié comme une classe, pas une union, énumération ou type fondamental. La classe peut
avoir des références et pointeurs, et ainsi de suite. Par conséquent, la plupart des fonctions trait de type acceptent deux types
incomplets spéciaux : void et array-of-unknown-bound (de types complets). Pour ces deux types incomplets, la plupart des
fonctions trait de type renvoient False.

Toutefois, quelques fonctions de type nécessitent des types complets. Par exemple, une déclaration de classe n'est pas
suffisante pour connaître les bases ou la trivialité.

Par souci de commodité, la fonction trait de type suivante est implémentée dans C++Builder :
__is_complete_type(T)
Cette fonction trait de type est unique dans le sens où elle peut renvoyer différents résultats à la compilation en fonction de son
emplacement dans l'unité de traduction. Des violations ODR peuvent survenir si vous utilisez cette fonction trait de type avec
3 négligence.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Working Draft

Standard for Programming Language C++: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

488
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.1.19.2.2 __alignment_of
Usage : unsigned int __alignment_of( typename T )

Cette fonction n'est pas nécessaire, étant donné que alignof ( see page 537) est un nouveau mot clé proposé.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 482)

3.1.4.1.19.2.3 __array_extent
Usage : unsigned int __array_extent( typename T, unsigned intI )

Renvoie : Si T n'est pas un type tableau, ou s'il a un rang inférieur à I, ou si I est égal à 0 et T a le type "tableau de dimension
inconnue de U", puis 0 ; sinon, la taille de la I'ième dimension de T.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.4 __array_rank
Usage : unsigned int __array_rank( typename T )

Renvoie : Si T nomme un type tableau, un entier représentant le nombre de dimensions de T ; sinon, 0..

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.5 __has_nothrow_assign
Usage : bool __has_nothrow_assign ( typename T )

Renvoie true si et seulement si le compilateur peut prouver que T a un opérateur d'affectation de copie qu'il ne peut pas
déclencher.

True si __has_trivial_assign(T).

Egalement true si l'opérateur d'affectation de copie a une spécification d'exception vide.

Interaction Ox false si l'affectation de copie est définie comme supprimée.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488) 3

3.1.4.1.19.2.6 __has_nothrow_copy_constructor
Usage : bool __has_nothrow_copy_constructor ( typename T )

Renvoie true si et seulement si le compilateur peut prouver que T a un constructeur de copie qu'il ne peut pas déclencher.

Erreur si T est un type incomplet.

489
Guide du langage C++ RAD Studio 3.1 Référence C++

True si __has_trivial_copy_constructor(T).

Interaction Ox false si le constructeur de copie est défini comme supprimé.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.7 __has_nothrow_default_constructor
Usage : bool __has_nothrow_default_constructor (typename T )

Renvoie true si et seulement si T peut prouver que T a un constructeur par défaut qu'il ne peut pas déclencher.

Erreur si T est un type incomplet.

True si __has_trivial_default_constructor(T).

True si le constructeur par défaut a une spécification d'exception vide.

False (mais bien formé) si un type de classe n'a pas de constructeur par défaut.

False si T est un type référence.

Interaction Ox false si le constructeur par défaut est défini comme supprimé.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.8 __has_trivial_assign
Usage : bool __has_trivial_assign (typename T )

Renvoie true si et seulement si T a un opérateur d'affectation de copie trivial.

Erreur si T est un type incomplet.

La définition de la section 20.4.4.3 du "Working Draft notes" indique qu'un type T a un opérateur d'affectation de copie trivial si T
n'est ni const ni un type référence, et T est un des types suivants :

• un type scalaire (ou array thereof)


• un type classe avec un opérateur d'affectation de copie trivial
Selon la section 21.8 p11 du "Working Draft", un opérateur d'affectation de copie pour la classe X est trivial si :
• il n'est pas fourni par l'utilisateur
• la classe X n'a pas de fonctions virtuelles
• la classe X n'a pas de classes de base virtuelles
3 • chaque classe de base directe de X a un opérateur d'affectation de copie trivial.
• pour tous les membres de données non-statiques de X qui sont de type classe (ou array thereof), chaque type classe a un
opérateur d'affectation de copie trivial ;
Un opérateur d'affectation de copie n'est pas fourni par l'utilisateur s'il est implicitement déclaré, ou défini inline comme =
default;.
Interaction Ox false si l'opérateur d'affectation de copie est définie comme supprimé.
Interaction Ox false si l'opérateur d'affectation de copie est définie comme supprimé.

490
3.1 Référence C++ RAD Studio Guide du langage C++

Interaction Ox false si le constructeur par défaut est défini comme supprimé.


Ox interaction avec les définitions de fonction par défaut.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft - Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.9 __has_trivial_copy_constructor
Usage : bool __has_trivial_copy_constructor ( typename T )

Renvoie true si et seulement si T a un constructeur par défaut trivial.

Erreur si T est un type incomplet.

False (mais bien formé) si un type classe n'a pas de constructeur par défaut

La définition (de la section 20.4.4.3 du "Working Draft notes") a un type T ayant un constructeur de copie trivial s'il est dans la
liste :

• un type scalaire (ou array thereof)


• un type référence (ou array thereof)
• un tableau de type classe avec un destructeur trivial
• un type classe avec un constructeur de copie trivial (12.8)
Selon la section 12.8 p6 du "Working Draft" :
Un constructeur de copie pour la classe X est trivial si :
• il n'est pas fourni par l'utilisateur (voir la section 8.4)
• la classe X n'a pas de fonctions virtuelles
• la classe X n'a pas de classes de base virtuelles
• chaque classe de base directe de X a un constructeur de copie trivial
• pour tous les membres de données non-statiques de X qui sont de type classe (ou array thereof), chaque type classe a un
constructeur de copie trivial.
Un constructeur de copie n'est pas fourni par l'utilisateur s'il est implicitement déclaré, ou défini inline comme = default;.
Interaction Ox false si le constructeur par défaut est défini comme supprimé.
Interaction Ox avec les définitions de fonction par défaut.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft - Standard for Programming Language C++: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf 3

3.1.4.1.19.2.10 __has_trivial_default_constructor
Usage : bool __has_trivial_default_constructor (typename T )

Renvoie true si et seulement si T a un constructeur par défaut trivial.

Erreur si T est un type incomplet.

491
Guide du langage C++ RAD Studio 3.1 Référence C++

False (mais bien formé) si un type de classe n'a pas de constructeur par défaut.

Selon la définition de la section 20.4.4.3 du "Working Draft notes", un type T a un opérateur d'affectation de copie trivial s'il est
dans la liste :

• un type scalaire (ou array thereof)


• un tableau de type classe avec un constructeur trivial par défaut
• un type classe avec un constructeur trivial par défaut
False en particulier pour les types référence.
Selon la section 21.1 p5 du "Working Draft", un constructeur par défaut est trivial si :
• il n'est pas fourni par l'utilisateur
• Sa classe n'a pas de fonctions virtuelles
• Sa classe n'a pas de classes de base virtuelles
• Chaque classe de base directe de X a un opérateur d'affectation de copie trivial.
• Toutes les classes de base directes de sa classe ont un constructeur par défaut trivial.
• Pour tous les membres de données non-statiques de sa classe qui sont de type classe (ou array thereof), chaque classe a un
constructeur par défaut trivial.
Un constructeur par défaut n'est pas fourni par l'utilisateur s'il est implicitement déclaré, ou défini inline comme = default;.
Interaction Ox si l'opérateur d'affectation de copie est défini comme supprimé.
Interaction Ox false si le constructeur par défaut est défini comme supprimé.
Interaction Ox avec les définitions de fonction par défaut.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft - Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.11 __has_trivial_destructor
Usage : bool __has_trivial_destructor (typename T )

Renvoie true si et seulement si T a un destructeur trivial.

Erreur si T est un type incomplet.

Remarque : La définition des notes 20.4.4.3 comporte un type T qui a un destructeur trivial si T est inclus dans la liste suivante :

• un type scalaire (ou array thereof)


• un type scalaire (ou array thereof)
• un tableau de type classe avec un destructeur trivial
• un tableau de type classe avec un destructeur trivial
3
• un type classe avec un destructeur trivial
Selon la section 12.4, p 3 du "Working Draft", un destructeur pour la classe X est trivial si :
• il n'est pas fourni par l'utilisateur
• la classe X n'a pas de fonctions virtuelles
• la classe X n'a pas de classes de base virtuelles
• toutes les classes de base directes de sa classe ont un destructeur trivial

492
3.1 Référence C++ RAD Studio Guide du langage C++

• pour tous les membres de données non-statiques de sa classe qui sont de type classe (ou array thereof), chaque classe a un
destructeur trivial.
Un destructeur n'est pas fourni par l'utilisateur s'il est implicitement déclaré, ou défini inline comme = default;
Interaction Ox false si le destructeur est défini comme supprimé.
Interaction Ox avec les définitions de fonction par défaut.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.12 __has_virtual_destructor
Usage : bool __has_virtual_destructor (typename T )

Renvoie true si et seulement si T est un type classe et le destructeur est déclaré virtuel.

Erreur si T est un type incomplet.

Les classes dérivées ont un destructeur virtuel si le destructeur de la classe de base est déclaré virtuel, même s'il n'est pas
déclaré explicitement comme virtuel dans la classe dérivée.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.13 __is_abstract
Décrit l'utilisation de la fonction trait de type C++0x __is_abstract.

Usage : bool __is_abstract( typename T )

Renvoie true si et seulement si T a un type de classe abstrait.

Erreur si T est un type incomplet.

Remarque: Une classe abstraite est une classe qui contient ou hérite (sans redéfinition) au moins une fonction virtuelle pure,
selon la section 10.4 du "Working Draft".

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.14 __is_arithmetic 3
Usage : bool __is_arithmetic ( typename T )

Renvoie __is_integral(T) || __is_floating_point(T).

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

493
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.1.19.2.15 __is_array
Usage : bool __is_array( typename T )

Renvoie true si et seulement si T est un type tableau.

Remarque: False pour référence vers tableau et pointeur vers tableau dégradé ; true pour tableau-de dimension inconnue.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.16 __is_base_of
Usage : bool __is_base_of (typename Base, typename Derived (Typename T)

Renvoie true si et seulement si Base est une classe de base de Derived.

Erreur si Derived est un type incomplet et Base un type-classe.

Remarque : False (mais bien formé) si Base ou Derived est une union ou un type non-classe, même si l'autre est un type
incomplet.

True si une classe du DAG des classes de base pour Derived est Base. Cela inclut les bases privées, protégées, ambiguës ou
virtuelles. Renvoie ainsi simplement true la première fois que la recherche trouve une correspondance.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.17 __is_class
Usage : bool __is_class(typename T)

Renvoie true si et seulement si T est un type classe, et PAS un type union.

Renvoie true pour les classes déclarées avec la clé-classe "class" ou "struct".

Renvoie false pour référence/pointeur sur type classe.

Renvoie true pour la spécialisation d'un template de classe.

Mal formé si appelé avec le nom d'un template, sans spécifier les paramètres de template. Un template n'est pas un type ; c'est
un générateur de type.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)


3
3.1.4.1.19.2.18 __is_complete_type
Usage : bool __is_complete_type(T)

Renvoie True si et seulement si T est un type complet au point de l'appel de la fonction.

C'est une fonction de support conçue pour aider les utilisateurs à détecter le code mal formé, et pas un trait de type distinct
requis par le standard. Cette fonction est typiquement utilisée dans les instructions static_assert, car la plupart des autres
utilisent le risque transgressant l'ODR. Notez que void et les tableaux de dimension inconnue sont toujours des types incomplets.

494
3.1 Référence C++ RAD Studio Guide du langage C++

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.19 __is_compound
Usage : bool __is_compound( typename T )

Renvoie true si et seulement si T est un type composé.

Un type composé est essentiellement un élément de la liste suivante :

• tableau
• fonction
• pointeur
• pointeur-vers-membre
• référence
• classe
• union
• énumération
Les types composés sont définis dans la section 3.92 du "Working Draft".
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft - Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.20 __is_const
Usage : bool __is_const(typename T)

Renvoie true si et seulement si T est un type const-qualifié.

Remarque : Les références ne sont jamais cv-qualifiés.

Pour les pointeurs, se réfère au type pointeur lui-même, et PAS le type pointé-vers.

Renvoie true si T est à la fois const et volatile qualifié.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)


3
3.1.4.1.19.2.21 __is_convertible
Usage : bool __is_convertible ( typename From, typename To )

Renvoie true si et seulement si From est implicitement convertible en To.

Erreur si From ou To est un type incomplet.

Remarque : Le test exact décrit dans la section 20.4.4.3 du "Working Draft" est true si le code suivant est bien formé :

495
Guide du langage C++ RAD Studio 3.1 Référence C++

template <class T>


typename add_rvalue_reference<T>::type create();

To test() { return create<From>(); |


Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft - Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.22 __is_empty
Usage : bool __is_empty( typename T )

Renvoie true si et seulement si T est un type 'vide'.

Erreur si T est un type incomplet.

La définition de __is_empty est donnée dans le tableau de la section 20.4.4.3 du "Working Draft".

Un type T est vide si T :

• est un type classe mais pas un type union.


• n'a pas de données membres non-statisques autres que les champs-bit de longueur 0
• n'a pas de fonctions membre virtuelles
• n'a pas de classes de base virtuelles
• n'a pas de classe de base non vide.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.23 __is_enum
Usage : bool _is_enum ( typename T )

Renvoie true si et seulement si T est un type enum.

Renvoie true pour les énumérations C++0x fortement typées.

Renvoie false pour référence/pointeur sur type enum.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
3
Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.24 __is_floating_point
Usage : bool __is_floating_point(typename T)

Renvoie true si et seulement si T est un type virgule flottante (potentiellement cv-qualifié).

L'ensemble standard des types virgule flottante est :

496
3.1 Référence C++ RAD Studio Guide du langage C++

• floating
• double
• long double
Les types virgule flottante sont définis dans la section 3.9.1 p 7 du "Working Draft".
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.25 __is_function
Usage : bool __is_function( typename T )

Renvoie true si et seulement si T est un type fonction.

Renvoie false pour référence/pointeur sur type fonction.

Renvoie true pour la spécialisation d'un template de fonction.

Mal formé si appelé avec le nom d'un template, sans spécifier les paramètres de template. Un template n'est pas un type ; c'est
un générateur de type.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Fonctions trait de type (C++0x) ( see page 488)

3.1.4.1.19.2.26 __is_fundamental
Usage : bool __is_fundamental( typename T )

Renvoie true si et seulement si T est un type fondamental.

Les types fondamentaux sont définis dans la section 3.9.1 du "Working Draft".

La définition est essentiellement __is_arithmetic(T) || __is_void(T)

Une alternative est un type composé, comme un pointeur, une référence, une énumération, une classe ou un tableau.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf 3

3.1.4.1.19.2.27 __is_integral
Usage : bool __is_integral(typename T)

Renvoie True si et seulement si T est un type intégral (potentiellement cv-qualifié).

Les types intégraux sont définis dans la section 3.9.1 page 7 du "Working Standard".

497
Guide du langage C++ RAD Studio 3.1 Référence C++

L'ensemble standard des types intégraux est : bool, char, signed char, unsigned char, char16_t, char32_t, wchar_t,
[unsigned]short, [unsigned] int, [unsigned] long et [unsigned] long.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.28 __is_lvalue_expr
Décrit l'utilisation de la fonction trait de type C++0x __is_lvalue_expr.

Usage : bool __is_lvalue_expr( typename T )

Renvoie true si et seulement si T est une expression lvalue.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.29 __is_lvalue_reference
Décrit l'utilisation de la fonction trait de type C++0x __is_lvalue_reference.

Usage : bool __is_lvalue_reference( typename T )

Renvoie true si et seulement si T est un type référence lvalue.

Peut être une référence à un objet ou un type fonction.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.30 __is_member_function_pointer
Usage : bool __is_member_function_pointer( typename T )

Renvoie true si et seulement si T est un type pointeur-vers-fonction-membre.

Renvoie false pour un pointeur-vers-données membres.

Renvoie false pour un pointeur d'objet régulier.

Voir aussi

3 Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.31 __is_member_object_pointer
Usage : bool __is_member_object_pointer( typename T )

Renvoie true si et seulement si T est un type pointeur-vers-données-membres.

498
3.1 Référence C++ RAD Studio Guide du langage C++

Renvoie false pour un pointeur-vers-fonction-membre.

Renvoie false pour un pointeur d'objet régulier.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.32 __is_member_pointer
Usage : bool __is_member_pointer( typename T )

Renvoie : __is_member_object_pointer(T) || __is_member_function_pointer(T).

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.33 __is_object
Usage : bool __is_object( typename T)

Renvoie true si et seulement si T est un type objet.

Défini dans la section 3.9 p8 du "Working Draft", essentiellement :


!__is_reference(T) && !__is_function(T) && !__is_void(T).

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.34 __is_pod
Usage : bool __is_pod( typename T )

Renvoie true si et seulement si T est un type POD (plain ol' data).

Erreur si T est un type incomplet.

Les types POD sont définis dans la section 3.9 p10 du "Working Draft".

Les classes POD sont définies dans la section 9 p9 du "Working Draft".

Effectively __is_trivial_type(T) && is standard_layout(T)

Voir aussi
3
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - ttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

499
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.1.19.2.35 __is_pointer
Usage : bool__is_pointer( typename T )

Renvoie true si et seulement si T est un type pointeur.

Peut être un pointeur d'objet ou un pointeur de fonction.

False pour pointeur-vers-membre.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.36 __is_polymorphic
Usage : bool __is_polymorphic( typename T )

Renvoie true si et seulement si T est un type classe polymorphique.

Erreur si T est un type incomplet.

Les types polymorphiques sont définis dans la section 10.3 du "Working Draft".

"Une classe qui déclare ou hérite une valeur virtuelle est appelée une classe polymorphique."

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.37 __is_reference
Usage : bool __is_reference( typename T )

Renvoie : __is_lvalue_reference(T) || __is_rvalue_reference(T).

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.38 __is_lvalue_expr
Décrit l'utilisation de la fonction trait de type C++0x __is_rvalue_expr.

3 Usage : bool __is_rvalue_expr( typename T )

Renvoie true si et seulement si T est une expression rvalue.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

500
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.1.19.2.39 __is_rvalue_reference
Usage : bool __is_rvalue_reference( typename T )

Renvoie true si et seulement si T est un type référence rvalue.

Peut être une référence à un type fonction ou objet, bien que les rvalues de type fonction ont peu de sens au-delà de la
métaprogrammation dans le système de types.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.40 __is_same
Usage : bool __is_same( typename T, typename U )

Renvoie true si et seulement si T et U sont de même type, avec des qualificateurs CV identiques.

Les noms de types lors de l'appel à __is_same peuvent être des alias différents pour le même type, s'ils sont appelés avec des
typedefs ou des paramètres de type template.

Interaction Ox : Les alias de template permettent une autre façon de définir l'alias du même nom de type.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.41 __is_scalar
Usage : bool __is_scalar( typename T )

Renvoie true si et seulement si T est un type scalaire.

Le type scalaire est défini dans la section 3.9 p10 du "Working Draft", essentiellement :
__is_arithmetic( T ) || __is_enumeration(T) ||
__is_pointer(T) || __is_member_pointer(T)

Les types scalaires ont une signification intégrée pour operator < ainsi que operator ==. Par conséquent, __closure n'est pas
un type scalaire.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf 3

3.1.4.1.19.2.42 __is_signed
Usage : _bool __is_signed( typename T )

Renvoie true si et seulement si __is_arithmetic(T) et T reconnaissent des valeurs inférieures à zéro.

501
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.43 __is_standard_layout
Usage : bool __is_standard_layout(typename T)

Renvoie true si et seulement si T est un type implémentation standard.

Erreur si T est un type incomplet.

Les classes d'implémentation standard sont définies dans la section 9, p 6 du "Working Draft".

Un type implémentation standard est :

• un type scalaire
• un tableau de types implémentation standard
• un type classe d'implémentation standard
Une classe d'implémentation standard est une classe qui :
• n'a pas de données membres non-statiques autres que les types implémentation standard
• a le même contrôle d'accès pour toutes les données membres non-statiques (comme public ou privé)
• n'a pas de classes de base autres que les classes d'implémentation standard
• n'a pas de fonctions virtuelles ni de classes de base virtuelles
• n'a pas plus d'une classe dans le DAG de l'arborescence d'héritage ayant des données non-statiques
• n'a pas de classe de base de même type que la première donnée membre non statique (s'il y en a)
Les types implémentation standard déclenchent plusieurs clauses spéciales dans le standard, qui peuvent affecter la génération
du code et les optimisations, ou simplement déterminer si certaines constructions ne sont pas définies. En particulier, les
classes d'implémentation standard requièrent l'optimisation de base vide.
Notez que les types implémentation standard sont une généralisation des PODs dans le standard 2003, si l'amélioration de
l'implémentation POD/standard n'est pas survenue quand cette fonction type a été initialement implantée.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.44 __is_trivial
Usage : bool __is_trivial( typename T )
3
Renvoie true si et seulement si T est un type trivial.

Erreur si T est un type incomplet.

Les types triviaux sont définis dans la section 3.9 p10 du "Working Draft".

Les classes triviales sont définies dans la section 9 p5 du "Working Draft".

Renvoie true si T est à la fois const et volatile qualifié.

502
3.1 Référence C++ RAD Studio Guide du langage C++

Un type est trivial s'il est :

• un type scalaire
• Un tableau de types triviaux
• un type classe/union où les 4 membres spéciaux sont triviaux :
• constructeur par défaut
• constructeur de copie
• opérateur d'affectation de copie
• destructeur
Consultez cette aide en ligne pour obtenir la définition de chaque trait __has_trivial_*.
Les types triviaux déclenchent plusieurs clauses spéciales dans le standard, qui peuvent affecter la génération du code et les
optimisations, ou simplement déterminer si certaines constructions ne sont pas définies.
Notez que les types triviaux sont une généralisation des PODs (objets "plain old data") dans le standard 2003, si l'amélioration
POD/trivial n'est pas survenue quand cette fonction type a été initialement implantée.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

Working Draft

Standard for Programming Language C++ - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2588.pdf

3.1.4.1.19.2.45 __is_union
Usage : bool __is_union( typename T )

Renvoie true si et seulement si T est un type union.

Remarque : les unions sont des types classe déclarés dans l'union clé-classe.

Renvoie false pour référence/pointeur sur type union.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.46 __is_unsigned
Usage : bool __is_unsigned

Renvoie true si _is_arithmetic(T) et T ne reconnaissent pas les valeurs inférieures à zéro

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
3
Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.47 __is_void
Usage : bool __is_void( typename T )

Renvoie True si T est void (potentiellement cv-qualifié). Sinon renvoie False, y compris pour pointeur ou référence sur void.

503
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.2.48 __is_volatile
Usage : bool __is_volatile( typename T )

Renvoie true si et seulement si T est un type volatile-qualifié.

Remarque : Les références ne sont jamais cv-qualifiées.

Pour les pointeurs, se réfère au type pointeur lui-même, et PAS le type pointé-vers.

Renvoie true si T est à la fois const et volatile qualifié.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Présentation des fonctions trait de type ( see page 488)

3.1.4.1.19.3 Attributs noreturn et final (C++0x)


Le standard C++0x inclut l'addition d'attributs qui peuvent être appliqués à la déclaration d'une classe, d'une fonction générale,
d'un constructeur, d'un tableau, et ainsi de suite. C++Builder 2009 implémente deux attributs : noreturn et final.

Les attributs sont désactivés dans le code par des double crochets, comme [[noreturn]].

L'attribut noreturn
L'attribut noreturn spécifie qu'une fonction n'a pas d'instruction return. Si une fonction marquée noreturn est appelée et
s'exécute éventuellement sans instruction return, le programme est considéré comme mal formé, mais le compilateur n'émet pas
de message.

Par exemple :
void f [[noreturn]] () {
throw "error"; // OK
}
void g [[noreturn]] (int i) { // mal formé si appelé avec i<=0
if (i > 0)
throw "positive";
}
L'attribut noreturn est utile pour quelques fonctions de bibliothèque qui ne peuvent pas avoir de retour, comme abort et exit.
Vous pouvez également définir vos propres fonctions qui n'ont jamais de retour en utilisant l'attribut noreturn.

Par exemple :
void fatal(void) [[noreturn]];
void fatal(...)
3 {
...
exit(1);
}
Le mot clé noreturn indique au compilateur C++ de considérer que fatal ne peut pas avoir de retour. Le compilateur peut alors
optimiser sans se soucier de ce qui arriverait si fatal ne renvoyait jamais de retour. Ainsi, l'usage de noreturn peut améliorer le
code. Plus important encore, il évite les faux avertissements de variables non initialisées. Vous ne pouvez pas supposer que les
registres enregistrés par la fonction appelante sont restaurés avant l'appel de la fonction avec l'attribut noreturn. Ca n'a aucun
sens pour une fonction noreturn d'avoir un type de retour autre que void.

504
3.1 Référence C++ RAD Studio Guide du langage C++

L'attribut final
L'attribut final empêche une classe ou une fonction d'être héritée. Vous pouvez ajouter l'attribut final à une définition de classe
ou à une déclaration de fonction membre virtuelle dans une définition de classe.

Une classe avec l'attribut final n'est pas autorisée à être une classe de base pour une autre classe. Une fonction virtuelle avec
l'attribut final n'est pas redéfinie dans une sous-classe. Si l'attribut est spécifié pour une définition de classe, il est équivalent
d'être spécifié pour chaque fonction membre virtuelle de cette classe, y compris les fonctions membre héritées.

Si une fonction membre virtuelle f d'une classe B est marquée final et est dérivée de B dans une classe D, une fonction D::f
redéfinit B::f, le programme est mal formé (le compilateur n'émet pas de message).

Par exemple :
struct B {
virtual void f [[ final ]] ();
};
struct D : B {
void f(); // mal formé
};
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

3.1.4.1.19.4 Opérateurs de conversion explicite (C++0x)


C++Builder 2009 inclut le support des opérateurs de conversion explicite, une des fonctionnalités du standard C++0x.

Vous pouvez maintenant appliquer le spécificateur de fonction explicit dans la définition d'un opérateur de conversion défini par
l'utilisateur. Auparavant, les constructeurs explicites (y compris les constructeurs de copie) ont été ajoutés au langage afin
d'empêcher les conversions involontaires appelées implicitement par le compilateur. Des opérateurs de conversion explicite ont
maintenant été ajoutés afin de fournir le même contrôle sur les appels de conversion involontaire. .

Les fonctions de conversion déclarées en tant que travail explicite dans les mêmes contextes que les constructeurs explicites
(c'est-à-dire, l'initialisation directe, la conversion de type explicite). Les opérateurs de conversion explicite génèrent des
diagnostics de compilation dans les mêmes contextes (copie-initialisation) que les constructeurs explicites.

Par exemple :
class T { };

class X {

public:

explicit operator T() const;

};

void m() {

X x;
3
// avec transtypage :

T tc = (T)x;// ok

// sans transtypage :

T t = x;// erreur: E2034

505
Guide du langage C++ RAD Studio 3.1 Référence C++

// obtient : Erreur E2034 x.cpp 13: Impossible de convertir 'X' en 'T' dans la fonction m()

}
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Draft Working Paper

Résumé des "Working Group Papers"

3.1.4.1.19.5 Templates extern (C++0x)


C++Builder 2009 inclut l'utilisation des templates extern, qui vous permettent de définir des templates qui ne sont pas instanciés
dans une unité de traduction. L'utilisation des templates extern réduit ainsi à la fois le temps de compilation et la taille du module
compilé. Cette fonctionnalité fait partie du nouveau standard C++0x.

Déclaration et instanciation explicites


Un template extern vous permet de déclarer un template sans l'instancier dans l'unité de traduction.

Pour illustrer, le code suivant crée et instancie un template :


template <class T>
class MyClass {
// code divers
}

template class MyClass<int>;


...
MyClass<int> myClass;
La ligne template class MyClass<int> est une définition de template explicite et provoque l'instanciation du template dans
son unité de code, ce qui génère du code pour le template dans cette unité. De même, la ligne MyClass<int> myClass;
instancie implicitement le template, générant également du code dans l'unité. Si l'une de ces lignes de code est dans votre unité,
le template est instancié ici.

Toutefois, supposons que vous souhaitez avoir une bibliothèque dans laquelle toutes les instanciations de ce template
surviennent, et que vous voulez faire référence à ces instanciations dans un exécutable. Pour rendre une déclaration de
template explicite qui n'instancie pas le template dans votre unité de code, utilisez le code suivant :
extern template class MyClass<int>;
Vous pouvez alors faire référence au template, mais le compilateur ne génère pas de code pour lui dans cette unité de
traduction.

Utilisation d'un template extern


Voici les règles d'utilisation des templates extern :

• Une instanciation de template doit suivre une déclaration de template explicite dans cette unité de traduction ou bien être
dans une autre unité de traduction. Cela est similaire à l'utilisation usuelle de extern : l'entité référencée doit être définie
3 quelque part.
• Une définition de template explicite doit se produire une seule fois dans une unité.
• Une définition de template explicite doit suivre une déclaration de template explicite si les deux sont présentes dans une unité
de traduction.
• Une déclaration de template explicite peut seulement s'appliquer aux noms des objets, fonctions et aux instanciations de
templates explicites. Elle ne peut pas faire référence à une fonction statique, mais peut s'appliquer à une fonction membre
statique.
• Le spécificateur extern ne peut pas être utilisé dans la déclaration de paramètres ou de membres de classe.

506
3.1 Référence C++ RAD Studio Guide du langage C++

• Une déclaration de template explicite supprime seulement la génération du code si ce template n'a pas été instancié avec la
même spécialisation. Par exemple :
template class MyClass<int>;
...
extern template class MyClass<int>; // non autorisé
extern template class MyClass<float>; // OK
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Working Draft

Standard for Programming Language C++ (Sec. 17.2)

3.1.4.1.19.6 Déclaration forward des énumérations (C++0x)


C++Builder 2009 introduit la déclaration forward des énumérations. Vous pouvez déclarer une énumération sans fournir une liste
d'énumérateurs. De telles déclarations ne sont pas des définitions et peuvent seulement être fournies pour les énumérations
avec des types sous-jacents fixes. Une énumération peut ensuite être redéclarée, avec fourniture possible de la liste des
énumérateurs manquante, mais la redéclaration doit correspondre à la déclaration précédente. Cette fonctionnalité fait partie
des fonctionnalités C++0x ajoutées à C++Builder 2009.
enum E : short; // OK: sans portée, le type sous-jacent est short
enum F: // illégal : enum-base est requis
enum class G : short // OK: de portée, le type sous-jacent est short
enum class H; // OK: de portée, le type sous-jacent est int
enum E : short; // OK: redéclaration de E
enum class G : short; // OK: redéclaration de G
enum class H; // OK: redéclaration de H
enum class H : int; // OK: redéclaration de H
enum class E : short; // illégal: préalablement déclaré "sans portée"
enum G : short; // illégal: préalablement déclaré "en portée"
enum E; // illégal: enum-base est requis
enum E : int // illégal: type sous-jacent différent
enum class G; // illégal: type sous-jacent différent
enum class H : short; // illégal: type sous-jacent différent
enum class H {/* */}] // OK: cette redéclaration est une définition
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Enumérations fortement typées ( see page 511)

3.1.4.1.19.7 Références rvalue (C++0x)


C++Builder 2009 inclut l'utilisation des références rvalue qui permettent la création d'une référence aux temporaires. De plus, les
références rvalue évitent la copie inutile et rendent possible les fonctions forward parfaites. Cette fonctionnalité fait partie du
standard C++0x.

Description
Les références rvalue représentent un type composé comme les références standard C++, qui sont désignées comme les 3
références lvalue. Une référence lvalue est formée en ajoutant le caractère esperluette (&) à un type :
SomeClass l;
SomeClass& lReference = l; // référence lvalue
La syntaxe d'une référence rvalue consiste à ajouter && après un type :
SomeClass r;
SomeClass&& rReference = r; // référence rvalue

507
Guide du langage C++ RAD Studio 3.1 Référence C++

Une référence rvalue se comporte comme une référence lvalue, sauf que vous pouvez lier une référence rvalue à un temporaire
-- un rvalue.
SomeClass a;
a = SomeClass();
SomeClass& lReference = a; //OK-la référence lvalue peut être liée à un lvalue comme
"a"
SomeClass& lReference2 = SomeClass(); //erreur-la référence lvalue ne peut pas être liée à
un rvalue
SomeClass&& rReference = SomeClass(); //OK pour lier la référence rvalue à rvalue

// Les deux références peuvent être utilisées de la même façon


SomeOtherClass value1 = SomeFunc(lReference);
SomeOtherClass value2 = SomeFunc(rReference);
Dans l'exemple ci-dessus, SomeClass() n'est pas lié à un identificateur, c'est ainsi un rvalue et il ne peut pas être lié à une
référence rvalue -- mais pas une référence lvalue.

Elimination de la copie inutile


Dans la plupart des cas, des données qui doivent seulement être déplacées sont copiées, c'est-à-dire que le conteneur des
données d'origine ne doit pas conserver les données. Un exemple est la permutation des données dans deux structures, ainsi
aucune des structures ne contient les données précédentes. Il serait logiquement suffisant de permuter simplement les
références aux données.

Les références rvalue peuvent être utilisées pour distinguer les cas qui nécessitent une copie des cas qui nécessitent
simplement le déplacement des données. Etant donné que la copie est une opération longue, vous souhaiterez l'éviter autant
que possible.

Si une fonction souhaite copier quelque chose qui lui a été passé en tant que rvalue, elle peut alors faire un déplacement au lieu
d'une copie, car elle sait que la valeur est temporaire. Si un lvalue a été passé à la fonction, il peut s'avérer nécessaire de faire
une copie complète car le remplacement de la copie ne s'applique pas. Vous pouvez distinguer ces cas avec la signature de
fonction.

Considérons une classe ExampleClass ayant une fonction clone qui effectue une copie complète des instances de classe. Vous
pouvez définir une fonction move qui déplace une valeur d'objet. Cette fonction peut être surchargée comme suit :
// Le paramètre est un lvalue
ExampleClass move(ExampleClass& l)
{
return l.clone(); // renvoie une copie puisque nous ne pouvons pas toucher à la valeur
d'origine

// Le paramètre est un rvalue


ExampleClass move(ExampleClass&& r)
{
return r; // renvoie une référence puisque nous ne soucions pas de la valeur du
temporaire
}
template class MyClass<int>;
...
extern template class MyClass<int>; // non autorisé
extern template class MyClass<float>; // OK
3 Nous pouvons ensuite utiliser la fonction move pour les rvalues et lvalues :
ExampleClass a, b, c;
a = ExampleClass();
b = b.move(a); // Le paramètre est un lvalue
c = c.move(ExampleClass()); // Le paramètre est un rvalue
Notez que la fonction move pour le paramètre rvalue est très petite afin qu'elle s'exécute beaucoup plus rapidement que la
fonction move pour un paramètre lvalue.

Vous pouvez utiliser une technique similaire pour les fonctions qui nécessitent des copies, comme les constructeurs de copie et

508
3.1 Référence C++ RAD Studio Guide du langage C++

les opérateurs d'affectation. Supposons que nous avons une classe template avec un pointeur sur une autre classe, où clone est
de nouveau une fonction de copie complète :
template <class T>
class PointerClass
{
private:
T* pointer;
public:
// Constructeur régulier
PointerClass(void);

// Constructeur de copie pour les lvalues


PointerClass(PointerClass& pcl) : pointer(pcl.pointer ? pcl.pointer.clone() : 0) {} //
faire une copie complète
// Constructeur de copie pour les rvalues
PointerClass(PointerClass&& pcr) : pointer(pcr.pointer) {pcr.pointer = 0;}
Le constructeur de copie qui prend un rvalue :

• Effectue un déplacement, pas une copie. Il renvoie simplement une référence aux données.
• Traite l'argument rvalue pcr comme un lvalue dans son code.
• Laisse l'objet rvalue dans un état défini afin qu'il puisse être supprimé en toute sécurité.
Types non copiables mais déplaçables
Les types qui ne sont pas copiables, comme ceux utilisant unique_ptr, peuvent être rendus déplaçables. Bien qu'ils ne puissent
pas définir des opérateurs d'affectation, ils peuvent implémenter des fonctions de déplacement et des fonctions de permutation,
puisque celles-ci ne nécessitent pas la copie quand des références rvalue sont utilisées. Une fonction de tri pourrait être
développée, puisqu'elle requiert seulement la permutation, et pas la copie.

Par exemple, considérons la fonction factory qui prend un argument :


template <class T, class U>
factory(const U& u)
{
return new T(u);
}
La définition ci-dessus de factory fonctionne dans ce cas :
T* p = factory<T>(7);
Toutefois, une erreur de compilation survient quand un T, dont le paramètre du constructeur est une référence non-const, est
utilisé. Vous pourriez corriger ce cas en retirant const de la définition :
template <class T, class U>
factory(U& u)
{
return new T(u);
}
Toutefois, l'exemple précédent échoue maintenant :
T* p = factory<T>(7); // erreur du compilateur
T* u = new T(7); // OK 3
Cela génère une erreur puisque la valeur 7 provoque la correspondance de l'argument template sur int &, mais cela n'effectue
pas la liaison au rvalue 7.

Cela pourrait être résolu en définissant une fonction factory pour chaque cas de const et non-const. C'est problématique, car le
nombre de fonctions nécessaires augmente de manière exponentielle avec le nombre d'arguments.

Si l'argument devient une référence rvalue, vous pouvez simplifier la situation :


template <class T, class U.

509
Guide du langage C++ RAD Studio 3.1 Référence C++

factory(u&& u)
{
return new T(forward<U>(u));
}
L'argument u est maintenant lié aux rvalues et lvalues. La fonction forward renvoie un rvalue ou un lvalue, exactement comme
s'il avait été passé. Elle peut être définie de cette façon :
template <class U>
struct identity
{
typedef U type;
};

template <class U>


U&& forward(typename identity<U>::type&& u)
{
return u;
}
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Proposition d'ajout d'une référence Rvalue au langage C++

Brève introduction aux références Rvalue

3.1.4.1.19.8 Assertions statiques (C++0x)


Le mot clé static_assert est utilisé pour tester les assertions durant la compilation. C'est l'une des fonctionnalités ajoutées à
C++Builder 2009.

Ce mot clé opère d'une façon différente de la macro assert, qui déclenche des assertions durant l'exécution. Le mot clé
static_assert diffère également de la directive de préprocesseur #error, qui opère durant le prétraitement et émet simplement
un message.

Syntaxe
La déclaration d'une assertion statique est :
static_assert (expression-constante, message erreur);
expression-constante doit être une expression qui peut être évaluée statiquement comme un booléen. Si
expression-constante est évaluée à true, l'instruction ne fait rien. Si elle est évaluée à false, le compilateur génère une
erreur avec le texte message-erreur. Puisque l'assertion est testée à la compilation, static_assert peut faire une erreur de
vérification dans les templates. Par exemple :
template <class T>
T Test(T x, T y) {
static_assert(sizeof T <= sizeof long, "Type trop grand");
...
};
static_assert est utile pour la vérification de type statique. Une certaine fonction peut échouer si l'implémentation d'un int est
3 trop petit, ainsi static_assert a son utilité en dehors des templates.

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Working Draft - Standard for Programming Language C++ (Sec. 7.1

Specifiers)

510
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.1.19.9 Enumérations fortement typées (C++0x)


C++Builder 2009 introduit les énumérations de portée. En outre, les énumérations existantes sont étendues avec le type
sous-jacent et la portée explicite. Cette fonctionnalité fait partie des fonctionnalités C++0x ajoutées à C++Builder 2009.

Les énumérations de portée sont généralement caractérisées comme suit :

• Les énumérateurs sont dans la portée de leur énumération.


• Les énumérateurs et les énumérations ne sont pas implicitement convertis en int (comme le font les énumérations et
énumérateurs "ordinaires").
• Les énumérations et les énumérateurs peuvent avoir un type sous-jacent défini.
Déclaration
Vous déclarez une énumération de portée en spécifiant enum class ou enum struct. Par exemple :
enum class A {A1, A2, A3 = 50, A4 /* = 51 */};
Pas de conversion de type implicite
Avec les énumérations de portée, il n'y a plus de conversion implicite vers ou depuis un integer.

Type sous-jacent
Pour les énumérations de portée, le type sous-jacent est bien spécifié (la valeur par défaut est int). Vous pouvez spécifier le type
sous-jacent de l'énumération et de tous les énumérateurs en écrivant : le type après le nom de l'énumération (vous pouvez
spécifier tout type intégral à l'exception de wchar_t). L'exemple suivant déclare une énumération de type sous-jacent unsigned
long :
enum class A : unsigned long {A1 = 1, A2 = 2, Abig = 0xFFFFFFFOU };
Portée
Une énumération de portée introduit sa propre portée. Les noms des énumérateurs sont dans la portée de l'énumération, et ne
sont pas injectés dans la portée englobante. Par exemple :
enum class A { A1, A2, A3 = 100, A4 /* = 101 */ };
A a1 = A1; // erreur
A a2 = A::A2; // OK-portée spécifiée
Changements apportés aux énumérations existantes
De plus, les énumérations existantes sont étendues comme suit :

• Vous pouvez maintenant spécifier le type sous-jacent de n'importe quelle énumération, simplement comme avec les
énumérations de portée (en ajoutant : type à la déclaration).
• Les énumérations existantes introduisent maintenant leur propre portée, simplement comme avec les énumérations de
portée. Les noms des énumérateurs sont définis dans la portée de l'énumération et sont également injectés dans la portée
englobante.
Par exemple :
enum B { B1, B2, B3 = 100, B4 /* = 101 */ };
B b1 = B1; // ok
B b2 = B::B2; // ok
3
Exemples
Les exemples suivants illustrent les deux points suivants :

• La méthode d'appel des énumérateurs de portée


• Le fait que 'enum class' (et 'enum struct') ne peuvent pas être spécifiés avec les spécificateurs de type élaboré
enum class E { a, b };
enum E x1 = E::a; // OK
enum class E x2 = E::a; // illégal

511
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Enumérations fortement typées (révision 3)

3.1.4.1.19.10 Spécificateur de type decltype (C++0x)


Le standard C++0x inclut l'opérateur et le mot clé decltype, qui représentent le type d'une expression. Cette fonctionnalité fait
partie des fonctionnalités C++0x ajoutées à C++Builder 2009.

Syntaxe
Voici le format de l'opérateur decltype :
decltype ( expression )
Voici les règles d'évaluation de decltype(e) :

• Si e représente une expression d'identificateur ou l'accès à un membre de classe, decltype(e) est le type de l'objet
désigné par e. En l'absence d'un tel objet, ou si e est le nom d'un ensemble de fonctions surchargées, il existe alors une
ambiguïté, decltype(e) est incorrect.
• Sinon, si e est un appel de fonction ou invoque un opérateur surchargé, decltype(e) est le type renvoyé par la fonction.
• Sinon, si e est un lvalue, decltype(e) est une référence à T (T&) où T est le type de e.
• Si aucun des autres cas s'applique, decltype(e) est le type de e.
Exemples
Voir le contenu incorporé des exemples suivants.
const char *namePtr, nameChar;
decltype(namePtr); // le type est const char*
decltype(nameChar); // le type est const char
int& F(void);
decltype(F()); // le type est int&

struct; D {double value; }


const D* d = new D();

decltype(d->value); // le type est double


decltype((d->value)); // le type est const double&

double GetValue(int one);


long int GetValue(double d);
decltype(GetValue); // mal formé -- ambigu
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Working Draft - Standard for Programming Language C++ (Sec. 7.1.6.2 - Simple Type Specifiers)

3.1.4.1.19.11 Littéraux et types de caractères Unicode (C++0x)


3
C++Builder 2009 implémente les nouveaux littéraux caractère et types de caractères pour Unicode. Ces types appartiennent aux
fonctionnalités C++0x ajoutées à C++Builder 2009.

Types de caractères char16_t et char32_t


Deux nouveaux types représentent les caractères Unicode :

• char16_t est un type de caractère 16 bits. char16_t est un mot clé C++. Ce type peut être utilisé pour les caractères UTF-16.
• char32_t est un type de caractère 32 bits. char32_t est un mot clé C++. Ce type peut être utilisé pour les caractères UTF-32.

512
3.1 Référence C++ RAD Studio Guide du langage C++

Le type wchar_t existant est le type d'un caractère étendu de l'ensemble des caractères étendus d'exécution. Un littéral
caractère étendu wchar_t commence par un L majuscule (comme L'c').
Les littéraux caractère u'caractère' et U'caractère'
Il existe deux nouvelles formes permettant de créer des littéraux des nouveaux types :

• u'caractère' est un littéral pour un caractère char16_t unique, comme u'g'. Un littéral multi-caractère comme u'kh' est mal
formé. La valeur d'un littéral char16_t est égale à la valeur de son point de code ISO 10646, à condition que le point de code
soit représentable sous la forme d'un cvalue 16 bits. Seuls les caractères du BMP (Basic Multi-lingual Plane) peuvent être
représentés.
• U'caractère' est un littéral pour un caractère char32_t unique, comme U't'. Un littéral multi-caractère comme U'de' est mal
formé. La valeur d'un littéral char32_t est égale à la valeur de son point de code ISO 10646.
Les littéraux caractère multi-octets étaient auparavant seulement de la forme L'caractères', représentant un ou plusieurs
caractères du type wchar_t. La valeur d'un littéral caractère étendu unique est le codage de ce caractère dans l'ensemble des
caractères étendus d'exécution.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Working Draft

Standard for Programming Language C++ (Sec. 2.13.2

Character Literals)

3.1.4.1.20 Unicode pour C++


Cette section contient les rubriques des fonctionnalités associées à Unicode pour C++.

Rubriques
Nom Description
Mappage TCHAR ( see page 513) TCHAR, qui est déclaré dans le fichier d'en-tête tchar.h, est un typedef (alias)
qui est mappé en char ou wchar_t. Lorsque vous voulez écrire du code
portable, utilisez TCHAR au lieu de coder en dur char ou wchar_t.
L'option Mappage de _TCHAR en contrôle la définition flottante de _TCHAR. Vos
choix sont

• wchar_t : définit les définitions UNICODE et _UNICODE et


utilise les définitions étendues de la bibliothèque standard
et des fonctions API.
• char : _TCHAR ne migre pas vers une définition étendue
Pour définir l'option Mappage de _TCHAR en, ouvrez la
page Projet... suite ( see page 513)
Fonctions flottantes ( see page 514) Cette rubrique décrit comment écrire du code portable qui utilise correctement
les définitions flottantes des fonctions RTL. La liste des fonctions flottantes est
utile pour choisir le variant correct d'une fonction.

3.1.4.1.20.1 Mappage TCHAR


3
TCHAR, qui est déclaré dans le fichier d'en-tête tchar.h, est un typedef (alias) qui est mappé en char ou wchar_t. Lorsque vous
voulez écrire du code portable, utilisez TCHAR au lieu de coder en dur char ou wchar_t.

L'option Mappage de _TCHAR en contrôle la définition flottante de _TCHAR. Vos choix sont

• wchar_t : définit les définitions UNICODE et _UNICODE et utilise les définitions étendues de la bibliothèque standard et des
fonctions API.
• char : _TCHAR ne migre pas vers une définition étendue

513
Guide du langage C++ RAD Studio 3.1 Référence C++

Pour définir l'option Mappage de _TCHAR en, ouvrez la page Projet Options Répertoires et Conditions.
Utiliser "Mappage de _TCHAR en" wchar_t pour la VCL
La VCL est implémentée dans Unicode et attend toujours Unicode. Pour utiliser la VCL, vous devez définir Mappage de
_TCHAR en sur wchar_t. Par exemple, le code suivant ne compile pas, à moins que vous ne définissiez _TCHAR sur wchar_t:
TResourceStream* res = new
TResourceStream(HInstance, ResourceId, RT_RCDATA);
Si _TCHAR est char, RT_RCDATA est mappé en un char*, mais la VCL attend wchar_t.

Utiliser la fonction _TEXT pour les chaînes constantes


Pour garantir que les chaînes constantes migrent correctement en ANSI ou Unicode, utilisez la fonction _TEXT ou _T. Par
exemple :
::MessageBox(0, _TEXT("Le message"),
_TEXT("Le libellé"), MB_OK);
Modifications de code nécessaires pour utiliser "Mappage de _TCHAR en wchar_t"
Avant de définir l'option _TCHAR sur wchar_t, votre projet doit avoir un point d'entrée appelé _tmain ou _tWinMain. Les
nouveaux projets créés avec C++Builder 2009 ont ces points d'entrée par défaut, mais les projets importés peuvent nécessiter
l'ajout manuel de ces points d'entrée. Vous devez également inclure le fichier d'en-tête tchar.h, qui contient les définitions
flottantes et les points d'entrée nécessaires. Pour obtenir la liste des fonctions flottantes contenues dans tchar.h, voir
floatingfunctions.xml ( see page 514).

Voir aussi
floatingfunctions.xml ( see page 514)

3.1.4.1.20.2 Fonctions flottantes


Cette rubrique décrit comment écrire du code portable qui utilise correctement les définitions flottantes des fonctions RTL. La
liste des fonctions flottantes est utile pour choisir le variant correct d'une fonction.

Exemple d'écriture d'un code portable utilisant _TCHAR


Les fonctions RTL sont disponibles dans les définitions ANSI/MBCS ou Unicode. Par exemple, la fonction RTL strlen peut être
utilisée dans le mode ANSI/MBCS comme suit :
void StorePersonData(const char* name)
{
PersistToDB(name, strlen(name));
}

Une façon plus portable d'écrire ce code est :

void StorePersonData(const _TCHAR* name)


{
PersistToDB(name, _tcstrlen(name));
}
Cet exemple suppose que PersistToDB a une version Unicode. Notez que pour les fonctions qui ne vont pas changer ou
3 migrer, vous devriez utiliser char ou wchar_t.

Liste des définitions flottantes de tchar.h


Le tableau suivant est dérivé du fichier d'en-tête tchar.h. La colonne char/ANSI liste les fonctions flottantes appropriées quand
_TCHAR est mappé en char, la version ANSI de la fonction. La colonne wchar_t/UNICODE liste les fonctions pour wchar_t, la
version UNICODE de la fonction. La colonne _TCHAR/Portable liste la version portable de la fonction, qui est mappée sur la
fonction appropriée (version ANSI ou UNICODE) comme déterminé par le paramétrage en cours de l'option de mappage
_TCHAR.

514
3.1 Référence C++ RAD Studio Guide du langage C++

Définitions de fonction flottante de tchar.h

char / ANSI wchar_t / UNICODE _TCHAR / Portable


_access _waccess _taccess
_atoi64 _wtoi64 _tstoi64
_atoi64 _wtoi64 _ttoi64
_cgets _cgetws cgetts
_chdir _wchdir _tchdir
_chmod _wchmod _tchmod
_cprintf _cwprintf _tcprintf
_cputs _cputws _cputts
_creat _wcreat _tcreat
_cscanf _cwscanf _tcscanf
_ctime64 _wctime64 _tctime64
_execl _wexecl _texecl
_execle _wexecle _texecle
_execlp _wexeclp _texeclp
_execlpe _wexeclpe _texeclpe
_execv _wexecv _texecv
_execve _wexecve _texecve
_execvp _wexecvp _texecvp
_execvpe _wexecvpe _texecvpe
_fdopen _wfdopen _tfdopen
_fgetchar _fgetwchar _fgettchar
_findfirst _wfindfirst _tfindfirst
_findnext64 _wfindnext64 _tfindnext64
_findnext _wfindnext _tfindnext
_findnexti64 _wfindnexti64 _tfindnexti64
_fputchar _fputwchar _fputtchar
_fsopen _wfsopen _tfsopen
_fullpath _wfullpath _tfullpath
_getch _getwch _gettch
_getche _getwche _gettche
_getcwd _wgetcwd _tgetcwd
3
_getdcwd _wgetdcwd _tgetdcwd
_ltoa _ltow _ltot
_makepath _wmakepath _tmakepath
_mkdir _wmkdir _tmkdir
_mktemp _wmktemp _tmktemp
_open _wopen _topen

515
Guide du langage C++ RAD Studio 3.1 Référence C++

_popen _wpopen _tpopen


_putch _putwch _puttch
_putenv _wputenv _tputenv
_rmdir _wrmdir _trmdir
_scprintf _scwprintf _sctprintf
_searchenv _wsearchenv _tsearchenv
_snprintf _snwprintf _sntprintf
_snscanf _snwscanf _sntscanf
_sopen _wsopen _tsopen
_spawnl _wspawnl _tspawnl
_spawnle _wspawnle _tspawnle
_spawnlp _wspawnlp _tspawnlp
_spawnlpe _wspawnlpe _tspawnlpe
_spawnv _wspawnv _tspawnv
_spawnve _wspawnve _tspawnve
_spawnvp _wspawnvp _tspawnvp
_spawnvpe _wspawnvpe _tspawnvpe
_splitpath _wsplitpath _tsplitpath
_stat64 _wstat64 _tstat64
_stat _wstat _tstat
_stati64 _wstati64 _tstati64
_strdate _wstrdate _tstrdate
_strdec _wcsdec _tcsdec
_strdup _wcsdup _tcsdup
_stricmp _wcsicmp _tcsicmp
_stricoll _wcsicoll _tcsicoll
_strinc _wcsinc _tcsinc
_strlwr _wcslwr _tcslwr
_strncnt _wcsncnt _tcsnbcnt
_strncnt _wcsncnt _tcsnccnt
_strncnt _wcsncnt _tcsnccnt
_strncoll _wcsncoll _tcsnccoll

3 _strnextc _wcsnextc _tcsnextc


_strnicmp _wcsnicmp _tcsncicmp
_strnicmp _wcsnicmp _tcsnicmp
_strnicoll _wcsnicoll _tcsncicoll
_strnicoll _wcsnicoll _tcsnicoll
_strninc _wcsninc _tcsninc
_strnset _wcsnset _tcsncset

516
3.1 Référence C++ RAD Studio Guide du langage C++

_strnset _wcsnset _tcsnset


_strrev _wcsrev _tcsrev
_strset _wcsset _tcsset
_strspnp _wcsspnp _tcsspnp
_strtime _wstrtime _tstrtime
_strtoi64 _wcstoi64 _tcstoi64
_strtoui64 _wcstoui64 _tcstoui64
_strupr _wcsupr _tcsupr
_tempnam _wtempnam _ttempnam
_ui64toa _ui64tow _ui64tot
_ultoa _ultow _ultot
_ungetch _ungetwch _ungettch
_unlink _wunlink _tunlink
_utime64 _wutime64 _tutime64
_utime _wutime _tutime
_vscprintf _vscwprintf _vsctprintf
_vsnprintf _vsnwprintf _vsntprintf
asctime _wasctime _tasctime
atof _wtof _tstof
atoi _wtoi _tstoi
atoi _wtoi _ttoi
atol _wtol _tstol
atol _wtol _ttol
ctime _wctime _tctime
fgetc fgetwc _fgettc
fgets fgetws _fgetts
fopen _wfopen _tfopen
fprintf fwprintf _ftprintf
fputc fputwc _fputtc
fputs fputws _fputts
freopen _wfreopen _tfreopen
fscanf fwscanf _ftscanf
getc getwc _gettc 3
getchar getwchar _gettchar
getenv _wgetenv _tgetenv
gets getws _getts
isalnum iswalnum _istalnum
isalpha iswalpha _istalpha
isascii iswascii _istascii

517
Guide du langage C++ RAD Studio 3.1 Référence C++

iscntrl iswcntrl _istcntrl


isdigit iswdigit _istdigit
isgraph iswgraph _istgraph
islower iswlower _istlower
isprint iswprint _istprint
ispunct iswpunct _istpunct
isspace iswspace _istspace
isupper iswupper _istupper
isxdigit iswxdigit _istxdigit
main wmain _tmain
perror _wperror _tperror
printf wprintf _tprintf
putc putwc _puttc
putchar putwchar _puttchar
puts _putws _putts
remove _wremove _tremove
rename _wrename _trename
scanf wscanf _tscanf
setlocale _wsetlocale _tsetlocale
sprintf swprintf _stprintf
sscanf swscanf _stscanf
strcat wcscat _tcscat
strchr wcschr _tcschr
strcmp wcscmp _tcscmp
strcoll wcscoll _tcscoll
strcpy wcscpy _tcscpy
strcspn wcscspn _tcscspn
strerror _wcserror _tcserror
strftime wcsftime _tcsftime
strlen wcslen _tcsclen
strlen wcslen _tcslen
strncat wcsncat _tcsncat

3 strncat wcsncat _tcsnccat


strncmp wcsncmp _tcsnccmp
strncmp wcsncmp _tcsncmp
strncpy wcsncpy _tcsnccpy
strncpy wcsncpy _tcsncpy
strpbrk wcspbrk _tcspbrk
strrchr wcsrchr _tcsrchr

518
3.1 Référence C++ RAD Studio Guide du langage C++

strspn wcsspn _tcsspn


strstr wcsstr _tcsstr
strtod wcstod _tcstod
strtok wcstok _tcstok
strtol wcstol _tcstol
strtoul wcstoul _tcstoul
strxfrm wcsxfrm _tcsxfrm
system _wsystem _tsystem
tmpnam _wtmpnam _ttmpnam
tolower towlower _totlower
toupper towupper _totupper
ungetc ungetwc _ungettc
vfprintf vfwprintf _vftprintf
vprintf vwprintf _vtprintf
vsprintf vswprintf _vstprintf
WinMain wWinMain _tWinMain

Voir aussi
tcharmapping.xml ( see page 513)

3.1.4.2 Liste alphabétique des mots clés


Cette section présente la liste alphabétique des mots clés.

Rubriques
Nom Description
__automated ( see page 528) Catégorie
Extensions des mots clés
Syntaxe
__classid ( see page 529) Catégorie
Opérateurs, Extensions des mots clés
Syntaxe
__closure ( see page 529) Catégorie
Extensions des mots clés
Syntaxe
__declspec ( see page 529) Catégorie
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe
__dispid ( see page 531) Catégorie 3
Modificateurs
Syntaxe
__except ( see page 531) Catégorie
Instructions, Extensions des mots clés
Syntaxe
__inline ( see page 531) Catégorie
Extensions des mots clés
Syntaxe

519
Guide du langage C++ RAD Studio 3.1 Référence C++

__int8, __int16, __int32, __int64, __int64 non signés, types entiers étendus ( Catégorie
see page 532) Extensions des mots clés
Description
Vous pouvez spécifier la taille des types entiers. Vous devez utiliser le suffixe
approprié avec les entiers étendus.
__msfastcall ( see page 532) Catégorie
Modificateurs, Extensions des mots clés
Syntaxe
__msreturn ( see page 533) Catégorie
Modificateurs, Extensions des mots clés
Syntaxe
__property ( see page 533) Catégorie
Extensions des mots clés
Syntaxe
__published ( see page 533) Catégorie
Extensions des mots clés
Syntaxe
Mot clé __rtti et option -RT ( see page 534) Catégorie (mot clé __rtti)
Modificateurs, Extensions des mots clés C++, Mots clés spécifiques C++
Description
L'identification de type à l'exécution est activée par défaut. Vous pouvez
désactiver RTTI sur la page C++ de la boîte de dialogue Options du projet. À
partir de la ligne de commande, utilisez l'option -RT- pour le désactiver ou -RT
pour l'activer.
Si RTTI est activé, ou si l'argument passé à typeid est un pointeur ou une
référence à une classe non polymorphe, typeid renvoie une référence à un objet
const type_info, qui décrit le type déclaré du pointeur ou de la référence, et
non... suite ( see page 534)
__thread, Variables multithreads ( see page 535) Catégorie
Extensions des mots clés
Description
Le mot clé __thread est utilisé dans des programmes multitâches pour conserver
une copie unique de variables classe globales et statiques. Chaque programme
thread conserve une copie privée d'une variable __thread pour chaque thread.
La syntaxe est Type __thread nom_variable. Par exemple :
__try ( see page 535) Catégorie
Instructions, Extensions des mots clés
Syntaxe
_export, __export ( see page 536) Catégorie
Modificateurs, Extensions des mots clés
Forme 1
_fastcall, __fastcall ( see page 536) Catégorie
Modificateurs, Extensions des mots clés
Syntaxe
_stdcall, __stdcall ( see page 537) Catégorie
Modificateurs, Extensions des mots clés
Syntaxe
alignof ( see page 537) Catégorie
Opérateurs, Extensions des mots clés
Syntaxe

520
3.1 Référence C++ RAD Studio Guide du langage C++

and, && ( see page 538) Catégorie


Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur and est une représentation alternative de l'opérateur && (AND
logique ou binaire).
Si les deux opérandes ont la valeur true, le résultat a la valeur true. Sinon, le
résultat a la valeur false. Les deux opérandes sont implicitement convertis en
bool et le type du résultat est bool.
A l'inverse de l'opérateur & (AND bit-à-bit), l'opérateur && garantit une évaluation
gauche-à-droite des opérandes. Si l'opérande gauche est évalué à 0 (ou false),
l'opérande droite n'est pas évalué.
Les opérateurs and et && sont des opérateurs court-circuits (c'est-à-dire que le...
suite ( see page 538)
asm, _asm, __asm ( see page 538) Catégorie
Extensions des mots clés, mots clés spécifiques à C++
Syntaxe
auto ( see page 539) Catégorie
Spécificateurs de classe de stockage
Syntaxe
bitand, & ( see page 539) Catégorie
Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur bitand est une représentation alternative de l'opérateur & (AND
bit-à-bit).
L'opérateur AND bit-à-bit compare chaque bit du premier opérande au bit
correspondant du second opérande. Quand les deux bits sont à 1, le bit de
résultat correspondant est défini sur 1. Sinon, il est défini sur 0.
Afin d'utiliser l'opérateur bitand, vous devez activer l'option Activer les
nouveaux noms d'opérateur (le commutateur -Vn du compilateur, disponible
sur la page Compatibilité de la boîte de dialogue Projet Options).
bitor, | ( see page 539) Catégorie
Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur bitor est une représentation alternative de l'opérateur |~ (OR
bit-à-bit).
bitor prend des opérandes entiers ou d'énumération. bitor peut passer deux ou
davantage d'arguments. Ces arguments doivent être des valeurs caractère ou
numérique.
Quand il est codé comme un mot clé, bitor peut seulement passer deux
arguments. Dans chaque cas, le type du résultat est le même que celui des
arguments. (1) non signé si tous les arguments sont non signés, ou (2) un
integer.
Afin d'utiliser l'opérateur bitor, vous devez activer l'option Activer les nouveaux
noms d'opérateur... suite ( see page 539)
bool, false, true ( see page 540) Catégorie
Mots clés spécifiques C++
Syntaxe
break ( see page 540) Catégorie
Instructions
Syntaxe
Description
Utilisez l'instruction break dans les boucles pour passer le contrôle à la première
instruction suivant le bloc switch, for, while ou do le plus intérieur. 3
Exemple
Cet exemple illustre l'utilisation des mots clés break, case, default et switch.
case ( see page 541) Catégorie
Instructions
Syntaxe
catch ( see page 542) Catégorie
Instructions, Mots clés spécifiques C++
Syntaxe

521
Guide du langage C++ RAD Studio 3.1 Référence C++

cdecl, _cdecl, __cdecl ( see page 542) Catégorie


Modificateurs, Extensions des mots clés
Syntaxe
char ( see page 543) Catégorie
Spécificateurs de type
Syntaxe
class ( see page 543) Catégorie
Mots clés spécifiques C++, Spécificateurs de type
Syntaxe
compl, ~ ( see page 544) Catégorie
Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur compl est une représentation alternative de l'opérateur ~ (NOT
bit-à-bit).
L'opérateur compl est l'abréviation de complément.
compl inverse true en false, et false en true. Le tilde (~) est placé devant l'integer
utilisé pour le complément.
Le complément de 1 est 0, et vice-versa.
En plus d'un integer, ~ génère également un type énumération ; cela peut être le
résultat du complément à 1 de l'opérande. Des calculs intégrals sont effectués.
Le type du résultat est le type de l'opérande promu.
Il peut y avoir une ambiguïté dans l'expression unaire... suite ( see page 544)
const ( see page 544) Catégorie
Modificateurs
Syntaxe
Const_cast (opérateur de transtypage) ( see page 545) Catégorie
Mots clés spécifiques C++
Syntaxe
continue ( see page 546) Catégorie
Instructions
Syntaxe
__declspec(dllexport) ( see page 546) Catégorie
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe
__declspec(dllimport) ( see page 547) Catégorie
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe
__declspec(naked) ( see page 547) Catégorie
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe
__declspec(noreturn) ( see page 547) Catégorie
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe
__declspec(nothrow) ( see page 548) Catégorie
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe
__declspec(novtable) ( see page 548) Catégorie
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe
__declspec(property) ( see page 549) Catégorie
3 Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe
__declspec(selectany) ( see page 549) Catégorie
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe
__declspec(thread) ( see page 550) Catégorie
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe

522
3.1 Référence C++ RAD Studio Guide du langage C++

__declspec(uuid("ComObjectGUID")) ( see page 550) Catégorie


Modificateurs, extensions de mot clé, spécificateurs de classe de stockage
Syntaxe
default ( see page 551) Catégorie
Instructions
Syntaxe
delete ( see page 552) Catégorie
Opérateurs, Mots clés spécifiques C++
Syntaxe
do ( see page 552) Catégorie
Instructions
Syntaxe
double ( see page 552) Catégorie
Spécificateurs de type
Syntaxe
Dynamic_cast (opérateur de transtypage) ( see page 553) Catégorie
Mots clés spécifiques C++
Description
Dans l'expression dynamic_cast< T > (ptr), T doit être un pointeur, ou une
référence, à un type classe défini ou void*. L'argument ptr doit être une
expression résultant en un pointeur ou en une référence.
Si T est void*, ptr doit aussi être un pointeur. Le pointeur qui en résulte peut alors
accéder à tout élément de la classe la plus dérivée dans la hiérarchie. Une
classe de ce genre ne peut servir de base à aucune autre classe.
Les conversions de classe dérivée en classe de base, ou de classe dérivée en...
suite ( see page 553)
enum ( see page 553) Catégorie
Spécificateurs de type
Syntaxe
explicit ( see page 554) Catégorie
Mots clés spécifiques C++
Syntaxe
export ( see page 555) Catégorie
Non implémenté
Syntaxe
extern ( see page 555) Catégorie
Spécificateurs de classe de stockage
Syntaxe
final ( see page 556) Catégorie
Attributs, extensions des mots clés
Syntaxe
__finally ( see page 556) Catégorie
Instructions, Extensions des mots clés
Syntaxe
float ( see page 557) Catégorie
Spécificateurs de type
Syntaxe
for ( see page 558) Catégorie
Instructions
Syntaxe
friend ( see page 558) Catégorie
Mots clés spécifiques C++ 3
Syntaxe
goto ( see page 559) Catégorie
Instructions
Syntaxe
if, else ( see page 559) Catégorie
Opérateurs
Syntaxe

523
Guide du langage C++ RAD Studio 3.1 Référence C++

import, _import, __import ( see page 559) Catégorie


Modificateurs, Extensions des mots clés
Forme 1
inline ( see page 560) Catégorie
Mots clés spécifiques C++
Syntaxe
int ( see page 560) Catégorie
Spécificateurs de type
Syntaxe
long ( see page 560) Catégorie
Spécificateurs de type
Syntaxe
mutable ( see page 561) Catégorie
Mots clés spécifiques C++, Spécificateurs de classe de stockage
Syntaxe
namespace ( see page 561) Catégorie
Mots clés spécifiques C++
Description
La plupart des applications réelles consistent en plusieurs fichiers source. Les
fichiers peuvent être écrits et maintenus par plusieurs développeurs. Le moment
venu, les fichiers séparés sont organisés et liés pour obtenir l'application finale.
Habituellement, l'organisation des fichiers exige que tous les noms qui ne sont
pas encapsulés dans un espace de nommage défini (comme une fonction, le
corps d'une classe ou une unité de traduction) partagent le même espace de
nommage global. Cependant, des définitions multiples de noms découvertes au
moment de la liaison de modules distincts imposent de distinguer chaque nom.
L'espace... suite ( see page 561)
new ( see page 561) Catégorie
Opérateurs, Mots clés spécifiques C++
Syntaxe
noreturn ( see page 562) Catégorie
Attributs, extensions des mots clés
Syntaxe
not, ! ( see page 563) Catégorie
Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur not est une représentation alternative de l'opérateur ! (négation
logique).
not renvoie true si son opérande est false, et false si son opérande est true.
Si un entier vaut 1, l'expression !1 indique que le nombre est différent de 1. not
peut également être utilisé pour les chaînes. L'expression !Smith indique que le
nom de la personne est autre que Smith. not inverse les bits de l'expression.
Afin d'utiliser l'opérateur not, vous devez activer l'option Activer les nouveaux
noms d'opérateur (le commutateur -VM du compilateur, disponible... suite (
see page 563)
not_eq, != ( see page 563) Catégorie
Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur not_eq est une représentation alternative de l'opérateur != (inégalité
binaire). Il teste l'inéquivalence logique.
not_eq compare deux expressions pour déterminer si elles sont ou pas les
mêmes.
3 Par conséquent, 7 != 8 renvoie true, tandis que 7 != 7 renvoie false. Il en est de
même pour toute expression comme Smith != Smith qui renvoie false.
Afin d'utiliser l'opérateur not_eq, vous devez activer l'option Activer les
nouveaux noms d'opérateur (le commutateur -VM du compilateur, disponible
sur la page Compatibilité de la boîte de dialogue Projet Options).
nullptr ( see page 563) Catégorie
Mots clés spécifiques C++
Syntaxe

524
3.1 Référence C++ RAD Studio Guide du langage C++

operator ( see page 564) Catégorie


Opérateurs, Mots clés spécifiques C++
Syntaxe
or, || ( see page 564) Catégorie
Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur or est une représentation alternative de l'opérateur || (OR logique).
Seules deux instructions peuvent être évaluées en même temps.
or renvoie true si deux valeurs sont différentes, comme 2 et 6.
or renvoie false si les deux valeurs sont identiques, comme 10 et 10.
Afin d'utiliser l'opérateur or, vous devez activer l'option Activer les nouveaux
noms d'opérateur (le commutateur -VM du compilateur, disponible sur la page
Compatibilité de la boîte de dialogue Projet Options).
or_eq, |= ( see page 564) Catégorie
Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur or_eq est une représentation alternative de l'opérateur != (OR
inclusif binaire).
or_eq teste l'équivalence logique ou l'égalité binaire.
or_eq opère sur deux valeurs. Quand la première ou la seconde valeur vaut 1,
true est renvoyé. Quand les valeurs sont égales à 0, false est renvoyé.
Afin d'utiliser l'opérateur not_eq, vous devez activer l'option Activer les
nouveaux noms d'opérateur (le commutateur -VM du compilateur, disponible
sur la page Compatibilité de la boîte de dialogue Projet Options).
pascal, _pascal, __pascal ( see page 565) Catégorie
Modificateurs, Extensions des mots clés
Syntaxe
private ( see page 565) Catégorie
Mots clés spécifiques C++
Syntaxe
protected ( see page 565) Catégorie
Mots clés spécifiques C++
Syntaxe
public ( see page 566) Catégorie
Mots clés spécifiques C++
Syntaxe
register ( see page 566) Catégorie
Spécificateurs de classe de stockage
Syntaxe
Reinterpret_cast (opérateur de transtypage) ( see page 567) Catégorie
Mots clés spécifiques C++
Syntaxe
return ( see page 567) Catégorie
Instructions
Syntaxe
short ( see page 567) Catégorie
Spécificateurs de type
Syntaxe
signed ( see page 568) Catégorie
Spécificateurs de type
Syntaxe 3

525
Guide du langage C++ RAD Studio 3.1 Référence C++

sizeof ( see page 568) Catégorie


Opérateurs
Description
L'opérateur sizeof a deux utilisations distinctes :
sizeof expression-unaire
sizeof (nom-type)
Dans les deux cas, le résultat est une constante entière qui donne la taille en
octets de l'espace mémoire utilisé par l'opérande (déterminé par son type, avec
quelques exceptions). La quantité de mémoire réservée pour chaque type
dépend de la machine.
Dans la première utilisation, le type de l'expression opérande est déterminé sans
évaluer l'expression (et donc sans effets de bord). Lorsque l'opérande est de
type char (signed ou unsigned), sizeof donne pour résultat 1. Lorsque
l'opérande est un élément non-paramètre de type tableau, le... suite ( see page
568)
static ( see page 569) Catégorie
Spécificateurs de classe de stockage
Syntaxe
static_assert ( see page 570) Catégorie
Instructions, Mots clés spécifiques C++
Syntaxe
Static_cast (opérateur de transtypage) ( see page 570) Catégorie
Mots clés spécifiques C++
Syntaxe
struct ( see page 571) Catégorie
Spécificateurs de type
Syntaxe
switch ( see page 572) Catégorie
Instructions
Syntaxe
template ( see page 573) Catégorie
Mots clés spécifiques C++
Syntaxe
this ( see page 573) Catégorie
Mots clés spécifiques C++
Exemple
throw ( see page 574) Catégorie
Instructions, Mots clés spécifiques C++
Syntaxe
try ( see page 574) Catégorie
Instructions, Mots clés spécifiques C++
Syntaxe
typedef ( see page 574) Catégorie
Spécificateurs de classe de stockage
Syntaxe
typeid ( see page 575) Catégorie
Opérateurs, Mots clés spécifiques C++
Syntaxe
typename ( see page 575) Catégorie
Mots clés spécifiques C++
Syntaxe 1
union ( see page 576) Catégorie
3 Spécificateurs de type
Syntaxe
unsigned ( see page 576) Catégorie
Spécificateurs de type
Syntaxe

526
3.1 Référence C++ RAD Studio Guide du langage C++

using (déclaration) ( see page 577) Catégorie


Mots clés spécifiques C++
Description
Il est possible d'accéder individuellement aux membres d'un espace de
nommage en utilisant la syntaxe de déclaration using. Quand vous utilisez une
déclaration using, vous ajoutez les identificateurs déclarés à l'espace de
nommage local. Sa grammaire est
déclaration-using :
using :: identificateur-non-qualifié;
virtual ( see page 577) Catégorie
Mots clés spécifiques C++
Syntaxe
void ( see page 578) Catégorie
Types spéciaux
Syntaxe
volatile ( see page 578) Catégorie
Modificateurs
Syntaxe
wchar_t ( see page 579) Catégorie
Mots clés spécifiques C++, Spécificateurs de type
Syntaxe
while ( see page 579) Catégorie
Instructions
Syntaxe
xor, ^ ( see page 579) Catégorie
Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur xor est une représentation alternative de l'opérateur ^ (xor bit-à-bit).
Il renvoie un résultat true booléen si seulement l'un de ses opérandes est true.
C'est en opposition avec un or inclusif qui indique que les deux instructions
doivent être des integers pour qu'une instruction true soit renvoyée.
Si 2 ou 8.25 sont définis comme des integers, une instruction true sera renvoyée
même si 8.25 est un décimal.
Si Jack et Jill sont tous deux définis comme homme, une instruction true sera
renvoyée même si Jill est une femme.
Afin... suite ( see page 579)
__classmethod ( see page 580) Catégorie
Modificateurs, Extensions des mots clés
Syntaxe
alignas ( see page 580) Catégorie
Mots clés spécifiques C++
Syntaxe
and_eq, &= ( see page 580) Catégorie
Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur and_eq est une représentation alternative de l'opérateur d'affectation
&= (AND bit-à-bit).
La valeur du premier opérande est ajoutée à la valeur du second opérande, et le
résultat est stocké dans le premier opérande.
Afin d'utiliser l'opérateur and_eq, vous devez activer l'option Activer les
nouveaux noms d'opérateur (le commutateur -Vn du compilateur, disponible
sur la page Compatibilité de la boîte de dialogue Projet Options). 3
axiom ( see page 581) Catégorie
Mots clés spécifiques C++
Syntaxe
concept ( see page 581) Catégorie
Mots clés spécifiques C++
Syntaxe
concept_map ( see page 581) Catégorie
Mots clés spécifiques C++
Syntaxe

527
Guide du langage C++ RAD Studio 3.1 Référence C++

constexpr ( see page 581) Catégorie


Mots clés spécifiques C++
Syntaxe
late_check ( see page 582) Catégorie
Mots clés spécifiques C++
Syntaxe
requires ( see page 582) Catégorie
Mots clés spécifiques C++
Syntaxe
thread_local ( see page 582) Catégorie
Mots clés spécifiques C++
Syntaxe
xor_eq, ^= ( see page 583) Catégorie
Représentations alternatives des opérateurs et tokens, Opérateurs
Syntaxe
Description
L'opérateur xor_eq est une représentation alternative de l'opérateur ^=;
(affectation XOR binaire).
True est renvoyé si un nombre du côté gauche de l'équation est identique à un
nombre du côté droit, comme 10*5!=10*2.
False est renvoyé même si 6*3=9*2.
Afin d'utiliser l'opérateur xor, vous devez activer l'option Activer les nouveaux
noms d'opérateur (le commutateur -VM du compilateur, disponible sur la page
Compatibilité de la boîte de dialogue Projet Options).

3.1.4.2.1 __automated
Catégorie

Extensions des mots clés

Syntaxe
_automated: <déclarations>
Description

Les règles de visibilité pour les membres automatisés sont les mêmes que celles s'appliquant aux membres publics. La seule
différence entre les membres automatisés et publics consiste en l'information OLE automation qui est générée pour les fonctions
et propriétés membre déclarées dans une section automated. Cette information de type OLE automation rend possible la
création de serveurs OLE automation.

• Pour une fonction membre, les types de tous les paramètres et le résultat éventuel de la fonction doivent être automatisables.
De même, pour une propriété, le type de la propriété et les types de tous les paramètres de propriété de tableau doivent être
automatisables. Les types automatisables sont : Currency, OleVariant, DelphiInterface, double, int, float, short, String,
TDateTime, Variant et unsigned short. La déclaration de fonctions membres ou de propriétés utilisant des types non
automatisables dans une section __automated provoque une erreur à la compilation.
• Les déclarations de fonctions membres doivent utiliser la convention d'appel __fastcall.
• Les fonctions membres peuvent être virtuelles.
• Les fonctions membres peuvent ajouter __dispid(constant int expression) après la parenthèse fermante de la liste de
3 paramètres.
• Les déclarations de propriétés ne peuvent inclure que des spécificateurs d'accès (__dispid, read et write). Aucun autre
spécificateur (index, stored, default, nodefault) n'est autorisé.
• Les spécificateurs d'accès aux propriétés doivent lister un identificateur de fonction membre. Les identificateurs de données
membre ne sont pas autorisés.
• Les fonctions membres d'accès aux propriétés doivent utiliser la convention d'appel __fastcall.
• Les redéfinitions de propriétés (déclarations de propriétés n'incluant pas le type de propriété) ne sont pas autorisées.

528
3.1 Référence C++ RAD Studio Guide du langage C++

Voir aussi
__dispid ( see page 531)

__closure ( see page 529)

__property ( see page 533)

__published ( see page 533)

3.1.4.2.2 __classid
Catégorie

Opérateurs, Extensions des mots clés

Syntaxe
__classid(classType)
Description

L'opérateur __classid a été ajouté pour prendre en charge le framework VCL. Normalement, les programmeurs ne doivent pas
utiliser directement cet opérateur. Pour de plus amples informations, voir les extensions des mots clés.

Voir aussi
__classmethod ( see page 580)

__property ( see page 533)

3.1.4.2.3 __closure
Catégorie

Extensions des mots clés

Syntaxe
<type> ( __closure * <id> ) (<liste de paramètres>);
Description

Le mot clé __closure a été ajouté pour prendre en charge le framework VCL ; il est utilisé lors de la déclaration des fonctions de
gestionnaire d'événement. Pour de plus amples informations, voir les extensions des mots clés.

Voir aussi
__property ( see page 533)

3.1.4.2.4 __declspec
Catégorie 3
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe
__declspec(<modificateur-decl>)
Description

Pour une liste des arguments du mot clé __declspec utilisés pour le framework VCL, voir la rubrique Déclarations des classes

529
Guide du langage C++ RAD Studio 3.1 Référence C++

VCL.

Utilisez le mot clé __declspec pour indiquer les attributs de classe de stockage pour une variable ou une fonction.

Le mot clé __declspec étend la syntaxe des attributs pour les modificateurs de classe de stockage pour que leur placement
dans une instruction déclarative soit plus souple. Le mot clé __declspec et ses arguments peuvent apparaître n'importe où dans
la liste du déclarateur, au contraire des anciens modificateurs qui ne pouvaient apparaître qu'immédiatement avant
l'identificateur à modifier.
__export void f(void); // incorrect
void __export f(void) // correct
void __declspec(dllexport) f(void); // correct
__declspec(dllexport)void f(void); // correct
class __declspec(dllexport) ClassName { } // correct
Outre les arguments présentés ci-dessus, les arguments gérés modificateur-decl pris en charge sont :

• dllexport
• dllimport
• naked
• noreturn
• nothrow
• novtable
• property
• selectany
• thread
• uuid
Ces arguments sont identiques aux mots clés d'attributs de classe de stockage suivants.

Argument Mot clé comparable


dllexport __export
dllimport __import
thread __thread

Voir aussi
_export ( see page 536)

_import ( see page 559)

__declspec(dllexport) ( see page 546)

__declspec(dllimport) ( see page 547)

__declspec(naked) ( see page 547)

3 __declspec(noreturn) ( see page 547)

__declspec(nothrow) ( see page 548)

__declspec(novtablet) ( see page 548)

__declspec(property) ( see page 549)

__declspec(selectany) ( see page 549)

__declspec(thread) ( see page 550)

530
3.1 Référence C++ RAD Studio Guide du langage C++

__declspec(uuid) ( see page 550)

3.1.4.2.5 __dispid
Catégorie

Modificateurs

Syntaxe
__dispid(expression constante entière)
Description

Une fonction membre qui a été déclarée dans la section __automated d'une classe peut inclure une directive facultative
__dispid(expression constante entière). La directive doit être déclarée après la parenthèse fermante de la liste de paramètres.

L'expression constante entière donne le numéro d'identification de répartition Automation de la fonction membre ou de la
propriété. Si aucune directive dispid n'est utilisée, le compilateur prend automatiquement un numéro supérieur de un au plus
grand numéro d'identification de répartition utilisé par toutes les fonctions membres ou propriétés dans la classe et ses classes
de base.

La spécification d'un numéro d'identification de répartition déjà utilisé dans une directive dispid provoque une erreur à la
compilation.

Voir aussi
__closure ( see page 529)

__property ( see page 533)

3.1.4.2.6 __except
Catégorie

Instructions, Extensions des mots clés

Syntaxe
__except (expression) instruction-composée
Description

Le mot clé __except spécifie l'action qui doit être effectuée lorsque l'exception spécifiée par expression a été déclenchée.

Voir aussi
__finally ( see page 556)

__try ( see page 535)

3.1.4.2.7 __inline 3
Catégorie

Extensions des mots clés

Syntaxe
__inline <type de données> <classe>_<fonction> (<paramètres>) { <instructions>; }
Description

531
Guide du langage C++ RAD Studio 3.1 Référence C++

Utilisez le mot clé __inline pour déclarer ou définir des fonctions C ou C++ inline. Le comportement du mot clé __inline est
identique à celui du mot clé inline, qui n'est pris en charge que dans C++.

Les fonctions inline sont réservées de préférence pour de petites fonctions, fréquemment utilisées.

3.1.4.2.8 __int8, __int16, __int32, __int64, __int64 non signés, types entiers
étendus
Catégorie

Extensions des mots clés

Description

Vous pouvez spécifier la taille des types entiers. Vous devez utiliser le suffixe approprié avec les entiers étendus.

Type Suffixe Exemple Stockage


__int8 i8 __int8 c = 127i8; 8 bits
__int16 i16 __int16 s = 32767i16; 16 bits
__int32 i32 __int32 i = 123456789i32; 32 bits
__int64 i64 __int64 big = 12345654321i64; 64 bits
unsigned __int64 ui64 unsigned __int64 hugeInt = 1234567887654321ui64; 64 bits

Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)

Constantes caractère ( see page 669)

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)


3

3.1.4.2.9 __msfastcall
Catégorie

Modificateurs, Extensions des mots clés

Syntaxe

532
3.1 Référence C++ RAD Studio Guide du langage C++

__msfastcall <nom-fonction>
Description

Cette convention d'appel émule l'implémentation Microsoft de la convention d'appel fastcall. Les deux premiers DWORD ou
arguments plus petits sont transmis dans les registres ECX et EDX, tous les autres arguments sont transmis de droite à gauche.
La fonction appelée est responsable de la suppression de ces arguments de la pile.

3.1.4.2.10 __msreturn
Catégorie

Modificateurs, Extensions des mots clés

Syntaxe
__msreturn <nom-fonction>
Description

Cette convention d'appel est utilisée pour obtenir des valeurs de retour compatibles avec la convention d'appel __fastcall de
Microsoft. Les structures ayant une taille supérieure à 4 octets et inférieure à 9 octets et ayant au moins un de leurs membres de
taille 4 octets ou plus, sont renvoyées dans EAX/EDX.

3.1.4.2.11 __property
Catégorie

Extensions des mots clés

Syntaxe
<déclaration de propriété> ::=
__property <type> <id> [ <liste dim prop> ] = "{" <liste attrib prop> "}"

<liste dim prop> ::=


"[" <type> [ <id> ] "]" [ <liste dim prop> ]

<liste attrib prop> ::=


<attrib prop> [ , <liste attrib prop> ]

<attrib prop> ::=


read = <id fonction/données> |
write = <id fonction/données> |
stored = <id fonction/données> |
stored = <constante booléenne> |
default = <constante> |
nodefault |
index = <expression const int>
Description

Le mot clé __property a été ajouté pour prendre en charge la VCL. 3


Voir aussi
__closure ( see page 529)

3.1.4.2.12 __published
Catégorie

533
Guide du langage C++ RAD Studio 3.1 Référence C++

Extensions des mots clés

Syntaxe
__published: <déclarations>
Description

Le mot clé __published a été ajouté pour prendre en charge la VCL.

Voir aussi
__closure ( see page 529)

__dispid ( see page 531)

3.1.4.2.13 Mot clé __rtti et option -RT


Catégorie (mot clé __rtti)

Modificateurs, Extensions des mots clés C++, Mots clés spécifiques C++

Description

L'identification de type à l'exécution est activée par défaut. Vous pouvez désactiver RTTI sur la page C++ de la boîte de dialogue
Options du projet. À partir de la ligne de commande, utilisez l'option -RT- pour le désactiver ou -RT pour l'activer.

Si RTTI est activé, ou si l'argument passé à typeid est un pointeur ou une référence à une classe non polymorphe, typeid
renvoie une référence à un objet const type_info, qui décrit le type déclaré du pointeur ou de la référence, et non l'objet auquel
le pointeur ou la référence est attaché.

Par ailleurs, même si RTTI est désactivé, vous pouvez faire en sorte que toutes les instances d'une classe donnée et de toutes
ses classes dérivées fournissent des identifications de type polymorphe à l'exécution (lorsque c'est nécessaire) en utilisant le
mot clé __rtti dans la définition de la classe.

Lorsque l'identification de type à l'exécution est désactivée, si une classe de base est déclarée __rtti, alors toutes les classes de
base polymorphes doivent aussi être déclarées __rtti.
struct __rtti S1 { virtual s1func(); }; /* Polymorphe */
struct __rtti S2 { virtual s2func(); }; /* Polymorphe */
struct X : S1, S2 { };
Si vous désactivez le mécanisme RTTI, il se pourrait que les informations de type ne soient plus disponibles pour les classes
dérivées. Lorsqu'une classe est dérivée de plusieurs classes, le fait qu'elle hérite ou non du mécanisme RTTI dépend de l'ordre
et du type des classes de base.

Lorsque vous avez des classes polymorphes et non polymorphes, l'ordre de l'héritage est important. Si vous compilez les
déclarations suivantes sans RTTI, vous devez déclarer X avec le modificateur __rtti. Sinon, basculer l'ordre des classes de base
de la classe X résulte en une erreur de compilation du type "Can't inherit non RTTI class from RTTI base 'S1'".
struct __rtti S1 { virtual func(); }; /* Classe polymorphe */
struct S2 { }; /* Classe non polymorphe */
struct __rtti X : S1, S2 { };
3
Remarque: La classe X est déclarée explicitement avec __rtti

. Cela rend moins dangereux le mélange de l'ordre et des types des classes. Dans l'exemple suivant, la classe X n'hérite que de
classes non polymorphes. La classe X n'a donc pas besoin d'être déclarée __rtti.
struct __rtti S1 { }; // Classe non polymorphe
struct S2 { };
struct X : S2, S1 { }; // L'ordre est sans importance
Ni le mot clé __rtti ni l'activation de RTTI ne transforme une classe statique en classe polymorphe.

534
3.1 Référence C++ RAD Studio Guide du langage C++

Voir aussi
Identification de type à l'exécution (RTTI) ( see page 471)

Identification de type à l'exécution et destructeurs ( see page 472)

3.1.4.2.14 __thread, Variables multithreads


Catégorie

Extensions des mots clés

Description

Le mot clé __thread est utilisé dans des programmes multitâches pour conserver une copie unique de variables classe globales
et statiques. Chaque programme thread conserve une copie privée d'une variable __thread pour chaque thread.

La syntaxe est Type __thread nom_variable. Par exemple :


int __thread x;
Cette instruction déclare un type entier qui sera global, mais propre à chaque mise en oeuvre dans le programme dans lequel
apparaît l'instruction.

3.1.4.2.15 __try
Catégorie

Instructions, Extensions des mots clés

Syntaxe
__try instruction-composée liste-gestionnaires__try
__try instruction-composée instruction-terminaison
Description

Le mot clé __try est pris en charge à la fois dans les programmes C et C++. Vous pouvez aussi utiliser try dans les programmes
C++.

Un bloc de code dans lequel une exception peut se produire doit être préfixé par le mot clé __try. A la suite du mot clé try, il y a
un bloc entouré par des accolades. Cela indique que le programme est préparé à tester l'existence d'exceptions. Si une
exception se produit, le flux normal du programme est interrompu. Le programme commence à chercher un gestionnaire
correspondant à l'exception. Si l'exception est générée dans un module C, il est possible de gérer l'exception structurée dans un
module C ou dans un module C++.

S'il est trouvé un gestionnaire pour l'exception structurée générée, les actions suivantes peuvent se produire :

• Exécution des actions spécifiées par le gestionnaire


• Ignorance de l'exception générée et reprise de l'exécution du programme
• Poursuite de la recherche d'un autre gestionnaire (régénération de l'exception) 3
Si aucun gestionnaire n'est trouvé, le programme appelle la fonction terminate. Si aucune exception ne se produit, le programme
s'exécute en mode normal.
Voir aussi
Catch ( see page 542)

__finally ( see page 556)

535
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.2.16 _export, __export


Catégorie

Modificateurs, Extensions des mots clés

Forme 1
class _export <nom de classe>
Forme 2
return_type _export <nom de fonction>
Forme 3
data_type _export <nom de données>
Description

Ces modificateurs sont utilisés pour exporter les classes, les fonctions et les données.

Le lieur entre des fonctions repérées avec _export ou __export dans une table d'exportation pour le module.

L'utilisation de _export ou __export supprime la nécessité d'une section EXPORTS dans votre fichier de définition de module.

Les fonctions non modifiées par _export ou __export reçoivent un code de prologue et d'épilogue abrégé, ce qui aboutit à un
fichier objet plus petit et une exécution légèrement plus rapide.

Remarque: Si vous utilisez _export

ou __export pour exporter une fonction, cette fonction sera exportée par nom et pas par numéro (l'exportation par numéro est
en général plus efficace). Si vous voulez modifier la valeur par défaut de certains attributs, vous aurez besoin d'un fichier de
définition de module.

Voir aussi
Le mot clé export

3.1.4.2.17 _fastcall, __fastcall


Catégorie

Modificateurs, Extensions des mots clés

Syntaxe
return-value _fastcall nom-fonction (liste-param)
return-value __fastcall nom-fonction (liste-param)
Description

Utilisez le modificateur __fastcall pour déclarer des fonctions qui attendent des paramètres transmis dans les registres. Les trois
3 premiers paramètres sont transmis (de gauche à droite) dans EAX, EDX et ECX, s'ils tiennent dans le registre. Les registres ne
sont pas utilisés si le paramètre est de type virgule flottante ou struct.

Remarque: Toutes les fonctions membres de classe VCL et fonctions membres de classe form doivent utiliser la convention
__fastcall

. Le compilateur traite cette convention d'appel comme un nouveau spécificateur de langage, dans les lignes de _cdecl et
_pascal.

Les fonctions déclarées en utilisant _cdecl ou _pascal ne peuvent pas avoir aussi le modificateur _fastcall car elles utilisent la

536
3.1 Référence C++ RAD Studio Guide du langage C++

pile pour transmettre des paramètres. De même, le modificateur __fastcall ne peut pas être utilisé en même temps que _export.

Le compilateur préfixe le nom de fonction __fastcall avec le signe ("@"). Ce préfixe s'applique à la fois aux noms de fonctions C
non substantypés et aux noms de fonctions C++ substantypés.

Pour implémenter __fastcall dans le style Microsoft C++, voir __msfastcall et __msreturn.

Remarque: Remarque : Le modificateur __fastcall est soumis au substantypage. Voir la description de l'option -VC.

3.1.4.2.18 _stdcall, __stdcall


Catégorie

Modificateurs, Extensions des mots clés

Syntaxe
__stdcall <nom-fonction>
_stdcall <nom-fonction>
Description

Les mots clés _stdcall et __stdcall obligent le compilateur à générer des appels de fonctions utilisant la convention d'appel
standard. Les fonctions doivent transmettre le nombre et le type d'arguments corrects ; ce n'est pas comme l'utilisation normale
en C, qui permet un nombre variable d'arguments de fonction.

De telles fonctions sont conformes à la convention de passage d'argument WIN32.

Remarque: Remarque : Le modificateur __stdcall est soumis au substanstypage. Voir la description de l'option -VC.

3.1.4.2.19 alignof
Catégorie

Opérateurs, Extensions des mots clés

Syntaxe
alignof(type);
Description

L'opérateur alignof vous indique l'alignement d'un type. Cette fonctionnalité fait partie des fonctionnalités C++0x ajoutées à
C++Builder 2009.

Le résultat est une constante entière de type std::size_t. La valeur indique les frontières sur lesquelles les éléments de ce
type sont alignés en mémoire. Par exemple, un alignement de 2 signifie que le type doit commencer sur une adresse mémoire
paire. Une valeur typique pour alignof (double) pourrait être 8.

L'application de alignof à un type référence provoque l'alignement du type référencé. Si vous appliquez alignof sur un type
tableau, vous obtenez l'alignement du type de ses éléments.

Voir aussi
3
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)

Working Draft

Standard for Programming Language C++ (Sec. 5.3.6)

537
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.2.20 and, &&


Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

Syntaxe

Description

L'opérateur and est une représentation alternative de l'opérateur && (AND logique ou binaire).

Si les deux opérandes ont la valeur true, le résultat a la valeur true. Sinon, le résultat a la valeur false. Les deux opérandes sont
implicitement convertis en bool et le type du résultat est bool.

A l'inverse de l'opérateur & (AND bit-à-bit), l'opérateur && garantit une évaluation gauche-à-droite des opérandes. Si l'opérande
gauche est évalué à 0 (ou false), l'opérande droite n'est pas évalué.

Les opérateurs and et && sont des opérateurs court-circuits (c'est-à-dire que le second opérande n'est pas évalué si le premier
est évalué à false). Ainsi, c'est à la fois correct et fiable de tester un pointeur null, comme dans l'exemple suivant :

Afin d'utiliser l'opérateur and, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -Vn du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

Exemple and
bool test( int * p ) {
return (p != 0) and (*p > 5);
};
}
Substituer && à and est également valide.

Surcharger && ou and

Vous pouvez surcharger l'opérateur && ainsi que la représentation alternative, and. N'oubliez pas que, quand l'opérateur est
surchargé, la logique n'est pas court-circuitée, et que le test du pointeur vide n'est pas fiable. Voici un exemple illustrant
comment surcharger and :
struct example { bool operator and ( const example & ) {return true;}// same as operator &&}
Utilisation de && dans les références rvalue

En tant que partie du nouveau standard C++0x, C++Builder supporte maintenant les références rvalue. Une référence rvalue est
formée en plaçant un && (mais pas un and) après un type dans une déclaration, comme suit :
Apt a;Apt&& a_ref1 = a;
Une différence majeure entre la référence lvalue familière et la nouvelle référence rvalue est que les références rvalue peuvent
être liées à un temporaire (c'est-à-dire un rvalue), mais une référence lvalue (au moins une qui n'est pas un const) ne peut pas
être liée à un rvalue.

3
3.1.4.2.21 asm, _asm, __asm
Catégorie

Extensions des mots clés, mots clés spécifiques à C++

Syntaxe
asm <code_opération> <opérandes> <; ou nouvelle ligne>_asm__asm
_asm <code_opération> <opérandes> <; ou nouvelle ligne>

538
3.1 Référence C++ RAD Studio Guide du langage C++

__asm <code_opération> <opérandes> <; ou nouvelle ligne>


Description

Utilisez le mot clé asm, _asm ou __asm pour placer des instructions en langage assembleur au milieu de votre code C ou C++.
Tous les symboles C++ sont remplacés par les équivalents appropriés en langage assembleur.

Vous pouvez grouper les instructions en langage assembleur en commençant le bloc d'instructions par le mot clé asm, puis en
entourant les instructions par des accolades ({}).

3.1.4.2.22 auto
Catégorie

Spécificateurs de classe de stockage

Syntaxe
[auto] <définition_données> ;
Description

Utilisez le modificateur auto pour définir une durée de vie locale pour une variable locale.

C'est le comportement par défaut pour les variables locales et c'est rarement utilisé.

3.1.4.2.23 bitand, &


Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

Syntaxe

Description

L'opérateur bitand est une représentation alternative de l'opérateur & (AND bit-à-bit).

L'opérateur AND bit-à-bit compare chaque bit du premier opérande au bit correspondant du second opérande. Quand les deux
bits sont à 1, le bit de résultat correspondant est défini sur 1. Sinon, il est défini sur 0.

Afin d'utiliser l'opérateur bitand, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -Vn du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

3.1.4.2.24 bitor, |
Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

Syntaxe
3
Description

L'opérateur bitor est une représentation alternative de l'opérateur |~ (OR bit-à-bit).

bitor prend des opérandes entiers ou d'énumération. bitor peut passer deux ou davantage d'arguments. Ces arguments doivent
être des valeurs caractère ou numérique.

Quand il est codé comme un mot clé, bitor peut seulement passer deux arguments. Dans chaque cas, le type du résultat est le
même que celui des arguments. (1) non signé si tous les arguments sont non signés, ou (2) un integer.

539
Guide du langage C++ RAD Studio 3.1 Référence C++

Afin d'utiliser l'opérateur bitor, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -VM du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

3.1.4.2.25 bool, false, true


Catégorie

Mots clés spécifiques C++

Syntaxe
bool <identificateur>;
Description

Utilisez bool et les littéraux false et true pour exécuter des tests logiques booléens.

Le mot clé bool représente un type pouvant prendre uniquement la valeur false ou la valeur true. Les mots clés false et true
sont des littéraux booléens dont les valeurs sont prédéfinies. false est équivalent au nombre zéro et true est équivalent au
nombre un. Ces littéraux booléens sont des rvalues ; vous ne pouvez pas leur affecter une valeur.

Vous pouvez convertir une rvalue de type bool en une rvalue de type int. La conversion numérique définit false à zéro et true à
un.

Vous pouvez convertir des rvalues de types arithmétique, énumération, pointeur ou pointeur sur membre en rvalue de type bool.
Une valeur zéro, une valeur de pointeur null ou un pointeur de membre null est converti en false. Toute autre valeur est
convertie en true.

3.1.4.2.26 break
Catégorie

Instructions

Syntaxe

Description

Utilisez l'instruction break dans les boucles pour passer le contrôle à la première instruction suivant le bloc switch, for, while ou
do le plus intérieur.

Exemple

Cet exemple illustre l'utilisation des mots clés break, case, default et switch.
#include <iostream>

using namespace std;

int main(int argc, char * argv[])


{
3 char ch;

cout << "APPUYEZ sur a, b OU c. TOUT AUTRE CHOIX METTRA FIN A CE PROGRAMME." << endl;
for ( /* TOUJOURS */; cin >> ch; )
switch (ch)
{
case 'a' : /* LE CHOIX DE a A SA PROPRE ACTION. */
cout << endl << "Option a sélectionnée." << endl;
break;
case 'b' : /* b ET c DONNENT LES MEMES RESULTATS. */

540
3.1 Référence C++ RAD Studio Guide du langage C++

case 'c' :
cout << endl << "Option b ou c sélectionnée." << endl;
break;
default:
cout << endl << "CHOIX INCORRECT ! Au revoir ..." << endl;
return(-1);
}
}
Voir aussi
continue ( see page 546)

do ( see page 552)

for ( see page 558)

while ( see page 579)

case ( see page 541)

default ( see page 551)

switch ( see page 572)

3.1.4.2.27 case
Catégorie

Instructions

Syntaxe
switch ( <variable switch> ) {casebreakdefault
case <expression constante> : <instruction>; [break;]
.
.
.
default: <instruction>;
}
Description

Utilisez l'instruction case avec des switch pour déterminer quelles instructions évaluer.

La liste des points de branchement possibles dans <instruction> est déterminée en faisant précéder les sous-instructions de
case <expression constante> : <instruction>;
où <expression constante> doit être un int et doit être unique.

Les valeurs de <expression constante> sont recherchées pour leur correspondance avec la <variable switch>.

Si une correspondance est trouvée, l'exécution se poursuit après l'instruction case de la correspondance jusqu'à ce qu'une
instruction break soit rencontrée ou que la fin de l'instruction switch soit atteinte.

Si aucune correspondance n'est trouvée, le contrôle est passé à l'instruction default. 3


Remarque: Il ne doit pas y avoir de constantes case

identiques dans la même instruction switch. Exemple

Cet exemple illustre l'utilisation des mots clés break, case, default et switch.
#include <iostream>

using namespace std;

541
Guide du langage C++ RAD Studio 3.1 Référence C++

int main(int argc, char * argv[])


{
char ch;

cout << "APPUYEZ sur a, b OU c. TOUT AUTRE CHOIX METTRA FIN A CE PROGRAMME." << endl;
for ( /* TOUJOURS */; cin >> ch; )
switch (ch)
{
case 'a' : /* LE CHOIX DE a A SA PROPRE ACTION. */
cout << endl << "Option a sélectionnée." << endl;
break;
case 'b' : /* b ET c DONNENT LES MEMES RESULTATS. */
case 'c' :
cout << endl << "Option b ou c sélectionnée." << endl;
break;
default:
cout << endl << "CHOIX INCORRECT ! Au revoir ..." << endl;
return(-1);
}
}
Voir aussi
break ( see page 540)

default ( see page 551)

switch ( see page 572)

3.1.4.2.28 catch
Catégorie

Instructions, Mots clés spécifiques C++

Syntaxe
catch (déclaration-exception) instruction-composée
Description

Le gestionnaire d'exceptions est indiqué par le mot clé catch. Le gestionnaire doit être utilisé immédiatement après les
instructions marquées par le mot clé try. Le mot clé catch peut aussi apparaître immédiatement après un autre catch. Chaque
gestionnaire n'évaluera qu'une seule exception qui correspond au type spécifié dans sa liste d'arguments, ou peut-être convertie
dans ce type.

3.1.4.2.29 cdecl, _cdecl, __cdecl


Catégorie

Modificateurs, Extensions des mots clés


3 Syntaxe
cdecl <données/définition de fonction> ;_cdecl__cdecl
_cdecl <données/définition de fonction> ;
__cdecl <données/définition de fonction> ;
Description

Utilisez un modificateur cdecl, _cdecl ou __cdecl pour déclarer une variable ou une fonction en utilisant les conventions de
nom de style C (sensible à la casse, avec un caractère de soulignement en début). Lorsque vous utilisez cdecl, _cdecl ou

542
3.1 Référence C++ RAD Studio Guide du langage C++

__cdecl en face d'une fonction, cela change la façon dont les paramètres sont transmis (les paramètres sont introduits de la
droite vers la gauche et l'appelant nettoie la pile). Le modificateur __cdeclredéfinit les directives du compilateur et les options de
l'EDI.

Les mots clés cdecl, _cdecl et __cdecl sont spécifiques à CodeGear C++.

3.1.4.2.30 char
Catégorie

Spécificateurs de type

Syntaxe
[signed|unsigned] char <nom_variable>
Description

Utilisez le spécificateur de type char pour définir un type de données caractère. Les variables de type char ont une longueur de
1 octet.

Un char peut être signé, non signé ou non spécifié. Par défaut, signed char est présumé.

Les objets déclarés comme caractères (char)sont suffisamment grands pour stocker n'importe quel membre du jeu de
caractères ASCII de base.

3.1.4.2.31 class
Catégorie

Mots clés spécifiques C++, Spécificateurs de type

Syntaxe
<clé_classe> <nom_classe> <liste_base> { <liste de membres> }
• <clé_classe> est une classe, une structure ou une union.
• <nom_classe> peut être n'importe quel nom, unique dans sa portée.
• <liste_base> liste les classes de base dont cette classe dérive. <liste_base> est facultatif
• <liste de membres> déclare les données membres de la classe et les fonctions membres.
Description
Utilisez le mot clé class pour définir une classe C++.
Dans une classe :
• les données sont appelées données membres
• les fonctions sont appelées fonctions membres
Voir aussi
3
Private ( see page 565)

Protected ( see page 565)

Public ( see page 566)

543
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.2.32 compl, ~
Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

Syntaxe

Description

L'opérateur compl est une représentation alternative de l'opérateur ~ (NOT bit-à-bit).

L'opérateur compl est l'abréviation de complément.

compl inverse true en false, et false en true. Le tilde (~) est placé devant l'integer utilisé pour le complément.

Le complément de 1 est 0, et vice-versa.

En plus d'un integer, ~ génère également un type énumération ; cela peut être le résultat du complément à 1 de l'opérande. Des
calculs intégrals sont effectués.

Le type du résultat est le type de l'opérande promu.

Il peut y avoir une ambiguïté dans l'expression unaire ~X(), où X est un nom de classe. L'ambiguïté est résolue en faveur du
traitement de ~ comme un complément unaire plutôt que le traitement de ~X comme un destructeur.

Afin d'utiliser l'opérateur compl, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -VM du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

3.1.4.2.33 const
Catégorie

Modificateurs

Syntaxe
const <nom de variable> [ = <valeur> ] ;
<nom de fonction> ( const <type>*<nom de variable> ;)
<nom de fonction> const;
Description

Utilisez le modificateur const pour que la valeur d'une variable ne soit plus modifiable.

Utilisez le modificateur const pour affecter une valeur initiale à une variable qui ne peut pas être changée par le programme.
Toute tentative ultérieure d'affectation de valeur const entraîne une erreur de compilation.

Un pointeur const ne peut pas être modifié, bien que l'objet sur lequel il pointe puisse l'être. Considérez les exemples suivants.
const float pi = 3.14;

3 // Utilisé seul, const équivaut à int.


const maxint = 12345;

// Un pointeur constant
char *const str1 = "Bonjour tout le monde";

// Un pointeur sur une chaîne de caractères constante.


char const *str2 = "CodeGear Corporation";
Etant donné ces déclarations, les instructions suivantes sont incorrectes.

544
3.1 Référence C++ RAD Studio Guide du langage C++

pi = 3.0; // Affecte une valeur à une constante.


i = maxint++; // Incrémente une constante.
str1 = "Bonjour !" // Pointe str1 vers autre chose.
Utilisation du mot clé const dans les programmes C++

C++ étend l'utilisation de const aux classes et aux fonctions membres. Dans une définition de classe C++, utilisez le
modificateur const suivant une déclaration de fonction membre. La fonction membre ne peut modifier aucune donnée dans la
classe.

Un objet classe défini avec le mot clé const tente de n'utiliser que des fonctions membres également définies avec const. Si
vous appelez une fonction membre non définie comme const, le compilateur émet un avertissement signalant qu'une fonction
non-const est appelée pour un objet const. Cette façon d'utiliser le mot clé const est une fonctionnalité de sécurité de C++.

Avertissement : Un pointeur peut modifier indirectement une variable const, comme dans cet exemple :
*(int *)&my_age = 35;
Si vous utilisez le modificateur const avec un paramètre pointeur dans une liste de paramètres de fonction, la fonction ne peut
pas modifier la variable sur laquelle le pointeur pointe. Par exemple,
int printf (const char *format, ...);
printf ne peut modifier la chaîne format.

Voir aussi
Mutable ( see page 561)

3.1.4.2.34 Const_cast (opérateur de transtypage)


Catégorie

Mots clés spécifiques C++

Syntaxe
const_cast< T > (arg)
Description

Utilisez l'opérateur const_cast pour ajouter ou supprimer à un type les modificateurs const ou volatile

Dans l'instruction const_cast< T > (arg), T et arg doivent être du même type, sauf pour les modificateurs const et volatile. Le
transtypage est résolu lors de la compilation. Le résultat est du type T. Vous pouvez, à l'aide d'une seule expression
const_cast, ajouter ou supprimer autant de modificateurs const ou volatile que vous le souhaitez.

Vous pouvez convertir un pointeur sur const en un pointeur sur non const qui soit, hormis cela, de type identique. Si l'opération
est réussie, le pointeur qui en résulte fait référence à l'objet d'origine.

Un objet const, ou une référence à une conversion const, a pour résultat un objet ou une référence non const qui est, hormis
cela, de type identique.

L'opérateur const_cast effectue des transtypages identiques sur le modificateur volatile. Le pointeur sur un objet volatile peut 3
être converti en un pointeur sur un objet de type non volatile sans pour autant changer le type de l'objet. Il en résulte un pointeur
sur l'objet d'origine. Un objet de type volatile, ou une référence au type volatile, peut être converti en un type non volatile
identique.

Voir aussi
Dynamic_cast (opérateur de transtypage) ( see page 553)

Reinterpret_cast (opérateur de transtypage) ( see page 567)

545
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.2.35 continue
Catégorie

Instructions

Syntaxe
continue;
Description

Utilisez l'instruction continue dans des boucles pour passer le contrôle à la fin de l'accolade la plus intérieure appartenant à une
construction de boucle, comme for ou while ; à ce point, la condition de continuation de boucle est de nouveau évaluée.

Exemple

Cet exemple illustre l'emploi du mot clé continue.


void __fastcall TForm1::Button1Click(TObject *Sender)
{
float array[20];

// Code d'initialisation du tableau...


for(int i = 0; i < 20; i++)
{
array[i] = random(i + 20);
}
array[6] = 0;

for(int i = 0; i < 20; i++)


{
if (array[i] == 0)
continue;
array[i] = 1/array[i];
ListBox1->Items->Add(array[i]);
}
}
Voir aussi
for ( see page 558)

while ( see page 579)

3.1.4.2.36 __declspec(dllexport)
Catégorie

Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe

3 __declspec( dllexport ) déclarateur


L'attribut de classe de stockage dllexport est utilisé pour assurer la compatibilité avec le langage Microsoft C et C++. Cet
attribut vous permet d'exporter des fonctions, des données et des objets depuis une DLL. Cet attribut définit explicitement
l'interface d'une DLL destinée à un client, qui peut être le fichier exécutable ou une autre DLL. La déclaration de fonctions
comme dllexport évitent de recourir à un fichier de définition de module (.DEF), au moins pour respecter les spécifications des
fonctions exportées.

Remarque: dllexport

546
3.1 Référence C++ RAD Studio Guide du langage C++

remplace le mot clé __export.

3.1.4.2.37 __declspec(dllimport)
Catégorie

Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe
__declspec( dllimport ) déclarateur
L'attribut de classe de stockage dllimport est utilisé pour assurer la compatibilité avec le langage Microsoft C et C++. Cet
attribut vous permet d'importer des fonctions, des données et des objets dans une DLL.

Remarque: Remarque

: dllimport remplace le mot clé __import.

3.1.4.2.38 __declspec(naked)
Catégorie

Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe
__declspec( naked ) déclarateur
L'utilisation de l'argument naked supprime le code prologue/épilogue. Lorsque vous utilisez __declspec(naked), sachez qu'un
cadre de pile normal n'est pas défini. Une fonction avec __declspec(naked) ne préservera pas les valeurs de registre qui sont
normalement préservées. Il est de la responsabilité du programmeur de se conformer aux conventions éventuelles attendues
par l'appelant ou la fonction.

Vous pouvez utiliser cette fonctionnalité pour écrire votre propre code prologue/épilogue en utilisant du code assembleur inline.
Les fonctions naked sont particulièrement utiles lors de l'écriture de pilotes de périphérique virtuels.

L'attribut naked ne concerne que la définition d'une fonction et n'est pas un modificateur de type.

Exemple

Ce code définit une fonction avec l'attribut naked :


// Exemple d'attribut naked
__declspec( naked ) int func( paramètres_formels )
{
// Corps de la fonction
}

3.1.4.2.39 __declspec(noreturn)
Catégorie 3
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe
__declspec( noreturn ) déclarateur
Cet attribut __declspec indique au compilateur qu'une fonction ne revient pas. Par conséquent, le compilateur sait que le code
suivant un appel à une fonction __declspec(noreturn) ne peut être atteint.

547
Guide du langage C++ RAD Studio 3.1 Référence C++

Si le compilateur trouve une fonction ayant un chemin de contrôle qui ne renvoie pas de valeur, il génère un avertissement. Si le
chemin de contrôle ne peut être atteint en raison d'une fonction qui ne revient pas, vous pouvez utiliser __declspec(noreturn)
pour éviter cet avertissement ou cette erreur.

Exemple

Considérez le code suivant. La clause else ne contient pas d'instruction return, aussi le programmeur déclare-t-il fatal comme
__declspec(noreturn) pour éviter un message d'erreur ou d'avertissement.
__declspec(noreturn) extern void fatal ()
{
// Code omis
}
int foo()
{
if(...)
return 1;
else if(...)
return 0;
else
fatal();
}

3.1.4.2.40 __declspec(nothrow)
Catégorie

Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe
__declspec( nothrow ) déclarateur
C'est un attribut étendu __declspec qui peut être utilisé dans la déclaration des fonctions. Cet attribut indique au compilateur
que la fonction déclarée et les fonctions qu'elle appelle ne déclenchent jamais d'exception. Avec le modèle de gestion des
exceptions synchrone, maintenant utilisé par défaut, le compilateur peut éliminer les mécanismes de suivi de la durée de vie de
certains objets tels qu'une fonction et réduit sensiblement la taille du code.

Les trois instructions suivantes sont équivalentes :


#define WINAPI __declspec(nothrow) __stdcall
void WINAPI foo1();
void __declspec(nothrow) __stdcall foo2();
void __stdcall foo3() throw();
L'utilisation de void __declspec(nothrow) __stdcall foo2(); présente l'avantage de pouvoir utiliser une définition API, comme
celle illustrée par l'instruction #define, pour spécifier facilement nothrow sur un ensemble de fonctions. La troisième déclaration,
void __stdcall foo3() throw(); est la syntaxe définie par le standard C++.

3.1.4.2.41 __declspec(novtable)
Catégorie
3
Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe
__declspec( novtable ) déclarateur
Cette forme de _declspec peut être appliquée à toute déclaration de classe, mais ne doit l'être qu'aux classes d'interface pure,
c'est-à-dire à des classes qui ne seront jamais instanciées d'elles-mêmes. _declspec empêche le compilateur de générer le
code d'initialisation du vfptr dans les constructeurs et le destructeur de la classe. Dans de nombreux cas, cela supprime les

548
3.1 Référence C++ RAD Studio Guide du langage C++

seules références à la vtable qui sont associées avec la classe et ainsi, le lieur la supprimera. L'utilisation de cette forme de
_declspec peut entraîner une réduction sensible de la taille du code.

3.1.4.2.42 __declspec(property)
Catégorie

Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe
__declspec( property( get=get_func_name ) ) déclarateur
__declspec( property( put=put_func_name ) ) déclarateur
__declspec( property( get=get_func_name, put=put_func_name ) ) déclarateur
Cet attribut peut être appliqué aux "données membre virtuelles" non statiques d'une définition de classe ou de structure. Le
compilateur traite ces "données membre virtuelles" commes des données membre en changeant leurs références en appels de
fonction.

Lorsque le compilateur voit une donnée membre déclarée avec cet attribut à droite d'un opérateur de sélection de membre ("."
ou "->"), il convertit l'opération en une fonction get ou put, selon qu'une telle expression est une l-value ou une r-value. Dans
des contextes plus complexes, comme "+=", une ré-écriture est effectuée avec à la fois get et put.

Cet attribut peut aussi être utilisé dans la déclaration d'un tableau vide dans une définition de classe ou de structure.

Exemple

__declspec(property(get=GetX, put=PutX)) int x[];

L'instruction ci-dessus indique que x[] peut être utilisé avec un ou plusieurs indices de tableau. Dans ce cas :
i=p->x[a][b]
deviendra :
i=p->GetX(a, b),
et
p->x[a][b] = i
deviendra
p->PutX(a, b, i);

3.1.4.2.43 __declspec(selectany)
Catégorie

Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe
__declspec( selectany ) déclarateur
3
Un élément de données globales peut normalement n'être initialisé qu'une fois dans une application ou une bibliothèque. Cet
attribut peut être utilisé dans l'initialisation des données globales définies par des en-têtes, lorsque le même en-tête apparaît
dans plusieurs fichiers source.

Remarque Cet attribut ne peut être appliqué qu'à l'initialisation réelle des éléments de données globales qui sont visibles de
façon externe.

Exemple

549
Guide du langage C++ RAD Studio 3.1 Référence C++

Ce code montre comment utiliser l'attribut selectany :

//Correct - x1 est initialisé et visible de façon externe

__declspec(selectany) int x1=1;

//Incorrect - une constante est par défaut statique en C++, donc

//x2 n'est pas visible de façon externe (C'est correct en C, car

//une constante n'est pas statique par défaut en C)

const __declspec(selectany) int x2 =2;

//Correct - x3 est une constante externe, donc visible de façon externe

extern const __declspec(selectany) int x3=3;

//Correct - x4 est une constante externe, donc visible de façon externe

extern const int x4;

const __declspec(selectany) int x4=4;

//Incorrect - __declspec(selectany) est appliqué à la déclaration non //initialisée de x5 extern __declspec(selectany) int x5;

3.1.4.2.44 __declspec(thread)
Catégorie

Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe
__declspec( thread ) déclarateur
Le stockage local de thread (Thread Local Storage, TLS) est la méthode par laquelle chaque thread d'un processus multithread
donné alloue du stockage pour les données spécifiques au thread.

Le modificateur de classe de stockage étendue de thread est utilisé pour déclarer une variable locale de thread. L'attribut de
thread doit être utilisé avec le mot clé __declspec.

3.1.4.2.45 __declspec(uuid("ComObjectGUID"))
Catégorie

Modificateurs, extensions de mot clé, spécificateurs de classe de stockage

Syntaxe
__declspec( uuid("ComObjectGUID") ) déclarateur
Le compilateur attache un GUID à une classe ou structure déclarée ou définie (définitions d'objets COM complètes uniquement)
3 avec l'attribut uuid. L'attribut uuid a pour argument une chaîne. La chaîne nomme un GUID en format de registre normal avec
ou sans les délimiteurs { }. Par exemple :

struct __declspec(uuid("00000000-0000-0000-c000-000000000046")) IUnknown;

struct __declspec(uuid("{00020400-0000-0000-c000-000000000046}")) IDispatch;

Cet attribut peut être appliqué dans une re-déclaration. Cela permet aux en-têtes système de fournir les définitions des
interfaces comme IUnknown et la re-déclaration dans un autre en-tête (comme COMDEF.H) pour fournir le GUID.

550
3.1 Référence C++ RAD Studio Guide du langage C++

Le mot clé __uuidof peut être appliqué pour récupérer le GUID constant attaché à un type défini par l'utilisateur.

3.1.4.2.46 default
Catégorie

Instructions

Syntaxe
switch ( <variable switch> ) {casebreakdefault
case <expression constante> : <instruction>; [break;]
.
.
.
default: <instruction>;
}
Description

Utilisez l'instruction default dans des blocs d'instruction switch.

• Si aucune correspondance case n'est trouvée et que l'instruction default est trouvée à l'intérieur de l'instruction switch,
l'exécution continue à ce point.
• Si aucune instruction default n'est définie dans l'instruction switch, le contrôle passe à l'instruction qui suit le bloc d'instruction
switch.
Exemple
Cet exemple illustre l'utilisation des mots clés break, case, default et switch.
#include <iostream>

using namespace std;

int main(int argc, char * argv[])


{
char ch;

cout << "APPUYEZ sur a, b OU c. TOUT AUTRE CHOIX METTRA FIN A CE PROGRAMME." << endl;
for ( /* TOUJOURS */; cin >> ch; )
switch (ch)
{
case 'a' : /* LE CHOIX DE a A SA PROPRE ACTION. */
cout << endl << "Option a sélectionnée." << endl;
break;
case 'b' : /* b ET c DONNENT LES MEMES RESULTATS. */
case 'c' :
cout << endl << "Option b ou c sélectionnée." << endl;
break;
default:
cout << endl << "CHOIX INCORRECT ! Au revoir ..." << endl;
return(-1);
}
}
3
Voir aussi
break ( see page 540)

case ( see page 541)

switch ( see page 572)

551
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.2.47 delete
Catégorie

Opérateurs, Mots clés spécifiques C++

Syntaxe
void operator delete(void *ptr) throw();
void operator delete(void *ptr, const std::nothrow_t&) throw();
void operator delete[](void *ptr) throw();
void operator delete[](void *ptr, const std::nothrow_t &) throw();
void operator delete(void *ptr, void *) throw(); // Fiche de placement
void operator delete[](void *ptr, void *) throw(); // Fiche de placement
Description

L'opérateur delete désalloue un bloc de mémoire alloué par des appels à new. Cela est similaire mais plus puissant qu'un appel
à la fonction standard free.

L'opérateur delete doit être utilisé pour libérer toute la mémoire allouée par l'opérateur new. Un échec de libération de la
mémoire provoquera des manques de mémoire.

Les fiches de placement par défaut de operator delete sont réservées et ne peuvent pas être redéfinies. L'opérateur de
placement par défaut delete ne réalise aucune action (dans la mesure où aucune mémoire n'a été allouée par l'opérateur de
placement par défaut new). Si vous surchargez la version de placement de l'opérateur new, vous pouvez à juste titre (bien que
cela ne soit pas obligatoire) surcharger l'opérateur de placement delete avec la signature correspondante.

Voir aussi
Opérateur delete avec les tableaux ( see page 454)

3.1.4.2.48 do
Catégorie

Instructions

Syntaxe
do <instruction> while ( <condition> );
Description

L'instruction do s'exécute jusqu'à ce que la condition devienne fausse (false).

<instruction> est exécuté de façon répétitive aussi longtemps que la valeur de <condition> reste true.

Puisque la condition est testée après chaque exécution de <instruction>, la boucle s'exécute au moins une fois.

Voir aussi

3 While ( see page 579)

3.1.4.2.49 double
Catégorie

Spécificateurs de type

Syntaxe

552
3.1 Référence C++ RAD Studio Guide du langage C++

[long] double <identificateur>


Description

Utilisez le spécificateur de type double pour définir un identificateur comme étant de type de données à virgule flottante. Le
modificateur facultatif long augmente la précision de la valeur en virgule flottante.

Si vous utilisez le mot clé double, le package mathématique virgule flottante sera automatiquement lié à votre programme.

Voir aussi
Float ( see page 557)

Long ( see page 560)

3.1.4.2.50 Dynamic_cast (opérateur de transtypage)


Catégorie

Mots clés spécifiques C++

Description

Dans l'expression dynamic_cast< T > (ptr), T doit être un pointeur, ou une référence, à un type classe défini ou void*.
L'argument ptr doit être une expression résultant en un pointeur ou en une référence.

Si T est void*, ptr doit aussi être un pointeur. Le pointeur qui en résulte peut alors accéder à tout élément de la classe la plus
dérivée dans la hiérarchie. Une classe de ce genre ne peut servir de base à aucune autre classe.

Les conversions de classe dérivée en classe de base, ou de classe dérivée en une autre, se présentent comme suit : si T est un
pointeur et si ptr pointe sur une classe qui n'est pas de base, mais qui entre dans la hiérarchie, le résultat est un pointeur sur la
sous-classe unique. Les références sont traitées de la même manière : si T est une référence et ptr une référence à une classe
non base, le résultat est une référence à l'unique sous-classe.

La conversion d'une classe de base en classe dérivée ne peut être effectuée que si la base est de type polymorphe.

La conversion en classe de base est résolue au moment de la compilation. La conversion d'une classe de base en classe
dérivée ou la conversion à travers une hiérarchie, est résolue au moment de l'exécution.

Si la conversion réussit, dynamic_cast< T > (ptr) convertit ptr au type souhaité. Si un transtypage de pointeur échoue, le pointeur
a pour valeur 0 lorsqu'il est renvoyé. Si un transtypage à un type référence échoue, l'exception Bad_cast est déclenchée.

Remarque: Les informations de type à l'exécution (RTTI) sont nécessaires pour dynamic_cast

Voir aussi
Const_cast (opérateur de transtypage) ( see page 545)

Reinterpret_cast (opérateur de transtypage) ( see page 567)

Mot clé __rtti et option -RT ( see page 534)

Static_cast (opérateur de transtypage) ( see page 570)


3

3.1.4.2.51 enum
Catégorie

Spécificateurs de type

553
Guide du langage C++ RAD Studio 3.1 Référence C++

Syntaxe
enum [<balise_de_type>] {<nom_de_constante> [= <valeur>], ...} [list_var];
• <balise_de_type> est une balise de type facultative qui nomme l'ensemble.
• <nom_de_constante> est le nom d'une constante à qui il peut être facultativement affecté la valeur de <valeur>. Ces
constantes sont aussi appelées constantes d'énumération.
• <valeur> doit être un entier. Si <value> est manquante, on la suppose : <prev> + 1 où <prev> représente la valeur de la
constante entière précédente dans la liste. Pour la première constante entière de la liste, la valeur par défaut est 0.
• <list_var> est une liste de variables facultative qui affecte des variables au type enum.
Description
Utilisez le mot clé enum pour définir un ensemble de constantes de type int, appelé type de données énumération.
Un type de données énumération fournit des identificateurs mnémoniques pour un ensemble de valeurs entières. Utilisez
l'indicateur -b pour inverser l'option Traiter les types énumérés comme des entiers. Les énumérations sont toujours
interprétées comme des int si la plage de valeurs le permet, mais si ce ne sont pas des int, la valeur est transformée en int
dans les expressions. Selon les valeurs des énumérateurs, les identificateurs d'une liste d'énumérateurs sont implicitement
considérés de type signed char, unsigned char, short, unsigned short, int ou unsigned int.
En C, il peut être affecté à une variable énumérée toute valeur de type int, il n'est effectué aucun contrôle de type. En C++, il ne
peut être affecté à une variable énumérée que l'un de ses énumérateurs.
En C++, vous pouvez omettre le mot clé enum si <balise_de_type> n'est pas le nom de quelque chose d'autre dans la même
portée. Vous pouvez également omettre <balise_de_type> si aucune variable supplémentaire de ce type enum n'est
nécessaire.
En l'absence de <valeur> la valeur zéro est affectée au premier énumérateur. Tous les noms suivants sans initialisateurs seront
augmentés de un. <valeur> peut être n'importe quelle expression donnant une valeur entière positive ou négative (après des
conversions possibles en entier). Ces valeurs sont d'habitude uniques, mais elles peuvent être en double.
Les balises d'énumération partagent le même espace de nommage que les balises de structure et d'union. Les énumérateurs
partagent le même espace de nommage que les identificateurs de variables ordinaires.
En C++, les énumérateurs déclarés dans une classe sont dans la portée de cette classe.

3.1.4.2.52 explicit
Catégorie

Mots clés spécifiques C++

Syntaxe
explicit <déclaration de constructeur de paramètre unique>
Description

Normalement, on peut affecter à une classe avec un seul constructeur de paramètre une valeur correspondant au type du
constructeur. Cette valeur est automatiquement (implicitement) convertie en un objet du type de la classe à laquelle il est affecté.
Vous pouvez empêcher cette sorte de conversion implicite en déclarant le constructeur de la classe avec le mot clé explicit.
Tous les objets de cette classe doivent alors se voir affecter des valeurs du type de la classe ; toute autre affectation provoque
3 une erreur de compilation.

On peut affecter aux objets de la classe suivante des valeurs correspondant au type du constructeur du type de la classe :
class X {
public:
X(int);
X(const char*, int = 0);
};
Les instructions d'affectation suivantes sont alors correctes.

554
3.1 Référence C++ RAD Studio Guide du langage C++

void f(X arg) {


X a = 1;
X B = "Jessie";
a = 2;
}
Toutefois, on ne peut affecter aux objets de la classe suivante que des valeurs correspondant au type de la classe :
class X {
public:
explicit X(int);
explicit X(const char*, int = 0);
};
Les constructeurs explicit nécessitent alors que les valeurs des instructions d'affectation suivantes soient converties dans le
type de la classe à laquelle elles sont affectées.
void f(X arg) {
X a = X(1);
X b = X("Jessie",0);
a = X(2);
}

3.1.4.2.53 export
Catégorie

Non implémenté

Syntaxe
export template < liste-paramètre-template > déclaration
Description

Le mot clé export est réservé pour une implémentation ultérieure et n'a aucun effet dans cette version.

Voir aussi
_export ( see page 536)

3.1.4.2.54 extern
Catégorie

Spécificateurs de classe de stockage

Syntaxe
extern <définition de données> ;
[extern] <prototype de fonction> ;
Description

Utilisez le modificateur extern pour indiquer que le stockage actuel et la valeur initiale d'une variable, ou le corps d'une fonction,
sont définis dans un module de code source séparé. Les fonctions déclarées avec extern sont visibles à travers tous les fichiers 3
source dans un programme, à moins que vous ne re-définissiez la fonction comme static.

Le mot clé extern est facultatif pour un prototype de fonction.

Utilisez le "C" extern pour éviter aux noms de fonctions d'être substantypés dans les programmes C++.

En outre, les templates extern vous permettent de définir des templates qui ne sont pas instanciés dans une unité de traduction.
L'utilisation des templates extern réduit ainsi à la fois le temps de compilation et la taille du module compilé. La fonctionnalité
template extern ( see page 506) fait partie du nouveau standard C++0x.

555
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.2.55 final
Catégorie

Attributs, extensions des mots clés

Syntaxe
return-type function-name [[final]]
Description

L'attribut final empêche une classe ou une fonction d'être héritée. Vous pouvez ajouter l'attribut final à une définition de classe
ou à une déclaration de fonction membre virtuelle dans une définition de classe. Si l'attribut est spécifié pour une définition de
classe, il est équivalent d'être spécifié pour chaque fonction membre virtuelle de cette classe, y compris les fonctions membre
héritées.

Voir aussi
Attributs noreturn et final ( see page 504)

3.1.4.2.56 __finally
Catégorie

Instructions, Extensions des mots clés

Syntaxe
__finally {instruction-composée}
Description

Le mot clé __finally spécifie les actions qui doivent être faites indépendamment de l'existence du flux à l'intérieur du __try
précédent.

Le fragment de code suivant montre l'utilisation de la construction try/__finally :


#include <stdio.h>
#include <string.h>
#include <windows.h>
class Exception
{
public:
Exception(char* s = "Inconnu"){what = strdup(s); }
Exception(const Exception& e ){what = strdup(e.what); }
~Exception() {libère(what); }
char* msg() const {return what; }
private:
char* what;
};
int main()
{
3 float e, f, g;
try
{
try
{
f = 1.0;
g = 0.0;
try
{
puts("Une autre exception:");

556
3.1 Référence C++ RAD Studio Guide du langage C++

e = f / g;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
puts("Interception d'une exception C.");
throw(Exception("Erreur matérielle: division par 0"));
}
}
catch(const Exception& e)
{
printf("Interception d'une exception C++ : %s :\n", e.msg());
}
}
__finally
{
puts("C++ autorise aussi __finally !");
}
return e;
}
#include <iostream>
#include <stdexcept>
using namespace std;
class MyException : public exception {
public:
virtual const char *what() const throw() {
return("MyException s'est produite.");
}
};
// Donnez-moi un entier...
void myFunc(int a)
{
MyException e;
// ...sauf celui-là.
if (a == 0)
throw(e);
}
void main()
{
int g;
// Remarquez que __finally doit être dans son propre bloc try (sans catch avant).
try {
try {
g = 0;
myFunc(g);
}
catch(MyException &e) {
cout << "Exception: " << e.what() << endl;
}
}
__finally {
cout << "Bloc finally atteint." << endl;
}
}
L'exécution du programme ci-dessus donne le résultat suivant :
Une autre exception : Interception d'une exception C. Interception d'une exception C++[Erreur 3
matérielle : division par 0] C++ autorise aussi __finally ! Exception : MyException s'est
produite. Bloc finally atteint.

3.1.4.2.57 float
Catégorie

Spécificateurs de type

557
Guide du langage C++ RAD Studio 3.1 Référence C++

Syntaxe
float <identificateur>
Description

Utilisez le spécificateur de type float pour définir un identificateur comme étant de type de données à virgule flottante.

Type Longueur Portée


float 32 bits 3.4 * (10**-38) à 3.4 * (10**+38)

Le package mathématique virgule flottante sera automatiquement lié à votre programme si vous utilisez des valeurs ou des
opérateurs à virgule flottante.

Voir aussi
Double ( see page 552)

3.1.4.2.58 for
Catégorie

Instructions

Syntaxe
for ( [<initialisation>] ; [<condition>] ; [<incrément>] ) <instruction>
Description

L'instruction for implémente une boucle itérative.

<condition> est testée avant la première entrée dans le bloc.

<instruction> est exécuté de façon répétitive JUSQU'A CE QUE la valeur de <condition> soit false.

• Avant la première itération de la boucle, <initialisation> initialise les variables de la boucle.


• Après chaque itération de la boucle, <incrément> incrémente un compteur de boucle. En conséquence, j++ est
fonctionnellement identique à ++j.
En C++, <initialisation> peut être une expression ou une déclaration.
La portée de tout identificateur déclaré à l'intérieur de la boucle for s'étend jusqu'à la fin de l'instruction de contrôle seulement.
Une variable définie dans l'expression for-initialisation a une portée limitée à l'intérieur du bloc for. Voir la description de l'option
-Vd.
Toutes les expressions sont facultatives. Si <condition> est omis, elle est supposée être toujours vraie (true).

3.1.4.2.59 friend
Catégorie
3 Mots clés spécifiques C++

Syntaxe
friend <identificateur>;
Description

Utilisez friend pour déclarer une fonction ou une classe avec tous les droits d'accès aux membres privés et protégés de la
classe, sans être un membre de cette classe. La classe extérieure a un accès complet à la classe qui déclare friend cette classe

558
3.1 Référence C++ RAD Studio Guide du langage C++

extérieure.

Sur tous les autres points, la fonction friend est une fonction normale en termes de portées, de déclarations et de définitions.

3.1.4.2.60 goto
Catégorie

Instructions

Syntaxe
goto <identificateur> ;
Description

Utilisez l'instruction goto pour transférer le contrôle à l'emplacement d'un label local spécifié par <identificateur>.

Les labels se terminent toujours par deux-points (:).

3.1.4.2.61 if, else


Catégorie

Opérateurs

Syntaxe
if ( <condition1> ) <instruction1>
if ( <condition1> ) <instruction1>;
else <instruction2>;
if ( <condition1> ) <instruction1>;
else if ( <condition2> ) <instruction2>;
else <instruction3>;
Description

Utilisez if pour implémenter une instruction conditionnelle.

Vous pouvez déclarer des variables dans l'expression condition. Par exemple,
if (int val = func(arg))
est syntaxiquement correct. La variable a pour portée toute l'instruction if et s'étend au bloc else s'il existe.

L'instruction condition doit être convertie en type bool. Sinon, la condition est mal formée.

Lorsque <condition> vaut true, <instruction1> est exécutée.

Si <condition> vaut false, <instruction2> est exécutée.

Le mot clé else est facultatif, mais il ne doit y avoir aucune instruction entre les instructions if et else.

Les instructions de préprocesseur #if et #else (directives) ressemblent aux instructions if et else, mais ont des effets très
différents. Elles contrôlent les lignes du fichier source qui sont compilées et celles qui sont ignorées. 3

3.1.4.2.62 import, _import, __import


Catégorie

Modificateurs, Extensions des mots clés

Forme 1

559
Guide du langage C++ RAD Studio 3.1 Référence C++

class _import <nom de classe>


class __import <nom de classe>
Forme 2
return_type _import <nom de fonction>
return_type __import <nom de fonction>
Forme 3
data_type _import <nom de données>
data_type __import <nom de données>
Description

Ce mot clé peut être utilisé comme classe, fonction ou modificateur de données.

3.1.4.2.63 inline
Catégorie

Mots clés spécifiques C++

Syntaxe
inline <type de données> <classe>_<fonction> (<paramètres>) { <instructions>;}
Description

Utilisez le mot clé inline pour déclarer ou définir des fonctions inline C++.

Les fonctions inline sont réservées de préférence pour de petites fonctions, fréquemment utilisées.

3.1.4.2.64 int
Catégorie

Spécificateurs de type

Syntaxe
[signed|unsigned] int <identificateur> ;
Description

Utilisez le spécificateur de type int pour définir un type de données entier.

Les variables de type int peuvent être signées (par défaut) ou non signées.

3.1.4.2.65 long
Catégorie

3 Spécificateurs de type

Syntaxe
long [int] <identificateur> ;
[long] double <identificateur> ;
Description

Utilisé pour modifier un double, il définit un type de données en virgule flottante, avec 80 bits de précision au lieu de 64.

560
3.1 Référence C++ RAD Studio Guide du langage C++

Le package mathématique virgule flottante sera automatiquement lié avec votre programme si vous utilisez des valeurs ou des
opérateurs en virgule flottante.

3.1.4.2.66 mutable
Catégorie

Mots clés spécifiques C++, Spécificateurs de classe de stockage

Syntaxe
mutable <nom de variable>;
Description

Utilisez le spécificateur mutable pour rendre modifiable une variable, même si elle est dans une expression qualifiée de const.

Utilisation du mot clé mutable

Seules les données membres de classe peuvent être déclarées mutable. Le mot clé mutable ne peut pas être utilisé sur des
noms static ou const. Le but de mutable est de spécifier quelles données membres peuvent être modifiées par des fonctions
membres const. Normalement, une fonction membre const ne peut pas modifier des données membres.

Voir aussi
Const ( see page 544)

3.1.4.2.67 namespace
Catégorie

Mots clés spécifiques C++

Description

La plupart des applications réelles consistent en plusieurs fichiers source. Les fichiers peuvent être écrits et maintenus par
plusieurs développeurs. Le moment venu, les fichiers séparés sont organisés et liés pour obtenir l'application finale.
Habituellement, l'organisation des fichiers exige que tous les noms qui ne sont pas encapsulés dans un espace de nommage
défini (comme une fonction, le corps d'une classe ou une unité de traduction) partagent le même espace de nommage global.
Cependant, des définitions multiples de noms découvertes au moment de la liaison de modules distincts imposent de distinguer
chaque nom. L'espace de nommage C++ propose une solution au problème des conflits de nom dans la portée globale.

Les espaces de nommage permettent à une application d'être partitionnée en plusieurs sous-systèmes. Chaque sous-système
peut définir et opérer dans une portée propre. Chaque développeur peut donc introduire les identificateurs dont il a besoin dans
son sous-système sans avoir à se préoccuper de savoir si ces identificateurs sont utilisés par quelqu'un d'autre. La portée du
sous-système est reconnue pour toute la durée de l'application par un identificateur unique.

L'utilisation d'espaces de nommage C++ passe par deux étapes : La première consiste à identifier de manière unique un espace
de nommage avec le mot clé namespace. La seconde est d'accéder aux éléments d'un espace de nommage identifié en
appliquant le mot clé using. 3

3.1.4.2.68 new
Catégorie

Opérateurs, Mots clés spécifiques C++

Syntaxe

561
Guide du langage C++ RAD Studio 3.1 Référence C++

void *operator new(std::size_t size) throw(std::bad_alloc);


void *operator new(std::size_t size, const std::nothrow_t &) throw();
void *operator new[](std::size_t size) throw(std::bad_alloc);
void *operator new[](std::size_t size, const std::nothrow_t &) throw();
void *operator new(std::size_t size, void *ptr) throw(); // Fiche de placement
void *operator new[](std::size_t size, void *ptr) throw(); // Fiche de placement
Description

Les opérateurs new permettent une allocation dynamique de la mémoire, similaire mais plus puissant que la fonction standard
malloc. Ces fonctions d'allocation essaient d'allouer taille octets de stockage. En cas de réussite, new renvoie un pointeur vers
la mémoire allouée. En cas d'échec de l'allocation, l'opérateur new appelle la fonction new_handler. Par défaut, new_handler
déclenche une exception de type bad_alloc. Si vous ne souhaitez pas qu'une exception soit déclenchée, utilisez la version
nothrow de operator new. Les versions nothrow renvoient un résultat de pointeur NULL en cas d'échec, au lieu de déclencher
une exception.

Les fiches de placement par défaut de operator new sont réservées et ne peuvent pas être redéfinies. Toutefois, vous pouvez
surcharger la fiche de placement avec une signature différente (c'est-à-dire portant un nombre ou type différent d'arguments).
Les fiches de placement par défaut acceptent un pointeur de type void, et ne font que renvoyer ce pointeur, inchangé. Cela peut
être utile lorsque vous souhaitez allouer un objet à une adresse connue. L'utilisation de la fiche de placement de new peut être
délicate car vous devez vous souvenir d'appeler explicitement le destructeur de votre objet puis de libérer le tampon mémoire
préalloué. N'appelez pas l'opérateur delete sur un objet alloué avec l'opérateur de placement new.

Une requête d'allocation non tableau utilise la fonction appropriée operator new(). Toutes les demandes d'allocation tableau
appellent la fonction operator new[]() appropriée. Pensez à utiliser la fiche tableau de operator delete[]() lors de la
désallocation d'un tableau créé avec operator new[]().

Remarque: Les tableaux de classes nécessitent la définition d'un constructeur par défaut dans la classe.

Une demande d'allocation de 0 octet renvoie un pointeur non NULL. La répétition de demandes de ce type renvoie des
pointeurs non NULL distincts.

Voir aussi
Delete ( see page 552)

Opérateur new avec les tableaux ( see page 455)

Opérateur new ( see page 455)

Syntaxe des arguments de l'opérateur new ( see page 453)

Gestion des erreurs pour l'opérateur new ( see page 453)

3.1.4.2.69 noreturn
Catégorie

Attributs, extensions des mots clés

Syntaxe
3
void function-name [[noreturn]]
Description

Utilisez le modificateur noreturn pour déclarer les fonctions n'ayant pas de valeur de retour.

562
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.2.70 not, !
Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

Syntaxe

Description

L'opérateur not est une représentation alternative de l'opérateur ! (négation logique).

not renvoie true si son opérande est false, et false si son opérande est true.

Si un entier vaut 1, l'expression !1 indique que le nombre est différent de 1. not peut également être utilisé pour les chaînes.
L'expression !Smith indique que le nom de la personne est autre que Smith. not inverse les bits de l'expression.

Afin d'utiliser l'opérateur not, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -VM du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

3.1.4.2.71 not_eq, !=
Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

Syntaxe

Description

L'opérateur not_eq est une représentation alternative de l'opérateur != (inégalité binaire). Il teste l'inéquivalence logique.

not_eq compare deux expressions pour déterminer si elles sont ou pas les mêmes.

Par conséquent, 7 != 8 renvoie true, tandis que 7 != 7 renvoie false. Il en est de même pour toute expression comme Smith !=
Smith qui renvoie false.

Afin d'utiliser l'opérateur not_eq, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -VM du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

3.1.4.2.72 nullptr
Catégorie

Mots clés spécifiques C++

Syntaxe
nullptr
Description 3
Réservé à une utilisation future. nullptr est un littéral qui peut être affecté à tout pointeur pour indiquer que le pointeur ne pointe
pas sur quelque chose.

Avertissement: C++Builder n'implémente pas nullptr

mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini. N'utilisez pas nullptr comme un identificateur.

563
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.2.73 operator
Catégorie

Opérateurs, Mots clés spécifiques C++

Syntaxe
operator <symbole opérateur>( <paramètres> )
{
<instructions>;
}
Description

Utilisez le mot clé operator pour définir une nouvelle action (surchargée) de l'opérateur donné. Lorsque l'opérateur est
surchargé comme fonction membre, un seul argument est autorisé, puisque this est implicitement le premier argument.

Lorsque vous surchargez un opérateur comme friend, vous pouvez spécifier deux arguments.

Voir aussi
Class ( see page 543)

3.1.4.2.74 or, ||
Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

Syntaxe

Description

L'opérateur or est une représentation alternative de l'opérateur || (OR logique).

Seules deux instructions peuvent être évaluées en même temps.

or renvoie true si deux valeurs sont différentes, comme 2 et 6.

or renvoie false si les deux valeurs sont identiques, comme 10 et 10.

Afin d'utiliser l'opérateur or, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -VM du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

3.1.4.2.75 or_eq, |=
Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

3 Syntaxe

Description

L'opérateur or_eq est une représentation alternative de l'opérateur != (OR inclusif binaire).

or_eq teste l'équivalence logique ou l'égalité binaire.

or_eq opère sur deux valeurs. Quand la première ou la seconde valeur vaut 1, true est renvoyé. Quand les valeurs sont égales
à 0, false est renvoyé.

564
3.1 Référence C++ RAD Studio Guide du langage C++

Afin d'utiliser l'opérateur not_eq, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -VM du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

3.1.4.2.76 pascal, _pascal, __pascal


Catégorie

Modificateurs, Extensions des mots clés

Syntaxe
pascal <définition-données/définition-fonction> ;
_pascal <définition-données/définition-fonction> ;
__pascal <définition-données/définition-fonction> ;
Description

Utilisez les mots clés pascal, _pascal et __pascal pour déclarer une variable ou une fonction utilisant une convention de nom
de style Pascal (nom en majuscules).

De plus, pascal, appliqué à un en-tête de fonction, déclare des conventions de passage de paramètres de style langage Delphi
(paramètres passés de gauche à droite et la fonction appelée nettoie la pile).

Dans les programmes C++, les fonctions déclarées avec le modificateur pascal sont encore substantypées.

3.1.4.2.77 private
Catégorie

Mots clés spécifiques C++

Syntaxe
private: <déclarations>
Description

L'accès aux membres de classe private est limité aux fonctions membres à l'intérieur de la classe et aux classes friend.

Les membres de classe sont private par défaut.

Les membres structure (struct) et union sont public par défaut. Vous pouvez redéfinir le spécificateur d'accès par défaut pour
les structures, mais pas pour les unions.

Les déclarations friend peuvent être placées n'importe où dans la déclaration de classe ; les amis ne sont pas touchés par les
spécificateurs de contrôle d'accès.

Voir aussi
Class ( see page 543)

Friend ( see page 558)

Protected ( see page 565)


3

3.1.4.2.78 protected
Catégorie

Mots clés spécifiques C++

565
Guide du langage C++ RAD Studio 3.1 Référence C++

Syntaxe
protected: <déclarations>
Description

L'accès aux membres de classe protected est limité aux fonctions membres à l'intérieur de la classe, aux fonctions membres
des classes dérivées et aux classes friend.

Les membres structure (struct) et union sont public par défaut. Vous pouvez redéfinir le spécificateur d'accès par défaut pour
les structures, mais pas pour les unions.

Les déclarations friend peuvent être placées n'importe où dans la déclaration de classe ; les amis ne sont pas touchés par les
spécificateurs de contrôle d'accès.

Voir aussi
Class ( see page 543)

Friend ( see page 558)

Private ( see page 565)

3.1.4.2.79 public
Catégorie

Mots clés spécifiques C++

Syntaxe
public: <déclarations>
Description

Membre de classe public pouvant être utilisé par toutes les fonctions.

Les membres d'une structure ou d'une union sont public par défaut.

Vous pouvez redéfinir le spécificateur d'accès par défaut pour les structures, mais pas pour les unions.

Les déclarations friend peuvent être placées n'importe où dans la déclaration de classe ; les amis ne sont pas touchés par les
spécificateurs de contrôle d'accès.

Voir aussi
Class ( see page 543)

Friend ( see page 558)

Private ( see page 565)

Protected ( see page 565)

__published ( see page 533)


3
Struct ( see page 571)

3.1.4.2.80 register
Catégorie

Spécificateurs de classe de stockage

566
3.1 Référence C++ RAD Studio Guide du langage C++

Syntaxe
register <définition de données> ;
Description

Utilisez le spécificateur de classe de stockage register pour stocker la variable déclarée dans un registre CPU (si c'est possible),
pour optimiser l'accès et réduire le code.

Remarque: Le compilateur peut ignorer les demandes d'allocation de registre. L'allocation de registres est basée sur l'analyse
du compilateur sur la manière dont une variable est utilisée.

3.1.4.2.81 Reinterpret_cast (opérateur de transtypage)


Catégorie

Mots clés spécifiques C++

Syntaxe
reinterpret_cast< T > (arg)
Description

Dans l'instruction reinterpret_cast< T > (arg), T doit être un pointeur, une référence, un type arithmétique, un pointeur de fonction
ou un pointeur de membre.

Un pointeur peut être explicitement converti en un type entier.

Un arg entier peut être converti en pointeur. Convertir un pointeur en un type entier et le reconvertir au même type de pointeur a
pour résultat la valeur d'origine.

Une classe qui n'est pas encore définie peut être utilisée dans une conversion de pointeur ou de référence.

Un pointeur de fonction peut être explicitement converti en un pointeur de type d'objet si le type du pointeur sur l'objet comporte
assez de bits pour contenir le pointeur de fonction. Un pointeur de type d'objet peut être explicitement converti en un pointeur de
fonction seulement si le type du pointeur sur la fonction est assez grand pour contenir le pointeur d'objet.

Voir aussi
Const_cast (opérateur de transtypage) ( see page 545)

Dynamic_cast (opérateur de transtypage) ( see page 553)

3.1.4.2.82 return
Catégorie

Instructions

Syntaxe
return [ <expression> ] ; 3
Description

Utilisez l'instruction returnpour revenir de la fonction en cours à la routine appelante, en renvoyant facultativement une valeur.

3.1.4.2.83 short
Catégorie

567
Guide du langage C++ RAD Studio 3.1 Référence C++

Spécificateurs de type

Syntaxe
short int <variable> ;
Description

Utilisez le modificateur de type short lorsque vous voulez une variable plus petite qu'un int (entier). Ce modificateur peut être
appliqué au type de base int.

Lorsque le type de base est omis dans une déclaration, il est supposé être int.

Voir aussi
Long ( see page 560)

Signed ( see page 568)

3.1.4.2.84 signed
Catégorie

Spécificateurs de type

Syntaxe
signed <type> <variable> ;
Description

Utilisez le modificateur de type signed lorsque la valeur de la variable peut être positive ou négative. Le modificateur signed peut
être appliqué aux types de base int, char, long, short et __int64.

Lorsque le type de base est omis dans une déclaration, il est supposé être int.

Voir aussi
Char ( see page 543)

Int ( see page 560)

Long ( see page 560)

Short ( see page 567)

Unsigned ( see page 576)

3.1.4.2.85 sizeof
Catégorie

Opérateurs

3 Description

L'opérateur sizeof a deux utilisations distinctes :

sizeof expression-unaire

sizeof (nom-type)

Dans les deux cas, le résultat est une constante entière qui donne la taille en octets de l'espace mémoire utilisé par l'opérande
(déterminé par son type, avec quelques exceptions). La quantité de mémoire réservée pour chaque type dépend de la machine.

568
3.1 Référence C++ RAD Studio Guide du langage C++

Dans la première utilisation, le type de l'expression opérande est déterminé sans évaluer l'expression (et donc sans effets de
bord). Lorsque l'opérande est de type char (signed ou unsigned), sizeof donne pour résultat 1. Lorsque l'opérande est un
élément non-paramètre de type tableau, le résultat est le nombre total d'octets dans le tableau (en d'autres termes, un nom de
tableau n'est pas converti en type pointeur). Le nombre d'éléments dans un tableau est égal à la taille du tableau divisée par la
taille de son premier élément (tableau[0]).

Si l'opérande est un paramètre déclaré de type tableau ou fonction, sizeof donne la taille du pointeur. Appliqué à des structures
et des unions, sizeof donne le nombre total d'octets, en incluant toute marge.

Vous ne pouvez pas utiliser sizeof avec des expressions de type fonction, de types incomplets, de noms parenthésés de tels
types ou avec une lvalue qui désigne un objet champ de bits.

Le type entier du résultat de sizeof est size_t.

Vous pouvez utiliser sizeof dans les directives de préprocesseur ; cela est spécifique à CodeGear C++.

En C++, sizeof(type_de_classe), où type_de_classe est dérivé d'une classe de base, renvoie la taille de l'objet (rappelez-vous
que cela inclut la taille de la classe de base).

Exemple
/* UTILISEZ L'OPERATEUR sizeof POUR OBTENIR LA TAILLE DES DIFFERENTS TYPES DE DONNEES. */
#include <stdio.h>
struct st {
char *name;
int age;
double height;
};
struct st St_Array[]= { /* UN TABLEAU DE structs */
{ "Jr.", 4, 34.20 }, /* St_Array[0] */
{ "Suzie", 23, 69.75 }, /* St_Array[1] */
};
int main()
{
long double LD_Array[] = { 1.3, 501.09, 0.0007, 90.1, 17.08 };
printf("\nNombre d'éléments de LD_Array = %d",
sizeof(LD_Array) / sizeof(LD_Array[0]));
/**** NOMBRE D'ELEMENTS DANS St_Array. ****/
printf("\nSt_Array a %d éléments",
sizeof(St_Array)/sizeof(St_Array[0]));
/**** LE NOMBRE D'OCTETS DANS CHAQUE ELEMENT DE St_Array. ****/
printf("\nSt_Array[0] = %d", sizeof(St_Array[0]));
/**** NOMBRE TOTAL D'OCTETS DE St_Array. ****/
printf("\nSt_Array=%d", sizeof(St_Array));
return 0;
}
Sortie
Nombre d'éléments dans LD_Array = 5
St_Array a 2 éléments
St_Array[0] = 16
St_Array= 32

3.1.4.2.86 static 3

Catégorie

Spécificateurs de classe de stockage

Syntaxe
static <définition de données> ;static
static <nom de fonction> <définition de fonction> ;

569
Guide du langage C++ RAD Studio 3.1 Référence C++

Description

Utilisez le spécificateur de classe de stockage static avec une variable locale pour préserver la dernière valeur entre des appels
successifs à cette fonction. Une variable static agit comme une variable locale mais a la durée de vie d'une variable externe.

Dans une classe, les données et les fonctions membres peuvent être déclarées static. Il n'existe qu'une seule copie des
données static pour tous les objets de la classe.

Une fonction membre static d'une classe globale a une liaison externe. Un membre d'une classe locale n'a pas de liaison. Une
fonction membre static n'est associée qu'à la classe dans laquelle elle est déclarée. C'est pourquoi ces fonctions membres ne
peuvent être virtual.

Les fonctions membres statiques ne peuvent appeler que d'autres fonctions membres static et n'ont accès qu'aux données
static. De telles fonctions membres n'ont pas de pointeur this.

3.1.4.2.87 static_assert
Catégorie

Instructions, Mots clés spécifiques C++

Syntaxe
static_assert (expression-constante, message erreur);
Description

Le mot clé static_assert est utilisé pour tester les assertions durant la compilation, plûtôt qu'au niveau du préprocesseur ou
durant l'exécution.

3.1.4.2.88 Static_cast (opérateur de transtypage)


Catégorie

Mots clés spécifiques C++

Syntaxe
static_cast< T > (arg)
Description

Dans l'instruction static_cast< T > (arg), T doit être un pointeur, une référence, un type arithmétique ou un type enum. T et arg
doivent tous deux être entièrement connus au moment de la compilation..

Un type complet peut être converti en un autre type par certaines méthodes déjà fournies par le langage ; une conversion
effectuée avec static_cast aboutit exactement au même résultat.

Les types entiers peuvent être convertis en types enum. Une demande de conversion de arg en une valeur qui n'est pas un
élément d'enum est non définie.
3 Le pointeur NULL est converti en la valeur de pointeur NULL du type de destination, T.

Un pointeur sur un type objet peut être converti en pointeur sur un autre type objet. Notez que le fait de pointer sur des types
semblables peut engendrer des problèmes d'accès si ces types n'ont pas le même alignement.

Vous pouvez convertir explicitement un pointeur sur une classe X en pointeur sur une classe Y si X est une classe de base pour
Y. Vous ne pouvez effectuer une conversion statique que sous les conditions suivantes :

• Une conversion sans ambiguïté de Y en X doit exister

570
3.1 Référence C++ RAD Studio Guide du langage C++

• X ne doit pas être une classe de base virtuelle


Un objet peut être explicitement converti en un type de référence X& si son pointeur peut être explicitement converti en X*. Le
résultat de la conversion est une lvalue. Aucun constructeur, ni aucune fonction de conversion n'est appelé.
Un objet ou une valeur peut être converti en un objet classe seulement si un constructeur ou un opérateur de conversion
approprié a été déclaré.
Un pointeur sur un membre peut être explicitement converti en un pointeur sur un membre de type différent seulement si les
deux types sont des pointeurs sur des membres de la même classe ou des pointeurs sur des membres de deux classes
différentes dont l'une est dérivée, sans ambiguïté, de l'autre.
Lorsque T est une référence, le résultat de static_cast< T > (arg) est une lvalue. Le résultat d'une conversion de pointeur ou de
référence se réfère à l'expression d'origine.
Voir aussi
Const_cast (opérateur de transtypage) ( see page 545)

Dynamic_cast (opérateur de transtypage) ( see page 553)

Reinterpret_cast (opérateur de transtypage) ( see page 567)

3.1.4.2.89 struct
Catégorie

Spécificateurs de type

Syntaxe
struct [<nom de type struct>] {
[<type> <nom-variable[, nom-variable, ...]>] ;
.
.
.
} [<variables structure>] ;
Description

Utilisez struct pour grouper des variables en un seul enregistrement.

<nom de type struct> Balise facultative qui fait référence au type structure.

<variables structure> Les définitions de données, également facultatif.

Bien que <nom de type struct> et <variables structure> soient toutes deux facultatives, l'une des deux doit apparaître.

Vous définissez les éléments de l'enregistrement en nommant un <type>, suivi par un ou plusieurs <nom-variable> (séparés par
des virgules).

Séparez les différents types de variables par un point-virgule.

Utilisez l'opérateur . ou l'opérateur -> pour accéder aux éléments dans une structure.

Pour déclarer des variables supplémentaires du même type, utilisez le mot clé struct, suivi par le <nom de type struct>, puis par
les noms des variables. En C++, le mot clé struct peut être omis. 3
Remarque: Le compilateur permet l'utilisation de structure anonyme incorporée dans une autre structure.

Voir aussi
Class ( see page 543)

Public ( see page 566)

Union ( see page 576)

571
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.2.90 switch
Catégorie

Instructions

Syntaxe
switch ( <variable switch> ) {casebreakdefault
case <expression constante> : <instruction>; [break;]
.
.
.
default: <instruction>;
}
Description

Utilisez l'instruction switch pour passer le contrôle à un case qui correspond à <variable switch>. Les instructions suivant le case
qui correspond sont évaluées.

Si aucun case ne satisfait la condition, le case par défaut est évalué.

Pour éviter l'évaluation de tout autre case et la perte du contrôle du switch, terminez chaque case par break.

Exemple

Cet exemple illustre l'utilisation des mots clés break, case, default et switch.
#include <iostream>

using namespace std;

int main(int argc, char * argv[])


{
char ch;

cout << "APPUYEZ sur a, b OU c. TOUT AUTRE CHOIX METTRA FIN A CE PROGRAMME." << endl;
for ( /* TOUJOURS */; cin >> ch; )
switch (ch)
{
case 'a' : /* LE CHOIX DE a A SA PROPRE ACTION. */
cout << endl << "Option a sélectionnée." << endl;
break;
case 'b' : /* b ET c DONNENT LES MEMES RESULTATS. */
case 'c' :
cout << endl << "Option b ou c sélectionnée." << endl;
break;
default:
cout << endl << "CHOIX INCORRECT ! Au revoir ..." << endl;
return(-1);
}
}
Voir aussi
3
break ( see page 540)

case ( see page 541)

default ( see page 551)

572
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.2.91 template
Catégorie

Mots clés spécifiques C++

Syntaxe
déclaration-template:templateclass
template < liste-argument-template > déclaration
liste-argument-template:
argument-template
liste-argument-template, argument-template
argument-template:
argument-type
déclaration-argument
argument-type:
class nomtype identificateur
nom-classe-template:
nom-template < liste-argument-template >
liste-argument-template:
argument-template
liste-argument-template , argument-template
argument-template:
expression
nom-type
< liste-argument-template > déclaration
Description

Utilisez les templates (aussi appelés types génériques ou paramétrés) pour construire une famille de fonctions ou de classes
associées.

3.1.4.2.92 this
Catégorie

Mots clés spécifiques C++

Exemple
class X {
int a;
public:
X (int b) {this -> a = b;}
};
Description

Dans les fonctions membres non statiques, le mot clé this est un pointeur sur l'objet pour lequel la fonction est appelée. Tous les
appels à des fonctions membres non statiques passent this en tant qu'argument caché.

this est une variable locale disponible dans le corps de toute fonction membre non statique. Utilisez-la implicitement à l'intérieur
3
de la fonction pour des références de membre. Elle n'a pas besoin d'être déclarée et on lui fait rarement référence explicitement
dans la définition d'une fonction.

Par exemple, dans call x.func(y) , où y est un membre de X, le mot clé this est défini à &x et y est défini à this->y, ce qui
équivaut à x.y.

Les fonctions membres statiques n'ont pas de pointeur this car elles sont appelées sans objet particulier à l'esprit. Ainsi, une
fonction membre statique ne peut pas accéder à des membres non statiques sans spécifier explicitement un objet avec . ou ->.

573
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
Class ( see page 543)

3.1.4.2.93 throw
Catégorie

Instructions, Mots clés spécifiques C++

Syntaxe
throw expression-affectation
Description

Lorsqu'une exception se produit, l'expression throw initialise un objet temporaire du type T (pour correspondre au type
d'argument arg) utilisé dans throw(T arg). D'autres copies peuvent être générées si nécessaire par le compilateur. En
conséquence, il peut être utile de définir un constructeur de copie pour l'objet exception.

Voir aussi
Catch ( see page 542)

3.1.4.2.94 try
Catégorie

Instructions, Mots clés spécifiques C++

Syntaxe
try instruction-composée liste-gestionnaire
Description

Le mot clé try n'est pris en charge que dans les programmes C++. Utilisez __try dans les programmes C. C++ autorise aussi
__try.

Un bloc de code dans lequel une exception peut se produire doit être préfixé par le mot clé try. A la suite du mot clé try, il y a un
bloc entouré par des accolades. Cela indique que le programme est préparé à tester l'existence d'exceptions. Si une exception
se produit, le flux du programme est interrompu. L'enchaînement des étapes se fait de la manière suivante :

• Le programme recherche un gestionnaire correspondant


• S'il en est trouvé un, la pile est déroulée jusqu'à ce point
• Le contrôle du programme est transféré au gestionnaire
Si aucun gestionnaire n'est trouvé, le programme appelle la fonction terminate. Si aucune exception ne se produit, le programme
s'exécute en mode normal.
Voir aussi
3
Catch ( see page 542)

3.1.4.2.95 typedef
Catégorie

Spécificateurs de classe de stockage

574
3.1 Référence C++ RAD Studio Guide du langage C++

Syntaxe
typedef <définition de type> <identificateur> ;
Description

Utilisez le mot clé typedef pour affecter le nom de symbole <identificateur> à la définition de type de données <définition de
type>.

3.1.4.2.96 typeid
Catégorie

Opérateurs, Mots clés spécifiques C++

Syntaxe
typeid( expression )
typeid( nom-type )
Description

Vous pouvez utiliser typeid pour obtenir l'identification de types et d'expressions à l'exécution. Un appel à typeid renvoie une
référence à un objet de type const type_info. L'objet renvoyé représente le type de l'opérande typeid.

Si l'opérande typeid est un pointeur déréférencé ou une référence à un type polymorphique, typeid renvoie le type dynamique
de l'objet réel pointé ou auquel il est fait référence. Si l'opérande n'est pas polymorphique, typeid renvoie un objet qui
représente le type statique.

Vous pouvez utiliser l'opérateur typeid avec les types de données fondamentaux aussi bien qu'avec les types définis par
l'utilisateur.

Quand l'opérande typeid est un objet classe Delphi ou une référence à une classe Delphi, typeid renvoie le type statique plutôt
que le type à l'exécution.

Si l'opérande typeid est un pointeur NULL déréférencé, l'exception Bad_typeid est déclenchée.

3.1.4.2.97 typename
Catégorie

Mots clés spécifiques C++

Syntaxe 1
typename identificateur
Syntaxe 2
template < typename identificateur > identificateur de classe
Description

Utilisez la syntaxe 1 pour faire référence à un type que vous n'avez pas encore défini. Voir l'exemple 1.
3

Utilisez la syntaxe 2 à la place du mot clé class dans une déclaration de template. Voir l'exemple 2.

Remarque: Lorsqu'on utilise le mot clé typename

dans des templates, le compilateur ne génère pas toujours une erreur dans les cas où le standard ANSI demande le mot clé
typename. Le compilateur va repérer l'omission de typename lorsqu'il sera invoqué avec le commutateur -A. Par exemple, le
code suivant :

575
Guide du langage C++ RAD Studio 3.1 Référence C++

#include <stdio.h>
struct A{ typedef int AInt; };
Remarque: Le compilateur va repérer l'omission de typename lorsqu'il sera invoqué avec le commutateur -A

Remarque: Compilez avec : bcc32 (pas de commutateur -A)

bc++bcc32 test.cpp
Le résultat est correct. Le compilateur ne doit pas supposer que AInt est un typename, mais il le fait à moins que le
commutateur -A ne soit utilisé.

Remarque: Compilez avec : bcc32 (commutateur -A

)
bc++bcc32 -A test.cpp
Il en résulte :

Erreur E2089 47071.cpp 7: L'identificateur 'AInt' ne peut pas avoir un qualificateur type

Erreur E2303 47071.cpp 7: Nom de type attendu

Erreur E2139 47071.cpp 7: ; manquant dans la déclaration

Les deux résultats sont attendus.

3.1.4.2.98 union
Catégorie

Spécificateurs de type

Syntaxe
union [<nom de type union>] {
<type> <noms de variable> ;
...
} [<variables union>] ;
Description

Utilisez des unions pour définir des variables qui partagent l'espace de stockage.

Le compilateur alloue assez de mémoire dans a_number pour faire tenir le plus grand élément de l'union.

A l'opposé d'une structure, les membres d'une union occupent le même emplacement en mémoire. Quand on écrit sur l'un deux,
on écrase les autres.

Utilisez le sélecteur d'enregistrement (.) pour accéder aux éléments d'une union.

3 Voir aussi
Class ( see page 543)

Public ( see page 566)

3.1.4.2.99 unsigned
Catégorie

576
3.1 Référence C++ RAD Studio Guide du langage C++

Spécificateurs de type

Syntaxe
unsigned <type> <variable> ;
Description

Utilisez le modificateur de type unsigned lorsque les valeurs d'une variable seront toujours positives. Le modificateur unsigned
peut être appliqué aux types de base int, char, long, short et __int64.

Lorsque le type de base est omis dans une déclaration, il est supposé être int.

Voir aussi
Char ( see page 543)

Int ( see page 560)

Long ( see page 560)

Short ( see page 567)

Signed ( see page 568)

3.1.4.2.100 using (déclaration)


Catégorie

Mots clés spécifiques C++

Description

Il est possible d'accéder individuellement aux membres d'un espace de nommage en utilisant la syntaxe de déclaration using.
Quand vous utilisez une déclaration using, vous ajoutez les identificateurs déclarés à l'espace de nommage local. Sa grammaire
est

déclaration-using :

using :: identificateur-non-qualifié;

3.1.4.2.101 virtual
Catégorie

Mots clés spécifiques C++

Syntaxe
virtual nom-classe
virtual nom-fonction
Description
3
Utilisez le mot clé virtual pour autoriser les classes dérivées de fournir différentes versions d'une fonction de la classe de base.
Une fois qu'une fonction est déclarée virtual, vous pouvez la redéfinir dans n'importe quelle classe dérivée, même si le nombre
et le type d'arguments sont les mêmes.

La fonction redéfinie remplace la fonction de la classe de base.

577
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.2.102 void
Catégorie

Types spéciaux

Syntaxe
void identificateur
Description

void est un type spécial indiquant l'absence de toute valeur. Utilisez le mot clé void comme type de retour d'une fonction si la
fonction ne renvoie pas de valeur.
void hello(char *name)
{
printf("Hello, %s.",name);
}
Utilisez void comme en-tête de fonction si la fonction ne prend aucun paramètre.
int init(void)
{
return 1;
}
Pointeurs void

Les pointeurs génériques peuvent aussi être déclarés void, ce qui signifie qu'ils peuvent pointer sur n'importe quel type.

Les pointeurs void ne peuvent pas être déréférencés sans conversion explicite car le compilateur ne peut pas déterminer la
taille de l'objet pointeur.

3.1.4.2.103 volatile
Catégorie

Modificateurs

Syntaxe
volatile <définition de données> ;
Description

Utilisez le modificateur volatile pour indiquer qu'une routine d'arrière plan, une routine d'interruption ou un port E/S peut modifier
une variable. La déclaration volatile d'un objet avertit le compilateur de ne pas faire de suppositions concernant la valeur de
l'objet en évaluant des expressions dans lesquelles il intervient car la valeur peut changer à tout moment. Il empêche également
le compilateur de faire de la variable une variable register.
volatile int ticks;
void timer( ) {
3 ticks++;
}
void wait (int interval) {
ticks = 0;
while (ticks < interval); // Ne fait rien
}
Les routines de cet exemple (en supposant que timer a été correctement associé à une interruption matérielle d'horloge)
implémentent une attente temporisée de ticks spécifiée par l'argument interval. Un compilateur hautement optimisé pourrait ne
pas charger la valeur de ticks à l'intérieur du test de la boucle while car la boucle ne modifie pas la valeur de ticks.

578
3.1 Référence C++ RAD Studio Guide du langage C++

Remarque: C++ étend l'utilisation de volatile

aux classes et aux fonctions membres. Si vous avez déclaré un objet volatile, vous ne pouvez utiliser que ses fonctions
membres volatile.

Voir aussi
Const ( see page 544)

3.1.4.2.104 wchar_t
Catégorie

Mots clés spécifiques C++, Spécificateurs de type

Syntaxe
wchar_t <identificateur>;
Description

Dans les programmes C++, wchar_t est un type de données fondamental qui peut représenter des codes distincts pour tout
élément dans le plus grand jeu de caractères étendu dans toutes les locales prises en charge. En CodeGear C++, wchar_t a la
même taille, la même signature (signé ou non) et le même besoin d'alignement qu'un type unsigned short.

3.1.4.2.105 while
Catégorie

Instructions

Syntaxe
while ( <condition> ) <instruction>
Description

Utilisez le mot clé while pour itérer une instruction de façon conditionnelle.

<instruction> est exécuté de façon répétitive jusqu'à ce que la valeur de <condition> soit false.

Le test prend place avant que <instruction> ne s'éxécute. C'est pourquoi, si <condition> est évalué à false à la première passe,
la boucle ne s'exécute pas.

3.1.4.2.106 xor, ^
Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

Syntaxe
3
Description

L'opérateur xor est une représentation alternative de l'opérateur ^ (xor bit-à-bit).

Il renvoie un résultat true booléen si seulement l'un de ses opérandes est true. C'est en opposition avec un or inclusif qui indique
que les deux instructions doivent être des integers pour qu'une instruction true soit renvoyée.

Si 2 ou 8.25 sont définis comme des integers, une instruction true sera renvoyée même si 8.25 est un décimal.

579
Guide du langage C++ RAD Studio 3.1 Référence C++

Si Jack et Jill sont tous deux définis comme homme, une instruction true sera renvoyée même si Jill est une femme.

Afin d'utiliser l'opérateur xor, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -VM du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

3.1.4.2.107 __classmethod
Catégorie

Modificateurs, Extensions des mots clés

Syntaxe
virtual __classmethod int <funcdecl> ( int );
__classmethod virtual int <funcdecl> (int );
Description

Le mot clé __classmethod a été ajouté pour déclarer des méthodes de classe dans C++. Le modificateur __classmethod
indique qu'une fonction peut être invoquée sur un nom de classe, ainsi que sur une instance de cette classe.

Voir aussi
__classid ( see page 529)

Méthodes de classe ( see page 422)

3.1.4.2.108 alignas
Catégorie

Mots clés spécifiques C++

Syntaxe
alignas
Description

Réservé à une utilisation future.

Avertissement: C++Builder n'implémente pas alignas

mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.

3.1.4.2.109 and_eq, &=


Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

Syntaxe
3
Description

L'opérateur and_eq est une représentation alternative de l'opérateur d'affectation &= (AND bit-à-bit).

La valeur du premier opérande est ajoutée à la valeur du second opérande, et le résultat est stocké dans le premier opérande.

Afin d'utiliser l'opérateur and_eq, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -Vn du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

580
3.1 Référence C++ RAD Studio Guide du langage C++

Voir aussi
Opérateurs d'affectation ( see page 595)

3.1.4.2.110 axiom
Catégorie

Mots clés spécifiques C++

Syntaxe
axiom
Description

Réservé à une utilisation future.

Avertissement: C++Builder n'implémente pas axiom

mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.

3.1.4.2.111 concept
Catégorie

Mots clés spécifiques C++

Syntaxe
concept
Description

Réservé à une utilisation future.

Avertissement: C++Builder n'implémente pas concept

mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.

3.1.4.2.112 concept_map
Catégorie

Mots clés spécifiques C++

Syntaxe
concept_map
Description

Réservé à une utilisation future. 3


Avertissement: C++Builder n'implémente pas concept_map

mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.

3.1.4.2.113 constexpr
Catégorie

581
Guide du langage C++ RAD Studio 3.1 Référence C++

Mots clés spécifiques C++

Syntaxe
constexpr
Description

Réservé à une utilisation future.

Avertissement: C++Builder n'implémente pas constexpr

mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.

3.1.4.2.114 late_check
Catégorie

Mots clés spécifiques C++

Syntaxe
late_check
Description

Réservé à une utilisation future.

Avertissement: C++Builder n'implémente pas late_check

mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.

3.1.4.2.115 requires
Catégorie

Mots clés spécifiques C++

Syntaxe
requires
Description

Réservé à une utilisation future.

Avertissement: C++Builder n'implémente pas requires

mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.

3.1.4.2.116 thread_local
Catégorie
3
Mots clés spécifiques C++

Syntaxe
thread_local
Description

Réservé à une utilisation future.

582
3.1 Référence C++ RAD Studio Guide du langage C++

Avertissement: C++Builder n'implémente pas thread_local

mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.

3.1.4.2.117 xor_eq, ^=
Catégorie

Représentations alternatives des opérateurs et tokens, Opérateurs

Syntaxe

Description

L'opérateur xor_eq est une représentation alternative de l'opérateur ^=; (affectation XOR binaire).

True est renvoyé si un nombre du côté gauche de l'équation est identique à un nombre du côté droit, comme 10*5!=10*2.

False est renvoyé même si 6*3=9*2.

Afin d'utiliser l'opérateur xor, vous devez activer l'option Activer les nouveaux noms d'opérateur (le commutateur -VM du
compilateur, disponible sur la page Compatibilité de la boîte de dialogue Projet Options).

3.1.4.3 Mots clés par catégorie


Cette section présente la liste thématique des mots clés.

Rubriques
Nom Description
Représentations alternatives de tokens ( see page 583) Cette section contient les rubriques relatives aux représentations alternatives des
tokens C++.
Attributs ( see page 584) Cette section contient les rubriques des mots clés des attributs C++.
Extensions de mots clés C++Builder ( see page 584) Cette section contient les rubriques relatives aux extensions de mots clés
C++Builder.
Mots clés spécifiques C++ ( see page 586) Cette section contient les rubriques relatives aux mots clés spécifiques à C++.
Modificateurs ( see page 587) Cette section contient les rubriques relatives aux mots clés des modificateurs
C++.
Opérateurs ( see page 587) Cette section contient les rubriques relatives aux mots clés des opérateurs C++.
Mots réservés ( see page 588) Cette section contient les rubriques relatives aux mots réservés de C++.
Types spéciaux ( see page 588) Cette section contient les rubriques relatives aux mots clés des types spéciaux
C++.
Instructions ( see page 588) Cette section contient les rubriques relatives aux mots clés des instructions C++.
Spécificateurs de classe de stockage ( see page 589) Cette section contient les rubriques relatives aux mots clés des spécificateurs de
classe de stockage C++.
Spécificateurs de type ( see page 590) Cette section contient les rubriques relatives aux mots clés des spécificateurs de
type C++.

3.1.4.3.1 Représentations alternatives de tokens


3
Cette section contient les rubriques relatives aux représentations alternatives des tokens C++.

Rubrique relative aux mots clés


Le tableau suivant récapitule les mots clés des représentations alternatives et le token que chaque mot clé représente.

583
Guide du langage C++ RAD Studio 3.1 Référence C++

Mot clé / Représentation Token représenté Définition


alternative
and && AND logique
and_eq &= Affectation par AND bit-à-bit
bitand & AND bit-à-bit
bitor | OR bit-à-bit
compl ~ NOT bit-à-bit (complément à 1 binaire)
not ! négation logique
not_eq != inégalité bit-à-bit
or || OR logique
or_eq |= OR inclusif bit-à-bit
xor ^ OR exclusif bit-à-bit
xor_eq ^= affectation XOR bit-à-bit

Voici les liens aux rubriques des mots clés de représentation alternative :

and ( see page 538)

and_eq ( see page 580)

bitand ( see page 539)

bitor ( see page 539)

compl ( see page 544)

not ( see page 563)

not_eq ( see page 563)

or ( see page 564)

or_eq ( see page 564)

xor ( see page 579)

xor_eq ( see page 583)

3.1.4.3.2 Attributs
Cette section contient les rubriques des mots clés des attributs C++.

Rubriques relatives aux mots clés


final ( see page 556)
3 noreturn ( see page 562)

Voir aussi
Noreturn et final (C++0x)

3.1.4.3.3 Extensions de mots clés C++Builder


Cette section contient les rubriques relatives aux extensions de mots clés C++Builder.

584
3.1 Référence C++ RAD Studio Guide du langage C++

Rubriques relatives aux mots clés


alignof ( see page 537)

asm ( see page 538)

__automated ( see page 528)

cdecl ( see page 542)

__classid ( see page 529)

__classmethod ( see page 580)

__closure ( see page 529)

__declspec ( see page 529)

__declspec(dllexport) ( see page 546)

__declspec(dllimport) ( see page 547)

__declspec(naked) ( see page 547)

__declspec(noreturn) ( see page 547)

__declspec(nothrow) ( see page 548)

__declspec(novtable) ( see page 548)

__declspec(property) ( see page 549)

__declspec(selectany) ( see page 549)

__declspec(thread) ( see page 550)

__declspec(uuid("ComObjectGUID")) ( see page 550)

__except ( see page 531)

_export ( see page 555)

_fastcall ( see page 536)

__finally ( see page 556)

_import ( see page 559)

__inline ( see page 531)

__int8 __int16 __int32 __int64 Unsigned_int64 (types integer étendus) ( see page 532)

__msfastcall ( see page 532)

__msreturn ( see page 533)

__thread ( see page 535)

Pascal ( see page 565) 3


__property ( see page 533)

__published ( see page 533)

__rtti ( see page 534)

_stdcall ( see page 537)

__try ( see page 535)

585
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.3.4 Mots clés spécifiques C++


Cette section contient les rubriques relatives aux mots clés spécifiques à C++.

Rubriques relatives aux mots clés


asm ( see page 538)

bool ( see page 540)

catch ( see page 542)

char16_t

char32_t

class ( see page 543)

const_cast (typecast operator) ( see page 535)

delete.xml ( see page 552)

dynamic_cast (typecast operator) ( see page 553)

explicit ( see page 554)

false ( see page 540)

friend ( see page 558)

inline ( see page 560)

mutable ( see page 561)

namespace ( see page 561)

new ( see page 561)

operator ( see page 564)

private ( see page 565)

protected ( see page 565)

public ( see page 566)

reinterpret_cast (typecast operator) ( see page 567)

__rtti ( see page 534)

static_cast (typecst operator) ( see page 570)

static_assert ( see page 570)

template ( see page 573)

3 this ( see page 573)

throw ( see page 574)

true ( see page 540)

try ( see page 574)

typeid ( see page 575)

typename ( see page 575)

586
3.1 Référence C++ RAD Studio Guide du langage C++

using (déclaration) ( see page 577)

virtual ( see page 577)

whar_t ( see page 579)

3.1.4.3.5 Modificateurs
Cette section contient les rubriques relatives aux mots clés des modificateurs C++.

Rubriques relatives aux mots clés


Cdecl ( see page 542)

__classmethod ( see page 580)

const ( see page 544)

__declspec ( see page 529)

__declspec(dllexport) ( see page 546)

__declspec(dllimport) ( see page 547)

__declspec(naked) ( see page 547)

__declspec(noreturn) ( see page 547)

__declspec(nothrow) ( see page 548)

__declspec(novtable) ( see page 548)

__declspec(property) ( see page 549)

__declspec(selectany) ( see page 549)

__declspec(thread) ( see page 550)

__declspec(uuid(“ComObjectGUID”)) ( see page 550)

dispid ( see page 531)

_export ( see page 555)

_fastcall ( see page 536)

_import ( see page 559)

__msfastcall ( see page 532)

__msreturn ( see page 533)

Pascal ( see page 565)

__rtti ( see page 534)

_stdcall ( see page 537) 3


volatile ( see page 578)

3.1.4.3.6 Opérateurs
Cette section contient les rubriques relatives aux mots clés des opérateurs C++.

587
Guide du langage C++ RAD Studio 3.1 Référence C++

Rubriques relatives aux mots clés


__classid ( see page 529)

alignof ( see page 537)

delete ( see page 552)

if ( see page 559)

new ( see page 561)

operator ( see page 564)

typeid ( see page 575)

sizeof ( see page 568)

3.1.4.3.7 Mots réservés


Cette section contient les rubriques relatives aux mots réservés de C++.

Rubrique relative aux mots clés


alignas ( see page 580)

axiom ( see page 581)

concept ( see page 581)

concept_map ( see page 581)

constexpr ( see page 581)

late_check ( see page 582)

nullptr ( see page 563)

requires ( see page 582)

thread_local ( see page 582)

3.1.4.3.8 Types spéciaux


Cette section contient les rubriques relatives aux mots clés des types spéciaux C++.

Rubriques relatives aux mots clés


nullptr ( see page 563)

void ( see page 578)

3 3.1.4.3.9 Instructions
Cette section contient les rubriques relatives aux mots clés des instructions C++.

Rubriques relatives aux mots clés


break ( see page 540)

case ( see page 541)

catch ( see page 542)

588
3.1 Référence C++ RAD Studio Guide du langage C++

continue ( see page 546)

default ( see page 551)

do ( see page 552)

__except ( see page 531)

__finally ( see page 556)

for ( see page 558)

goto ( see page 559)

return ( see page 567)

static_assert ( see page 570)

switch ( see page 572)

throw ( see page 574)

__try ( see page 535)

try ( see page 574)

while ( see page 579)

3.1.4.3.10 Spécificateurs de classe de stockage


Cette section contient les rubriques relatives aux mots clés des spécificateurs de classe de stockage C++.

Rubriques relatives aux mots clés


auto ( see page 539)

__declspec ( see page 529)

__declspec(dllexport) ( see page 546)

__declspec(dllimport) ( see page 547)

__declspec(naked) ( see page 547)

__declspec(noreturn) ( see page 547)

__declspec(nothrow) ( see page 548)

__declspec(novtable) ( see page 548)

__declspec(property) ( see page 549)

__declspec(selectany) ( see page 549)

__declspec(thread) ( see page 550)

__declspec(uuid(“ComObjectGUID”)) ( see page 550) 3


extern ( see page 555)

mutable ( see page 561)

register ( see page 566)

static ( see page 569)

typedef ( see page 546)

589
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.3.11 Spécificateurs de type


Cette section contient les rubriques relatives aux mots clés des spécificateurs de type C++.

Rubriques relatives aux mots clés


char ( see page 543)

case ( see page 541)

char16_t

char32_t

class ( see page 543)

decltype

double ( see page 552)

enum ( see page 553)

float ( see page 557)

int ( see page 560)

long ( see page 560)

short ( see page 567)

signed ( see page 568)

struct ( see page 571)

union ( see page 576)

unsigned ( see page 576)

wchar_t ( see page 579)

3.1.4.4 Structure du langage


Les rubriques de cette section fournissent une définition formelle du langage C++ et de son implémentation dans le compilateur
CodeGear C++. Elles décrivent les méthodes de combinaisons autorisées des divers tokens lexicaux en vue de former des
expressions, des instructions et d'autres unités significatives.

Rubriques
Nom Description
Opérateurs binaires ( see page 591) Cette section traite des opérateurs binaires.
Déclarations ( see page 597) Cette section contient les rubriques relatives aux déclarations.
Syntaxe de déclaration ( see page 604) Les six attributs connexes (classe de stockage, type, portée, visibilité, durée de
3 vie et attribut de liaison) sont déterminés de différentes façons par les
déclarations.
Il existe deux types de déclarations : les déclarations de définition (appelées
simplement définitions) ou les déclarations de référence (parfois appelées
déclarations de non définition). Les premières, comme leur nom l'indique,
permettent de déclarer et de définir ; les secondes exigent qu'une définition soit
créée à un quelconque niveau du programme. Une déclaration de référence
introduit simplement un ou plusieurs noms d'identificateurs dans un programme.
Une définition, en revanche, alloue de la mémoire à un objet et... suite ( see
page 604)
Enumérations ( see page 622) Cette section traite des énumérations.

590
3.1 Référence C++ RAD Studio Guide du langage C++

Expressions ( see page 624) Cette section traite des expressions.


Fonctions ( see page 629) Cette section traite des fonctions.
Résumé des opérateurs ( see page 640) Cette section présente le résumé les opérateurs.
Pointeurs ( see page 642) Cette section traite des pointeurs.
Opérateurs d'expressions postfixées ( see page 647) Cette section traite des opérateurs d'expressions postfixés.
Opérateurs d'expressions primaires ( see page 649) Cette section traite des opérateurs d'expressions primaires.
Instructions ( see page 651) Cette section traite des instructions.
Structures ( see page 654) Cette section traite des structures.
Opérateurs unaires ( see page 661) Cette section traite des opérateurs unaires.
Unions ( see page 664) Cette section traite des unions.

3.1.4.4.1 Opérateurs binaires


Cette section traite des opérateurs binaires.

Rubriques
Nom Description
Opérateurs binaires ( see page 591) Voici les opérateurs binaires de CodeGear C++ :
Opérateurs bit à bit ( see page 593) Syntaxe
Opérateurs spécifiques au C++ ( see page 594) Les opérateurs spécifiques au C++ sont les suivants :
Opérateurs d'égalité ( see page 594) Il existe deux opérateurs d'égalité : == et !=. Ils testent l'égalité ou l'inégalité de
deux valeurs arithmétiques ou pointeurs, en appliquant des règles très proches
de celles qui concernent les opérateurs relationnels.
Remarque: Notez que les opérateurs d'égalité ==
et != ont une moins grande priorité que les opérateurs relationnels < et >, <= et
>=. Par ailleurs, avec == et != vous pouvez comparer des types pointeurs que les
opérateurs relationnels ne permettent pas de comparer. La syntaxe est :
Opérateurs logiques ( see page 594) Syntaxe
Opérateurs relationnels ( see page 595) Syntaxe
Opérateurs d'affectation ( see page 595) Syntaxe
Opérateur virgule ( see page 596) Syntaxe
Opérateurs conditionnels ( see page 596) Syntaxe
Opérateurs de multiplication ( see page 597) Syntaxe

3.1.4.4.1.1 Opérateurs binaires


Voici les opérateurs binaires de CodeGear C++ :

Opérateur arithmétique Description


+ Plus binaire (addition)
— Moins binaire (soustraction)
* Multiplier
/ Diviser
% Reste (modulo)

Opérateur bit à bit Description


<< Décalage gauche
>> Décalage droite
& AND bit-à-bit
^ XOR bit à bit (OU exclusif)

591
Guide du langage C++ RAD Studio 3.1 Référence C++

| OR inclusif bit à bit

Opérateur logique Description


&& AND logique

Opérateur d'affectation Description


= Affectation
*= Affectation produit
/= Affectation quotient
%= Affectation reste (modulo)
+= Affectation somme
—= Affectation différence
<<= Affectation décalage gauche
>>= Affectation décalage droite
&= Affectation AND bit à bit
^= Affectation XOR bit à bit
|= Affectation OR bit à bit

Opérateur relationnel Description


< Inférieur à
> Supérieur à
<= Inférieur ou égal à
>= Supérieur ou égal à
== Egal à
!= Différent

Opérateur de sélection de composant Description


. Sélecteur de composant direct
-> Sélecteur de composant indirect
3

Opérateur de membre de Description


classe
:: Accès/résolution de portée
.* Déréférencement d'un pointeur sur un membre de classe
->* Déréférencement d'un pointeur sur un membre de classe

592
3.1 Référence C++ RAD Studio Guide du langage C++

Opérateur Description
conditionnel
?: Réellement un opérateur ternaire. Par exemple : a ? x : y signifie "if a then x else y"

Opérateur virgule Description


, Evaluer

3.1.4.4.1.2 Opérateurs bit à bit


Syntaxe
expression-ET & expression-égalité
expression-OU-exclusif ^ expression-ET
expression-OU-inclusif | expression-OU-exclusive
~expression-transtypage
expression-décalage << expression-addition
expression-décalage >> expression-addition
Remarques

Utilisez les opérateurs bit à bit pour modifier les bits individuels au lieu du nombre.

Opérateur Action
& ET bit à bit ; compare deux bits et génère 1 si les deux bits sont à 1, et 0 dans les autres cas.
| OU inclusif bit à bit ; compare deux bits et génère 1 si un des deux bits ou les deux sont à 1, et 0 dans les autres
cas.
^ OU exclusif bit à bit ; compare deux bits et génère 1 si les bits sont complémentaires, et 0 s'ils ne le sont pas.
~ Complément bit à bit ; inverse chaque bit. ~ est utilisé pour créer des destructeurs.
>> Décalage bit à bit droit ; décale les bits vers la droite en ignorant les bits décalés et, si non signé, affecte la valeur 0
aux bits les plus à gauche, sinon le signe est étendu.
<< Décalage bit à bit gauche ; décale les bits vers la gauche en ignorant les bits décalés et en affectant la valeur 0
aux bits les plus à droite.

Les deux opérandes d'une expression bit à bit doivent être de type entier.

A B A&B A^B A|B


0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 0 1 3
Remarque: &, >>, << sont sensibles au contexte. & peut être aussi l'opérateur de référencement de pointeur.

Remarque: >> est souvent surchargé pour être l'opérateur d'entrée dans des expressions E/S. << est souvent surchargé pour
être l'opérateur de sortie dans des expressions E/S.

593
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.4.1.3 Opérateurs spécifiques au C++


Les opérateurs spécifiques au C++ sont les suivants :

Opérateur Signification
:: Opérateur d'accès (ou de résolution) de portée.
.* Pointeur de déréférencement sur des membres de classes
->* Déréférence un pointeur sur un pointeur des membres d'une classe
const_cast Ajoute ou retire d'un type le modificateur const ou volatile
delete Désalloue dynamiquement de la mémoire
dynamic_cast Convertit un pointeur au type voulu
new Alloue dynamiquement de la mémoire
reinterpret_cast Remplace les transtypages dans le cas de conversions dangereuses ou dépendantes de l'implémentation
static_cast Convertit un pointeur au type voulu
typeid Obtient une identification de types et expressions à l'exécution

Utilisez l'opérateur d'accès (ou de résolution) de portée :: (deux points-virgules) pour accéder à un nom global (ou de la durée du
fichier) même s'il est caché par une redéclaration locale de ce nom.

Utilisez les opérateurs .* et ->* pour déréférencer des pointeurs sur des membres de classe ou des pointeurs sur des pointeurs
de membres de classe.

3.1.4.4.1.4 Opérateurs d'égalité


Il existe deux opérateurs d'égalité : == et !=. Ils testent l'égalité ou l'inégalité de deux valeurs arithmétiques ou pointeurs, en
appliquant des règles très proches de celles qui concernent les opérateurs relationnels.

Remarque: Notez que les opérateurs d'égalité ==

et != ont une moins grande priorité que les opérateurs relationnels < et >, <= et >=. Par ailleurs, avec == et != vous pouvez
comparer des types pointeurs que les opérateurs relationnels ne permettent pas de comparer. La syntaxe est :
expression-égalité:==!=
expression-relationnelle
expression-égalité == expression-relationnelle
expression-égalité != expression-relationnelle

3.1.4.4.1.5 Opérateurs logiques


Syntaxe
expression-ET-logique && expression-OU-inclusif
expression-OU-logique || expression-ET-logique
! expression-transtypage
3 Remarques

Les opérandes d'une expression logique doivent être de type scalaire.

&& ET logique ; renvoie true seulement si les deux expressions sont évaluées à une valeur différente de zéro (sinon, renvoie
false). Si la première expression est évaluée à false, la seconde expression n'est pas évaluée.

|| OU logique ; renvoie true si l'une des expressions est évaluée à une valeur différente de zéro (sinon, renvoie false). Si la
première expression est évaluée à true, la seconde expression n'est pas évaluée.

594
3.1 Référence C++ RAD Studio Guide du langage C++

! Négation logique ; renvoie true si l'expression est évaluée à une valeur différente de zéro (sinon, renvoie false). L'expression
!E est équivalente à (0 == E).

3.1.4.4.1.6 Opérateurs relationnels


Syntaxe
expression-relationnelle < expression-décalage
expression-relationnelle > expression-décalage
expression-relationnelle <= expression-décalage
expression-relationnelle >= expression-décalage
Remarques

Utilisez les opérateurs relationnels pour tester l'égalité ou l'inégalité des expressions. Si l'instruction est évaluée à true, elle
renvoie un caractère différent de zéro ; sinon le résultat est false (0).

> supérieur à

< inférieur à

>= supérieur ou égal à

<= inférieur ou égal à

Dans l'expression
E1 <opérateur> E2
les opérandes doivent être conformes à l'une des conditions suivantes :

• 1. E1 et E2 sont toutes deux de type arithmétique.


• 2. E1 et E2 sont toutes deux des pointeurs sur des versions qualifiées ou non de types compatibles.
• 3. L'une des expressions E1 et E2 est un pointeur sur un objet ou type incomplet, et l'autre est un pointeur sur une version
qualifiée ou non de void.
• 4. L'une des expressions E1 et E2 est un pointeur et l'autre une constante pointeur NULL.

3.1.4.4.1.7 Opérateurs d'affectation


Syntaxe
expression-unaire opérateur-affectation expression-affectation
Remarques

Voici la liste des opérateurs d'affectation :


= *= /= %= += -=
<<= >>= &= ^= |=
L'opérateur = est le seul opérateur d'affectation simple, les autres sont des opérateurs d'affectation composés.

Dans l'expression E1 = E2, E1 doit être une lvalue modifiable. L'expression d'affectation n'est pas elle-même une lvalue.

L'expression
3
E1 op= E2
a le même effet que :
E1 = E1 op E2
en dehors du fait que la lvalue E1 n'est évaluée qu'une fois. Par exemple, E1 += E2 est équivalent à E1 = E1 + E2.

La valeur de l'expression est E1 après son évaluation.

595
Guide du langage C++ RAD Studio 3.1 Référence C++

Pour les affectations simples et composées, les opérandes E1 et E2 doivent obéir à l'une des règles suivantes :

• 1. E1 est un type arithmétique qualifié ou non et E2 est un type arithmétique.


• 2. E1 est une version qualifiée ou non d'un type structure ou union compatible avec celui de E2.
• 3. E1 et E2 sont des pointeurs sur des versions qualifiées ou non, de types compatibles. Le type pointé par le membre
gauche a tous les qualificateurs du type pointé par le membre droit.
• 4. Soit E1, soit E2 est un pointeur sur un objet ou un type incomplet et l'autre est un pointeur sur une version qualifiée ou non
du type void. Le type pointé par le membre gauche a tous les qualificateurs du type pointé par le membre droit.
• 5. E1 est un pointeur et E2 est une constante pointeur NULL.
Remarque: Les espaces séparant les opérateurs composés (+<espace>=) génèreront des erreurs.
Remarque: Il existe certaines conditions dans lesquelles les opérateurs d'affectation ne sont pas gérés lors de l'utilisation
avec les propriétés.

3.1.4.4.1.8 Opérateur virgule


Syntaxe
expression , expression-affectation
Remarques

La virgule sépare les éléments dans la liste d'arguments d'une fonction.

La virgule sert aussi d'opérateur dans les expressions à virgules. L'association des deux emplois de la virgule est légal, mais
vous devez utiliser les parenthèses pour les distinguer.

L'opérande gauche E1 est évalué en tant qu'expression void, puis E2 est évalué pour fournir le résultat et le type de l'expression
virgule. Par récursion, l'expression
E1, E2, ..., En
résultera en une évaluation de gauche à droite de chaque élément Ei. La valeur et le type de En donneront le résultat de toute
l'expression.

Pour éviter toute ambiguïté entre les virgules utilisées dans les arguments de fonction et celles qui apparaissent dans les listes
d'initialisation, vous devez ajouter des parenthèses. Par exemple,
func(i, (j = 1, j + 4), k);
provoque l'appel de func avec trois arguments (i, 5, k) et non quatre.

3.1.4.4.1.9 Opérateurs conditionnels


Syntaxe
expression-OU-logique ? expression : expression-conditionnelle
Remarques

L'opérateur conditionnel ?: est un opérateur ternaire.


3
Dans l'expression E1 ? E2 : E3, E1 est d'abord évaluée. Si sa valeur est à true, E2 est alors évaluée et E3 est ignorée. Si E1 est
évaluée à false, E3 est alors évaluée et E2 est ignorée.

Le résultat de E1 ? E2 : E3 sera la valeur de E2 ou E3 en fonction de l'évaluation.

E1 doit être une expression scalaire. E2 et E3 doivent obéir à l'une des règles suivantes :

• 1. Les deux opérandes sont de type arithmétique. E2 et E3 sont soumises aux conversions arithmétiques habituelles qui
déterminent le type résultant.

596
3.1 Référence C++ RAD Studio Guide du langage C++

• 2. Les deux opérandes sont de type struct ou union compatible. Le type résultant est le type union ou structure de E2 et E3.
• 3. Les deux opérandes sont de type void. Le type résultant est void.
• 4. Les deux opérandes sont de type pointeur sur une version qualifiée ou non de types compatibles. Le type résultant est un
pointeur sur un type qualifié par tous les qualificateurs des types pointés par les deux opérandes.
• 5. Un opérande est un pointeur et l'autre est une constante pointeur NULL. Le type résultant est un pointeur sur un type
qualifié par tous les qualificateurs des types pointés par les deux opérandes.
• 6. Un opérande est un pointeur sur un objet ou un type incomplet et l'autre est un pointeur sur une version qualifiée ou non de
void. Le type résultant est celui de l'opérande qui n'est pas un pointeur sur void.

3.1.4.4.1.10 Opérateurs de multiplication


Syntaxe
expr-multiplication * expr-transtypage
expr-multiplication / expr-transtypage
expr-multiplication % expr-transtypage
Remarques

Voici les trois opérateurs de multiplication :

• * (multiplication)
• / (division)
• % (modulo ou reste)
Les conversions arithmétiques habituelles sont effectuées sur les opérandes.
(op1 * op2) Produit de deux opérandes
(op1 / op2) Quotient de (op1 divisé par op2)
(op1 % op2) Reste de (op1 divisé par op2)
Pour / et %, op2 doit être différent de zéro. op2 = 0 produit une erreur. (Vous ne pouvez pas diviser par zéro.)
Lorsque op1 et op2 sont des entiers et que le quotient n'est pas un entier :
• 1. Si op1 et op2 sont de même signe, op1 / op2 correspond au plus grand entier plus grand que le vrai quotient, et op1 % op2
prend le signe de op1.
• 2. Si op1 et op2 sont de signes opposés, op1 / op2 correspond au plus petit entier plus grand que le vrai quotient, et op1 %
op2 prend le signe de op1.
Remarque: Les valeurs sont toujours arrondies vers zéro.
* est sensible au contexte et peut être utilisé comme opérateur de référencement de pointeur.

3.1.4.4.2 Déclarations
Cette section contient les rubriques relatives aux déclarations.

Rubriques
Nom Description
3
Durée ( see page 598) La durée de vie, en relation étroite avec la classe de stockage, définit la période
pendant laquelle les identificateurs déclarés ont des objets physiques réels
affectés en mémoire. Nous faisons également une distinction entre les objets
établis pendant la compilation et ceux qui l'ont été pendant l'exécution. Les
variables, par exemple, à l'inverse des types et des typedef, ont une affectation
réelle en mémoire durant l'exécution. Il existe trois types de durée de vie :
statique, locale et dynamique.
Statique
Les objets ayant une durée de vie statique ont une allocation mémoire dès le
début de l'exécution ; cette allocation de... suite ( see page 598)

597
Guide du langage C++ RAD Studio 3.1 Référence C++

Liaison ( see page 599) Un programme exécutable est généralement créé par compilation de plusieurs
unités de traduction autonomes, puis par connexion des fichiers objet résultants
avec des bibliothèques préexistantes. Un problème se pose lorsque le même
identificateur est déclaré dans des portées différentes (par exemple, dans des
fichiers différents), ou s'il est déclaré plusieurs fois dans une même portée. La
connexion, ou liaison, est le processus qui permet l'association correcte de
chaque instance d'un identificateur à une fonction ou à un objet particulier. Tous
les identificateurs possèdent l'un de ces trois attributs de liaison, en relation
étroite avec leur portée : liaison externe, liaison interne... suite ( see page 599)
Objets ( see page 601) Un objet est une région spécifique de la mémoire qui peut contenir une valeur
fixe ou variable (ou un ensemble de valeurs). (Le mot objet employé dans ce
sens ne doit pas être confondu avec le terme plus général utilisé dans les
langages orientés objet). Chaque valeur possède un nom et un type (appelé type
de données) qui lui sont associés. Le nom permet d'accéder à l'objet. Il peut
s'agir d'un simple identificateur ou d'une expression complexe qui désigne l'objet
de façon unique. Le type sert à :

• déterminer correctement les exigences d'allocation


mémoire ;
• interpréter les configurations de bits rencontrées... suite
( see page 601)
Portée ( see page 602) La portée d'un identificateur est la partie du programme dans laquelle il est
possible d'accéder à son objet. Il existe six catégories de portée : bloc (ou
locale), fonction, prototype de fonction, fichier, classe (C++ uniquement) et
espace de nommage (C++ uniquement). Elles dépendent du mode et du lieu de
déclaration des identificateurs.

• Bloc. La portée bloc, ou locale, d'un identificateur


commence au point de déclaration et se termine à la fin
du bloc contenant la déclaration (on parle de bloc
englobant). Les déclarations de paramètres d'une
définition de fonction ont aussi une portée locale, limitée
au bloc qui définit... suite ( see page 602)
Types et classes de stockage ( see page 603) L'association des identificateurs et des objets nécessite que chaque identificateur
possède au moins deux attributs : une classe de stockage et un type (aussi
appelé type de données). Le compilateur C++ déduit ces attributs des
déclarations implicites ou explicites du code source.
La classe de stockage détermine l'emplacement d'un objet et sa durée de vie (le
temps d'exécution total du programme, ou le temps d'exécution de certains blocs
de code). La classe de stockage sera déduite de la syntaxe de la déclaration, de
son emplacement dans le code source, ou de ces deux éléments.
Le type détermine la part de mémoire... suite ( see page 603)
Unités de traduction ( see page 603) L'expression unité de traduction se réfère à un fichier en code source ainsi qu'à
tous les fichiers inclus, à l'exception des lignes source exclues par les directives
conditionnelles du préprocesseur. Sur le plan syntaxique, une unité de traduction
est définie comme une séquence de déclarations externes :
Visibilité ( see page 604) La visibilité d'un identificateur correspond à la partie du code source depuis
laquelle il est possible d'atteindre légalement l'objet associé à l'identificateur.
La portée et la visibilité coïncident généralement, bien que, dans certains cas, un
objet soit provisoirement caché par l'apparition d'un deuxième identificateur :
l'objet existe encore, mais l'identificateur original ne permet pas de l'atteindre tant
que l'identificateur en double n'est pas sorti de sa portée.
Remarque: La visibilité ne peut pas être supérieure à la portée, mais cette
dernière peut en revanche excéder la visibilité.
Là encore, des règles spécifiques s'appliquent aux noms de classes cachés et
aux noms... suite ( see page 604)

3 3.1.4.4.2.1 Durée
La durée de vie, en relation étroite avec la classe de stockage, définit la période pendant laquelle les identificateurs déclarés ont
des objets physiques réels affectés en mémoire. Nous faisons également une distinction entre les objets établis pendant la
compilation et ceux qui l'ont été pendant l'exécution. Les variables, par exemple, à l'inverse des types et des typedef, ont une
affectation réelle en mémoire durant l'exécution. Il existe trois types de durée de vie : statique, locale et dynamique.

Statique

598
3.1 Référence C++ RAD Studio Guide du langage C++

Les objets ayant une durée de vie statique ont une allocation mémoire dès le début de l'exécution ; cette allocation de mémoire
dure jusqu'à la fin du programme. Toutes les fonctions, lorsqu'elles sont définies, ont des objets à durée statique. Toutes les
variables à portée fichier ont une durée statique. D'autres variables peuvent avoir une durée statique si vous utilisez les
spécificateurs de classe de stockage explicites static ou extern.

Les objets à durée de vie statique sont initialisés à zéro (ou à NULL) en l'absence de toute valeur d'initialisation explicite ou,
dans C++, de constructeur de classe.

Il ne faut pas confondre la durée de vie statique avec la portée fichier, ou portée globale. Un objet peut avoir une durée de vie
statique et une portée locale.

Locale

Les objets à durée de vie locale, également appelés objets automatiques, ont une existence plus précaire. Ils sont créés dans
une pile (ou un registre) lorsque le bloc englobant ou la fonction commence à s'exécuter. Une fois que le programme quitte ce
bloc ou cette fonction, ils sont désalloués. Les objets à durée de vie locale doivent être initialisés de façon explicite ; sinon, leur
contenu n'est pas prévisible. Ils doivent toujours avoir une portée locale ou une portée fonction. Il est possible d'utiliser le
spécificateur de classe de stockage auto au moment de la déclaration des variables de durée locale, mais cette démarche est
généralement redondante car auto est la valeur par défaut des variables déclarées dans un bloc. Un objet à durée de vie locale
a également une portée locale puisqu'il n'existe pas en dehors de son bloc englobant. La réciproque n'est pas vraie : un objet de
portée locale peut avoir une durée de vie statique.

Lors de la déclaration de variables (par exemple, int, char, float), le spécificateur de classe de stockage register sous-entend
également auto ; mais une demande est transmise au compilateur pour qu'un registre soit, si possible, alloué à l'objet. Le
compilateur permet l'allocation d'un registre à une variable locale entière ou pointeur. Si aucun registre n'est disponible, la
variable est définie comme un objet local, de type auto, sans qu'aucun avertissement ni message d'erreur ne soit émis.

Remarque: Le compilateur peut ignorer les demandes d'allocation de registre. L'allocation de registre est basée sur l'analyse,
par le compilateur, du mode d'utilisation d'une variable.

Dynamique

Les objets à durée de vie dynamique sont créés et détruits par des appels de fonctions spécifiques au cours de l'exécution. Ils
sont définis dans une zone réservée de la mémoire appelée tas, soit à partir de fonctions de bibliothèque standard comme
malloc, soit par l'intermédiaire de l'opérateur C++ new. Pour les désallocations correspondantes, free ou delete est utilisée.

Voir aussi
Déclarations ( see page 597)

Objets ( see page 601)

Types et classes de stockage ( see page 603)

Portée ( see page 602)

Visibilité ( see page 604)

Liaison ( see page 599)

Le mot clé static ( see page 569)


3
3.1.4.4.2.2 Liaison
Un programme exécutable est généralement créé par compilation de plusieurs unités de traduction autonomes, puis par
connexion des fichiers objet résultants avec des bibliothèques préexistantes. Un problème se pose lorsque le même
identificateur est déclaré dans des portées différentes (par exemple, dans des fichiers différents), ou s'il est déclaré plusieurs fois
dans une même portée. La connexion, ou liaison, est le processus qui permet l'association correcte de chaque instance d'un
identificateur à une fonction ou à un objet particulier. Tous les identificateurs possèdent l'un de ces trois attributs de liaison, en

599
Guide du langage C++ RAD Studio 3.1 Référence C++

relation étroite avec leur portée : liaison externe, liaison interne ou absence d'attribut de liaison. Ces attributs sont déterminés
par l'emplacement et le format de vos déclarations, ainsi que par l'utilisation explicite (ou implicite) du spécificateur de classe de
stockage static ou extern.

Chaque instance d'un identificateur particulier caractérisé par une liaison externe représente le même objet ou la même fonction
dans l'ensemble des fichiers et bibliothèques qui constituent le programme. Chaque instance d'un identificateur particulier
caractérisé par une liaison interne représente le même objet ou la même fonction dans un seul fichier. Enfin, les identificateurs
sans attribut de liaison représentent des entités uniques.

Règles des attributs de liaison externe et interne

Tout identificateur de fichier ou d'objet ayant une portée fichier sera caractérisé par une liaison interne si sa déclaration contient
le spécificateur de classe de stockage static.

Si le même identificateur apparaît avec, à la fois, les attributs de liaison externe et interne dans le même fichier, il sera
caractérisé en C++ par une liaison externe. En C, il aura une liaison interne.

Si la déclaration d'un identificateur d'objet ou de fonction contient le spécificateur de classe de stockage extern, il aura le même
attribut de liaison que toute autre déclaration visible de cet identificateur à portée fichier. S'il n'existe pas de déclaration visible,
l'identificateur sera caractérisé par une liaison externe.

Si une fonction est déclarée sans spécificateur de classe de stockage, son attribut de liaison est déterminé comme si le
spécificateur extern était utilisé.

Si un identificateur d'objet à portée fichier est déclaré sans spécificateur de classe de stockage, il sera caractérisé par une
liaison externe.

Les identificateurs suivants n'ont pas d'attribut de liaison :

• Les identificateurs déclarés pour être autre chose qu'un objet ou une fonction (par exemple, un identificateur typedef)
• Les paramètres de fonction
• Les identificateurs à portée bloc (locale) pour des objets déclarés sans spécificateur de classe de stockage extern
Substantypage
Quand un module C++ est compilé, le compilateur génère des noms de fonctions qui tiennent compte des types de leurs
arguments. Ce mécanisme est connu sous le nom de substantypage (name mangling en anglais). Il permet la surcharge des
fonctions et aide le lieur à gérer les erreurs lors de l'appel de fonctions provenant d'autres modules. Mais ce dispositif n'est
pas toujours souhaitable. Lors de la compilation d'un module C++ à lier avec un autre ne pratiquant pas le substantypage, le
compilateur C++ doit être avisé de ne pas substantyper les noms des fonctions de l'autre module. Ce genre de situation est
typiquement celui de la liaison avec des bibliothèques ou des fichiers .obj issus d'un compilateur C.
Pour indiquer au compilateur C++ de ne pas substantyper le nom d'une fonction, il suffit de la déclarer comme extern "C" :
extern "C" void Cfunc( int );
Cette déclaration indique au compilateur de ne pas substantyper les références à la fonction Cfunc.

La déclaration extern "C" s'applique également à un bloc de noms :


extern "C" {
void Cfunc1( int );
void Cfunc2( int );
3 void Cfunc3( int );
};
Cette déclaration "multiple" fonctionne comme celle concernant une seule fonction ; le compilateur ne substantype pas les
références aux fonctions Cfunc1, Cfunc2 et Cfunc3. Cette forme de déclaration est également utilisable quand le bloc des noms
de fonctions est contenu dans un fichier en-tête :
extern "C" {
#include "locallib.h"
};

600
3.1 Référence C++ RAD Studio Guide du langage C++

Remarque: extern "C" ne peut pas être utilisé avec des identificateurs de classe.

Voir aussi
Déclarations ( see page 597)

Objets ( see page 601)

Types et classes de stockage ( see page 603)

Portée ( see page 602)

Visibilité ( see page 604)

Durée ( see page 598)

3.1.4.4.2.3 Objets
Un objet est une région spécifique de la mémoire qui peut contenir une valeur fixe ou variable (ou un ensemble de valeurs). (Le
mot objet employé dans ce sens ne doit pas être confondu avec le terme plus général utilisé dans les langages orientés objet).
Chaque valeur possède un nom et un type (appelé type de données) qui lui sont associés. Le nom permet d'accéder à l'objet. Il
peut s'agir d'un simple identificateur ou d'une expression complexe qui désigne l'objet de façon unique. Le type sert à :

• déterminer correctement les exigences d'allocation mémoire ;


• interpréter les configurations de bits rencontrées dans l'objet durant les différents accès ;
• contrôler, lors de certaines vérifications, que les affectations illégales sont bien détectées.
Le compilateur C++ de Borland accepte tous les types de données standard, y compris les entiers signés et non signés de
différentes tailles, les nombres en virgule flottante de différentes précisions, les structures, les unions, les tableaux et les
classes. En outre, il est possible d'établir des pointeurs vers la plupart de ces objets et de les manipuler dans divers modèles
mémoire.

Objets et déclarations
Les déclarations permettent d'établir la correspondance nécessaire entre identificateurs et objets. Chaque déclaration associe
un identificateur à un type de données. La plupart des déclarations, appelées déclarations de définition, entraînent aussi la
création de l'objet (où et quand), à savoir l'allocation de mémoire physique et son éventuelle initialisation. D'autres
déclarations, dites de référence, permettent simplement d'indiquer au compilateur les identificateurs et les types. Un même
identificateur peut avoir plusieurs déclarations de référence, notamment dans un programme multifichier ; en revanche, une
seule déclaration de définition est autorisée.
De manière générale, un identificateur ne peut pas être légalement utilisé dans un programme avant son point de déclaration
dans le code source. Les exceptions légales à cette règle, appelées références aval, concernent les classes, les étiquettes,
les structures, les noms d'unions et les appels de fonctions non déclarées.
lvalue
Une lvalue est un localisateur d'objet : une expression qui désigne un objet. Un exemple de lvalue est l'expression *P, P étant
une expression dont le résultat est un pointeur non NULL. Une lvalue modifiable est un identificateur ou une expression
concernant un objet mémoire qui peut être atteint et modifié. Par exemple, un pointeur de type const sur une constante n'est
pas une lvalue modifiable. En revanche, un pointeur sur une constante est modifiable, (mais sa valeur déréférencée ne l'est
pas).
3
A l'origine, le l, correspondant à l'initiale du mot anglais "left", signifiait qu'une lvalue pouvait se trouver à gauche d'une
instruction d'affectation. Aujourd'hui, seules les lvalue modifiables peuvent légalement constituer le membre gauche d'une
instruction d'affectation. Par exemple, si a et b sont des identificateurs entier variables correctement créés, ils peuvent tous
les deux être des lvalue modifiables et les affectations telles que a=1 ; et b=a+b ; sont correctes.
rvalue
L'expression a + b n'est pas une lvalue : a + b = a est illégale car le membre gauche de cette expression n'est pas associable à
un objet. Ces expressions sont fréquemment appelées rvalue (le r correspondant à l'initiale de "right").

601
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
Déclarations ( see page 597)

Types et classes de stockage ( see page 603)

Portée ( see page 602)

Visibilité ( see page 604)

Durée ( see page 598)

Liaison ( see page 599)

3.1.4.4.2.4 Portée
La portée d'un identificateur est la partie du programme dans laquelle il est possible d'accéder à son objet. Il existe six
catégories de portée : bloc (ou locale), fonction, prototype de fonction, fichier, classe (C++ uniquement) et espace de nommage
(C++ uniquement). Elles dépendent du mode et du lieu de déclaration des identificateurs.

• Bloc. La portée bloc, ou locale, d'un identificateur commence au point de déclaration et se termine à la fin du bloc contenant
la déclaration (on parle de bloc englobant). Les déclarations de paramètres d'une définition de fonction ont aussi une portée
locale, limitée au bloc qui définit la fonction.
• Fonction. Les seuls identificateurs qui ont une portée fonction sont les étiquettes d'instruction. Les noms d'étiquettes sont
utilisables avec les instructions goto en tout point de la fonction dans laquelle l'étiquette est déclarée. Les étiquettes sont
déclarées implicitement par l'écriture du nom_label : suivi d'une instruction. Les noms d'étiquette doivent être uniques au sein
d'une même fonction.
• Prototype de fonction. Les identificateurs déclarés dans la liste des paramètres d'un prototype de fonction (qui ne font pas
partie de la définition de la fonction) ont une portée prototype de fonction. Cette portée se termine à la fin du prototype de
fonction.
• Fichier. Les identificateurs ayant une portée fichier, appelés identificateurs globaux, sont déclarés en dehors des blocs et des
classes. Leur portée part du point de déclaration et se termine à la fin du fichier contenant cette déclaration.
• Classe (C++). Une classe est un ensemble nommé de membres, comprenant des structures de données et des fonctions qui
agissent sur celles-ci. La portée classe s'applique aux noms des membres d'une classe particulière. Les classes et les objets
obéissent à plusieurs règles spécifiques d'accès et de portée ; voir la rubrique Classes.
• Condition (C++). Il est possible d'effectuer des déclarations à l'intérieur de conditions. Des variables peuvent être déclarées
dans l'expression des instructions if, while et switch. La portée de la variable est celle de l'instruction. Dans le cas d'une
instruction if, la variable se trouve également dans la portée du bloc else.
• Espace de nommage (C++). Un espace de nommage est un regroupement logique d'entités de programme (identificateurs,
classes et fonctions). Les espaces de nommage sont ouverts, c'est-à-dire qu'ils peuvent s'étendre sur plusieurs unités de
compilation. Vous pouvez considérer un espace de nommage comme une portée de nommage, comparable en de nombreux
points à une classe en C++. Voir le mot-clé namespace dans l'aide pour de plus amples informations sur la façon de déclarer
et d'utiliser les espaces de nommage.
Espaces de nommage
L'espace de nommage correspond à la portée à l'intérieur de laquelle un identificateur doit être unique. Remarquez qu'un
espace de nommage en C++ étend ce concept en vous autorisant à donner un nom à la portée. Outre la capacité de C++ à
3 nommer les portées, le langage C utilise quatre catégories distinctes d'identificateurs :
• Les noms d'étiquette goto. Ils doivent être uniques au sein de la fonction dans laquelle ils sont déclarés.
• Les noms de structure, d'unions et d'énumérations. Ils doivent être uniques dans le bloc où ils sont définis. Les noms déclarés
hors de toute fonction doivent être uniques.
• Les noms de membres de structures et d'unions. Ils doivent être uniques dans la structure ou dans l'union où ils ont été
définis. Il n'y a pas de restriction quant au type ou à la position des membres ayant le même nom dans des structures
différentes.
• Les variables, les typedef, les fonctions et les membres d'énumération. Ils doivent être uniques au sein de la portée dans

602
3.1 Référence C++ RAD Studio Guide du langage C++

laquelle ils ont été définis. Les identificateurs déclarés en externe doivent être uniques parmi les variables déclarées de façon
externe.
Voir aussi
Déclarations ( see page 597)

Objets ( see page 601)

Types et classes de stockage ( see page 603)

Visibilité ( see page 604)

Durée ( see page 598)

Liaison ( see page 599)

3.1.4.4.2.5 Types et classes de stockage


L'association des identificateurs et des objets nécessite que chaque identificateur possède au moins deux attributs : une classe
de stockage et un type (aussi appelé type de données). Le compilateur C++ déduit ces attributs des déclarations implicites ou
explicites du code source.

La classe de stockage détermine l'emplacement d'un objet et sa durée de vie (le temps d'exécution total du programme, ou le
temps d'exécution de certains blocs de code). La classe de stockage sera déduite de la syntaxe de la déclaration, de son
emplacement dans le code source, ou de ces deux éléments.

Le type détermine la part de mémoire réservée à un objet et la manière dont le programme interprète les configurations binaires
rencontrées dans la mémoire allouée à cet objet. Un type donné peut être perçu comme l'ensemble des valeurs (souvent
dépendantes de l'implémentation) que les identificateurs de ce type peuvent prendre, associé à l'ensemble des opérations
réalisables sur ces valeurs. A la compilation, l'opérateur sizeof permet de déterminer la taille, en octets, des types, qu'ils soient
standard ou définis par le programmeur. Pour plus d'informations sur cet opérateur, voir sizeof.

Voir aussi
Déclarations ( see page 597)

Objets ( see page 601)

Portée ( see page 602)

Visibilité ( see page 604)

Durée ( see page 598)

Liaison ( see page 599)

3.1.4.4.2.6 Unités de traduction


L'expression unité de traduction se réfère à un fichier en code source ainsi qu'à tous les fichiers inclus, à l'exception des lignes
source exclues par les directives conditionnelles du préprocesseur. Sur le plan syntaxique, une unité de traduction est définie
comme une séquence de déclarations externes :
3
unité-traduction:
déclaration-externe
unité-traduction déclaration externe
déclaration-externe
définition-fonction
déclaration
En langage C, le mot external a plusieurs connotations ; ici, il désigne des déclarations effectuées ailleurs que dans une fonction
et qui, par conséquent, ont une portée fichier. La liaison externe est une propriété distincte ; voir la section Liaison. Les
déclarations qui réservent un emplacement de stockage à un objet ou à une fonction sont appelées définitions (ou déclarations

603
Guide du langage C++ RAD Studio 3.1 Référence C++

de définition). Pour plus de détails, voir la rubrique Déclarations externes et définitions.

Voir aussi
Déclarations ( see page 597)

Objets ( see page 601)

Types et classes de stockage ( see page 603)

Portée ( see page 602)

Visibilité ( see page 604)

Durée ( see page 598)

Liaison ( see page 599)

3.1.4.4.2.7 Visibilité
La visibilité d'un identificateur correspond à la partie du code source depuis laquelle il est possible d'atteindre légalement l'objet
associé à l'identificateur.

La portée et la visibilité coïncident généralement, bien que, dans certains cas, un objet soit provisoirement caché par l'apparition
d'un deuxième identificateur : l'objet existe encore, mais l'identificateur original ne permet pas de l'atteindre tant que
l'identificateur en double n'est pas sorti de sa portée.

Remarque: La visibilité ne peut pas être supérieure à la portée, mais cette dernière peut en revanche excéder la visibilité.

Là encore, des règles spécifiques s'appliquent aux noms de classes cachés et aux noms des membres de classe : des
opérateurs spéciaux en C++ permettent d'accéder aux identificateurs cachés, ceci dans certaines conditions.

Voir aussi
Déclarations ( see page 597)

Objets ( see page 601)

Types et classes de stockage ( see page 603)

Portée ( see page 602)

Durée ( see page 598)

Liaison ( see page 599)

3.1.4.4.3 Syntaxe de déclaration


Les six attributs connexes (classe de stockage, type, portée, visibilité, durée de vie et attribut de liaison) sont déterminés de
différentes façons par les déclarations.

Il existe deux types de déclarations : les déclarations de définition (appelées simplement définitions) ou les déclarations de
référence (parfois appelées déclarations de non définition). Les premières, comme leur nom l'indique, permettent de déclarer et
3 de définir ; les secondes exigent qu'une définition soit créée à un quelconque niveau du programme. Une déclaration de
référence introduit simplement un ou plusieurs noms d'identificateurs dans un programme. Une définition, en revanche, alloue de
la mémoire à un objet et associe à ce dernier un identificateur.

604
3.1 Référence C++ RAD Studio Guide du langage C++

Rubriques
Nom Description
Définitions facultatives ( see page 606) La norme ANSI du langage C introduit un nouveau concept, celui de définition
facultative. Toute déclaration de données externe qui ne contient pas de
spécificateur de classe de stockage, ni de valeur d'initialisation est considérée
comme définition facultative. Si l'identificateur déclaré apparaît dans une
définition ultérieure, la définition facultative est traitée comme si le spécificateur
de stockage extern existait. En d'autre termes, la définition facultative devient
une simple déclaration.
Si la fin d'une unité de traduction est atteinte sans qu'aucune définition ne soit
apparue avec une valeur d'initialisation pour l'identificateur, la définition
facultative devient une définition à part entière, et... suite ( see page 606)
Déclarations possibles ( see page 607) Les objets qu'il est possible de déclarer sont les suivants :

• Variables
• Fonctions
• Classes et membres de classe (C++)
• Types
• Noms de structure, d'union et d'énumération
• Membres de structure
• Membres d'union
• Tableaux d'autres types
• Constantes d'énumération
• Etiquettes d'instruction
• Macros de préprocesseur
La syntaxe complète des déclarations est présentée dans les
tableaux ci-après. La nature récursive de cette syntaxe
autorise des déclarateurs complexes. Il est conseillé
d'utiliser typedefs pour assurer une meilleure lisibilité.
Dans la syntaxe des déclarations en CodeGear C++, vous
remarquerez qu'il existe certaines restrictions quant au
nombre et à l'ordre des modificateurs et des
qualificateurs. Par ailleurs,... suite ( see page 607)
Définitions et déclarations externes ( see page 610) Les spécificateurs de classe de stockage auto et register ne peuvent pas
apparaître dans une déclaration external. Pour chaque identificateur d'une unité
de traduction déclaré avec attribut de liaison interne, une seule définition externe
est possible.
Une définition externe est une déclaration externe qui définit aussi un objet ou
une fonction; c'est-à-dire qui alloue également de la mémoire. Si un identificateur
déclaré avec attribut de liaison externe est utilisé dans une expression (autre que
dans l'opérande de sizeof), il doit exister très exactement pour lui une seule
définition externe dans l'ensemble du programme.
Le compilateur C++ autorise des déclarations ultérieures... suite ( see page
610)
Spécificateurs de type ( see page 612) Le type détermine l'espace mémoire alloué à un objet et la manière dont le
programme interprète les configurations de bits rencontrées dans l'allocation de
stockage de l'objet. Un type de données est l'ensemble de valeurs (souvent
dépendant de l'implémentation) que les identificateurs peuvent prendre en 3
charge avec l'ensemble des opérations permises sur ces valeurs.
Le spécificateur de type avec un ou plusieurs modificateurs facultatifs sert à
préciser le type de l'identificateur déclaré :
Catégories de types ( see page 612) Fournit des informations sur les catégories de types C++.
Les quatre catégories de type élémentaires et leurs sous-types sont les
suivantes :
Types fondamentaux ( see page 613) Les spécificateurs de types fondamentaux sont établis à partir des mots clés
suivants :

605
Guide du langage C++ RAD Studio 3.1 Référence C++

Initialisation ( see page 616) Les initialisateurs, ou valeurs d'initialisation, fixent la valeur enregistrée dans un
objet (variables, tableaux, structures, etc.). Si vous n'initialisez pas un objet et si
celui-ci a une durée statique, sa valeur d'initialisation par défaut sera déterminée
comme suit :

• à zéro s'il s'agit d'un type arithmétique


• à NULL s'il s'agit d'un type pointeur
Remarque: En cas de durée de stockage automatique, la
valeur est indéterminée.
Syntaxe des initialisateurs
Déclaration et déclarateurs ( see page 617) Une déclaration est une liste de noms. Les noms sont parfois référencés
comme des déclarateurs ou des identificateurs. La déclaration commence par
des spécificateurs de classe de stockage, des spécificateurs de type et autres
modificateurs facultatifs. Les identificateurs sont séparés par des virgules, et la
liste se termine par un point-virgule.
Les déclarations simples d'identificateurs de variables se présentent comme
suit :
Utilisation des spécificateurs de classe de stockage ( see page 619) Fournit des informations sur les spécificateurs de classe de stockage C++.
Les spécificateurs de classe de stockage sont appelés également spécificateurs
de type. Ils déterminent l'emplacement (segment de données, registre, tas ou
pile) d'un objet et sa durée de vie (le temps d'exécution total du programme, ou
le temps d'exécution de certains blocs de code).
Une classe de stockage peut être établie dans la syntaxe de déclaration, par son
emplacement dans le code ou par les deux à la fois.
Le mot clé mutable n'affecte pas la durée de vie du membre de classe auquel il
est appliqué.
Les spécificateurs... suite ( see page 619)
Modificateurs de variables ( see page 619) En plus des spécificateurs de classe de stockage, il est possible d'utiliser des
modificateurs pour changer certains aspects de l'identificateur. Les modificateurs
disponibles sont résumés dans Modificateurs de CodeGear C++.
Le tableau suivant résume les effets d'un modificateur appliqué à une fonction
appelée. Pour chaque modificateur, le tableau montre l'ordre dans lequel les
paramètres de la fonction sont placés dans la pile. Ensuite, il indique si c'est le
programme d'appel (l'appelant) ou la fonction appelée (l'appelé) qui est
responsable de l'éjection des paramètres hors de la pile. Enfin, il montre l'effet du
modificateur sur le nom de la fonction globale... suite ( see page 619)
Conventions d'appel multilangage ( see page 620) Fournit des informations sur les conventions d'appel multilangage C++.
Cette section décrit les conventions d'appel multilangage C++.
Vous pouvez appeler des routines écrites dans d'autres langages, et
inversement. Lorsque vous mélangez les langages, deux questions essentielles
se posent, à savoir le passage des identificateurs et celui des paramètres.
Par défaut, le compilateurs sauvegarde tous les identificateurs globaux dans leur
type de caractères d'origine (minuscules, majuscules, ou les deux) avec un signe
souligné "_" placé avant l'identificateur. Pour retirer la valeur par défaut, vous
pouvez utiliser l'option en ligne de commande -u.
Remarque: La section Liaison ( see page 599) vous indique comment
utiliser... suite ( see page 620)
Variables multithread ( see page 620) La rubrique suivante décrit les variables multithread C++.
Modificateurs de fonctions ( see page 621) Cette section décrit les modificateurs de fonctions disponibles avec le
compilateur CodeGear C++.
Vous pouvez utiliser les modificateurs __declspec(dllexport),
__declspec(dllimport) et __saveregs pour modifier les fonctions.
Dans les programmes 32 bits, le mot clé peut être appliqué aux déclarations de
classes, fonctions et variables
Le modificateur __declspec(dllexport) rend la fonction exportable depuis
Windows. Le modificateur __declspec(dllimport) rend une fonction disponible
3 pour une application Windows. Ces mots clés sont utilisés dans un exécutable (si
vous n'utilisez pas de rappels smart) ou dans une DLL.
Les fonctions déclarées avec le modificateur __fastcall n'ont pas les mêmes
noms que leurs équivalents non... suite ( see page 621)

3.1.4.4.3.1 Définitions facultatives


La norme ANSI du langage C introduit un nouveau concept, celui de définition facultative. Toute déclaration de données externe
qui ne contient pas de spécificateur de classe de stockage, ni de valeur d'initialisation est considérée comme définition

606
3.1 Référence C++ RAD Studio Guide du langage C++

facultative. Si l'identificateur déclaré apparaît dans une définition ultérieure, la définition facultative est traitée comme si le
spécificateur de stockage extern existait. En d'autre termes, la définition facultative devient une simple déclaration.

Si la fin d'une unité de traduction est atteinte sans qu'aucune définition ne soit apparue avec une valeur d'initialisation pour
l'identificateur, la définition facultative devient une définition à part entière, et l'objet défini n'est pas initialisé. Par exemple,
int x;
int x; /*légal, une copie de x est réservée */
int y;
int y = 4; /* légal, y est initialisé à 4 */
int z = 5;
int z = 6; /* illégal, les deux sont des définitions avec des valeurs d'initialisation */
A la différence de la norme ANSI du langage C, le C++ ne présente pas de concept de définition facultative ; une déclaration de
données externe sans spécificateur de classe de stockage est toujours une définition.

Voir aussi
Syntaxe de déclaration

Déclarations possibles ( see page 607)

Déclarations externes et définitions ( see page 610)

Catégories de types ( see page 612)

Les types fondamentaux ( see page 613)

Initialisation ( see page 616)

Déclarations et déclarateurs ( see page 617)

Modificateurs de variables ( see page 619)

Modificateurs de fonctions ( see page 621)

3.1.4.4.3.2 Déclarations possibles


Les objets qu'il est possible de déclarer sont les suivants :

• Variables
• Fonctions
• Classes et membres de classe (C++)
• Types
• Noms de structure, d'union et d'énumération
• Membres de structure
• Membres d'union
• Tableaux d'autres types
• Constantes d'énumération
• Etiquettes d'instruction 3
• Macros de préprocesseur
La syntaxe complète des déclarations est présentée dans les tableaux ci-après. La nature récursive de cette syntaxe autorise
des déclarateurs complexes. Il est conseillé d'utiliser typedefs pour assurer une meilleure lisibilité.
Dans la syntaxe des déclarations en CodeGear C++, vous remarquerez qu'il existe certaines restrictions quant au nombre et à
l'ordre des modificateurs et des qualificateurs. Par ailleurs, les modificateurs cités sont le seul ajout à la syntaxe du
déclarateur non conforme à la norme ANSI du C ou de C++. Pour plus d'informations sur ces modificateurs, voir les rubriques
Modificateurs de variables et Modificateurs de fonctions.

607
Guide du langage C++ RAD Studio 3.1 Référence C++

Syntaxe des déclarations en CodeGear C++

déclaration: spécificateur-type-élaboré:
<spécificateurs-decl> clé-classe identificateur
<liste-déclarateurs>;
déclaration-asm clé-classe nom-classe
déclaration-fonction enum nom-enum
spécification-liaisons clé-classe: (spécifique au C++)
spécificateur-decl: class
spécificateur-classe-stockage struct
spécificateur-type union
spécificateur-fonction spécificateur-enum:
friend (spécifique C++) enum <identificateur> { <liste-enum> }
typedef liste-enum:
spécificateurs-decl: énumérateur
<spécificateurs-decl> liste-énumérateur , énumérateur
spécificateur-decl
spécificateur-classe-stockage: énumérateur:
auto identificateur
register identificateur = expression-constante
static expression-constante:
extern expression-conditionnelle
spécificateur-fonction: spécification-liaisons: (spécifique au C++)
(spécifique au C++)
inline extern chaîne { <liste-déclaration> }
virtual extern chaîne-déclaration
nom-type-simple: spécificateur-type:
nom-classe nom-type-simple
typedef-nom spécificateur-classe
boolean
char spécificateur-enum
short spécificateur-type-élaboré
int const
__int8
__int16
3
__int32
__int64
long volatile
signed liste-déclarations:
unsigned déclaration
float liste-déclarations ; déclaration

608
3.1 Référence C++ RAD Studio Guide du langage C++

double
void
liste-déclarateurs: nom-type:
déclarateur-init spécificateur-type <déclarateur-abstrait>
liste-déclarateurs , déclarateur-abstrait:
déclarateur-init
déclarateur-init: opérateur-pointeur <déclarateur-abstrait>
déclarateur <initialisateur> <déclarateur-abstrait> ( liste-déclarations-argument )
déclarateur: <liste-qualificateurs-cv>
dnom <déclarateur-abstrait> [ <expression-constante> ]
liste-modificateurs ( déclarateur-abstrait )
déclarateur-opérateur-pointeur liste-déclarations-argument:
déclarateur ( <liste-déclarations-arg>
liste-déclarations-paramètre )
<liste-qualificateurs-cv> liste-déclarations-arg , ...
(<liste-qualificateurs-cv > ne <liste-déclarations-arg> ... (spécifique au C++)
concerne que C++.)
déclarateur [ liste-déclarations-arg:
<expression-constante> ]
( déclarateur ) déclaration-argument
liste-modificateurs: liste-déclarations-arg , déclaration-argument
modificateur déclaration-argument:
liste-modificateurs spécificateurs-decl déclarateur
modificateur
modificateur: spécificateurs-decl déclarateur = expression
__cdecl (spécifique au C++)
__pascal spécificateurs-decl <déclarateur-abstrait>
__stdcall spécificateurs-decl <déclarateur-abstrait> = expression
__fastcall (spécifique au C++)
définition-fonction:
corps-fonction:
opérateur-pointeur: instruction-composée

• <liste-qualificateurs-cv> initialisateur:

& <liste-qualificateurs-cv> = expression


(spécifique C++) 3
nom-classe :: * = { liste initialisateurs }
<liste-qualificateurs-cv>
(spécifique au C++) ( liste-expressions ) (spécifique C++)
liste-qualificateurs-cv: liste initialisateurs:
qualificateur-cv expression
<liste-qualificateurs-cv>

609
Guide du langage C++ RAD Studio 3.1 Référence C++

qualificateur-cv liste initialisateurs, expression


const { liste-initialisateurs <,> }
volatile
nomd:
nom
nom-classe (spécifique C++)
~ nom-classe (spécifique au
C++)
nom-typedef

Voir aussi
Syntaxe de déclaration

Définitions facultatives ( see page 606)

Déclarations externes et définitions ( see page 610)

Catégories de types ( see page 612)

Les types fondamentaux ( see page 613)

Initialisation ( see page 616)

Déclarations et déclarateurs ( see page 617)

Modificateurs de variables ( see page 619)

Modificateurs de fonctions ( see page 621)

3.1.4.4.3.3 Définitions et déclarations externes


Les spécificateurs de classe de stockage auto et register ne peuvent pas apparaître dans une déclaration external. Pour chaque
identificateur d'une unité de traduction déclaré avec attribut de liaison interne, une seule définition externe est possible.

Une définition externe est une déclaration externe qui définit aussi un objet ou une fonction; c'est-à-dire qui alloue également de
la mémoire. Si un identificateur déclaré avec attribut de liaison externe est utilisé dans une expression (autre que dans
l'opérande de sizeof), il doit exister très exactement pour lui une seule définition externe dans l'ensemble du programme.

Le compilateur C++ autorise des déclarations ultérieures de noms externes, comme des tableaux, des structures et des unions,
afin de compléter les informations contenues dans les déclarations existantes. Par exemple :
int a[]; // pas de taille
struct mystruct; // nom uniquement, pas de déclarateurs de membre
.
.
.
int a[3] = {1, 2, 3}; // contient taille et initialisation
3 struct mystruct {
int i, j;
}; // ajoute des déclarateurs de membre
La syntaxe des déclarations de classes de CodeGear C++ (C++ seulement) concerne la syntaxe des déclarations de classes.
Dans la section relative aux classes (commençant à la rubrique Classes), vous trouverez quelques exemples de déclarations
d'une classe. La rubrique Référencement décrit en détail les types de références C++ (en rapport avec les types de pointeurs).
Enfin, reportez-vous à Utilisation des templates pour une description des classes de type template.

Syntaxe des déclarations de classes de CodeGear C++ (C++ seulement)

610
3.1 Référence C++ RAD Studio Guide du langage C++

spécificateur-classe: spécificateur-base:

en-tête-classe { <liste membres> } : liste-bases

en-tête-classe: liste-bases:

clé-classe <identificateur> <spécificateur-base> spécificateur-base

clé-classe nom-classe <spécificateur-base> liste-bases , spécificateur-base

liste-membres: spécificateur-base:

déclaration-membre <liste-membres> nom-classe

spécificateur-accès : <liste-membres> virtual <spécificateur-accès> nom-classe

déclaration-membre: spécificateur-accès <virtual> nom-classe

<spécificateurs-decl> <liste-déclarateurs-membre> ; spécificateur-accès:

définition-fonction <;> private

nom-qualifié ; protected

liste-déclarateurs-membre: public

déclarateur-membre nom-fonction-conversion:

liste-déclarateurs-membre, déclarateur-membre operator nom-type-conversion

déclarateur-membre: nom-type-conversion:

déclarateur <spécificateur-pur> spécificateurs-type <opérateur-pointeur>

<identificateur> : expression-constante initialisateur-constructeur:

spécificateur-pur: : liste-initialisateurs-membre

=0

liste-initialisateurs-membre: nom-opérateur: un parmi

initialisateur-membre new delete sizeof typeid

initialisateur-membre, liste-initialisateurs-membre + - * / % ^

initialisateur-membre: & | ~ ! = <>

nom classe ( <liste-arguments> ) += -= =* /= %= ^=

identificateur ( <liste-arguments> ) &= |= << >> >>= <<=

nom-fonction-opérateur: == != <= >= && ||

operator nom-opérateur ++ __ , ->* -> ()

[ ] .*

Voir aussi
3
Syntaxe de déclaration

Définitions facultatives ( see page 606)

Déclarations possibles ( see page 607)

Catégories de types ( see page 612)

Types fondamentaux ( see page 613)

611
Guide du langage C++ RAD Studio 3.1 Référence C++

Initialisation ( see page 616)

Déclarations et déclarateurs ( see page 617)

Modificateurs de variables ( see page 619)

Modificateurs de fonctions ( see page 621)

3.1.4.4.3.4 Spécificateurs de type


Le type détermine l'espace mémoire alloué à un objet et la manière dont le programme interprète les configurations de bits
rencontrées dans l'allocation de stockage de l'objet. Un type de données est l'ensemble de valeurs (souvent dépendant de
l'implémentation) que les identificateurs peuvent prendre en charge avec l'ensemble des opérations permises sur ces valeurs.

Le spécificateur de type avec un ou plusieurs modificateurs facultatifs sert à préciser le type de l'identificateur déclaré :
int i; // déclare i comme un entier
unsigned char ch1, ch2; // déclare deux chars non signés
Traditionnellement, si le spécificateur de type est omis, le type par défaut adopté est signed int (ou l'équivalent, int).
Cependant, en C++, il est des cas où l'absence d'un spécificateur de type entraîne une ambiguïté syntaxique, de sorte qu'il est
préférable en C++ d'entrer explicitement tous les spécificateurs de type int.

Voici la liste des mots clés des spécificateurs de type dans le compilateur CodeGear C++ :

char float signed


wchar_t
class int struct
double long union
enum short unsigned

Utilisez les opérateurs sizeof pour trouver la taille en octets de tout type prédéfini ou défini par l'utilisateur.

3.1.4.4.3.5 Catégories de types


Fournit des informations sur les catégories de types C++.

Les quatre catégories de type élémentaires et leurs sous-types sont les suivantes :
Agrégation Tableau
struct
union
classe (C++ uniquement)
Fonction
Scalaire
Arithmétique
Enumération
Pointeur
Référence (C++ seulement)
void
3
Les types peuvent également être visualisés d'une autre façon : ils peuvent être des types fondamentaux ou des types dérivés.
Les types fondamentaux sont void, char, int, float et double, ainsi que les variantes short, long, signed et unsigned. Les
types dérivés incluent des pointeurs et des références à d'autres types, des tableaux d'autres types, des types fonctions,
classes, des structures et des unions.

Un objet classe par exemple peut contenir un certain nombre d'objets de types différents, ainsi que des fonctions pour traiter ces
objets, plus un mécanisme pour contrôler l'accès et l'héritage depuis d'autres classes.

Etant donné un type nonvoid type (avec certaines restrictions), vous pouvez déclarer des types dérivés de la façon suivante :

612
3.1 Référence C++ RAD Studio Guide du langage C++

Déclaration de types

Déclaration Description
type t; Un objet de type type
type array[10]; Dix types : array[0] - array[9]
type *ptr; ptr est un pointeur sur type
type &ref = t; ref est une référence vers type (C++)
type func(void); func renvoie une valeur de type type
void func1(type t); func1 prend un paramètre de type type
struct st {type t1;type t2}; La structure st contient deux types

Remarque: type& var, type &var et type & var sont tous équivalents.

Voir aussi
Syntaxe de déclaration

Définitions facultatives ( see page 606)

Déclarations possibles ( see page 607)

Déclarations externes et définitions ( see page 610)

Types fondamentaux ( see page 613)

Initialisation ( see page 616)

Déclarations et déclarateurs ( see page 617)

Modificateurs de variables ( see page 619)

Modificateurs de fonctions ( see page 621)

Le mot clé void ( see page 578)

3.1.4.4.3.6 Types fondamentaux


Les spécificateurs de types fondamentaux sont établis à partir des mots clés suivants :

char __int8 long


double __int16 signed
float __int32 short
int __int64 unsigned

A partir de ces mots clés, vous pouvez établir des types entiers et en virgule flottante appelés aussi types arithmétiques. long,
short, signed et unsigned sont des modificateurs applicables aux types entiers. Le fichier limits.h contient les intervalles de
valeurs correspondant à chacun des types fondamentaux. 3
Types entiers

char, short, int et long, ainsi que leurs variantes non signées, sont tous considérés comme des types de données entières. La
section types entiers présente les spécificateurs du type entier, avec les synonymes possibles

Types entiers

613
Guide du langage C++ RAD Studio 3.1 Référence C++

char, signed char Synonymes si char par défaut est


signed.
unsigned char
char, unsigned char Synonymes si char par défaut est
unsigned.
signed char
int, signed int
unsigned, unsigned int
short, short int, signed short int
unsigned short, unsigned short int
long, long int, signed long int
unsigned long, unsigned long int

Remarque: Ces synonymes ne sont pas corrects en C++. Voir la rubrique Les trois types char.

Un seul des deux types signed ou unsigned est utilisable avec char, short, int ou long. Les mots clés signed et unsigned,
employés seuls, correspondent respectivement à signed int et à unsigned int.

En l'absence de unsigned, signed est la valeur par défaut supposée pour les types entiers. Une exception toutefois s'applique
à char. Vous pouvez fixer la valeur par défaut de char à signed ou à unsigned. (Si vous ne la déterminez pas vous-même,
cette valeur par défaut est signed.) Si vous choisissez unsigned comme valeur par défaut, la déclaration char ch déclare ch
comme étant unsigned. Vous devrez utiliser signed char ch pour annuler l'effet de la valeur par défaut. De même, si vous
choisissez signed comme valeur par défaut pour char, vous devez mentionner explicitement unsigned char ch pour déclarer un
unsigned char.

Un seul des types long ou short est utilisable avec int. Les mots clés long et short, employés seuls, correspondent
respectivement à long int et à short int.

La norme ANSI du langage C ne fixe pas la taille ou les représentations directes de ces types, et souligne seulement que short,
int et long forment une séquence non décroissante "short <= int <= long". Ces trois types peuvent légalement être les mêmes.
C'est important si vous écrivez un code portable vers d'autres plates-formes.

Le compilateur considère les types int et long comme équivalents, leur taille étant de 32 bits. Les variantes signées sont toutes
stockées dans le format complément à 2, le bit de poids le plus fort étant le bit de signe : 0 pour valeur positive, 1 pour valeur
négative (ce qui explique les intervalles indiqués dans Intervalles, tailles et types de données 32 bits). Dans les variantes non
signées, tous les bits sont utilisés pour permettre d'écrire des nombres de 0 - (2 puissance n - 1), où n est égal à 8, 16 ou 32.

Types de données en virgule flottante

Les représentations et les ensembles de valeurs des types en virgule flottante sont fonction de l'implémentation, à savoir que
chaque mise en oeuvre de C est libre de les définir. Le compilateur utilise les formats en virgule flottante IEEE. Voir la rubrique
Implémentations spécifiques de la norme ANSI.
3 float et double sont des types de données en virgule flottante 32 et 64 bits, respectivement. long est utilisable avec double
pour déclarer un identificateur en virgule flottante d'une précision de 80 bits : long double test_case, par exemple.

Le tableau de la rubrique Intervalles, tailles et types de données 32 bits indique la mémoire allouée aux types en virgule flottante.

Conversions arithmétiques standard

Lorsque vous utilisez une expression arithmétique comme a + b où a et b sont d'un type arithmétique différent, le compilateur
exécute certaines conversions internes avant le calcul de l'expression. Ces conversions standard supposent le passage de types
"inférieurs" à des types "supérieurs" à des fins de précision et de cohérence.

614
3.1 Référence C++ RAD Studio Guide du langage C++

Voici comment procède le compilateur pour convertir les opérandes d'une expression arithmétique :

• 1. Tous les types entiers de petite valeur sont convertis comme indiqué dans Méthodes utilisées dans les conversions
arithmétiques standard. Après quoi, les deux valeurs associées à un opérateur sont soit int (y compris avec les modificateurs
long et unsigned), soit de type double, float ou long double.
• 2. Si l'un des deux opérandes est de type long double, l'autre est converti en long double.
• 3. Sinon, si l'un des deux opérandes est de type double, l'autre est converti en double.
• 4. Sinon, si l'un des deux opérandes est de type float, l'autre est converti en float.
• 5. Si l'un des deux opérandes est de type unsigned long, l'autre est converti en unsigned long.
• 6. Sinon, si l'un des deux opérandes est de type long, l'autre est converti en long.
• 7. Sinon, si l'un des deux opérandes est de type unsigned, l'autre est converti en unsigned.
• 8. Sinon, les deux opérandes sont de type int.
Le résultat de l'expression est du même type que les deux opérandes
Méthodes utilisées dans les conversions arithmétiques standard

Type Converti en Méthode


char int Zéro ou extension du signe (selon le
type par défaut de char)
unsigned char int Octet de poids fort rempli par 0
(toujours)
signed char int Extension du signe (toujours)
short int Même valeur ; extension du signe
unsigned short unsigned int Même valeur ; rempli par 0
enum int Même valeur

Conversions spéciales char, int et enum

Remarque: Les conversions abordées ici sont spécifiques à au compilateur Borland C++.

Affecter un objet entier à un objet char signé (par exemple, une variable) entraîne l'extension automatique du signe. Les objets
de type signed char subissent toujours cette extension ; les objets de type unsigned char, lorsqu'ils sont convertis en int, ont
toujours 0 dans l'octet de poids fort.

La conversion d'un type entier long en un type entier court tronque les bits de poids fort sans toucher aux bits de poids faible. Le
passage à un type plus long entraîne une extension du signe ou l'ajout de zéro pour les bits supplémentaires de la nouvelle
valeur, selon que le type plus court est signed ou unsigned.

Voir aussi
Syntaxe de déclaration

Définitions facultatives ( see page 606)

Déclarations possibles ( see page 607) 3


Déclarations externes et définitions ( see page 610)

Catégories de types ( see page 612)

Initialisation ( see page 616)

Déclarations et déclarateurs ( see page 617)

Modificateurs de variables ( see page 619)

615
Guide du langage C++ RAD Studio 3.1 Référence C++

Modificateurs de fonctions ( see page 621)

3.1.4.4.3.7 Initialisation
Les initialisateurs, ou valeurs d'initialisation, fixent la valeur enregistrée dans un objet (variables, tableaux, structures, etc.). Si
vous n'initialisez pas un objet et si celui-ci a une durée statique, sa valeur d'initialisation par défaut sera déterminée comme suit :

• à zéro s'il s'agit d'un type arithmétique


• à NULL s'il s'agit d'un type pointeur
Remarque: En cas de durée de stockage automatique, la valeur est indéterminée.
Syntaxe des initialisateurs
initialisateur
= expression
= {liste-initialisateurs} <,>}
(liste expressions)
liste-initialisateurs
expression
liste initialisateurs, expression
{liste-initialisateurs} <,>}
Règles régissant l'initialisation

Le nombre des valeurs d'initialisation dans la liste ne doit pas dépasser le nombre des objets à initialiser.

L'élément à initialiser doit être un objet (par exemple, un tableau).

Toutes les expressions doivent être constantes si elles apparaissent dans un de ces emplacements (non requis pour C++) :

dans une valeur d'initialisation pour un objet à durée statique ;

dans une liste de valeurs d'initialisation pour un tableau, une structure ou une union (les expressions utilisant sizeof sont
également autorisées).

• Si une déclaration pour un objet donné a une portée bloc et si l'identificateur est caractérisé par une liaison externe ou
interne, cette déclaration ne peut pas avoir de valeur d'initialisation pour l'identificateur.
• S'il y a moins de valeurs d'initialisation dans une liste entre accolades qu'il n'y a de membres dans la structure, le reste de la
structure est initialisé implicitement comme les objets ayant une durée statique.
Les types scalaires sont initialisés avec une expression unique, qui peut éventuellement être placée entre accolades. La valeur
initiale de l'objet est celle de l'expression ; les mêmes restrictions que pour le type et les conversions s'appliquent aux
affectations uniques.
Pour les unions, les valeurs d'initialisation entre accolades initialisent le membre qui apparaît en premier dans la liste de
déclaration de l'union. Pour les structures ou les unions ayant une durée automatique, la valeur d'initialisation doit être, au
choix :
• une liste de valeurs d'initialisation telle que décrite à la rubrique Tableaux, structures et unions.
• une expression unique avec un type structure ou union compatible. Dans ce cas, la valeur initiale de l'objet est celle de
l'expression.
Tableaux, structures et unions
3 Vous initialisez des tableaux et des structures (au moment de la déclaration, par exemple) avec une liste placée entre accolades
contenant des valeurs d'initialisation pour les membres ou les éléments de l'objet en question. Les valeurs d'initialisation sont
mentionnées dans l'ordre croissant des membres ou des indices du tableau. Vous initialisez les unions avec une valeur mise
entre accolades pour le premier membre de l'union. Par exemple, vous pouvez déclarer un tableau jours, pour compter
combien de fois chaque jour de la semaine apparaît dans le mois (en supposant que chaque jour apparaîtra au moins une
fois), de la façon suivante :
int jours[7] = { 1, 1, 1, 1, 1, 1, 1 }
Utilisez ces règles pour initialiser les tableaux de caractères et les tableaux de caractères larges :

616
3.1 Référence C++ RAD Studio Guide du langage C++

• Vous pouvez initialiser des tableaux de type caractère avec une chaîne littérale, éventuellement mise entre accolades.
Chaque caractère de la chaîne, y compris le terminateur NULL, initialise les éléments successifs du tableau. Par exemple,
vous allez déclarer :
*
char nom[] = { "Inconnu" };
pour un tableau de huit éléments, qui sont 'I' (pour nom[0]), 'n' (pour nom[1]), etc., jusqu'au caractère de fin.

• Vous pouvez initialiser un tableau de caractères larges (compatible avec wchar_t) à l'aide d'une chaîne littérale "large",
éventuellement placée entre accolades. Comme précédemment, les codes de cette chaîne initialisent successivement tous
les éléments du tableau.
* Voici un exemple d'initialisation de structure :
struct mystruct {
int i;
char str[21];
double d;
} s = { 20, "Borland", 3.141 };
Les membres complexes d'une structure, comme des tableaux ou des structures, peuvent être initialisés à l'aide d'expressions
adéquates placées entre accolades imbriquées.

Voir aussi
Syntaxe de déclaration

Définitions facultatives ( see page 606)

Déclarations possibles ( see page 607)

Déclarations externes et définitions ( see page 610)

Catégories de types ( see page 612)

Types fondamentaux ( see page 613)

Déclarations et déclarateurs ( see page 617)

Modificateurs de variables ( see page 619)

Modificateurs de fonctions ( see page 621)

3.1.4.4.3.8 Déclaration et déclarateurs


Une déclaration est une liste de noms. Les noms sont parfois référencés comme des déclarateurs ou des identificateurs. La
déclaration commence par des spécificateurs de classe de stockage, des spécificateurs de type et autres modificateurs
facultatifs. Les identificateurs sont séparés par des virgules, et la liste se termine par un point-virgule.

Les déclarations simples d'identificateurs de variables se présentent comme suit :


type-de-données var1 <=init1>, var2 <=init2>, ...;
où var1, var2,... est une séquence d'identificateurs avec, facultativement, des valeurs d'initialisation. Chaque variable est
déclarée du type type-de-données. Par exemple :
3
int x = 1, y = 2;
crée deux variables entières x et y (qui sont initialisées respectivement à 1 et à 2).

Ce sont des définitions ; l'espace mémoire est réservé et les valeurs d'initialisation, s'il y a lieu, sont appliquées.

La valeur d'initialisation pour un objet automatique peut être n'importe quelle expression légale qui a pour résultat une valeur
d'affectation compatible avec le type de la variable en question. Les valeurs d'initialisation pour les objets statiques doivent être
des constantes ou des expressions constantes.

617
Guide du langage C++ RAD Studio 3.1 Référence C++

En C++, une valeur d'initialisation pour un objet statique peut être toute expression intégrant des constantes, des variables déjà
déclarées et des fonctions.

Le format du déclarateur indique le mode d'interprétation du nom déclaré lorsqu'il est utilisé dans une expression. Si type est un
type quelconque, si le spécificateur de classe de stockage est un spécificateur de classe de stockage quelconque et si D1 et D2
sont deux déclarateurs, la déclaration :
spécificateur-classe-stockage type D1, D2;
indique que chaque occurrence de D1 ou D2 dans une expression sera traitée comme un objet de type type et dont la classe de
stockage est celle mentionnée par spécificateur-classe-stockage. Le type de nom dans le déclarateur sera une phrase contenant
type, comme "type", "pointeur sur type", "tableau de type", "fonction renvoyant type" ou "pointeur sur fonction renvoyant type",
etc.

Par exemple, dans la rubrique Exemples de syntaxes de déclarations, chaque déclarateur est utilisable comme rvalue (ou
comme lvalue dans certains cas) dans les expressions où un objet unique int aurait sa place. Les types d'identificateurs
imbriqués sont dérivés de leurs déclarateurs, de la façon suivante :

Exemples de syntaxes de déclarations

Syntaxe du déclarateur Type impliqué de nom Exemple


type nom; type int compte;
type nom[]; tableau (ouvert) de type int compte[];
type nom[3]; Tableau fixe de trois éléments, int compte[3] (nom[0], nom[1] et nom[2]
tous de type;
type *nom; Pointeur sur type int *compte;
type *nom[]; tableau (ouvert) de pointeurs sur type int *compte[];
type *(nom[]); Idem int *(compte[]);
type (*nom)[]; Pointeur sur un tableau (ouvert) de type int (*compte) [];
type &nom; Référence de type (C++ seulement) int &compte;
type nom(); Fonction renvoyant type int compte();
type *nom(); Fonction renvoyant un pointeur sur type int *compte();
type *(nom()); Idem int *(compte());
type (*nom)(); Pointeur sur une fonction renvoyant type int (*compte) ();

Notez la nécessité des parenthèses dans (*nom)[] et (*nom)() puisque la priorité du déclarateur de tableau [ ] et du déclarateur
de fonction ( ) est supérieure à celle du déclarateur de pointeur *. Les parenthèses dans *(nom[]) sont facultatives.

Remarque: Voir la rubrique Syntaxe des déclarations CodeGear C++ pour la syntaxe des déclarateurs. La définition couvre à la
fois les déclarateurs d'identificateur et de fonction.

Voir aussi
Syntaxe de déclaration
3
Définitions facultatives ( see page 606)

Déclarations possibles ( see page 607)

Déclarations externes et définitions ( see page 610)

Catégories de types ( see page 612)

Types fondamentaux ( see page 613)

618
3.1 Référence C++ RAD Studio Guide du langage C++

Initialisation ( see page 616)

Modificateurs de variables ( see page 619)

Modificateurs de fonctions ( see page 621)

3.1.4.4.3.9 Utilisation des spécificateurs de classe de stockage


Fournit des informations sur les spécificateurs de classe de stockage C++.

Les spécificateurs de classe de stockage sont appelés également spécificateurs de type. Ils déterminent l'emplacement
(segment de données, registre, tas ou pile) d'un objet et sa durée de vie (le temps d'exécution total du programme, ou le temps
d'exécution de certains blocs de code).

Une classe de stockage peut être établie dans la syntaxe de déclaration, par son emplacement dans le code ou par les deux à la
fois.

Le mot clé mutable n'affecte pas la durée de vie du membre de classe auquel il est appliqué.

Les spécificateurs de classe de stockage en C++ sont :

• auto ( see page 539)


• __declspec ( see page 529)
• extern ( see page 555)
• mutable ( see page 561)
• register ( see page 566)
• static ( see page 569)
• typedef ( see page 574)
Voir aussi
Mots clés des spécificateurs de classe de stockage ( see page 589)

3.1.4.4.3.10 Modificateurs de variables


En plus des spécificateurs de classe de stockage, il est possible d'utiliser des modificateurs pour changer certains aspects de
l'identificateur. Les modificateurs disponibles sont résumés dans Modificateurs de CodeGear C++.

Le tableau suivant résume les effets d'un modificateur appliqué à une fonction appelée. Pour chaque modificateur, le tableau
montre l'ordre dans lequel les paramètres de la fonction sont placés dans la pile. Ensuite, il indique si c'est le programme d'appel
(l'appelant) ou la fonction appelée (l'appelé) qui est responsable de l'éjection des paramètres hors de la pile. Enfin, il montre
l'effet du modificateur sur le nom de la fonction globale

Conventions d'appel

Modificateur Entrée des paramètres Sortie des Modification du nom


paramètres (uniquement en C)
__cdecl1 De droite à gauche Appelant Précédé de '_' 3
__fastcall De gauche à droite Appelé Précédé de '@'
__pascal De gauche à droite Appelé Majuscule
__stdcall De droite à gauche Appelé Aucune modification

1. Il s'agit de la version par défaut.


Remarque: Remarque : __fastcall et __stdcall sont toujours substantypées en C++. Voir la description de l'option -VC dans

619
Guide du langage C++ RAD Studio 3.1 Référence C++

BCC32.

Voir aussi
Syntaxe de déclaration ( see page 604)

Définitions facultatives ( see page 606)

Déclarations possibles ( see page 607)

Déclarations externes et définitions ( see page 610)

Catégories de types ( see page 612)

Types fondamentaux ( see page 613)

Initialisation ( see page 616)

Déclarations et déclarateurs ( see page 617)

Modificateurs de fonctions ( see page 621)

Conventions d'appel multilangage ( see page 620)

Le mot clé const ( see page 544)

Le mot clé volatile ( see page 578)

3.1.4.4.3.11 Conventions d'appel multilangage


Fournit des informations sur les conventions d'appel multilangage C++.

Cette section décrit les conventions d'appel multilangage C++.

Vous pouvez appeler des routines écrites dans d'autres langages, et inversement. Lorsque vous mélangez les langages, deux
questions essentielles se posent, à savoir le passage des identificateurs et celui des paramètres.

Par défaut, le compilateurs sauvegarde tous les identificateurs globaux dans leur type de caractères d'origine (minuscules,
majuscules, ou les deux) avec un signe souligné "_" placé avant l'identificateur. Pour retirer la valeur par défaut, vous pouvez
utiliser l'option en ligne de commande -u.

Remarque: La section Liaison ( see page 599) vous indique comment utiliser extern

qui permet de référencer des noms en C, depuis un programme en C++.

Rubriques
Cdecl ( see page 542)

_fastcall ( see page 536)

Pascal ( see page 565)

_stdcall ( see page 537)


3
3.1.4.4.3.12 Variables multithread
La rubrique suivante décrit les variables multithread C++.

Rubriques
__thread ( see page 535)

620
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.4.3.13 Modificateurs de fonctions


Cette section décrit les modificateurs de fonctions disponibles avec le compilateur CodeGear C++.

Vous pouvez utiliser les modificateurs __declspec(dllexport), __declspec(dllimport) et __saveregs pour modifier les fonctions.

Dans les programmes 32 bits, le mot clé peut être appliqué aux déclarations de classes, fonctions et variables

Le modificateur __declspec(dllexport) rend la fonction exportable depuis Windows. Le modificateur __declspec(dllimport)


rend une fonction disponible pour une application Windows. Ces mots clés sont utilisés dans un exécutable (si vous n'utilisez
pas de rappels smart) ou dans une DLL.

Les fonctions déclarées avec le modificateur __fastcall n'ont pas les mêmes noms que leurs équivalents non __fastcall. Le
compilateur fait précéder le nom de la fonction __fastcall d'un @. Ce préfixe s'applique à la fois aux noms de fonctions C non
substantypés et aux noms de fonctions C++ substantypés.

Modificateurs CodeGear C++

Modificateur Utilisé avec Description

const1 Variables Empêche de modifier l'objet


volatile1 Variables Empêche l'utilisation de registres et supprime l'optimisation qui s'y
rapporte. Avertit le compilateur que l'objet peut être sujet à des
changements externes durant l'évaluation.
__cdecl2 Fonctions Impose la convention de passage d'arguments du C. Affecte le lieur et
les noms de liaison.
__cdecl2 Variables Active la sensibilité à la distinction minuscule/majuscule et le préfixe
caractère de soulignement en C.
__pascal Fonctions Active la convention de passage d'arguments du Pascal. Affecte le
lieur et les noms de liaison.
__pascal Variables Désactive la sensibilité à la distinction minuscule/majuscule et le
préfixe caractère de soulignement en C.
__import Fonctions/classes Indique au compilateur les fonctions et classes à importer.
__export Fonctions/classes Indique au compilateur les fonctions et classes à exporter.
__declspec(dllimport) Fonctions/classes Indique au compilateur les fonctions et classes à importer. Ceci est la
méthode préférée.
__declspec(dllexport) Fonctions/classes Indique au compilateur les fonctions et classes à exporter. Ceci est la
méthode préférée.
__fastcall Fonctions Impose la convention de passage des paramètres par les registres.
Affecte le lieur et les noms de liaison.
__stdcall Fonction Impose la convention de passage des paramètres standard de WIN32.

1. C++ étend const et volatile afin d'inclure les classes et les fonctions membre.
2. Il s'agit de la version par défaut.
3
Voir aussi
Syntaxe de déclaration

Définitions facultatives ( see page 606)

Déclarations possibles ( see page 607)

Déclarations externes et définitions ( see page 610)

621
Guide du langage C++ RAD Studio 3.1 Référence C++

Catégories de types ( see page 612)

Types fondamentaux ( see page 613)

Initialisation ( see page 616)

Déclarations et déclarateurs ( see page 617)

Modificateurs de variables ( see page 619)

Modificateurs de fonctions

3.1.4.4.4 Enumérations
Cette section traite des énumérations.

Rubriques
Nom Description
Enumérations ( see page 622) Un type énumération de données permet d'obtenir des identificateurs
mnémoniques pour un ensemble de valeurs entières. Par exemple, la déclaration
suivante :
Affectation aux types enum ( see page 623) Les règles concernant des expressions impliquant des types enum sont plus
rigoureuses. Le compilateur applique ces règles avec des messages d'erreur si
le commutateur -A de compilation est activé (strictement ANSI C++).
L'affectation d'un entier à une variable de type enum provoque une erreur :

3.1.4.4.4.1 Enumérations
Un type énumération de données permet d'obtenir des identificateurs mnémoniques pour un ensemble de valeurs entières. Par
exemple, la déclaration suivante :
enum jours { lun, mar, mer, jeu, ven, sam, dim } touslesjours;
établit un type entier unique, enum jours, une variable de ce type touslesjours et un ensemble d'énumérateurs (dim, lun,...) avec
des valeurs entières constantes.

L'option du compilateur -b contrôle l'option "Traiter les Enums comme des Ints". Quand ce commutateur est utilisé, le
compilateur alloue un mot entier (un int sur quatre octets) pour les types énumération (variables de type enum). L'option est
activée par défaut, ce qui signifie que les enums concernent toujours des int) si l'intervalle des valeurs l'autorise, mais la valeur
est toujours transformée en int lorsqu'elle apparaît dans des expressions. Les identificateurs utilisés dans une liste
d'énumérateurs sont implicitement du type signed char, unsigned char ou int, selon la valeur de ces énumérateurs. S'il est
possible de représenter toutes les valeurs dans un signed ou unsigned char, cela devient le type de chaque énumérateur.

En C, une variable de type énumération peut recevoir n'importe quelle valeur de type int ; aucune vérification n'est effectuée. En
C++, une variable de type énumération ne peut recevoir de valeur que de l'un de ses énumérateurs : Ainsi :
anyday = mon; // OK
anyday = 1; // illégal, même si lun == 1
L'identificateur jours est le sélecteur facultatif utilisable dans les déclarations suivantes de variables d'énumérations de type
enum jours :
3
enum jours jours_travail, jours_congé; // déclare deux variables
En C++, il est possible d'omettre le mot clé enum si jours ne désigne pas autre chose dans la même portée.

Comme dans les déclarations struct et union, vous pouvez laisser de côté le sélecteur si aucune autre variable de ce type
enum n'est nécessaire :
enum jours { dim, lun, mar, mer, jeu, ven, sam } un_jour;
/* type enum anonyme */

622
3.1 Référence C++ RAD Studio Guide du langage C++

Les énumérateurs placés entre accolades sont aussi appelés constantes d'énumération. Chacun reçoit une valeur fixe entière.
En l'absence de valeurs d'initialisation explicites, le premier énumérateur (dim) est égal à zéro, et chaque énumérateur qui suit
est incrémenté de un (lun = 1, mar = 2, etc.). Pour plus d'informations sur les constantes d'énumération, voir Constantes
d'énumération.

En utilisant des initialisateurs entiers, vous pouvez attribuer des valeurs spécifiques aux énumérateurs. Tous les noms suivants
sans initialisateurs seront augmentés de un. Par exemple, dans la déclaration ci-dessous,
/* une expression d'initialisation peut inclure des énumérateurs déjà déclarés */
enum pieces { penny = 1, tuppence, nickel = penny + 4, dime = 10,
quarter = nickel * nickel } mitraille;
tuppence acquiert la valeur 2, nickel la valeur 5 et quarter la valeur 25.

La valeur d'initialisation est une expression ayant pour résultat une valeur entière positive ou négative (après d'éventuelles
conversions en entier). Ces valeurs sont d'habitude uniques, mais elles peuvent être en double.

Les types enum peuvent apparaître chaque fois que int est possible.
enum jours { lun, mar, mer, jeu, ven, sam, dim } touslesjours;
enum jours jours_travail;
typedef enum jours JOURS;
DAYS *joursptr;
int i = mar;
anyday = mon; // OK
*joursptr = un_jour; // OK
lun = mar; // ILLEGAL : lun est une constante
Les balises d'énumération partagent le même espace de nommage que les balises de structure et d'union. Les énumérateurs
appartiennent au même espace de nommage que les identificateurs de variables ordinaires :
int lun = 11;
{
enum jours { lun, mar, mer, jeu, ven, sam, dim } touslesjours;
/* l'énumérateur lun cache la déclaration externe de int lun */
struct jours { int i, j;}; // ILLEGAL : sélecteur de jour répété
double sam; // ILLEGAL : redéfinition de sam
}
lun = 12; // retour dans portée int lun
En C++, les énumérateurs déclarés dans une classe sont dans la portée de cette classe.

En C++, il est possible de surcharger la plupart des opérateurs d'une énumération. Cependant, comme les opérateurs =, [ ], ( )
et -> doivent être surchargés en tant que fonctions membre, il n'est pas possible de les surcharger pour enum. Voir exemple
montrant comment surcharger les opérateurs d'incrémentation suffixe et préfixe.

3.1.4.4.4.2 Affectation aux types enum


Les règles concernant des expressions impliquant des types enum sont plus rigoureuses. Le compilateur applique ces règles
avec des messages d'erreur si le commutateur -A de compilation est activé (strictement ANSI C++).

L'affectation d'un entier à une variable de type enum provoque une erreur :
enum color
{ 3
red, green, blue
};
int f()
{
color c;
c = 0;
return c;
}

623
Guide du langage C++ RAD Studio 3.1 Référence C++

Il en est de même lors du passage d'un entier en tant que paramètre à une fonction. Notez que le type de résultat de
l'expression flag1|flag2 est int :
enum e
{
flag1 = 0x01,
flag2 = 0x02
};
void p(e);
void f()
{
p(flag1|flag2);
}
Pour rendre l'exemple compilable, l'expression flag1|flag2 doit être transtypée en type enum : e (flag1|flag2).

3.1.4.4.5 Expressions
Cette section traite des expressions.

Rubriques
Nom Description
Expressions ( see page 625) Une expression est une séquence d'opérateurs, d'opérandes et de séparateurs
qui spécifie un calcul. La syntaxe formelle mentionnée dans Expressions de
CodeGear C++ indique que les expressions sont définies de manière récursive :
des sous-expressions peuvent être imbriquées, sans qu'il y ait de limite à cette
pratique. Toutefois, le compilateur renvoie un message d'erreur s'il ne parvient
pas à compiler une expression trop complexe.
Remarque: Expressions de Borland C++ montre comment sont combinés les
identificateurs et les opérateurs pour former des phrases grammaticalement
légales.
Les expressions sont évaluées selon certaines règles de conversion, de
groupement, d'associativité et de priorité, qui dépendent... suite ( see page 625)
Priorité des opérateurs ( see page 627) Il existe seize catégories de priorité, certaines ne contenant qu'un seul opérateur.
Les opérateurs d'une même catégorie ont une priorité égale.
Lorsque des opérateurs apparaissent plusieurs fois dans le tableau, la première
occurrence est unaire, la deuxième binaire. Chaque catégorie possède sa règle
d'associativité : de gauche à droite, ou de droite à gauche. En l'absence de
parenthèses, ces règles résolvent le groupement d'expressions avec des
opérateurs d'égale priorité.
La priorité de chaque catégorie est indiquée par l'ordre d'apparition dans le
tableau. La première catégorie (première ligne du tableau) a la plus haute
priorité. Les opérateurs d'une même ligne ont la... suite ( see page 627)
Expressions et C++ ( see page 628) C++ permet de surcharger certains opérateurs standard du C, comme expliqué
dans Surcharger les fonctions opérateur. Un opérateur surchargé est défini pour
remplir un rôle particulier lorsqu'il est appliqué à des expressions de type classe.
Par exemple, l'opérateur d'égalité == peut être défini dans la classe complex
pour tester l'égalité de deux nombres complexes sans modifier son utilisation
normale avec les autres types de données non classes.
Un opérateur surchargé est mis en oeuvre comme une fonction ; celle-ci
détermine le type d'opérande, la lvalue, l'ordre d'évaluation à appliquer lorsque
l'opérateur surchargé est utilisé. Cependant, la surcharge ne peut pas modifier...
suite ( see page 628)
Ordre d'évaluation ( see page 629) L'ordre dans lequel le compilateur évalue les opérandes d'une expression n'est
pas spécifié, sauf lorsqu'un opérateur l'énonce explicitement. Le compilateur
essaie de réordonner l'expression afin d'améliorer la qualité du code généré.
3 Vous devez donc être attentif aux expressions où une valeur est modifiée
plusieurs fois. En général, évitez d'écrire des expressions qui modifient et
utilisent la valeur du même objet. Par exemple, soit l'expression :
Erreurs et débordements ( see page 629) Associativité et priorité des opérateurs CodeGear C++ résume la priorité et
l'associativité des opérateurs. Durant l'évaluation d'une expression, il arrive que
le compilateur rencontre des situations problématiques, comme une division par
zéro ou des valeurs en virgule flottante hors de l'intervalle admis. Le
débordement d'entier est ignoré (C utilise le modulo 2n sur les registres de n
bits), mais les erreurs détectées par les fonctions mathématiques des
bibliothèques sont traitées par des routines standard ou définies par le
programmeur. Voir _matherr et signal.

624
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.4.5.1 Expressions
Une expression est une séquence d'opérateurs, d'opérandes et de séparateurs qui spécifie un calcul. La syntaxe formelle
mentionnée dans Expressions de CodeGear C++ indique que les expressions sont définies de manière récursive : des
sous-expressions peuvent être imbriquées, sans qu'il y ait de limite à cette pratique. Toutefois, le compilateur renvoie un
message d'erreur s'il ne parvient pas à compiler une expression trop complexe.

Remarque: Expressions de Borland C++ montre comment sont combinés les identificateurs et les opérateurs pour former des
phrases grammaticalement légales.

Les expressions sont évaluées selon certaines règles de conversion, de groupement, d'associativité et de priorité, qui
dépendent des opérateurs utilisés, de la présence de parenthèses, et des types de données des opérandes. Les conversions
standard sont détaillées dans Méthodes utilisées dans les conversions arithmétiques standard. La manière dont sont groupés
les opérandes et les sous-expressions n'indique pas nécessairement l'ordre réel dans lequel ils seront évalués par le
compilateur (voir Ordre d'évaluation).

Les expressions peuvent fournir une lvalue, une rvalue, ou pas de valeur. Elles ont éventuellement des effets de bord selon
qu'elles fournissent, ou non, un résultat.

La priorité et l'associativité des opérateurs sont résumées à la rubrique Associativité et priorité des opérateurs CodeGear C++.
La grammaire des expressions de CodeGear C++ définit de manière complète la priorité et l'associativité des opérateurs.

Expressions CodeGear C++


expression-primaire:
littéral
this (spécifique au C++)
:: identificateur (spécifique au C++)
:: nom-fonction-opérateur (spécifique au C++)
:: nom-qualifié (spécifique au C++)
(expression)
nom
littéral:
constante-entière
constante-caractère
constante-flottante
littéral-chaîne
nom :
identificateur
nom-fonction-opérateur (spécifique au C++)
nom-fonction-conversion (spécifique au C++)

~ nom-classe (spécifique au C++)


nom-qualifié (spécifique au C++)

nom-qualifié: (spécifique au C++)


nom-classe-qualifié :: nom
expression-postfixée:
expression-primaire
expression-postfixée [ expression ]
expression-postfixée (<liste-expressions>)
nom-type-simple (<liste-expressions>) (spécifique au C++)
3
expression-postfixée . nom
expression-postfixée -> nom
expression-postfixée ++

expression-postfixée --
const_cast < type-id > ( expression ) (spécifique au C++)
dynamic_cast < type-id > ( expression ) (spécifique au C++)
reinterpret_cast < type-id > ( expression ) (spécifique au C++)
static_cast < type-id > ( expression ) (spécifique au C++)

625
Guide du langage C++ RAD Studio 3.1 Référence C++

typeid ( expression ) (spécifique au C++)


typeid ( nom-type ) (spécifique au C++)
liste-expressions:
expression-affectation
liste-expressions , expression-affectation
expression-unaire:
expression-postfixée
++ expression-unaire
- - expression-unaire
opérateur-unaire expression-transtypage
sizeof expression- unaire
sizeof (nom-type)
expression-allocation (spécifique au C++)
expression-désallocation (spécifique au C++)
opérateur-unaire: un parmi & * + - !
expression-allocation: (spécifique au C++)
<::> new <placement> nom-type-new <initialisateur>
<::> new <placement> (nom-type) <initialisateur>
placement: (spécifique au C++)
(liste-expressions)
nom-type-new: (spécifique au C++)
spécificateurs-type <déclarateur-new>
déclarateur-new: (spécifique au C++)
opérateur-ptr <déclarateur-new>
déclarateur-new [<expression>]
expression-désallocation: (spécifique au C++)
<::> delete expression-transtypage
<::> delete [ ] expression-transtypage
expression-transtypage:
expression-unaire
(nom-type) expression-transtypage

pm-expression:
expression-transtypage
pm-expression .* expression-transtypage (spécifique au C++)
pm-expression ->* expression-transtypage (spécifique au C++)
expression-multiplication:
pm-expression
expression-multiplication * pm-expression
expression-multiplication / pm-expression
expression-multiplication % pm-expression
expression-addition:
expression-multiplication
expression-addition + expression-multiplication
expression-addition - expression-multiplication
expression-décalage:
expression-addition
expression-décalage << expression-addition
expression-décalage >> expression-addition
expression-relationnelle:
expression-décalage
expression-relationnelle < expression-décalage
expression-relationnelle > expression-décalage
expression-relationnelle <= expression-décalage
expression-relationnelle >= expression-décalage
expression qualité :
3 expression-relationnelle
expression-égalité == expression-relationnelle
expression-égalité != expression-relationnelle
expression-ET:
expression-égalité
expression-ET & expression-égalité
expression-OU-exclusif:
expression-ET
expression-OU-exclusif ^ expression-ET
expression OU inclusif:

626
3.1 Référence C++ RAD Studio Guide du langage C++

expression-OU-exclusif
expression-OU-inclusif | expression-OU-exclusif
expression-ET-logique:

expression-OU-inclusif
expression-ET-logique && expression-OU-inclusif
expression-OU-logique:
expression-ET-logique
expression-OU-logique || expression-ET-logique
expression-conditionnelle:
expression-OU-logique
expression-OU-logique ? expression : expression-conditionnelle
expression-affectation:
expression-conditionnelle
expression-unaire opérateur-affectation expression-affectation
opérateur-affectation: un parmi

= *= /= %= += -=

<< => >= &= ^= |=


expression:
expression-affectation
expression , expression-affectation
expression-constante:
expression-conditionnelle

3.1.4.4.5.2 Priorité des opérateurs


Il existe seize catégories de priorité, certaines ne contenant qu'un seul opérateur. Les opérateurs d'une même catégorie ont une
priorité égale.

Lorsque des opérateurs apparaissent plusieurs fois dans le tableau, la première occurrence est unaire, la deuxième binaire.
Chaque catégorie possède sa règle d'associativité : de gauche à droite, ou de droite à gauche. En l'absence de parenthèses,
ces règles résolvent le groupement d'expressions avec des opérateurs d'égale priorité.

La priorité de chaque catégorie est indiquée par l'ordre d'apparition dans le tableau. La première catégorie (première ligne du
tableau) a la plus haute priorité. Les opérateurs d'une même ligne ont la même priorité.

Opérateurs Associativité
() gauche à droite
[]
->
::
.
! droite à gauche
~
+
-
++
-- 3
&
*
sizeof
new
delete

627
Guide du langage C++ RAD Studio 3.1 Référence C++

.* gauche à droite
->*
* gauche à droite
/
%
+ gauche à droite
-
<< gauche à droite
>>
< gauche à droite
<=
>
>=
== gauche à droite
!=
& gauche à droite
^ gauche à droite
| gauche à droite
&& gauche à droite
|| droite à gauche
?: gauche à droite
= droite à gauche
*=
/=
%=
+=
-=
&=
^=
|=
<<=
>>=
, gauche à droite

3.1.4.4.5.3 Expressions et C++


3 C++ permet de surcharger certains opérateurs standard du C, comme expliqué dans Surcharger les fonctions opérateur. Un
opérateur surchargé est défini pour remplir un rôle particulier lorsqu'il est appliqué à des expressions de type classe. Par
exemple, l'opérateur d'égalité == peut être défini dans la classe complex pour tester l'égalité de deux nombres complexes sans
modifier son utilisation normale avec les autres types de données non classes.

Un opérateur surchargé est mis en oeuvre comme une fonction ; celle-ci détermine le type d'opérande, la lvalue, l'ordre
d'évaluation à appliquer lorsque l'opérateur surchargé est utilisé. Cependant, la surcharge ne peut pas modifier la priorité d'un
opérateur. De même, C++ permet au programmeur de définir des conversions entre objets de classe et types fondamentaux.
N'oubliez donc pas que certaines des règles gérant les opérateurs et les conversions du C peuvent ne pas s'appliquer aux

628
3.1 Référence C++ RAD Studio Guide du langage C++

expressions de C++.

3.1.4.4.5.4 Ordre d'évaluation


L'ordre dans lequel le compilateur évalue les opérandes d'une expression n'est pas spécifié, sauf lorsqu'un opérateur l'énonce
explicitement. Le compilateur essaie de réordonner l'expression afin d'améliorer la qualité du code généré. Vous devez donc
être attentif aux expressions où une valeur est modifiée plusieurs fois. En général, évitez d'écrire des expressions qui modifient
et utilisent la valeur du même objet. Par exemple, soit l'expression :
i = v[i++]; // i est non défini
La valeur de i est différente selon que i est incrémenté avant ou après l'affectation. De même :
int total = 0;
somme = (total = 3) + (++total); // somme = 4 ou somme = 7 ??
est ambiguë pour somme et total. La solution est de reformuler l'expression en utilisant une variable temporaire :
int temp, total = 0;
temp = ++total;
somme = (total = 3) + temp;
Lorsque la syntaxe met en oeuvre une séquence d'évaluation, il est plus sûr d'avoir plusieurs évaluations :
somme = (i = 3, i++, i++); // OK: somme = 4, i = 5
Chaque sous-expression d'une expression avec virgule est évaluée de gauche à droite, et l'ensemble a pour résultat la valeur la
plus à droite.

Le compilateur regroupe les expressions, en réordonnant les opérateurs associatifs et commutatifs indépendamment des
parenthèses, afin de créer une expression compilée de façon optimale ; en aucun cas ce réarrangement n'affecte la valeur de
l'expression.

3.1.4.4.5.5 Erreurs et débordements


Associativité et priorité des opérateurs CodeGear C++ résume la priorité et l'associativité des opérateurs. Durant l'évaluation
d'une expression, il arrive que le compilateur rencontre des situations problématiques, comme une division par zéro ou des
valeurs en virgule flottante hors de l'intervalle admis. Le débordement d'entier est ignoré (C utilise le modulo 2n sur les registres
de n bits), mais les erreurs détectées par les fonctions mathématiques des bibliothèques sont traitées par des routines standard
ou définies par le programmeur. Voir _matherr et signal.

3.1.4.4.6 Fonctions
Cette section traite des fonctions.

Rubriques
Nom Description
Déclarations et définitions ( see page 630) Chaque programme doit contenir une fonction externe unique nommée main ou
WinMain, qui marque le point d'entrée du programme. Les fonctions sont
généralement déclarées comme prototypes dans les fichiers en-tête standard ou
définis par l'utilisateur, ou dans les fichiers du programme. Les fonctions sont 3
external par défaut et sont accessibles depuis n'importe quel fichier du
programme. Il est possible de réduire leur accessibilité en utilisant le
spécificateur de classe de stockage static (voir Liaison).
Les fonctions sont définies dans vos fichiers source ou rendues disponibles par
liaison des bibliothèques précompilées.
Il est possible de déclarer une même fonction plusieurs fois... suite ( see page
630)
La fonction main() ( see page 631)

629
Guide du langage C++ RAD Studio 3.1 Référence C++

Déclarations et prototypes ( see page 637) Dans le style de déclaration défini à l'origine par Kernighan et Ritchie, une
fonction pouvait implicitement être déclarée par son apparition dans un appel de
fonction, ou explicitement de la façon suivante :
<type> func()
où type est le type de la valeur renvoyée par la fonction (par défaut, int). En
C++, cette déclaration se lit : <type> func(void). Il est possible de déclarer une
fonction renvoyant n'importe quel type, sauf tableau ou fonction. Cette approche
ne permet pas au compilateur de vérifier que le type ou le nombre d'arguments
utilisés dans un appel de fonction concorde... suite ( see page 637)
Définitions ( see page 639) La syntaxe générale pour les définitions de fonctions externes est la suivante.
Définitions de fonctions externes
E/S formatées de types étendus ( see page 639) Le tableau suivant présente les nouveaux spécificateurs de format implémentés
dans C++ Builder pour la famille printf et scanf de fonctions. Cette
implémentation permet l'entrée et la sortie d'entiers 64 bits et offre une plus
grande souplesse des E/S pour les autres types.
Déclarations de paramètres formels ( see page 639) La liste de déclaration des paramètres formels obéit à une syntaxe semblable à
celle des déclarateurs dans les déclarations normales d'identificateurs. Voici
quelques exemples :
Appels de fonctions et conversion d'arguments ( see page 640) Une fonction est appelée avec certains arguments réels placés dans la même
séquence que leurs paramètres formels. Les arguments réels sont convertis
comme s'il s'agissait d'une initialisation aux types déclarés pour les paramètres
formels.
Voici un résumé des règles qui déterminent la façon dont le compilateur traite les
modificateurs de langage et les paramètres formels dans les appels de fonction,
avec et sans prototypes :

• Les modificateurs de langage pour une définition de


fonction doivent correspondre à ceux utilisés dans la
déclaration de la fonction au niveau de tous les appels la
concernant.
• Une fonction peut modifier la valeur de ses... suite ( see
page 640)

3.1.4.4.6.1 Déclarations et définitions


Chaque programme doit contenir une fonction externe unique nommée main ou WinMain, qui marque le point d'entrée du
programme. Les fonctions sont généralement déclarées comme prototypes dans les fichiers en-tête standard ou définis par
l'utilisateur, ou dans les fichiers du programme. Les fonctions sont external par défaut et sont accessibles depuis n'importe quel
fichier du programme. Il est possible de réduire leur accessibilité en utilisant le spécificateur de classe de stockage static (voir
Liaison).

Les fonctions sont définies dans vos fichiers source ou rendues disponibles par liaison des bibliothèques précompilées.

Il est possible de déclarer une même fonction plusieurs fois dans un programme, à condition que les déclarations soient
compatibles. Les déclarations de fonctions (et non les définitions) sous forme de prototypes fournissent au compilateur une
description détaillée de leurs paramètres permettant les transtypages ainsi qu'un contrôle des types et du nombre des
arguments.

Remarque: En C++, vous devez toujours utiliser les prototypes de fonctions. Nous vous conseillons aussi de les utiliser en C.

En dehors des cas de surcharge des fonctions C++, une seule définition par fonction est autorisée. Les déclarations, s'il y en a,
doivent correspondre à la définition. La différence essentielle entre une définition et une déclaration est que la première contient
3 le corps de la fonction.

Voir aussi
Fonctions

Déclarations et définitions

Déclarations et prototypes ( see page 637)

Définitions ( see page 639)

630
3.1 Référence C++ RAD Studio Guide du langage C++

Déclarations de paramètres formels ( see page 639)

Appels de fonctions et conversion d'arguments ( see page 640)

3.1.4.4.6.2 La fonction main()


Rubriques
Nom Description
A propos de la fonction main() ( see page 632) Chaque programme C et C++ doit avoir une fonction de démarrage du
programme.

• Les programmes console appellent la fonction main au


démarrage.
• Les programmes GUI (Interface Utilisateur Graphique)
Windows appellent la fonction WinMain au démarrage.
L'endroit où vous placez la fonction de démarrage est une
question de préférence. Certains programmeurs placent la
fonction main au début du fichier, d'autres à la fin. Quel
que soit son emplacement, les points suivants relatifs à la
fonction main s'appliquent toujours.
• Arguments transmis à main
• Arguments génériques
• Utilisation de -p (convention d'appel Pascal)
• Valeur renvoyée par main()
Arguments à main() ( see page 633) Trois paramètres (arguments) sont transmis à main par la routine de démarrage
de CodeGear C++Builder : argc, argv et env.

• argc (un entier) est le nombre d'arguments en ligne de


commande transmis à main, y compris le nom de
l'exécutable lui-même.
• argv est un tableau de pointeurs sur des chaînes (char
*[]). argv[0] est le nom du chemin complet du programme
en cours d'exécution. argv[1] pointe sur la première
chaîne typée sur la ligne de commande du système
d'exploitation située après le nom du programme. argv[2]
pointe sur la seconde chaîne typée située après le nom
du programme.... suite ( see page 633)
Bibliothèques d'exécution par défaut ( see page 633) BCC32.EXE est le compilateur en ligne de commande. Les bibliothèques par
défaut utilisées avec ce compilateur sont C0W32.OBJ (code de démarrage),
CW32.LIB (bibliothèque d'exécution à thread unique statique) et IMPORT32.LIB
(bibliothèque d'importation pour Win32).
Bibliothèques de liaison dynamique ( see page 634) Les versions DLL (bibliothèque de liaison dynamique) de la bibliothèque
d'exécution sont contenues dans le sous-répertoire BIN de votre installation.
Elles sont listées ci-dessous, en précisant si elles sont multithread.
Répertoire : BIN

631
Guide du langage C++ RAD Studio 3.1 Référence C++

Programmes multithreads ( see page 634) Les programmes Win32 peuvent créer plusieurs threads d'exécution. Si votre
programme crée plusieurs threads et si ces threads utilisent également la
bibliothèque d'exécution C++, vous devez utiliser à la place la bibliothèque
CW32MT.LIB ou CW32MTI.
Les bibliothèques multithreads fournissent les fonctions suivantes que vous
utilisez pour créer des threads :

• _beginthread
• _beginthreadex
• _beginthreadNT
Les bibliothèques multithreads fournissent également les
fonctions correspondantes suivantes qui terminent les
threads :
• _endthread
• _endthreadex
• _threadid est une variable globale qui contient le numéro
d'identification en cours du thread également connu sous
le terme ID de thread).
Le fichier en-tête stddef.h contient la déclaration de
_threadid.... suite ( see page 634)
Transmission des informations de fichier aux processus enfant ( see page 635) Si votre programme utilise la fonction exec ou spawn pour créer un nouveau
processus, celui-ci héritera normalement de tous les handles de fichier ouverts
ayant été créés par le processus d'origine. Toutefois, certaines informations
relatives à ces handles seront perdues, y compris le mode d'accès utilisé pour
ouvrir le fichier. Par exemple, si votre programme ouvre un fichier pour un accès
en lecture seule en mode binaire, puis lance un processus enfant, celui-ci peut
endommager le fichier en écrivant dedans ou en le lisant en mode texte.
Pour que les processus enfant héritent de telles informations à propos des
fichiers... suite ( see page 635)
Bibliothèques d'exécution statiques ( see page 635) Voici la liste des noms des bibliothèques statiques C++Builder, ainsi que leur
utilisation.
Répertoire de BCB\LIB (fichiers LIB)
Valeur renvoyée par main() ( see page 637) La valeur renvoyée par main est le code de statut du programme de type int.
Toutefois, si votre programme utilise la routine exit (ou _exit) pour terminer, la
valeur renvoyée par main est l'argument transmis à l'appel de exit (ou à _exit).
Par exemple, si votre programme contient l'appel
Utilisation de --p (convention d'appel Pascal) ( see page 637) Si vous compilez votre programme en utilisant les conventions d'appel Pascal,
vous devez déclarer explicitement main comme un type C. Faites-le avec le mot
clé __cdecl, comme ceci :
Arguments génériques ( see page 637) Les arguments en ligne de commande contenant des caractères génériques
peuvent être étendus à tous les noms de fichier correspondants, de la même
façon que le système DOS étend les caractères génériques des commandes
comme COPY. Tout ce que vous avez à faire pour obtenir le développement des
caractères génériques consiste à lier votre programme au fichier objet
WILDARGS.OBJ inclus avec CodeGear C++.
Remarque: Les arguments à caractères génériques ne sont utilisés que dans
les applications en mode console.
Lorsque WILDARGS.OBJ est lié dans votre code de programme, vous pouvez
envoyer des arguments à caractères génériques (comme *.* ) à... suite ( see
page 637)

3 3.1.4.4.6.2.1 A propos de la fonction main()


Chaque programme C et C++ doit avoir une fonction de démarrage du programme.

• Les programmes console appellent la fonction main au démarrage.


• Les programmes GUI (Interface Utilisateur Graphique) Windows appellent la fonction WinMain au démarrage.
L'endroit où vous placez la fonction de démarrage est une question de préférence. Certains programmeurs placent la fonction
main au début du fichier, d'autres à la fin. Quel que soit son emplacement, les points suivants relatifs à la fonction main
s'appliquent toujours.

632
3.1 Référence C++ RAD Studio Guide du langage C++

• Arguments transmis à main


• Arguments génériques
• Utilisation de -p (convention d'appel Pascal)
• Valeur renvoyée par main()
Voir aussi
Arguments transmis à main ( see page 633)

Arguments génériques ( see page 637)

Utilisation de -p (convention d'appel Pascal) ( see page 637)

Valeur renvoyée par main() ( see page 637)

3.1.4.4.6.2.2 Arguments à main()


Trois paramètres (arguments) sont transmis à main par la routine de démarrage de CodeGear C++Builder : argc, argv et env.

• argc (un entier) est le nombre d'arguments en ligne de commande transmis à main, y compris le nom de l'exécutable
lui-même.
• argv est un tableau de pointeurs sur des chaînes (char *[]). argv[0] est le nom du chemin complet du programme en cours
d'exécution. argv[1] pointe sur la première chaîne typée sur la ligne de commande du système d'exploitation située après le
nom du programme. argv[2] pointe sur la seconde chaîne typée située après le nom du programme. argv[argc-1] pointe sur
le dernier argument transmis à main. argv[argc] contient NULL.
• env est également un tableau de pointeurs sur des chaînes. Chaque élément de env[] contient une chaîne de la forme
ENVVAR=valeur. ENVVAR est le nom d'une variable d'environnement, telle que PATH et valeur représente la valeur
définissant ENVVAR, comme C:\APPS;C:\TOOLS.
Si vous déclarez ces paramètres, vous devez les déclarer exactement dans l'ordre ci-après : argc, argv, env. Par exemple, voici
des déclarations valides d'arguments transmis à main :
int main()
int main(int argc) /* correct mais très improbable */
int main(int argc, char * argv[])
it ain(int argc, char * argv[], char * env[])]
La déclaration int main(int argc) est correcte, mais il est peu probable que vous utilisiez argc dans votre programme sans utiliser
également les éléments de argv.

L'argument env est également disponible à travers la variable globale _environ..

Pour toutes les plates-formes, argc et argv sont également disponibles via les variables globales _argc et _argv.

Utilisation de la fonction main avec une application Unicode


Voici la version Unicode de la fonction main :
int wmain (int argc, wchar_t *argv[])
Les paramètres argv et le paramètre facultatif envp prennent en charge les caractères étendus.

La fonction _tmain est une macro qui développe la version appropriée de la fonction main selon le type de l'application :
3
int _tmain (int argc, _TCHAR *argv[])
Voir aussi
La fonction main() ( see page 632)

3.1.4.4.6.2.3 Bibliothèques d'exécution par défaut


BCC32.EXE est le compilateur en ligne de commande. Les bibliothèques par défaut utilisées avec ce compilateur sont

633
Guide du langage C++ RAD Studio 3.1 Référence C++

C0W32.OBJ (code de démarrage), CW32.LIB (bibliothèque d'exécution à thread unique statique) et IMPORT32.LIB
(bibliothèque d'importation pour Win32).

Voir aussi
La fonction main() ( see page 632)

3.1.4.4.6.2.4 Bibliothèques de liaison dynamique


Les versions DLL (bibliothèque de liaison dynamique) de la bibliothèque d'exécution sont contenues dans le sous-répertoire BIN
de votre installation. Elles sont listées ci-dessous, en précisant si elles sont multithread.

Répertoire : BIN

Nom du fichier
CC3260.DLL 32 bits, thread unique
CC3260MT.DLL 32 bits, multithread

Voir aussi
La fonction main() ( see page 632)

3.1.4.4.6.2.5 Programmes multithreads


Les programmes Win32 peuvent créer plusieurs threads d'exécution. Si votre programme crée plusieurs threads et si ces
threads utilisent également la bibliothèque d'exécution C++, vous devez utiliser à la place la bibliothèque CW32MT.LIB ou
CW32MTI.

Les bibliothèques multithreads fournissent les fonctions suivantes que vous utilisez pour créer des threads :

• _beginthread
• _beginthreadex
• _beginthreadNT
Les bibliothèques multithreads fournissent également les fonctions correspondantes suivantes qui terminent les threads :
• _endthread
• _endthreadex
• _threadid est une variable globale qui contient le numéro d'identification en cours du thread également connu sous le terme
ID de thread).
Le fichier en-tête stddef.h contient la déclaration de _threadid.
Lorsque vous compilez ou liez un programme qui utilise plusieurs threads, vous devez utiliser le commutateur -tWM du
compilateur. Par exemple :
BCC32 -tWM THREAD.C
Remarque: Soyez prudent lors de l'utilisation de la fonction signal

3 dans un programme multithread. Les signaux SIGINT, SIGTERM et SIGBREAK ne peuvent être utilisés que par le thread
principal (thread un) dans une application non-Win32. Lorsqu'un de ces signaux survient, le thread en cours d'exécution est
suspendu et le contrôle est transféré au gestionnaire de signaux (le cas échéant) configuré par le thread un. Les autres signaux
peuvent être gérés par n'importe quel thread. Un gestionnaire de signaux ne doit pas utiliser les fonctions de la bibliothèque
d'exécution C++ car un verrou mortel de sémaphore peut survenir. Le gestionnaire doit plutôt définir simplement un indicateur ou
poster un sémaphore, et effectuer immédiatement un retour.

Voir aussi
La fonction main() ( see page 632)

634
3.1 Référence C++ RAD Studio Guide du langage C++

_beginthread ( see page 985)

_beginthreadex ( see page 989)

_beginthreadNT ( see page 987)

_endthread ( see page 992)

_endthreadex ( see page 993)

_threadid ( see page 1014)

signal ( see page 1009)

3.1.4.4.6.2.6 Transmission des informations de fichier aux processus enfant


Si votre programme utilise la fonction exec ou spawn pour créer un nouveau processus, celui-ci héritera normalement de tous
les handles de fichier ouverts ayant été créés par le processus d'origine. Toutefois, certaines informations relatives à ces
handles seront perdues, y compris le mode d'accès utilisé pour ouvrir le fichier. Par exemple, si votre programme ouvre un
fichier pour un accès en lecture seule en mode binaire, puis lance un processus enfant, celui-ci peut endommager le fichier en
écrivant dedans ou en le lisant en mode texte.

Pour que les processus enfant héritent de telles informations à propos des fichiers ouverts, vous devez lier votre programme au
fichier objet FILEINFO.OBJ.

Par exemple :
BCC32 TEST.C \BCB\LIB\FILEINFO.OBJ
Les informations de fichier sont transmises dans la variable d'environnement _C_FILE_INFO. Cette variable contient des
informations binaires codées. Votre programme ne doit pas essayer de lire ou de modifier sa valeur. Le programme enfant doit
avoir été construit avec la bibliothèque d'exécution C++ afin d'hériter correctement de ces informations.

D'autres programmes peuvent ignorer _C_FILE_INFO. Ils n'hériteront pas des informations de fichier.

Voir aussi
La fonction main() ( see page 632)

exec

spawn

3.1.4.4.6.2.7 Bibliothèques d'exécution statiques


Voici la liste des noms des bibliothèques statiques C++Builder, ainsi que leur utilisation.

Répertoire de BCB\LIB (fichiers LIB)

Nom du fichier Utilisation


cp32mt.lib Bibliothèque statique multithread C RTL compatible VCL
cp32mti.lib Bibliothèque d'importation compatible VCL pour cc3260mt.dll C RTL multithread
3
cw32.lib Bibliothèque statique à thread unique RTL
cw32i.lib Bibliothèque d'importation pour cc3260.dll RTL
cw32mt.lib Bibliothèque statique multithread RTL
cw32mti.lib Bibliothèque d'importation pour cc3260mt.dll RTL multithread
dxextra.lib Bibliothèque statique DirectX
import32.lib Bibliothèque d'importation ; inclut Winsock 1.x

635
Guide du langage C++ RAD Studio 3.1 Référence C++

memmgr.lib Bibliothèque d'importation pour BORLNDMM.DLL


msextra.lib Bibliothèque d'importation pour les APIs dont les noms de module diffèrent entre NT et Win95
mswsock.lib Bibliothèque d'importation pour MSWSOCK.DLL
noeh32.lib Bibliothèque de support sans gestion d'exception
ole2w32.lib Bibliothèque d'importation pour l'API OLE 2.0 32 bits
oleaut32.lib Bibliothèque d'importation pour l'API OLE 2.0 32 bits
qrpt50.lib Bibliothèque statique Quick Reports
rpcextra.lib Bibliothèque d'importation incluant des APIs RPC dont les noms de module diffèrent entre NT et Win95
tee50.lib Bibliothèque statique TChart
teedb50.lib Bibliothèque de diagnostic TChart
teeui50.lib Bibliothèque d'importation TChart
th32.lib Bibliothèque d'importation pour l'API ToolHelp 32 bits sous Win95
uuid.lib Bibliothèque statique GUID pour Direct 3D, DirectDraw, DirectSound, Shell extensions, DAO, Active
Scripting, etc.
vcl.lib Bibliothèque VCL, contenant des références à toutes les autres bibliothèques VCL ; usage dans
MAKEFILES avec no version #
vcljpg50.lib Bibliothèque statique pour le composant VCL JPEG
w32inet.lib Bibliothèque d'importation pour les DLLs Internet MS
ws2_32.lib Bibliothèque d'importation pour l'API WinSock 2.0 32 bits
wininnt.lib Bibliothèque d'importation pour wininet.dll

Répertoire de BCB\LIB (fichiers OBJ)

Nom du fichier Utilisation


c0d32.obj Module de démarrage de DLL
c0d32w.obj Module de démarrage de DLL, version caractères étendus
c0d32x.obj Module de démarrage de DLL, pas de gestion d'exception
c0pkg32.obj Module de démarrage de package
c0w32.obj Module de démarrage de GUI EXE
c0w32w.obj Module de démarrage de GUI EXE, version caractères étendus
c0x32.obj Module de démarrage d'EXE en mode console 32 bits
c0x32w.obj Module de démarrage d'EXE en mode console 32 bits, version caractères étendus
fileinfo.obj Passe les informations de handle de fichier ouvert aux processus enfant
gp.obj Imprime les informations de vidage des registres quand une exception se produit
3 wildargs.obj Transforme les arguments génériques d'un tableau d'arguments en main()/wmain() dans les applications
en mode console

(Sous-répertoire Lib\PSDK) Bibliothèques d'importation pour le SDK de la plate-forme

Voir aussi
La fonction main() ( see page 632)

636
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.4.6.2.8 Valeur renvoyée par main()


La valeur renvoyée par main est le code de statut du programme de type int. Toutefois, si votre programme utilise la routine exit
(ou _exit) pour terminer, la valeur renvoyée par main est l'argument transmis à l'appel de exit (ou à _exit).

Par exemple, si votre programme contient l'appel


exit(1)
le statut est 1.
Voir aussi
A propos de la fonction main() ( see page 632)

exit ( see page 1120)

_exit ( see page 1104)

3.1.4.4.6.2.9 Utilisation de --p (convention d'appel Pascal)


Si vous compilez votre programme en utilisant les conventions d'appel Pascal, vous devez déclarer explicitement main comme
un type C. Faites-le avec le mot clé __cdecl, comme ceci :
int __cdecl main(int argc, char* argv[], char
* envp[])
Voir aussi
La fonction main() ( see page 632)

3.1.4.4.6.2.10 Arguments génériques


Les arguments en ligne de commande contenant des caractères génériques peuvent être étendus à tous les noms de fichier
correspondants, de la même façon que le système DOS étend les caractères génériques des commandes comme COPY. Tout
ce que vous avez à faire pour obtenir le développement des caractères génériques consiste à lier votre programme au fichier
objet WILDARGS.OBJ inclus avec CodeGear C++.

Remarque: Les arguments à caractères génériques ne sont utilisés que dans les applications en mode console.

Lorsque WILDARGS.OBJ est lié dans votre code de programme, vous pouvez envoyer des arguments à caractères génériques
(comme *.* ) à votre fonction main. L'argument sera étendu (dans le tableau argv) à tous les fichiers correspondant au masque à
caractères génériques. La taille maximale du tableau argv varie selon la quantité de mémoire disponible dans votre tas.

Si aucun fichier correspondant n'est trouvé, l'argument est transmis inchangé. Ainsi, une chaîne représentant le masque à
caractères génériques est transmise à la fonction main.

Les arguments entre guillemets ("...") ne sont pas développés.

Voir aussi
A propos de la fonction main ( see page 632)

3.1.4.4.6.3 Déclarations et prototypes 3


Dans le style de déclaration défini à l'origine par Kernighan et Ritchie, une fonction pouvait implicitement être déclarée par son
apparition dans un appel de fonction, ou explicitement de la façon suivante :

<type> func()

où type est le type de la valeur renvoyée par la fonction (par défaut, int). En C++, cette déclaration se lit : <type> func(void). Il
est possible de déclarer une fonction renvoyant n'importe quel type, sauf tableau ou fonction. Cette approche ne permet pas au
compilateur de vérifier que le type ou le nombre d'arguments utilisés dans un appel de fonction concorde avec la déclaration.

637
Guide du langage C++ RAD Studio 3.1 Référence C++

Ce problème a été résolu par l'introduction des prototypes de fonctions dont la syntaxe de déclaration est la suivante :

<type> func(liste-déclarateurs-paramètre);

Remarque: Vous pouvez activer un avertissement dans le compilateur en ligne de commande : "Function called without a
prototype.".

Les déclarateurs spécifient le type de chaque paramètre de la fonction. Le compilateur utilise ces informations pour vérifier la
validité des appels. Il peut aussi attribuer aux arguments le type adéquat. Supposons que vous ayez le fragment de code
suivant :
extern long lmax(long v1, long v2); /* prototype */
foo()
{
int limit = 32;
char ch = 'A';
long mval;
mval = lmax(limit,ch); /* appel de la fonction */
}
Ce programme, du fait qu'il contient un prototype de fonction pour lmax, convertit limit et ch à long, en appliquant les règles
standard d'affectation, avant de les placer sur la pile pour l'appel de lmax. Sans le prototype, limit et ch seraient placés sur la pile
en tant qu'entier et caractère ; dans ce cas, la pile passée à lmax n'aurait pas la taille ni le contenu que lmax attendait, causant
ainsi certains problèmes. Le style de déclaration classique ne permettant pas de vérifier ni le type ni le nombre des paramètres
des fonctions, l'utilisation des prototypes facilite considérablement la détection des erreurs de programmation.

Les prototypes de fonctions sont également utiles pour documenter le code. Par exemple, la fonction strcpy accepte deux
paramètres : une chaîne source et une chaîne destinataire. La question est de les différencier. Le prototype de fonction :
char *strcpy(char *dest, const char *source);
rend claire la formulation. Si un fichier en-tête contient des prototypes de fonctions, vous pouvez l'imprimer pour savoir comment
écrire les programmes qui appellent ces fonctions. Si vous introduisez un identificateur dans un paramètre de prototype, il n'est
utilisé que pour d'éventuels messages d'erreur relatifs à ce paramètre.

Un déclarateur avec le mot void entre parenthèses indique une fonction qui n'accepte aucun argument :
func(void);
En C++, func() déclare aussi une fonction sans argument.

Un prototype de fonction déclare généralement une fonction acceptant un nombre fixe de paramètres. Pour les fonctions qui
admettent un nombre variable de paramètres (comme printf), un prototype peut se terminer par des points de suspension (...),
comme suit :
f(int *count, long total, ...)
Avec cette forme de prototype, les paramètres fixes sont vérifiés au moment de la compilation, et les paramètres variables sont
transmis sans contrôle de type.

Remarque: Les fichiers stdarg.h et varargs.h contiennent des macros que vous pouvez utiliser dans des fonctions définies par
vous, avec un nombre variable de paramètres.

Voici quelques exemples de déclarateurs de fonctions et de prototypes :


3
int f();/* En C, une fonction renvoyant un int sans information concernant ses paramètres.
C'est le "style traditionnel" de K&R */ */
int f();/* En C++, une fonction sans argument */
int f(void);/* Une fonction sans paramètre renvoyant un int. */
int p(int,long);/* Une fonction renvoyant un int et acceptant deux paramètres : le premier,
un int; le second, un long. */
int __pascal q(void);/* Une fonction pascal renvoyant un int, sans paramètre. */
int printf(char *format,...; /* Une fonction renvoyant un int et acceptant un pointeur sur
un paramètre fixe char et un certain nombre d'autres paramètres de type inconnu. */

638
3.1 Référence C++ RAD Studio Guide du langage C++

int (*fp)(int)/* Un pointeur sur une fonction renvoyant un int et acceptant un seul
paramètre int. */

3.1.4.4.6.4 Définitions
La syntaxe générale pour les définitions de fonctions externes est la suivante.

Définitions de fonctions externes


file
définition-externe
fichier définition-externe
définition-externe:
définition-fonction
déclaration
instruction-asm
définition-fonction:
<spécificateurs-déclaration> déclarateur <liste-déclarations>
instruction-composée
En général, une définition de fonction comprend les sections suivantes (la grammaire autorise des cas bien plus complexes) :

• 1. Les spécificateurs (facultatifs) de classe de stockage : extern ou static. La valeur par défaut est extern.
• 2. Un type de renvoi, éventuellement void. La valeur par défaut est int.
• 3. Des modificateurs facultatifs : __pascal, __cdecl, __export__saveregs. Les modificateurs par défaut dépendent du
modèle mémoire et des options du compilateur.
• 4. Le nom de la fonction.
• 5. Une liste de déclaration des paramètres, qui peut être vide, et placée entre parenthèses. En C, le moyen le plus simple
d'indiquer que la liste est vide est de taper func(void). L'ancienne formulation func est légale en C mais elle est désuète et
parfois peu sûre.
• 6. Le corps de la fonction représentant le code à exécuter lorsque la fonction est appelée.
Remarque: Il est possible de mélanger des éléments de 1 et 2.

3.1.4.4.6.5 E/S formatées de types étendus


Le tableau suivant présente les nouveaux spécificateurs de format implémentés dans C++ Builder pour la famille printf et scanf
de fonctions. Cette implémentation permet l'entrée et la sortie d'entiers 64 bits et offre une plus grande souplesse des E/S pour
les autres types.

Caractère de format Fonctionnalité


%Ld __int64
%I8d Entier étendu 8 bits (char)
%I16d Entier étendu 16 bits (short)
%I32d Entier étendu 32 bits (long)
%I64d Entier étendu 64 bits (__int64)

Notez que le tableau ci-dessus utilise le format %d comme exemple. Les préfixes I8, I16, I32, I64 peuvent être utilisés avec les
3
formats d, i, o, x, X, ainsi que le nouveau préfixe L auparavant autorisé uniquement sur float pour spécifier le type long double.

3.1.4.4.6.6 Déclarations de paramètres formels


La liste de déclaration des paramètres formels obéit à une syntaxe semblable à celle des déclarateurs dans les déclarations
normales d'identificateurs. Voici quelques exemples :
int func(void) { // Sans argument

639
Guide du langage C++ RAD Studio 3.1 Référence C++

int func(T1 t1, T2 t2, T3 t3=1) { // Trois paramètres simples


// un avec un argument par défaut
int func(T1* ptr1, T2& tref) { // Un pointeur et un argument référence
int func(register int i) { // Demande de registre pour l'argument
int func(char *str,...) { { /* Un argument chaîne et un nombre variable d'autres
arguments, ou un nombre fixe d'arguments de types divers */
En C++, vous pouvez fournir des arguments par défaut. Les paramètres ayant des valeurs par défaut doivent être les derniers
de la liste. Les types d'arguments sont des scalaires, des structures, des unions et des énumérations, des pointeurs ou des
références de structures et d'unions, des pointeurs sur des fonctions, des classes ou des tableaux.

Les points de suspension (...) indiquent que la fonction sera appelée avec un jeu d'arguments différent selon les occasions. Les
points de suspension peuvent être placés après la sous-liste des arguments connus. Cette forme de prototype réduit le nombre
des vérifications que le compilateur doit faire.

Les paramètres déclarés ont tous une portée et une durée de vie automatiques pour le temps de validité de la fonction. Le seul
spécificateur de classe de stockage autorisé est register.

Les modificateurs const et volatile sont utilisables avec les déclarateurs des paramètres formels.

3.1.4.4.6.7 Appels de fonctions et conversion d'arguments


Une fonction est appelée avec certains arguments réels placés dans la même séquence que leurs paramètres formels. Les
arguments réels sont convertis comme s'il s'agissait d'une initialisation aux types déclarés pour les paramètres formels.

Voici un résumé des règles qui déterminent la façon dont le compilateur traite les modificateurs de langage et les paramètres
formels dans les appels de fonction, avec et sans prototypes :

• Les modificateurs de langage pour une définition de fonction doivent correspondre à ceux utilisés dans la déclaration de la
fonction au niveau de tous les appels la concernant.
• Une fonction peut modifier la valeur de ses paramètres formels, mais ceci n'a aucun effet sur les arguments réels dans la
routine appelante, sauf pour les arguments références en C++.
Lorsqu'un prototype de fonction n'a pas été préalablement déclaré, le compilateur convertit les arguments entiers de l'appel
d'une fonction selon les règles ordinaires de conversion des valeurs entières décrites dans Conversions arithmétiques
standard. Lorsqu'un prototype de fonction est accessible, le compilateur convertit chaque argument dans le type du
paramètre déclaré comme s'il s'agissait d'une affectation.
Lorsqu'un prototype de fonction contient des points de suspension (...), le compilateur convertit les arguments donnés jusqu'aux
points de suspension comme pour tout autre prototype. Le compilateur convertit ensuite les arguments qui suivent les
paramètres fixes, selon les règles normales applicables aux arguments des fonctions sans prototype.
S'il existe un prototype, les nombres d'arguments du prototype et de l'appel de la fonction doivent être les mêmes (sauf présence
de points de suspension dans le prototype). Les types doivent simplement être compatibles puisqu'une affectation peut
légalement les convertir. Vous pouvez toujours utiliser une conversion explicite des types pour transformer un argument et lui
donner un type acceptable pour le prototype.
Remarque: Si votre prototype de fonction ne correspond pas à la définition réelle de la fonction, le compilateur le détecte si,
et uniquement si, cette définition figure dans la même unité de compilation que le prototype. Si vous créez une bibliothèque
de routines avec un fichier en-tête pour les prototypes, prévoyez d'inclure celui-ci au moment de la compilation de la
bibliothèque, afin que les éventuelles contradictions entre les prototypes et les définitions réelles soient détectées. C++ offre
une connexion sûre, de sorte que les différences entre les paramètres prévus et réels seront mises en lumière par le lieur.
3
3.1.4.4.7 Résumé des opérateurs
Cette section présente le résumé les opérateurs.

640
3.1 Référence C++ RAD Studio Guide du langage C++

Rubriques
Nom Description
Présentation des opérateurs ( see page 641) Les opérateurs sont des unités qui déclenchent des calculs lorsqu'ils sont
appliqués aux variables et autres objets d'une expression.
Arithmétique ( see page 662)
Affectation ( see page 595)
Binaire ( see page 593)
Spécifique au C++ ( see page 594)
Virgule ( see page 596)
Conditionnel ( see page 596)
Egalité ( see page 594)
Logique ( see page 594)
Opérateurs d'expressions postfixées
Opérateurs d'expressions primaires ( see page 650)
Préprocesseur
Opérateurs de Référence/Indirection ( see page 663)
Relationnel ( see page 595)
sizeof ( see page 568)
typeid ( see page 575)
Tous les opérateurs peuvent être surchargés à l'exception de :

• . sélecteur de composant direct C++


• .* déréférencement C++
• :: accès/résolution de portée C++
• ?: conditionnel
Selon le contexte, le même opérateur peut avoir une
signification différente. Par exemple, l'opérateur & peut
s'interpréter comme :
• un ET binaire (A & B)
• un opérateur d'adresse (&A)
• en C++, un modificateur de... suite ( see page 641)

3.1.4.4.7.1 Présentation des opérateurs


Les opérateurs sont des unités qui déclenchent des calculs lorsqu'ils sont appliqués aux variables et autres objets d'une
expression.

Arithmétique ( see page 662)

Affectation ( see page 595)

Binaire ( see page 593)

Spécifique au C++ ( see page 594)

Virgule ( see page 596)

Conditionnel ( see page 596)


3
Egalité ( see page 594)

Logique ( see page 594)

Opérateurs d'expressions postfixées

Opérateurs d'expressions primaires ( see page 650)

Préprocesseur

641
Guide du langage C++ RAD Studio 3.1 Référence C++

Opérateurs de Référence/Indirection ( see page 663)

Relationnel ( see page 595)

sizeof ( see page 568)

typeid ( see page 575)

Tous les opérateurs peuvent être surchargés à l'exception de :

• . sélecteur de composant direct C++


• .* déréférencement C++
• :: accès/résolution de portée C++
• ?: conditionnel
Selon le contexte, le même opérateur peut avoir une signification différente. Par exemple, l'opérateur & peut s'interpréter
comme :
• un ET binaire (A & B)
• un opérateur d'adresse (&A)
• en C++, un modificateur de références
Remarque: Les espaces ne sont pas autorisés dans les opérateurs composés. En effet, ils changent la signification de
l'opérateur et provoquent une erreur.
Voir aussi
Priorité des opérateurs ( see page 627)

3.1.4.4.8 Pointeurs
Cette section traite des pointeurs.

Rubriques
Nom Description
Tableaux ( see page 643) La déclaration
type déclarateur [<expression-constante>]
déclare un tableau composé d'éléments de type. Un tableau est une zone de
stockage continue suffisamment grande pour contenir tous ses éléments.
Si une expression est contenue dans un déclarateur de tableau, elle doit fournir
comme résultat une valeur positive entière. La valeur est le nombre d'éléments
du tableau. Chacun des éléments est numéroté de zéro au nombre total des
éléments moins un.
Les tableaux multidimensionnels sont construits en déclarant des tableaux de
tableaux. Les exemples suivants montrent une façon de déclarer un tableau
bidimensionnel. Il est implémenté avec trois lignes et cinq colonnes,... suite (
see page 643)
Déclarations de type référence dans C++ ( see page 644) Les types références en C++ sont étroitement liés aux types pointeurs. Les types
références créent des alias pour les objets de données et permettent de passer
des paramètres aux fonctions, par référence. C passe des arguments
uniquement par valeur. Dans C++, vous pouvez passer des arguments par
valeur ou par référence. Pour de plus amples informations, voir Référencement
( see page 470).
3
Opérations arithmétiques et pointeurs ( see page 644) Les opérations arithmétiques sur les pointeurs sont l'addition, la soustraction et la
comparaison. Les opérations arithmétiques lorsqu'elles sont effectuées sur des
pointeurs d'objets de type "pointeur sur type" prennent automatiquement en
compte la taille de type, c'est-à-dire le nombre d'octets nécessaires pour stocker
un objet type.
Les calculs arithmétiques internes exécutés sur les pointeurs dépendent du
modèle mémoire et des éventuels modificateurs de pointeurs.
Les opérations arithmétiques sur les pointeurs supposent que les pointeurs en
question pointent sur des tableaux d'objets. Ainsi, si un pointeur pointe sur type,
l'addition d'une valeur entière à ce pointeur le... suite ( see page 644)

642
3.1 Référence C++ RAD Studio Guide du langage C++

Constantes pointeur ( see page 645) Un pointeur ou un objet pointé peut être déclaré avec le modificateur const.
Aucun élément de type const ne peut changer de valeur. De même, il est illégal
de créer un pointeur qui pourrait aller à l'encontre des lois de non affectabilité
d'un objet constant. Prenons les exemples suivants :
Conversions de pointeurs ( see page 645) Les types pointeurs peuvent être convertis grâce au transtypage.
Déclarations de pointeurs ( see page 646) Un pointeur doit pointer un type particulier de données, même s'il s'agit du type
void (qui désigne en réalité un pointeur sur n'importe quoi). Une fois déclaré, le
pointeur peut généralement être réaffecté pour pointer un objet d'un autre type.
Le compilateur permet de réaffecter les pointeurs sans transtypage, mais il
affiche un message d'avertissement, à moins que le pointeur n'ait été déclaré à
l'origine comme étant void. En C (mais pas en C++), vous pouvez affecter un
pointeur void* à un pointeur non void*. Voir void pour plus de détails.
Avertissement : Les pointeurs doivent être initialisés... suite ( see page 646)
Pointeurs ( see page 646) Les pointeurs appartiennent à deux grandes catégories : les pointeurs d'objets et
les pointeurs de fonctions. Les deux sont des objets particuliers qui contiennent
des adresses mémoire.
Les deux catégories de pointeurs ont des propriétés, des objectifs et des règles
de manipulation distinctes, bien qu'elles partagent certaines caractéristiques. En
général, les pointeurs de fonctions sont utilisés pour accéder à des fonctions et
passer des fonctions, prises comme paramètres, à d'autres fonctions ; il n'est pas
possible d'effectuer des opérations arithmétiques sur des pointeurs de fonctions.
Les pointeurs d'objets, en revanche, sont régulièrement incrémentés ou
décrémentés à mesure que vous analysez des tableaux... suite ( see page 646)
Pointeurs de fonctions ( see page 647) Un pointeur de fonction peut être envisagé comme une adresse, généralement
dans un segment de code, où est enregistré le code exécutable de la fonction en
question. Il s'agit en fait de l'adresse qui prend le contrôle lorsque la fonction est
appelée.
Un pointeur de fonction est du type "pointeur de fonction renvoyant type", où
type est le type de la valeur renvoyée par la fonction. Par exemple,
Pointeurs d'objets ( see page 647) Un pointeur de type "pointeur sur un objet type" contient l'adresse d'un objet de
type type. Les pointeurs étant des objets, il est possible d'avoir un pointeur
désignant un pointeur, etc. Citons, parmi les objets couramment pointés, les
tableaux, les structures, les unions et les classes.

3.1.4.4.8.1 Tableaux
La déclaration

type déclarateur [<expression-constante>]

déclare un tableau composé d'éléments de type. Un tableau est une zone de stockage continue suffisamment grande pour
contenir tous ses éléments.

Si une expression est contenue dans un déclarateur de tableau, elle doit fournir comme résultat une valeur positive entière. La
valeur est le nombre d'éléments du tableau. Chacun des éléments est numéroté de zéro au nombre total des éléments moins un.

Les tableaux multidimensionnels sont construits en déclarant des tableaux de tableaux. Les exemples suivants montrent une
façon de déclarer un tableau bidimensionnel. Il est implémenté avec trois lignes et cinq colonnes, mais il peut être facilement
modifié pour s'adapter à ce que saisira un utilisateur au moment de l'exécution.
/* ALLOCATION MEMOIRE DYNAMIQUE POUR UN OBJET MULTIDIMENSIONNEL. */
#include <stdio.h>
#include <stdlib.h>
typedef long double TYPE;
typedef TYPE *OBJECT;
unsigned int rows = 3, columns = 5;
void de_allocate(OBJECT); 3
int main(void) {
OBJECT matrix;
unsigned int i, j;
/* ETAPE 1: DEFINIR LES LIGNES. */
matrix = (OBJECT) calloc( rows, sizeof(TYPE *));
/* ETAPE 2: DEFINIR LES COLONNES. */
for (i = 0; i < rows; ++i)
matrix[i] = (TYPE *) calloc( columns, sizeof(TYPE));
for (i = 0; i < rows; i++)
for (j = 0; j < columns; j++)

643
Guide du langage C++ RAD Studio 3.1 Référence C++

matrix[i][j] = i + j; /* INITIALISER */
for (i = 0; i < rows; ++i) {
printf("\n\n");
for (j = 0; j < columns; ++j)
printf("%5.2Lf", matrix[i][j]);
de_allocate(matrix);
return 0;
}
void de_allocate(OBJECT x) {
int i;
for (i = 0; i < rows; i++) /* ETAPE 1: SUPPRIMER LES COLONNES */
free(x[i]);
free(x); /* ETAPE 2: SUPPRIMER LES LIGNES. */
}
Ce code produit les résultats suivants :
0.00 1.00 2.00 3.00 4.00
1.00 2.00 3.00 4.00 5.00
2.00 3.00 4.00 5.00 6.00
Dans certains contextes, le premier déclarateur d'une série peut ne contenir aucune expression entre crochets. Un tel tableau
est de taille indéterminée. C'est possible lorsque la taille du tableau n'est pas indispensable pour réserver un espace.

Par exemple, dans une déclaration extern de tableau, il est inutile de mentionner les dimensions exactes, de même que pour un
paramètre de fonction de type tableau. Par une extension de la norme ANSI du langage C, Borland C++ accepte également un
tableau de taille indéterminée comme membre final d'une structure. Ces tableaux n'augmentent pas la taille de la structure ;
toutefois l'ajout de caractères de remplissage permet de s'assurer que le tableau est correctement aligné. Ces structures sont
généralement utilisées dans les allocations dynamiques, la taille du tableau réellement nécessaire doit être explicitement
mentionnée et ajoutée à la taille de la structure pour que la réservation de l'espace requis soit correcte.

Sauf lorsqu'il s'agit de l'opérande d'un opérateur sizeof ou &, une expression de type tableau est convertie en pointeur sur le
premier élément du tableau.

Voir aussi
Tableaux

3.1.4.4.8.2 Déclarations de type référence dans C++


Les types références en C++ sont étroitement liés aux types pointeurs. Les types références créent des alias pour les objets de
données et permettent de passer des paramètres aux fonctions, par référence. C passe des arguments uniquement par valeur.
Dans C++, vous pouvez passer des arguments par valeur ou par référence. Pour de plus amples informations, voir
Référencement ( see page 470).

3.1.4.4.8.3 Opérations arithmétiques et pointeurs


Les opérations arithmétiques sur les pointeurs sont l'addition, la soustraction et la comparaison. Les opérations arithmétiques
lorsqu'elles sont effectuées sur des pointeurs d'objets de type "pointeur sur type" prennent automatiquement en compte la taille
de type, c'est-à-dire le nombre d'octets nécessaires pour stocker un objet type.

3 Les calculs arithmétiques internes exécutés sur les pointeurs dépendent du modèle mémoire et des éventuels modificateurs de
pointeurs.

Les opérations arithmétiques sur les pointeurs supposent que les pointeurs en question pointent sur des tableaux d'objets. Ainsi,
si un pointeur pointe sur type, l'addition d'une valeur entière à ce pointeur le fait avancer du même nombre d'objets du type
considéré. Si type a une taille de 10 octets et si on ajoute 5 à un pointeur sur type, le pointeur avance de 50 octets en mémoire.
La soustraction correspond au nombre d'éléments du tableau qui séparent les deux opérandes. Par exemple, si ptr1 pointe sur
le troisième élément d'un tableau, et ptr2 sur le dixième, le résultat de ptr2 - ptr1 sera 7.

644
3.1 Référence C++ RAD Studio Guide du langage C++

La soustraction entre deux pointeurs n'a de sens que si les deux pointent sur les données d'un même tableau.

Lorsqu'un entier est ajouté à un "pointeur sur type", ou soustrait de celui-ci, le résultat est également de type "pointeur sur type".

Il n'existe pas d'élément tel que "pointeur sur le dernier élément plus un", mais un pointeur peut prendre une telle valeur. Si P
pointe sur le dernier élément d'un tableau, P+1 est légal, mais P+2 est non défini. Si P pointe sur le dernier élément plus un, P-1
est légal, et on obtient un pointeur sur le dernier élément. Cependant, le fait d'appliquer l'opérateur d'indirection * à un "pointeur
du dernier élément plus un" aboutit à un comportement non défini.

On peut dire que P + n fait avancer le pointeur de (n * sizeof(type)) octets, dès lors que le pointeur reste dans la fourchette de
valeurs permises (jusqu'au premier élément qui suit le dernier).

La soustraction de deux pointeurs d'éléments du même objet tableau donne une valeur entière de type ptrdiff_t définie dans
stddef.h. Cette valeur représente la différence entre les deux indices des éléments référencés, à condition qu'elle soit comprise
dans la fourchette de ptrdiff_t. Dans l'expression P1-P2, où P1 et P2 sont du type pointeur sur type (ou pointeur sur type
qualifié), P1 et P2 doivent pointer sur des éléments existants ou sur le dernier élément plus un. Si P1 pointe sur l'élément i et P2
sur j, P1-P2 aura la valeur (i-j).

3.1.4.4.8.4 Constantes pointeur


Un pointeur ou un objet pointé peut être déclaré avec le modificateur const. Aucun élément de type const ne peut changer de
valeur. De même, il est illégal de créer un pointeur qui pourrait aller à l'encontre des lois de non affectabilité d'un objet constant.
Prenons les exemples suivants :
int i; // i est un int
int * pi; // pi est un pointeur sur int (non initialisé)
int * const cp = &i; // cp est un pointeur constant sur int
const int ci = 7; // ci est un int constant
const int * pci; // pci est un pointeur sur un int constant
const int * const cpc = &ci; // cpc est un pointeur constant sur un
// int constant
Les affectations suivantes sont légales :
i = ci; // Affecte int-const à int
*cp = ci; // Affecte int-const à un objet
// pointé par un pointeur constant
++pci; // Incrémente un pointeur de const
pci = cpc; // Affecte un pointeur-const-sur-const
// à un pointeur-sur-const
Les affectations suivantes sont illégales :
ci = 0; // NON - affectation impossible d'un int-const
ci--; // NON - impossible de modifier un int-const
*pci = 3; // NON - affectation impossible d'un objet
// pointé par un pointeur-sur-const
cp = &ci; // NON - affectation impossible d'un pointeur-const,
// même si la valeur reste inchangée
cpc++; // NON - impossible de modifier un pointeur-const
pi = pci; // NON - si cette affectation était permise,
// vous pourriez donner une valeur à *pci
// (valeur constante) en donnant une valeur à *pi.
3
Des règles semblables s'appliquent au modificateur volatile. Remarquez que const et volatile peuvent modifier un même
identificateur.

3.1.4.4.8.5 Conversions de pointeurs


Les types pointeurs peuvent être convertis grâce au transtypage.
char *str;

645
Guide du langage C++ RAD Studio 3.1 Référence C++

int *ip;
str = (char *)ip;
Plus généralement, le transtypage (type*) convertit un pointeur en "pointeur sur type".

Pour plus d'informations sur les mécanismes du transtypage en C++, voir Spécifique au C++.

3.1.4.4.8.6 Déclarations de pointeurs


Un pointeur doit pointer un type particulier de données, même s'il s'agit du type void (qui désigne en réalité un pointeur sur
n'importe quoi). Une fois déclaré, le pointeur peut généralement être réaffecté pour pointer un objet d'un autre type. Le
compilateur permet de réaffecter les pointeurs sans transtypage, mais il affiche un message d'avertissement, à moins que le
pointeur n'ait été déclaré à l'origine comme étant void. En C (mais pas en C++), vous pouvez affecter un pointeur void* à un
pointeur non void*. Voir void pour plus de détails.

Avertissement : Les pointeurs doivent être initialisés avant d'être utilisés.

Si type est un type prédéfini ou défini par le programmeur (y compris void), la déclaration
type *ptr; /* Pointeur non initialisé */
déclare que ptr est un "pointeur sur type". Toutes les règles de portée, durée de vie et visibilité s'appliquent à l'objet ptr.

Pour un pointeur, une valeur NULL est une adresse assurée d'être différente de tout autre pointeur valide utilisé dans le
programme. L'affectation de la constante entière 0 à un pointeur attribue une valeur NULL au pointeur.

Le mnémonique NULL (défini dans les fichiers en-tête de la bibliothèque standard, comme stdio.h) améliore la lisibilité des
sources. Tous les pointeurs peuvent être testés pour contrôler s'ils sont égaux ou non à NULL.

Ne confondez pas "pointeur sur void" avec le pointeur NULL. La déclaration


void *vptr;
revient à dire que vptr est un pointeur générique qui peut faire l'objet d'une affectation par une quelconque valeur "pointeur sur
type", y compris la valeur NULL. Les affectations sans transtypage entre un "pointeur sur type1" et un "pointeur sur type2", où
type1 et type2 sont différents, peuvent entraîner une erreur ou un avertissement du compilateur. Si type1 est une fonction et
type2 ne l'est pas (ou inversement), les affectations de pointeurs sont illégales. Si type1 est un pointeur sur void, aucun
transtypage n'est nécessaire. Dans C, si type2 est un pointeur sur void, aucun transtypage n'est nécessaire.

3.1.4.4.8.7 Pointeurs
Les pointeurs appartiennent à deux grandes catégories : les pointeurs d'objets et les pointeurs de fonctions. Les deux sont des
objets particuliers qui contiennent des adresses mémoire.

Les deux catégories de pointeurs ont des propriétés, des objectifs et des règles de manipulation distinctes, bien qu'elles
partagent certaines caractéristiques. En général, les pointeurs de fonctions sont utilisés pour accéder à des fonctions et passer
des fonctions, prises comme paramètres, à d'autres fonctions ; il n'est pas possible d'effectuer des opérations arithmétiques sur
des pointeurs de fonctions. Les pointeurs d'objets, en revanche, sont régulièrement incrémentés ou décrémentés à mesure que
vous analysez des tableaux ou autres structures plus complexes de données en mémoire.

3 Bien que les pointeurs soient des nombres ayant la plupart du temps les caractéristiques des entiers non signés, ils ont leurs
propres règles et restrictions d'affectation, de conversion et d'arithmétique. Les exemples des sections suivantes illustrent ces
règles et restrictions.

Remarque: Pour plus d'informations sur le référencement et déréférencement, voir Référencement.

Voir aussi
Pointeurs d'objets ( see page 647)

Pointeurs de fonctions ( see page 647)

646
3.1 Référence C++ RAD Studio Guide du langage C++

Déclarations de pointeurs ( see page 646)

Constantes pointeur ( see page 645)

Opérations arithmétiques et pointeurs ( see page 644)

Conversions de pointeurs ( see page 645)

Déclarations de type référence dans C++ ( see page 644)

3.1.4.4.8.8 Pointeurs de fonctions


Un pointeur de fonction peut être envisagé comme une adresse, généralement dans un segment de code, où est enregistré le
code exécutable de la fonction en question. Il s'agit en fait de l'adresse qui prend le contrôle lorsque la fonction est appelée.

Un pointeur de fonction est du type "pointeur de fonction renvoyant type", où type est le type de la valeur renvoyée par la
fonction. Par exemple,
void (*func)();
En C++, c'est un pointeur de fonction ne prenant aucun argument et renvoyant void. En C, il s'agit d'un pointeur de fonction
prenant un nombre indéfini d'arguments et renvoyant void. Dans cet exemple,
void (*func)(int);
*func est le pointeur d'une fonction prenant un argument int et renvoyant void.

En C++, un tel pointeur peut être utilisé pour accéder à des fonctions membre statiques. Les pointeurs sur les membres d'une
classe doivent utiliser les opérateurs pointant sur des membres. Pour plus d'informations, voir static_cast.

3.1.4.4.8.9 Pointeurs d'objets


Un pointeur de type "pointeur sur un objet type" contient l'adresse d'un objet de type type. Les pointeurs étant des objets, il est
possible d'avoir un pointeur désignant un pointeur, etc. Citons, parmi les objets couramment pointés, les tableaux, les structures,
les unions et les classes.

3.1.4.4.9 Opérateurs d'expressions postfixées


Cette section traite des opérateurs d'expressions postfixés.

Rubriques
Nom Description
Sélecteur de membre direct (.) ( see page 647) Syntaxe
Sélecteur de membre indirect (->) ( see page 648) Syntaxe
Opérateur d'accès à un tableau ( see page 648) Les crochets ([ ]) indiquent les indices de tableaux à une ou plusieurs
dimensions. L'expression
Opérateurs d'incrémentation/décrémentation ( see page 648) Opérateur d'incrémentation ( ++ )
Syntaxe
Opérateur d'appel de fonction ( see page 649) Syntaxe
3
3.1.4.4.9.1 Sélecteur de membre direct (.)
Syntaxe
expression postfixée . identificateur
expression-postfixée doit être de type union ou structure.

identificateur doit être le nom d'un membre du type de la structure ou de l'union.

647
Guide du langage C++ RAD Studio 3.1 Référence C++

Remarques

Utilisez l'opérateur de sélection (.) pour accéder aux membres d'une structure et d'une union.

Soit l'objet s est du type structure S et sptr est un pointeur sur S. Alors, si m est un membre de type M déclaré dans S,
l'expression :
s.m
est de type M, et représente l'objet membre m de s.

3.1.4.4.9.2 Sélecteur de membre indirect (->)


Syntaxe
expression-postfixée -> identificateur
expression-postfixée doit être du type pointeur sur structure ou pointeur sur union.

identificateur doit être le nom d'un membre du type de la structure ou de l'union.

L'expression désigne un membre de l'objet structure ou union. La valeur est celle du membre sélectionné; ce sera une lvalue si
et seulement si expression-postfixée est une lvalue.

Remarques

Vous utilisez l'opérateur de sélection (->) pour accéder aux membres d'une structure et d'une union.

Soit l'objet s est du type structure S et sptr est un pointeur sur S. Alors, si m est un membre de type M déclaré dans S,
l'expression :
sptr->m
est de type M, et représente l'objet membre m de s.

L'expression
s->sptr
est un synonyme commode de (*sptr).m.

3.1.4.4.9.3 Opérateur d'accès à un tableau


Les crochets ([ ]) indiquent les indices de tableaux à une ou plusieurs dimensions. L'expression
<exp1>[exp2]
est définie comme
*((exp1) + (exp2))
où :

• soit exp1 est un pointeur et exp2 un entier


• soit exp1 est un entier et exp2 un pointeur
3
3.1.4.4.9.4 Opérateurs d'incrémentation/décrémentation
Opérateur d'incrémentation ( ++ )

Syntaxe
expression-postfixée ++ (postincrémentation)
++ expression-unaire (préincrémentation)
L'expression-postfixée est l'opérande. Il doit être du type scalaire (type arithmétique ou pointeur) et être une lvalue modifiable.

648
3.1 Référence C++ RAD Studio Guide du langage C++

Opérateur de postincrémentation

La valeur de l'expression complète est celle de l'expression postfixée avant incrémentation.

L'opérande est incrémenté de 1 après évaluation de l'expression.

Opérateur de préincrémentation

L'opérande est incrémenté de 1 avant l'évaluation de l'expression. La valeur de l'expression résultante est celle de la valeur
incrémentée de l'opérande.

La valeur de l'incrément est appropriée au type de l'opérande.

Les types pointeurs suivent les règles d'arithmétique des pointeurs.

Opérateur de décrémentation ( -- )

Syntaxe
expression-postfixée -- (postdécrémentation)
-- expression-unaire (prédécrémentation)
L'opérateur de décrémentation suit les mêmes règles que celui d'incrémentation, hormis le fait que l'opérande est décrémenté
de 1 après ou avant l'évaluation de l'expression.

3.1.4.4.9.5 Opérateur d'appel de fonction


Syntaxe
expression-postfixée (<liste-expression-arg>)
Remarques

Parenthèses (())

• groupent des expressions


• isolent des expressions conditionnelles
• indiquent des appels de fonctions ou des paramètres de fonctions.
La valeur de l'expression d'appel de fonction est, le cas échéant, déterminée par l'instruction de renvoi figurant dans la définition
de la fonction.
Il s'agit d'un appel à la fonction donnée par l'expression postfixée.
liste-expressions-arg est une liste délimitée par des virgules d'expressions de type quelconque représentant les valeurs réelles
des arguments de la fonction.

3.1.4.4.10 Opérateurs d'expressions primaires


Cette section traite des opérateurs d'expressions primaires.

649
Guide du langage C++ RAD Studio 3.1 Référence C++

Rubriques
Nom Description
Opérateurs d'expressions primaires ( see page 650) Selon la norme ANSI du C, les expressions primaires sont de type littéral (parfois
appelé constant), identificateur et (expression). En langage C++, cette liste des
expressions primaires comprend également le mot clé this, l'opérateur de
résolution de portée ::, nom et le destructeur de classe ~ (tilde).
Les expressions primaires sont résumées dans la liste suivante.
expression-primaire:

1. littéral this (spécifique au C++)


2. :: identificateur (spécifique au C++)
3. :: nom-fonction-opérateur (spécifique au C++)
4. :: nom-qualifié (spécifique au C++)
5. (expression) nom
littéral:
1. constante-entière
2. constante-caractère
3. constante-flottante
4. littéral-chaîne
nom:
1. identificateur
2. nom-fonction-opérateur (spécifique au C++)
3. nom-fonction-conversion (spécifique au C++)
4. ~ nom-classe (spécifique C++)... suite ( see page 650)

3.1.4.4.10.1 Opérateurs d'expressions primaires


Selon la norme ANSI du C, les expressions primaires sont de type littéral (parfois appelé constant), identificateur et (expression).
En langage C++, cette liste des expressions primaires comprend également le mot clé this, l'opérateur de résolution de portée
::, nom et le destructeur de classe ~ (tilde).

Les expressions primaires sont résumées dans la liste suivante.

expression-primaire:

1. littéral this (spécifique au C++)


2. :: identificateur (spécifique au C++)
3. :: nom-fonction-opérateur (spécifique au C++)
4. :: nom-qualifié (spécifique au C++)
5. (expression) nom
3 littéral:
1. constante-entière
2. constante-caractère
3. constante-flottante
4. littéral-chaîne
nom:

650
3.1 Référence C++ RAD Studio Guide du langage C++

1. identificateur
2. nom-fonction-opérateur (spécifique au C++)
3. nom-fonction-conversion (spécifique au C++)
4. ~ nom-classe (spécifique C++)
5. nom-qualifié (spécifique au C++)
nom-qualifié: (spécifique au C++)
nom-classe-qualifié :: nom

Pour une description de l'expression primaire this, voir this (mot clé). Le mot clé this ne peut pas être utilisé hors du corps d'une
fonction membre de classe.
L'opérateur de résolution de portée permet de faire référence à un type, à un objet, à une fonction ou à un énumérateur, même
si l'identificateur est caché.
Les parenthèses placées autour d'une expression ne modifient pas l'expression elle-même.
L'expression primaire nom est limitée à la catégorie des expressions primaires qui apparaissent parfois après les opérateurs
d'accès aux membres . (point) et –>. Par conséquent, nom doit être une lvalue ou une fonction. Voir aussi la description des
opérateurs d'accès aux membres.
Un identificateur est une expression primaire à condition qu'il ait été déclaré comme il convient. Vous trouverez une description
et une définition formelle des identificateurs à la rubrique Eléments lexicaux : Identificateurs.
Voir la description de l'utilisation de l'opérateur destructeur ~ (tilde).

3.1.4.4.11 Instructions
Cette section traite des instructions.

Rubriques
Nom Description
Blocs ( see page 652) Une instruction composée, ou bloc, est une liste (éventuellement vide)
d'instructions délimitées par des accolades ({ }). Syntaxiquement, un bloc peut
être envisagé comme une instruction simple, mais il joue en outre un rôle dans la
portée des identificateurs. Un identificateur déclaré dans un bloc a une portée qui
commence au point de déclaration et se termine à l'accolade fermante. Il est
possible d'imbriquer des blocs les uns dans les autres dans la limite de l'espace
disponible en mémoire.
Spécificités du C++ ( see page 652) C++ est un langage de programmation orienté objet issu du C. En règle
générale, vous pouvez compiler des programmes C sous C++, mais l'inverse
n'est pas permis si le programme utilise des constructions spécifiques à C++.
Certaines situations nécessitent une attention spéciale. Par exemple, la même
fonction func déclarée deux fois en C avec des types d'arguments différents
entraîne une condition d'erreur pour répétition de nom. En C++, func sera
interprétée comme une fonction surchargée. La légalité de cette surcharge
dépend quant à elle d'autres éléments.
Bien que C++ fasse appel à de nouveaux mots clés et opérateurs pour traiter...
suite ( see page 652)
Instructions expression ( see page 653) Toute expression suivie d'un point-virgule est une instruction expression :
Instructions d'itération ( see page 653) Ces instructions permettent d'établir des boucles. Il existe trois formes d'itération
dans C++ : boucles while, do while et for. 3
Instructions de branchement ( see page 653) Une instruction de branchement, lorsqu'elle est exécutée, passe le contrôle à
l'instruction suivante sans condition. Il existe quatre instructions de
branchement : break, continue, goto et return

651
Guide du langage C++ RAD Studio 3.1 Référence C++

Instructions étiquette ( see page 653) Il est possible d'associer une étiquette à une instruction, ceci de différentes
façons :

• identificateur-étiquette : instruction
* L'identificateur étiquette sert de cible pour l'instruction
inconditionnelle goto. Les identificateurs étiquette ont leur
propre espace de nommage et bénéficient de la portée
fonction. Remarquez qu'en C++ vous pouvez associer
des étiquettes aussi bien à des déclarations qu'à des
instructions non déclaratives.
• case expression-constante : instruction
* default : instruction
case et default sont des instructions avec étiquettes utilisées
uniquement en association avec des instructions de
branchement.
Instructions de sélection ( see page 653) Elles permettent de choisir une direction particulière dans le déroulement du
programme, par test de certaines valeurs. Il existe deux types d'instructions
sélectives : if...else et switch.
Instructions ( see page 653) Les instructions servent à préciser le sens de déroulement d'un programme. En
l'absence d'instructions de branchement ou de sélection, les instructions sont
exécutées séquentiellement, dans l'ordre de leur apparition dans le code source.
Les instructions de CodeGear C++ définissent la syntaxe des instructions.
Instructions CodeGear C++

3.1.4.4.11.1 Blocs
Une instruction composée, ou bloc, est une liste (éventuellement vide) d'instructions délimitées par des accolades ({ }).
Syntaxiquement, un bloc peut être envisagé comme une instruction simple, mais il joue en outre un rôle dans la portée des
identificateurs. Un identificateur déclaré dans un bloc a une portée qui commence au point de déclaration et se termine à
l'accolade fermante. Il est possible d'imbriquer des blocs les uns dans les autres dans la limite de l'espace disponible en
mémoire.

3.1.4.4.11.2 Spécificités du C++


C++ est un langage de programmation orienté objet issu du C. En règle générale, vous pouvez compiler des programmes C
sous C++, mais l'inverse n'est pas permis si le programme utilise des constructions spécifiques à C++. Certaines situations
nécessitent une attention spéciale. Par exemple, la même fonction func déclarée deux fois en C avec des types d'arguments
différents entraîne une condition d'erreur pour répétition de nom. En C++, func sera interprétée comme une fonction surchargée.
La légalité de cette surcharge dépend quant à elle d'autres éléments.

Bien que C++ fasse appel à de nouveaux mots clés et opérateurs pour traiter les classes, certaines des caractéristiques de C++
ont des applications en dehors du contexte des classes. Ce chapitre reprend les aspects de C++ utilisables indépendamment
des classes, puis décrit les particularités des classes et leurs mécanismes.

Voir Gestion des exceptions C++ et Exceptions structurées du langage C pour de plus amples informations sur la compilation
des programmes C et C++ avec gestion des exceptions.
3 Voir aussi
Référencement ( see page 470)

Classes C++ ( see page 403)

Introduction aux constructeurs et destructeurs ( see page 432)

Classes polymorphes ( see page 465)

Portée en C++ ( see page 448)

652
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.4.11.3 Instructions expression


Toute expression suivie d'un point-virgule est une instruction expression :
<expression>;
Le compilateur exécute une instruction expression en évaluant l'expression. Tous les effets de bord résultant de cette évaluation
sont calculés avant l'exécution de l'instruction suivante. La plupart des expressions sont des instructions d'affectation ou des
appels de fonction.

Un cas spécial est celui de l'instruction NULL, formée uniquement d'un point-virgule (;). Elle ne fait rien, mais elle est utile dans
certains cas où la syntaxe de C++ attend une instruction alors que le programme n'en a pas besoin.

3.1.4.4.11.4 Instructions d'itération


Ces instructions permettent d'établir des boucles. Il existe trois formes d'itération dans C++ : boucles while, do while et for.

3.1.4.4.11.5 Instructions de branchement


Une instruction de branchement, lorsqu'elle est exécutée, passe le contrôle à l'instruction suivante sans condition. Il existe
quatre instructions de branchement : break, continue, goto et return

3.1.4.4.11.6 Instructions étiquette


Il est possible d'associer une étiquette à une instruction, ceci de différentes façons :

• identificateur-étiquette : instruction
* L'identificateur étiquette sert de cible pour l'instruction inconditionnelle goto. Les identificateurs étiquette ont leur propre
espace de nommage et bénéficient de la portée fonction. Remarquez qu'en C++ vous pouvez associer des étiquettes aussi
bien à des déclarations qu'à des instructions non déclaratives.
• case expression-constante : instruction
* default : instruction
case et default sont des instructions avec étiquettes utilisées uniquement en association avec des instructions de branchement.

3.1.4.4.11.7 Instructions de sélection


Elles permettent de choisir une direction particulière dans le déroulement du programme, par test de certaines valeurs. Il existe
deux types d'instructions sélectives : if...else et switch.

3.1.4.4.11.8 Instructions
Les instructions servent à préciser le sens de déroulement d'un programme. En l'absence d'instructions de branchement ou de
sélection, les instructions sont exécutées séquentiellement, dans l'ordre de leur apparition dans le code source. Les instructions
de CodeGear C++ définissent la syntaxe des instructions.

Instructions CodeGear C++ 3

653
Guide du langage C++ RAD Studio 3.1 Référence C++

instruction instruction-étiquette
instruction-composée
instruction-expression
instruction-sélection
instruction-itération
instruction-saut
instruction-asm
déclaration (spécifique C++)
instruction-étiquette: identificateur : instruction
case expression-constante : instruction
default : instruction
instruction-composée: { <liste-déclarations> <liste-instructions> }
liste-déclarations: déclaration
liste-déclarations déclaration
liste-instructions: instruction
liste-instructions instruction
expression-instruction: <expression>;
instruction-asm: asm tokens saut-de-ligne
asm tokens;
asm { tokens; <tokens;>= <tokens;>}
instruction-sélection: if ( expression ) instruction
if ( expression ) instruction else instruction
switch ( expression ) instruction
instruction-itération: while ( expression ) instruction
do instruction while ( expression ) ;
for (instruction-init-for <expression> ; <expression>) instruction
instruction-init-for: instruction-expression
déclaration (spécifique C++)
instruction-saut: goto identificateur ;
continue ;
break ;
return <expression> ;

3.1.4.4.12 Structures
Cette section traite des structures.
3

654
3.1 Référence C++ RAD Studio Guide du langage C++

Rubriques
Nom Description
Structures ( see page 655) Une structure est un type dérivé représentant généralement un ensemble, défini
par le programmeur, de membres nommés (ou composants). Les membres
peuvent avoir n'importe quel type, fondamental ou dérivé (avec certaines
restrictions que nous verrons plus loin), dans un ordre quelconque. De plus, un
membre de structure peut être de type champ de bits (inadmissible en tout autre
endroit). Le type structure permet de manipuler des structures complexes de
données aussi aisément que des variables simples. L'initialisation des structures
est traitée à la section Tableaux, structures et unions de la rubrique d'aide
Initialisation ( see page 616).
En C++, un type structure est... suite ( see page 655)
Structures sans sélecteur et typedef ( see page 656) Si vous n'indiquez pas de sélecteur de structure, vous obtenez une structure
sans sélecteur. Ce genre de structure est utilisable pour attribuer à une liste
d'identificateurs (délimitée par des virgules) le type structure donné (ou un type
dérivé), mais il n'est pas possible de déclarer ailleurs d'autres éléments de ce
type :
Déclarations des membres d'une structure ( see page 656) La liste-déclarateurs-membre entre accolades déclare le type et le nom des
membres de la structure, en utilisant la syntaxe de déclarateur indiquée à la
rubrique Syntaxe des déclarations CodeGear C++
Un membre de structure peut avoir n'importe quel type, à deux exceptions près :
Le type du membre ne doit pas être le type struct en cours de déclaration :
Structures et fonctions ( see page 657) Une fonction peut renvoyer un type structure ou un pointeur sur un type
structure.
Accès aux membres d'une structure ( see page 657) Les membres des structures et des unions sont accessibles à l'aide des
opérateurs suivants :

• . (point)
• -> (flèche droite)
Supposons que l'objet s soit une structure de type S et sptr
un pointeur sur S. Si m est un identificateur de membre de
type M déclaré dans S, les expressions s.m et sptr->m
sont de type M, et représentent toutes deux l'objet
membre m de S. L'expression sptr->m est un synonyme
pratique pour (*sptr).m.
L'opérateur . est appelé opérateur d'accès direct au membre,
l'opérateur -> est dit opérateur d'accès indirect au
membre. Par exemple :
Espaces de nommage des structures ( see page 658) Les noms des sélecteurs de structures appartiennent à l'espace de nommage
des sélecteurs d'unions et d'énumérations (cependant, en C++, enums dans une
structure appartient à un espace de nommage différent). La conséquence est
que les sélecteurs doivent avoir un nom unique dans une même portée.
Toutefois, ces noms ne doivent pas obligatoirement être différents des
identificateurs figurant dans les trois autres espaces de nommage : l'espace de
nommage des étiquettes, celui des membres et l'espace de nommage simple
(celui des variables, fonctions, typedef et énumérateurs).
Les noms de membres dans une structure ou une union donnée doivent être
uniques, mais ils... suite ( see page 658)
Déclarations incomplètes ( see page 658) Les déclarations incomplètes sont aussi connues sous le terme "déclarations
forward".
Un pointeur sur une structure A peut légalement apparaître dans la déclaration
d'une autre structure B avant que A ne soit déclarée :
Champs de bits ( see page 659) Les champs de bits correspondent à un nombre spécifié de bits ayant ou pas un
identificateur associé. Les champs de bits permettent de subdiviser des
structures (structures, unions, classes) en parties nommées dont la taille est
3
déterminée par l'utilisateur.
Déclaration de champs de bits
La largeur du champ de bit et l'identificateur facultatif sont déclarés de la manière
suivante :

3.1.4.4.12.1 Structures
Une structure est un type dérivé représentant généralement un ensemble, défini par le programmeur, de membres nommés (ou

655
Guide du langage C++ RAD Studio 3.1 Référence C++

composants). Les membres peuvent avoir n'importe quel type, fondamental ou dérivé (avec certaines restrictions que nous
verrons plus loin), dans un ordre quelconque. De plus, un membre de structure peut être de type champ de bits (inadmissible en
tout autre endroit). Le type structure permet de manipuler des structures complexes de données aussi aisément que des
variables simples. L'initialisation des structures est traitée à la section Tableaux, structures et unions de la rubrique d'aide
Initialisation ( see page 616).

En C++, un type structure est traité comme un type classe (avec certaines différences toutefois : l'accès par défaut est public,
ainsi que la classe de base par défaut). Ceci permet un contrôle strict de l'accès aux membres, à l'aide des spécificateurs
d'accès de C++ : public (par défaut), private et protected. Mis à part ces mécanismes d'accès et les exceptions signalées, les
explications qui suivent sur la syntaxe et l'utilisation des structures concernent les structures de C et de C++.

Les structures sont déclarées à l'aide du mot clé struct. Par exemple :
struct mastruct { ... }; // mastruct est le sélecteur de la structure
.
.
.
struct mastruct s, *ps, arrs[10];
/* s est de type struct mastruct; ps est de type pointeur sur struct mastruct;
arrs est un tableau de struct mastruct. */

3.1.4.4.12.2 Structures sans sélecteur et typedef


Si vous n'indiquez pas de sélecteur de structure, vous obtenez une structure sans sélecteur. Ce genre de structure est utilisable
pour attribuer à une liste d'identificateurs (délimitée par des virgules) le type structure donné (ou un type dérivé), mais il n'est pas
possible de déclarer ailleurs d'autres éléments de ce type :
struct { ... } s, *ps, arrs[10]; // structure sans sélecteur
Vous pouvez créer un typedef au moment de la déclaration d'une structure, avec ou sans sélecteur :
typedef struct mystruct { ... } MYSTRUCT;
MYSTRUCT s, *ps, arrs[10]; // identique à struct mystruct s, etc.
typedef struct { ... } YRSTRUCT; // pas de sélecteur
YRSTRUCT y, *yp, arry[20];
Il n'est généralement pas nécessaire d'utiliser à la fois un sélecteur et typedef : l'un ou l'autre suffit dans les déclarations de
structure.

Les membres d'unions et de structures sans sélecteur sont ignorés durant l'initialisation.

3.1.4.4.12.3 Déclarations des membres d'une structure


La liste-déclarateurs-membre entre accolades déclare le type et le nom des membres de la structure, en utilisant la syntaxe de
déclarateur indiquée à la rubrique Syntaxe des déclarations CodeGear C++

Un membre de structure peut avoir n'importe quel type, à deux exceptions près :

Le type du membre ne doit pas être le type struct en cours de déclaration :


struct mystruct { mystruct s } s1, s2; // illégal
Cependant, un membre peut être un pointeur sur la structure en cours de déclaration, comme dans l'exemple suivant :
3
struct mystruct { mystruct *ps } s1, s2; // OK
De même, une structure peut contenir des types structures préalablement définis lorsque vous déclarez une instance d'une
structure déjà déclarée.

Sauf en C++, un membre ne peut pas avoir le type "fonction renvoyant ...", mais le type "pointeur sur fonction renvoyant ..." est
possible. En C++, une struct peut avoir des fonctions membre.

Remarque: En C++, vous pouvez omettre le mot clé struct

656
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.4.12.4 Structures et fonctions


Une fonction peut renvoyer un type structure ou un pointeur sur un type structure.
mystruct func1(void); // func1() renvoie une structure
mystruct *func2(void); // func2() renvoie un pointeur sur structure
Il est possible de transmettre à une fonction une structure comme argument :
void func1(mystruct s); // directement
void func2(mystruct *sptr); // via un pointeur
void func3(mystruct &sref); // par référence (C++ seulement)

3.1.4.4.12.5 Accès aux membres d'une structure


Les membres des structures et des unions sont accessibles à l'aide des opérateurs suivants :

• . (point)
• -> (flèche droite)
Supposons que l'objet s soit une structure de type S et sptr un pointeur sur S. Si m est un identificateur de membre de type M
déclaré dans S, les expressions s.m et sptr->m sont de type M, et représentent toutes deux l'objet membre m de S.
L'expression sptr->m est un synonyme pratique pour (*sptr).m.
L'opérateur . est appelé opérateur d'accès direct au membre, l'opérateur -> est dit opérateur d'accès indirect au membre. Par
exemple :
struct mystruct
{
int i;
char str[21];
double d;
} s, *sptr = &s;
.
.
.
s.i = 3; // affectation au membre i de mystruct s
sptr -> d = 1.23; // affecte au membre d de mystruct s
L'expression s.m est une lvalue, à condition que s ne soit pas une lvalue et m ne soit pas de type tableau. L'expression sptr->m
est une lvalue à moins que m ne soit un type tableau

Si la structure B contient un champ dont le type est la structure A, les membres de A sont accessibles par deux applications des
sélecteurs de membre
struct A {
int j;
double x;
};
struct B {
int i;
struct A a;
double d;
} s, *sptr; 3
.
.
.
s.i = 3; // affectation au membre i de B
s.a.j = 2; // affectation au membre j de A
sptr->d = 1.23; // affectation au membre d de B
sptr->a.x = 3.14 // affectation au membre x de A
Chaque déclaration de structure introduit un type unique de structure, de sorte que dans

657
Guide du langage C++ RAD Studio 3.1 Référence C++

struct A {
int i,j;
double d;
} a, a1;
struct B {
int i,j;
double d;
} b;
les objets a et a1 sont tous les deux de type structure A, mais a et b sont des types structures différents. Les structures ne
peuvent faire l'objet d'affectation que si la source et la destination ont le même type :
a = a1; // OK: même type, donc affectation membre par membre
a = b; // ILLEGAL: types différents
a.i = b.i; a.j = b.j; a.d = b.d /* mais vous pouvez faire une affectation membre par membre */

3.1.4.4.12.6 Espaces de nommage des structures


Les noms des sélecteurs de structures appartiennent à l'espace de nommage des sélecteurs d'unions et d'énumérations
(cependant, en C++, enums dans une structure appartient à un espace de nommage différent). La conséquence est que les
sélecteurs doivent avoir un nom unique dans une même portée. Toutefois, ces noms ne doivent pas obligatoirement être
différents des identificateurs figurant dans les trois autres espaces de nommage : l'espace de nommage des étiquettes, celui des
membres et l'espace de nommage simple (celui des variables, fonctions, typedef et énumérateurs).

Les noms de membres dans une structure ou une union donnée doivent être uniques, mais ils peuvent être identiques à ceux
figurant dans d'autres structures ou unions. Par exemple :
goto s;
.
.
.
s: // étiquette
struct s { // OK: espaces de nommage différents pour les sélecteurs et les étiquettes
int s; // OK: espaces de nommage différents pour les sélecteurs, les étiquettes et les
membres
float s; // ILLEGAL: nom de membre répété
} s; // OK: espace de nommage différent pour les variables Dans C++, cela ne peut
// être fait que si s n'a pas de constructeur.
union s { // ILLEGAL: nom de sélecteur répété
int s; // OK: nouvel espace de nommage des membres
float f;
} f; // OK: espace de nommage des variables
struct t {
int s; // OK: espace de nommage membre différent
.
.
.
} s; // ILLEGAL: nom var répété

3.1.4.4.12.7 Déclarations incomplètes


Les déclarations incomplètes sont aussi connues sous le terme "déclarations forward".

Un pointeur sur une structure A peut légalement apparaître dans la déclaration d'une autre structure B avant que A ne soit
3 déclarée :
struct A; // incomplète
struct B { struct A *pa };
struct A { struct B *pb };
La première apparition de A est dite incomplète car, à ce stade, il n'existe pas de définition la concernant. Les déclarations
incomplètes sont permises dans ce cas, puisque la définition de B n'a pas besoin de connaître la taille de A.

658
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.4.12.8 Champs de bits


Les champs de bits correspondent à un nombre spécifié de bits ayant ou pas un identificateur associé. Les champs de bits
permettent de subdiviser des structures (structures, unions, classes) en parties nommées dont la taille est déterminée par
l'utilisateur.

Déclaration de champs de bits

La largeur du champ de bit et l'identificateur facultatif sont déclarés de la manière suivante :


spécificateur-type <id-champdebit> : largeur;
En C++, spécificateur-type est bool, char, unsigned char, short, unsigned short, long, unsigned long, int, unsigned int,
__int64 ou unsigned __int64. En ANSI C, spécificateur-type est int ou unsigned int.

l'expression largeur doit être présente et doit s'évaluer en une constante entière. En C++ , la largeur d'un champ de bits peut
être déclarée de taille quelconque. En ANSI C, la largeur d'un champ de bits ne peut excéder la taille du type déclarée. Un
champ de bits de longueur zéro passe à l'unité d'allocation suivante.

Si l'identificateur du champ de bits est omis, le nombre de bits spécifiés par largeur est alloué, mais le champ n'est pas
accessible. Cela vous permet de correspondre à des masques de bits, par exemple pour des registres matériels dont certains
bits sont inutilisés.

Il est possible de déclarer des champs de bits uniquement dans des structures, des unions et des classes. Ils sont accessibles
avec le même sélecteur de membre ( . et ->) que celui utilisé pour les autres membres.

Limitations dans l'utilisation des champs de bits

Quand vous utilisez des champs de bits, tenez compte des problèmes suivants :

• Le code n'est pas portable car l'organisation des bits à l'intérieur d'un octet et des celle des octets à l'intérieur d'un mot
dépend du processeur.
• Il n'est pas possible d'utiliser l'adresse d'un champ de bits ; l'expression &mastruct.x est illégale si x est un identificateur de
champ de bits car rien n'assure que mastruct.x se trouve à une adresse d'octet.
• Les champs de bits sont utilisés pour regrouper plusieurs variables dans une zone de données plus petite, mais ils obligent le
compilateur à générer du code supplémentaire pour manipuler ces variables. Cela entraîne un coût en terme de taille de code
et en temps d'exécution.
Compte tenu de ces inconvénients, l'utilisation des champs de bits est généralement à éviter sauf pour de la programmation de
bas niveau. Plutôt que d'employer des champs de bits, il est recommandé d'utiliser define. Par exemple :
#define Nothing 0x00
#define bitUn 0x01
#define bitDeux 0x02
#define bitTrois 0x04
#define bitQuatre 0x08
#define bitCinq 0x10
#define bitSix 0x20
3
#define bitSept 0x40
#define bitHuit 0x80
qui peut s'utiliser pour écrire du code comme le suivant :
if (flags & bitUn) {...} // si le bit Un est activé
flags |= bitDeux; // Active le bit Deux
flags &= ~bitTrois; // Désactive le bit Trois
Vous pouvez utiliser le même mécanisme pour des champs de bits d'une taille quelconque.

659
Guide du langage C++ RAD Studio 3.1 Référence C++

Complément des champs de bits

En C++ , Si la largueur est supérieure à celle du type du champ de bits, le compilateur insère un complément d'une taille égale à
celle de la taille demandée moins la taille du type du champ de bits. Ainsi, la déclaration :
struct mystruct
{
int i : 40;
int j : 8;
};
crée un stockage de a 32 bit pour 'i', un complément de 8 bits et un stockage de 8 bits pour 'j'. Pour optimiser l'accès, le
compilateur traite 'i' comme une variable int normale et pas comme un champ de bits

Disposition et alignement

Les champs de bits sont décomposés en groupes de champs de bits consécutifs du même type sans tenir compte du signe.
Chaque groupe de champs de bits est aligné en utilisant l'alignement du type des membres du groupe. Cet alignement est
déterminé par le type et par la valeur de l'alignement global (définit par l'option d'alignement d'octet –aN). Dans chaque groupe,
le compilateur groupe les champs de bits dans des zones aussi grande que la taille du type des champs de bits. Néanmoins, un
champ de bits ne peut chevaucher deux de ces zones. La taille de la structure totale est alignée en fonction de l'alignement en
cours.

Exemple de disposition, de complément et d'alignement de champs de bits

Dans la déclaration C++ suivante, ma_struct contient six champs de bits de trois types différents, int, long, et char :
struct ma_struct
{
int un : 8;
unsigned int deux : 16;
unsigned long trois : 8;
long quatre: 16;
long cinq : 16;
char six : 4;
};
Les champs de bits 'un' et 'deux' sont regroupés dans la même zone de 32 bits.

Ensuite, le compilateur ajoute un complément, si nécessaire, en fonction de l'alignement en cours, et le type de trois, car le type
change entre la déclaration des variables deux et trois. Par exemple, si l'alignement en cours se fait à l'octet (-a1), il n'y a pas
besoin de complément ; mais si l'alignement est de 4 octets (-a4), alors un complément de 8 bits est inséré.

Ensuite, les variables trois, quatre et cinq sont toutes de type long. Les variables trois et quatre sont regroupées dans une zone
de 32 bits, mais cinq ne peut être placé dans la même zone, car cela crée une zone de 40 bits ce qui dépasse les 32 bits alloués
au type long. Pour commencer une nouvelle zone pour cinq, le compilateur n'insère pas de complément si l'alignement en cours
se fait à l'octet, et il insère 8 bits de complément si l'alignement en cours est un dword (4 octets).

Avec la variable six, le type change à nouveau. Comme char est toujours aligné sur un octet, il n'y a pas besoin de complément.
Pour forcer l'alignement pour toute la structure, le compilateur complète la dernière zone avec 4 bits de complément si
l'alignement se fait à l'octet ou avec 12 bits si l'alignement dword est utilisé.

La taille totale de ma_struct est de 9 octets avec l'alignement à l'octet et de 12 octets avec l'alignement dword.
3
Pour obtenir de meilleurs résultats en utilisant des champs de bits, vous devez :

• Trier les champs de bits par type.


• Vérifier qu'ils sont regroupés dans des zones en les triant afin qu'aucun champ de bits ne chevauche une limite de zone.
• Vérifier que la structure est, dans la mesure, du possible remplie.
Il est aussi conseillé de forcer un alignement à l'octet pour cette structure en utilisant "#pragma option -a1". Si vous voulez savoir
la taille de votre structure, faites-la suivre d'un "#pragma sizeof(mastruct)", qui vous en donne la taille.

660
3.1 Référence C++ RAD Studio Guide du langage C++

Utilisation de champs d'un bit signé


Pour un type signé d'un seul bit, les valeurs possibles sont 0 ou –1. Pour un type non signé d'un seul bit, les valeurs possibles
sont 0 ou 1. Ainsi, si vous affectez "1" à un champ d'un bit signé, la valeur est évaluée en –1.
Quand vous stockez les valeurs true et false dans un champ d'un seul bit de type signé, vous ne pouvez pas tester l'égalité
avec true car les champs d'un bit signé ne peuvent contenir que les valeurs '0' et '-1', qui ne sont pas compatibles avec true
et false. Vous pouvez par contre tester si la valeur est non-nulle.
Pour les types non signés, et bien entendu pour le type bool, tester l'égalité avec true fonctionne normalement.
Par conséquent :
struct mystruct
{
int flag : 1;
} M;
int testing()
{
M.flag = true;
if(M.flag == true)
printf("a réussi");}
ne fonctionne pas, mais :
struct mystruct
{
int flag : 1;
} M;
int testing()
{
M.flag = true;
if(M.flag)
printf("a réussi");
}
fonctionne.

Remarques sur la compatibilité

Entre différentes versions du compilateur, il peut y avoir des modifications de l'alignement par défaut (par exemple dans un souci
de compatibilité avec d'autres compilateurs. Cela peut donc modifier l'alignement des champs de bits. Vous n'avez donc pas de
garanties sur la cohérence de l'alignement des champs de bits entre différentes versions du compilateur. Pour tester la
compatibilité ascendante des champs de bits dans votre code vous pouvez ajouter une instruction assert pour vérifier si les
structures ont la taille attendue.

Selon les spécification des langages C et C++, l'alignement et le stockage des champs de bits est défini par l'implémentation.
Donc, des compilateurs différents peuvent aligner et stocker différemment des champs de bits. Si vous voulez un contrôle
complet de la disposition de vos champs de bits, il est préférable d'écrire vos propres routines d'accès aux bits et de créer vos
propres champs de bits.

3.1.4.4.13 Opérateurs unaires


Cette section traite des opérateurs unaires.
3
Rubriques
Nom Description
Opérateurs unaires ( see page 662) Syntaxe
Opérateurs arithmétiques ( see page 662) Syntaxe
Opérateurs plus et moins ( see page 662) Unaire
Dans ces expressions unaires + -
Opérateurs de référencement/déréférencement ( see page 663) Syntaxe

661
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.4.13.1 Opérateurs unaires


Syntaxe
<opérateur-unaire> <expression-unaire>
OU
<opérateur-unaire> <type><expression-unaire>
Remarques

Les opérateurs unaires sont regroupés de droite à gauche.

Le langage C++ propose les opérateurs unaires suivants :

• ! Négation logique
• * Indirection
• ++ Incrémentation
• ~ Complément binaire
• -- Décrémentation
• - Moins unaire
• + Plus unaire

3.1.4.4.13.2 Opérateurs arithmétiques


Syntaxe
+ expression-transtypage
- expression-transtypage
expression-addition + expression-multiplication
expression-addition - expression-multiplication
expr-multiplication * expr-transtypage
expr-multiplication / expr-transtypage
expr-multiplication % expr-transtypage
expression-postfixée ++ (postincrémentation)
++ expression-unaire (préincrémentation)
expression-postfixée -- (postdécrémentation)
-- expression-unaire (prédécrémentation)
Remarques

Utilisez les opérateurs arithmétiques pour effectuer des calculs mathématiques.

Les expressions unaires de + et - affectent une valeur négative ou positive à l'expression-transtypage.

• (addition), - (soustraction), * (multiplication) et / (division) effectuent leur calcul arithmétique algébrique de base sur tous les
types de données, entiers et à virgule flottante.
% (opérateur modulo) renvoie le reste de la division entière et ne peut être utilisé avec des nombres à virgule flottante.
++ (incrémentation) ajoute un à la valeur de l'expression. La postincrémentation ajoute un à la valeur de l'expression après son
3 évaluation, tandis que la préincrémentation ajoute un avant son évaluation.
-- (décrémentation) soustrait un de la valeur de l'expression. La postdécrémentation soustrait un de la valeur de l'expression
après son évaluation, tandis que la prédécrémentation soustrait un avant son évaluation.

3.1.4.4.13.3 Opérateurs plus et moins


Unaire

Dans ces expressions unaires + -

662
3.1 Référence C++ RAD Studio Guide du langage C++

+ expression-transtypage
- expression-transtypage
L'opérande expression-transtypage doit être de type arithmétique.

Résultats

• expression-transtypage Valeur de l'opérande après toutes les conversions d'entiers requises.


• expression-transtypage Valeur négative de l'opérande après toutes les conversions d'entiers requises.
Binaire
Syntaxe
expression-addition + expression-multiplication
expression-addition - expression-multiplication
Types d'opérande autorisés pour op1 + op2 :

• 1. op1 et op2 sont tous deux de type arithmétique.


• 2. op1 est de type entier et op2 est de type pointeur sur objet.
• 3. op2 est de type entier et op1 est de type pointeur sur objet.
Dans le cas 1, les opérandes sont soumis aux conversions arithmétiques standard et le résultat est la somme arithmétique des
opérandes.
Dans les cas 2 et 3, les règles concernant les pointeurs arithmétiques sont applicables.
Types d'opérandes autorisés pour op1 - op2 :
• 1. op1 et op2 sont tous deux de type arithmétique.
• 2. op1 et op2 sont tous deux de type pointeur sur des objets compatibles.
• 3. op1 est de type pointeur sur objet et op2 de type entier.
Dans le cas 1, les opérandes sont sujets aux conversions arithmétiques standard et le résultat est la différence arithmétique des
opérandes.
Dans les cas 2 et 3, les règles concernant les pointeurs arithmétiques sont applicables.
Remarque: Le type qualifié <type> est considéré comme compatible avec les types qualifiés const type, volatile type et const
volatile type.

3.1.4.4.13.4 Opérateurs de référencement/déréférencement


Syntaxe
& expression-transtypage
* expression-transtypage
Remarques

Les opérateurs & et * peuvent être combinés pour référencer ou déréférencer des pointeurs transmis à des fonctions.

Opérateur de référencement ( & )

L'opérateur de référencement permet de transmettre l'adresse d'un pointeur à une fonction hors de main().
3
L'opérande expression-transtypage doit être soit :

• un désignateur de fonction
• une lvalue désignant un objet qui n'est pas un champ de bits et qui n'est pas déclaré au moyen du spécificateur de stockage
de classe register.
Si l'opérande est du type <type>, le résultat est du type pointeur sur <type>.
Certains identificateurs non lvalue, comme des noms de fonctions et des noms de tableaux, sont automatiquement convertis en

663
Guide du langage C++ RAD Studio 3.1 Référence C++

types "pointeur sur X" lorsqu'ils apparaissent dans certains contextes. L'opérateur & est utilisable avec ces objets, mais son
emploi est alors redondant et nous le déconseillons.
Dans l'exemple suivant :
T t1 = 1, t2 = 2;
T *ptr = &t1; // Pointeur initialisé
*ptr = t2; // Même effet que t1 = t2
T *ptr = &t1 est traité comme
T *ptr;
ptr = &t1;
de sorte que c'est ptr, et non pas *ptr, qui fait l'objet d'une affectation. Une fois que ptr a été initialisé avec l'adresse de &t1, il
peut être déréférencé pour donner la lvalue *ptr.

Opérateur d'indirection ( * )

Utilisez l'astérisque (*) dans une expression variable pour créer des pointeurs. Il faut utiliser l'opérateur d'indirection dans une
fonction externe pour obtenir la valeur d'un pointeur transmis par adresse.

Si l'opérande est du type pointeur de fonction, le résultat est un descripteur de fonction.

Si l'opérande est un pointeur d'objet, le résultat est une lvalue désignant cet objet.

Dans les situations suivantes, le résultat de l'indirection n'est pas défini :

• 1. L'expression-transtypage est un pointeur NULL.


• 2. L'expression-transtypage est l'adresse d'une variable automatique alors que l'exécution du bloc qui la définit est terminée.
Remarque: & peut également servir d'opérateur ET bit à bit.
Remarque: * peut également servir d'opérateur multiplicatif.

3.1.4.4.14 Unions
Cette section traite des unions.

Rubriques
Nom Description
Unions ( see page 665) Les types unions sont des types dérivés possédant un grand nombre de
caractéristiques syntaxiques et fonctionnelles identiques aux types structures. La
principale différence est que, dans une union, un seul membre à la fois peut être
"actif". La taille d'une union est celle de son membre le plus grand. La valeur d'un
seul de ses membres peut être stockée à tout moment. Dans le cas suivant :
Unions anonymes ( see page 665) Une union sans sélecteur qui n'est pas utilisée pour déclarer un objet nommé (ou
autre type) est appelée union anonyme. Elle adopte la forme suivante :
Déclarations d'union ( see page 666) La syntaxe générale des déclarations d'unions ressemble beaucoup à celle des
structures. Les différences sont les suivantes :

• Les unions peuvent contenir des champs de bits, mais un


seul peut être actif. Ces champs débutent tous au
commencement de l'union. (Rappelez-vous que des
problèmes se posent lors de l'écriture de code portable :
3 en effet, les champs de bits dépendent de la machine
utilisée.)
• Contrairement aux structures, les types unions en C++ ne
peuvent pas utiliser les spécificateurs d'accès aux
classes : public, private et protected. Tous les champs
d'une union sont public.
• Il n'est possible d'initialiser les unions que... suite ( see
page 666)

664
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.4.14.1 Unions
Les types unions sont des types dérivés possédant un grand nombre de caractéristiques syntaxiques et fonctionnelles
identiques aux types structures. La principale différence est que, dans une union, un seul membre à la fois peut être "actif". La
taille d'une union est celle de son membre le plus grand. La valeur d'un seul de ses membres peut être stockée à tout moment.
Dans le cas suivant :
union myunion { /* sélecteur d'union = myunion */
int i;
double d;
char ch;
} mu, *muptr=&mu;
l'identificateur mu, du type union myunion, est utilisable pour contenir un int, un double sur 8 octets ou un char à octet unique,
mais il ne peut contenir qu'une seule de ces valeurs à la fois.

Remarque: Les unions correspondent au type enregistrement avec variantes de Delphi.

sizeof(union myunion) et sizeof(mu) renvoient l'un et l'autre la valeur 8, mais 4 octets restent inutilisés (avec des caractères de
remplissage) lorsque mu contient un objet int, et 7 octets restent inutilisés lorsque mu contient un char. Vous accédez aux
membres de l'union par les opérateurs d'accès aux membres des structures (. et ->), avec un minimum de précautions toutefois :
mu.d = 4.016;
printf("mu.d = %f\n",mu.d); //OK: affiche mu.d = 4.016
printf("mu.i = %d\n",mu.i); //résultat bizarre
mu.ch = 'A';
printf("mu.ch = %c\n",mu.ch); //OK: affiche mu.ch = A
printf("mu.d = %f\n",mu.d); //résultat bizarre
muptr->i = 3;
printf("mu.i = %d\n",mu.i); //OK: affiche mu.i = 3
Le deuxième printf est légal puisque mu.i est de type entier. Cependant la configuration de mu.i correspond à des parties de
double ayant précédemment fait l'objet d'une affectation, et le résultat ne correspond à rien d'utile.

Après conversion correcte, un pointeur d'union pointe sur chacun de ses membres, et inversement.

3.1.4.4.14.2 Unions anonymes


Une union sans sélecteur qui n'est pas utilisée pour déclarer un objet nommé (ou autre type) est appelée union anonyme. Elle
adopte la forme suivante :
union { liste-membre };
Il est possible d'accéder directement à ses membres dans la portée de déclaration de l'union, sans utiliser la syntaxe x.y ni p->y.

Les unions anonymes peuvent être globales, imbriquées ou non-imbriquées. Le C ANSI n'autorise jamais les unions anonymes.
Le C++ ANSI autorise les trois types d'unions anonymes.

Unions anonymes C++

Une union anonyme ne peut avoir de fonctions membre ou de membres privés ou protégés. Au niveau du ficher, une union
anonyme doit être déclarée comme statique. Les unions anonymes locales doivent être automatiques ou statiques ; en d'autres
termes, une union anonyme ne peut avoir de liaison externes. Seul le C++ autorise les unions anonymes non imbriquées. 3
Unions anonymes imbriquées

La structure externe, classe ou union, d'une union anonyme imbriquée doit avoir une balise. Borland C et C++ autorise par
défaut les unions anonymes imbriquées. En C, une union anonyme imbriquée peut avoir, de manière facultative, une balise.

Exemple :
struct externe {

665
Guide du langage C++ RAD Studio 3.1 Référence C++

int x;
};
int main (void)
{
struct externe o;
}

3.1.4.4.14.3 Déclarations d'union


La syntaxe générale des déclarations d'unions ressemble beaucoup à celle des structures. Les différences sont les suivantes :

• Les unions peuvent contenir des champs de bits, mais un seul peut être actif. Ces champs débutent tous au commencement
de l'union. (Rappelez-vous que des problèmes se posent lors de l'écriture de code portable : en effet, les champs de bits
dépendent de la machine utilisée.)
• Contrairement aux structures, les types unions en C++ ne peuvent pas utiliser les spécificateurs d'accès aux classes : public,
private et protected. Tous les champs d'une union sont public.
• Il n'est possible d'initialiser les unions que par le biais de leur premier membre déclaré :
union local87 {
int i;
double d;
} a = { 20 };
Une union ne peut pas figurer dans une hiérarchie de classes. Elle ne peut pas non plus être dérivée d'une classe, ni être une
classe de base. En revanche, une union peut avoir un constructeur.

3.1.4.5 Eléments lexicaux


Cette section traite des éléments lexicaux.

Rubriques
Nom Description
Eléments lexicaux ( see page 666) Ces rubriques fournissent une définition formelle des éléments lexicaux de
Borland C++. Elles décrivent les différentes catégories des unités lexicales
appelées éléments (tokens) reconnues par le langage.
Les tokens d'un fichier source C++ sont issus d'une série de traitements
effectués sur vos programmes par le compilateur et son préprocesseur intégré.
Le préprocesseur analyse le texte du programme à la recherche de directives du
préprocesseur (pour plus d'informations, voir Directives du préprocesseur). Par
exemple, la directive #include <fic_inc> ajoute (ou inclut) le contenu du fichier
fic_inc dans le programme avant la phase de compilation. Le préprocesseur
développe aussi toutes les macros... suite ( see page 666)
Présentation des tokens ( see page 667) Cette section traite des tokens.
Présentation des caractères inertes ( see page 690) Cette section présente les caractères inertes.

3.1.4.5.1 Eléments lexicaux


Ces rubriques fournissent une définition formelle des éléments lexicaux de Borland C++. Elles décrivent les différentes
catégories des unités lexicales appelées éléments (tokens) reconnues par le langage.
3 Les tokens d'un fichier source C++ sont issus d'une série de traitements effectués sur vos programmes par le compilateur et son
préprocesseur intégré.

Le préprocesseur analyse le texte du programme à la recherche de directives du préprocesseur (pour plus d'informations, voir
Directives du préprocesseur). Par exemple, la directive #include <fic_inc> ajoute (ou inclut) le contenu du fichier fic_inc dans le
programme avant la phase de compilation. Le préprocesseur développe aussi toutes les macros trouvées dans le programme
ainsi que dans les fichiers inclus.

Un programme en C++, c'est d'abord une suite de caractères ASCII représentant le code source, générée dans un éditeur de

666
3.1 Référence C++ RAD Studio Guide du langage C++

texte approprié (par exemple, l'éditeur de l'EDI). L'unité de base d'un programme en C++ est un fichier source (habituellement
désigné en intégrant ".c" ou ".cpp" à son nom), et tous les fichiers d'en-tête et autres fichiers source inclus par la directive du
préprocesseur #include. Les fichiers source sont habituellement désignés par un nom en ".c" ou ".cpp", alors que les fichiers
d'en-tête sont habituellement désignés par un nom en ".h" ou ".hpp".

Lors de la compilation, en phase d'analyse des tokens, le code source est analysé, c'est-à-dire fragmenté en tokens et en
caractères inertes (whitespace)

Voir aussi
Caractère inerte ( see page 692)

Tokens ( see page 684)

3.1.4.5.2 Présentation des tokens


Cette section traite des tokens.

Rubriques
Nom Description
Présentation des constantes ( see page 667) Cette section traite des constantes.
Tokens ( see page 684) Les tokens sont des unités reconnues par un langage de programmation (tels les
mots d'une langue). Le compilateur reconnaît six classes de tokens.
La définition formelle d'un token est la suivante :

• mot-clé
• identificateur
• constante
• littéral-chaîne
• opérateur
• ponctuation (appelé aussi séparateur)
Lors de l'analyse du code source, le système extrait les
tokens en tentant de trouver le token le plus long possible
à partir de la séquence de caractères sélectionnée. Par
exemple, l'analyse permettra d'extraire comme
identificateur external au lieu d'extraire le mot-clé extern
suivi de l'identificateur al.
Pour de plus amples informations sur la fusion de tokens,
voir la rubrique... suite ( see page 684)
Présentation des identificateurs ( see page 684) Cette section traite des identificateurs.
Présentation des mots clés ( see page 686) Cette section traite des mots clés.
Présentation des séparateurs ( see page 687) Cette section traite des séparateurs.

3.1.4.5.2.1 Présentation des constantes


Cette section traite des constantes. 3
Rubriques
Nom Description
Présentation des constantes caractère ( see page 668) Cette section traite des constantes caractère.

667
Guide du langage C++ RAD Studio 3.1 Référence C++

Constantes ( see page 673) Les constantes sont des tokens représentant des valeurs fixes, numériques ou
caractères.
Le compilateur supporte quatre classes de constantes : entière, en virgule
flottante, d'énumération et caractère (y compris les chaînes).
La représentation interne des types numériques montrent comment ces types
sont représentés de manière interne.
Le type de données d'une constante est déduit par le compilateur à partir de la
valeur numérique et du format utilisés dans le code source. La définition formelle
d'une constante est présentée dans le tableau suivant
Constantes : Définitions formelles
Constante entière sans L ni U ( see page 675) Constantes décimales
Expressions constantes ( see page 676) Cette section traite des expressions constante.
Constantes et représentation interne ( see page 677) Cette section traite de la représentation interne des constantes.
Constantes en virgule flottante ( see page 678) Les constantes en virgule flottante sont formées des éléments suivants :

• Entier décimal
• Séparateur décimal
• Fraction décimale
• e ou E et un exposant entier signé (facultatif)
• Suffixe de type : f, F, l ou L (facultatif)
Vous pouvez omettre l'entier décimal ou la fraction décimale,
mais non les deux. Vous pouvez omettre le séparateur
décimal ou la lettre e (ou E) suivie de l'exposant entier
signé, mais non les deux. Ces règles permettent des
notations conventionnelles et scientifiques (exposants).
Les constantes en virgule flottante négatives sont
considérées comme des constantes positives avec
l'opérateur unaire moins (-) en préfixe.
Voici quelques exemples :... suite ( see page 678)
Constantes énumération ( see page 679) Cette section traite des constantes énumération.
Constantes entières ( see page 681) Les constantes entières peuvent être décimales (base 10), octales (base 8) ou
hexadécimales (base 16). En l'absence de suffixe de redéfinition, le type de
données d'une constante entière est issu de sa valeur, comme le montre la
rubrique Constantes entières sans L ni U. Remarquez bien que les règles
diffèrent selon qu'il s'agit de constantes décimales ou non décimales.
Décimal
Les constantes décimales de 0 to 4 294 967 295 sont autorisées. Les constantes
dépassant cette limite sont tronquées. Les constantes décimales ne doivent pas
comporter de zéro initial. Une constante entière qui commence par un zéro est
interprétée comme constante octale. Par... suite ( see page 681)
Représentation interne des types numériques ( see page 682) Cette section traite de la représentation interne des types numériques.
Constantes chaîne ( see page 683) Cette section traite des constantes chaîne.

3.1.4.5.2.1.1 Présentation des constantes caractère


Cette section traite des constantes caractère.

668
3.1 Référence C++ RAD Studio Guide du langage C++

Rubriques
Nom Description
Constantes caractère ( see page 669) Une constante caractère contient un ou plusieurs caractères délimités par des
apostrophes, comme 'A', '+' ou '\n'. En langage C, les constantes
mono-caractères ont le type int. En langage C++, une constante caractère est du
type char. En C comme en C++, les constantes multi-caractères ont le type int.
Pour de plus amples informations sur les constantes caractère, voir les rubriques
suivantes.

• Types de données char ( see page 672)


• Séquences d'échappement ( see page 670)
• Constantes à caractères larges et à caractères multiples
( see page 672)
Remarque: Pour comparer la taille des types de
caractères, compilez le programme suivant en C puis en
C++.

Séquences d'échappement ( see page 670) La barre oblique inversée (\) sert à introduire une séquence d'échappement
permettant la représentation visuelle de certains caractères non graphiques. Par
exemple, la constante \n désigne un caractère de saut de ligne.
La barre oblique inversée est utilisée avec un nombre octal ou hexadécimal afin
de représenter le symbole ASCII ou le code de contrôle correspondant au
nombre. Par exemple, '\03' correspond à Ctrl-C, et '\x3F' au point d'interrogation.
Dans une séquence d'échappement, vous pouvez utiliser n'importe quelle chaîne
de trois valeurs octales au maximum, ou autant de chiffres hexadécimaux que
vous le voulez, à condition que la valeur soit... suite ( see page 670)
Les trois types char ( see page 672) Une constante monocaractère, comme 'A', '\t' et '\007', est représentée comme
un int. Dans ce cas, l'octet de poids faible est signé dans le bit de poids fort ;
c'est-à-dire, si la valeur est supérieure à 127 (en base 10), le bit de poids fort est
mis à -1 (=0xFF). Vous pouvez annuler cet effet en déclarant que le type char
par défaut est unsigned.
Les trois types de caractères, char, signed char et unsigned char, nécessitent
une mémoire de stockage de 8 bits (un octet). Par défaut, le compilateur traite
les déclarations de caractères comme étant... suite ( see page 672)
Constantes à caractères larges et à caractères multiples ( see page 672) Les types de caractères larges permettent de représenter un caractère ne
rentrant pas dans l'espace de stockage alloué pour un type char. Un caractère
large est stocké sur deux octets. Une constante caractère précédée
immédiatement par un L est une constante de caractère large ayant le type de
données wchar_t (défini dans stddef.h). Par exemple :

3.1.4.5.2.1.1.1 Constantes caractère


Une constante caractère contient un ou plusieurs caractères délimités par des apostrophes, comme 'A', '+' ou '\n'. En langage C,
les constantes mono-caractères ont le type int. En langage C++, une constante caractère est du type char. En C comme en
C++, les constantes multi-caractères ont le type int.

Pour de plus amples informations sur les constantes caractère, voir les rubriques suivantes.

• Types de données char ( see page 672)


• Séquences d'échappement ( see page 670)
• Constantes à caractères larges et à caractères multiples ( see page 672)
3
Remarque: Pour comparer la taille des types de caractères, compilez le programme suivant en C puis en C++.

#include <stdio.h>
#define CH 'x' /* UNE CONSTANTE CARACTERE */
void main(void) {
char ch = 'x'; /* UNE VARIABLE char */
printf("\nSizeof int = %d", sizeof(int) );
printf("\nSizeof char = %d", sizeof(char) );

669
Guide du langage C++ RAD Studio 3.1 Référence C++

printf("\nSizeof ch = %d", sizeof(ch) );


printf("\nSizeof CH = %d", sizeof(CH) );
printf("\nSizeof wchar_t = %d", sizeof(wchar_t) );
}
Remarque: Les tailles sont exprimées en octets.

Tailles des types de caractères

Sortie après compilation en C Sortie après compilation en C++


Sizeof int = 4 Sizeof int = 4
Sizeof char = 1 Sizeof char = 1
Sizeof ch = 1 Sizeof ch = 1
Sizeof CH = 4 Sizeof CH = 1
Sizeof wchar_t = 2 Sizeof wchar_t = 2

Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)

3.1.4.5.2.1.1.2 Séquences d'échappement


La barre oblique inversée (\) sert à introduire une séquence d'échappement permettant la représentation visuelle de certains
caractères non graphiques. Par exemple, la constante \n désigne un caractère de saut de ligne.

La barre oblique inversée est utilisée avec un nombre octal ou hexadécimal afin de représenter le symbole ASCII ou le code de
contrôle correspondant au nombre. Par exemple, '\03' correspond à Ctrl-C, et '\x3F' au point d'interrogation. Dans une séquence
3 d'échappement, vous pouvez utiliser n'importe quelle chaîne de trois valeurs octales au maximum, ou autant de chiffres
hexadécimaux que vous le voulez, à condition que la valeur soit comprise dans l'intervalle autorisé pour le type de données char
(de 0 à 0xff). Les grands nombres entraînent une erreur de compilation, signalée par le message "Constante numérique trop
grande". Par exemple, le nombre octal \777 est supérieur à la valeur maximale permise qui est \377 ; une erreur est donc
générée. Le premier caractère non octal ou non hexadécimal rencontré dans une séquence d'échappement octale ou
hexadécimale marque la fin de celle-ci.

Par exemple,
printf("\x0072.1Un système d'exploitation");

670
3.1 Référence C++ RAD Studio Guide du langage C++

L'interprétation attendue serait \x007 et "2.1Un système d'exploitation". Cependant, le compilateur compile cette écriture comme
le nombre hexadécimal \x0072 et la chaîne littérale ".1Un système d'exploitation".

Pour éviter ces problèmes, écrivez votre code sous cette nouvelle forme :
printf("\x007" "2.1Un système d'exploitation");
D'autres ambiguïtés peuvent surgir si une séquence d'échappement octale est suivie d'un chiffre non octal. Par exemple, comme
les chiffres 8 et 9 ne sont pas admis en base 8, la constante \258 sera interprétée comme une constante de deux caractères,
formée de \25 et de 8.

Le tableau ci-après indique les séquences d'échappement possibles.

Séquences d'échappement

Remarque: Vous devez utiliser \\ pour représenter la barre oblique inversée ASCII servant, par exemple, aux chemins d'accès
du système d'exploitation.

Séquence Valeur Car Effet

\a 0x07 BEL Signal sonore


\b 0x08 BS Retour arrière
\f 0x0C FF Saut de page
\n 0x0A LF Saut de ligne
\r 0x0D CR Retour chariot
\t 0x09 HT Tabulation horizontale
\v 0x0B VT Tabulation verticale
\\ 0x5c \ Barre oblique inversée
\' 0x27 ' Apostrophe
\" 0x22 " Guillemet
\? 0x3F ? Point d'interrogation
\O quelconque O=une chaîne en octal sur trois chiffres
\xH quelconque H=une chaîne de chiffres hexadécimaux
\XH quelconque H=une chaîne de chiffres hexadécimaux

Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)


3
Constantes caractère ( see page 669)

Les trois types char ( see page 672)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

671
Guide du langage C++ RAD Studio 3.1 Référence C++

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)

3.1.4.5.2.1.1.3 Les trois types char


Une constante monocaractère, comme 'A', '\t' et '\007', est représentée comme un int. Dans ce cas, l'octet de poids faible est
signé dans le bit de poids fort ; c'est-à-dire, si la valeur est supérieure à 127 (en base 10), le bit de poids fort est mis à -1
(=0xFF). Vous pouvez annuler cet effet en déclarant que le type char par défaut est unsigned.

Les trois types de caractères, char, signed char et unsigned char, nécessitent une mémoire de stockage de 8 bits (un octet).
Par défaut, le compilateur traite les déclarations de caractères comme étant signed. Utilisez l'option de compilation –K pour qu'il
traite les déclarations de caractères comme étant unsigned. Le comportement des programmes en C n'est pas affecté par cette
distinction entre les trois types de caractères.

Dans un programme en C++, une fonction peut être surchargée par des arguments du type char, signed char ou unsigned
char. Par exemple, les prototypes de fonction suivants sont valides et distincts :
void func(char ch);
void func(signed char ch);
void func(unsigned char ch);
Si un seul de ces prototypes existe, il acceptera n'importe lequel des trois types de caractères. Par exemple, ce qui suit est
accepté :
void func(unsigned char ch);
void main(void)
{
signed char ch = 'x';
func(ch);
}
Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)

Constantes caractère ( see page 669)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)


3
Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)

3.1.4.5.2.1.1.4 Constantes à caractères larges et à caractères multiples


Les types de caractères larges permettent de représenter un caractère ne rentrant pas dans l'espace de stockage alloué pour un
type char. Un caractère large est stocké sur deux octets. Une constante caractère précédée immédiatement par un L est une

672
3.1 Référence C++ RAD Studio Guide du langage C++

constante de caractère large ayant le type de données wchar_t (défini dans stddef.h). Par exemple :
wchar_t ch = L'A';
Lorsque wchar_t est utilisé dans un programme C, c'est un type défini dans le fichier en-tête stddef.h. Dans les programmes
C++, wchar_t est un mot clé pouvant représenter des codes distincts pour tout élément dans le plus grand jeu de caractères
étendu dans toutes les locales prises en charge. En CodeGear C++, wchar_t a la même taille, la même signature (signé ou
non) et le même besoin d'alignement qu'un type unsigned short.

Une chaîne précédée immédiatement par un L est une chaîne de caractère large. La mémoire allouée pour une chaîne est de
deux octets par caractère. Par exemple :
wchar_t *str = L"ABCD";
Constantes à caractères multiples

Le compilateur admet aussi des constantes à plusieurs caractères. Les constantes à caractères multiples peuvent comporter
jusqu'à quatre caractères. Par exemple, la constante '\006\007\008\009' n'est correcte que pour un programme CodeGear C++.
Les constantes à caractères multiples sont toujours des valeurs int 32 bits. Ces constantes ne sont pas portables dans les
autres compilateurs C++.

Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)

Constantes caractère ( see page 669)

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)

3.1.4.5.2.1.2 Constantes
Les constantes sont des tokens représentant des valeurs fixes, numériques ou caractères.

Le compilateur supporte quatre classes de constantes : entière, en virgule flottante, d'énumération et caractère (y compris les
chaînes).

La représentation interne des types numériques montrent comment ces types sont représentés de manière interne.
3
Le type de données d'une constante est déduit par le compilateur à partir de la valeur numérique et du format utilisés dans le
code source. La définition formelle d'une constante est présentée dans le tableau suivant

Constantes : Définitions formelles

673
Guide du langage C++ RAD Studio 3.1 Référence C++

constante : chiffre-non-zéro : un parmi


constante-flottante 123456789
constante-entière
constante-énumération
constante-caractère
constante-flottante : chiffre-octal : un parmi
constante-fractionnaire <exposant> <suffixe-flottant> 01234567
séquence-chiffres exposant <suffixe-flottant>
constante-fractionnaire : chiffre-hexadécimal : un parmi
<séquence-chiffres> . séquence-chiffres 0123456789
séquence-chiffres . a b c d e f ABCDEF
exposant : suffixe-entier :
e <signe> séquence-chiffres suffixe-nonsigné <suffixe long>
E <signe> séquence-chiffres suffixe long <suffixe-nonsigné>
signe : un parmi suffixe-nonsigné : un parmi
• - uU

séquence-chiffres : suffixe-long : un parmi


chiffre lL
séquence-chiffres chiffre
suffixe-flottant : un parmi constante-énumération :
flFL identificateur
constante-entière : constante-caractère
constante-décimale <suffixe-entier> séquence-car-c
constante-octale <suffixe-entier>
constante-hexadécimale <suffixe-entier>
constante-décimale : séquence-car-c :
chiffre-non-zéro car-c
constante-décimale chiffre séquence-car-c car-c
constante-octale : car-c :
0 Tout caractère de l'ensemble de caractères source
constante-octale chiffre-octal sauf l'apostrophe ('), la barre oblique inversée (\), ou
la séquence-échappement de saut de ligne.
constante hexadécimale : séquence-échappement : un parmi
0 x chiffre-hexadécimal \" \' \? \\
0 X chiffre-hexadécimal t \a \b \f \n
constante-hexadécimale chiffre-hexadécimal \o \oo \ooo \r
\t \v \Xh... \xh...
3
Voir aussi
Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)

Constantes caractère ( see page 669)

674
3.1 Référence C++ RAD Studio Guide du langage C++

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)

__int8 ( see page 532)

3.1.4.5.2.1.3 Constante entière sans L ni U


Constantes décimales

0 à 32,767 int
32,768 à 2,147,483,647 long
2 147 483 648 à 4 294 967 295 unsigned long
> 4294967295 tronqué

Constantes octales

00 à 077777 int
010000 à 0177777 unsigned int
02000000 à 017777777777 long
020000000000 à 037777777777 unsigned long
> 037777777777 tronqué

Constantes hexadécimales

0x0000 à 0x7FFF int


0x8000 à 0xFFFF unsigned int
0x10000 à 0x7FFFFFFF long
0x80000000 à 0xFFFFFFFF unsigned long
>0xFFFFFFFF tronqué

Voir aussi
Constantes ( see page 673) 3
Constantes entières ( see page 681)

Constantes en virgule flottante ( see page 678)

Constantes caractère ( see page 669)

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

675
Guide du langage C++ RAD Studio 3.1 Référence C++

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)

__int8 ( see page 532)

3.1.4.5.2.1.4 Expressions constantes


Cette section traite des expressions constante.

Rubriques
Nom Description
Expressions constantes ( see page 676) Une expression constante est une expression qui a toujours pour résultat une
constante (ce résultat est déterminé au moment de la compilation et est
obligatoirement compris dans l'intervalle des valeurs représentables par le type
de l'expression). Ces expressions sont évaluées au même titre que des
expressions régulières. Vous pouvez utiliser une expression constante chaque
fois qu'une constante est légale. La syntaxe est la suivante :

3.1.4.5.2.1.4.1 Expressions constantes


Une expression constante est une expression qui a toujours pour résultat une constante (ce résultat est déterminé au moment
de la compilation et est obligatoirement compris dans l'intervalle des valeurs représentables par le type de l'expression). Ces
expressions sont évaluées au même titre que des expressions régulières. Vous pouvez utiliser une expression constante
chaque fois qu'une constante est légale. La syntaxe est la suivante :
expression-constante:
expression-conditionnelle
Les expressions constantes ne peuvent pas contenir les opérateurs mentionnés ci-dessous à moins que ces derniers figurent
dans l'opérande d'un opérateur sizeof :

• Affectation
• Virgule
• Décrémentation
• Appel de fonction
• Incrément
Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)


3 Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)

Constantes caractère ( see page 669)

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

676
3.1 Référence C++ RAD Studio Guide du langage C++

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

3.1.4.5.2.1.5 Constantes et représentation interne


Cette section traite de la représentation interne des constantes.

Rubriques
Nom Description
Constantes et représentation interne ( see page 677) La norme ANSI du langage C reconnaît que la taille et l'intervalle des valeurs
numériques des types de base (ainsi que leurs différentes permutations) sont
spécifiques à l'implémentation et découlent habituellement de l'architecture de
l'ordinateur hôte. Pour CodeGear C++, la plate-forme cible appartient à la famille
des IBM PC et compatibles, de sorte que l'architecture des microprocesseurs
Intel 80x86 et des microprocesseurs de la famille Pentium détermine le choix des
représentations internes des types de données.
Les tableaux suivants récapitulent la taille et les intervalles de valeurs
correspondant aux types de données. La représentation interne des types
numériques montrent comment... suite ( see page 677)

3.1.4.5.2.1.5.1 Constantes et représentation interne


La norme ANSI du langage C reconnaît que la taille et l'intervalle des valeurs numériques des types de base (ainsi que leurs
différentes permutations) sont spécifiques à l'implémentation et découlent habituellement de l'architecture de l'ordinateur hôte.
Pour CodeGear C++, la plate-forme cible appartient à la famille des IBM PC et compatibles, de sorte que l'architecture des
microprocesseurs Intel 80x86 et des microprocesseurs de la famille Pentium détermine le choix des représentations internes des
types de données.

Les tableaux suivants récapitulent la taille et les intervalles de valeurs correspondant aux types de données. La représentation
interne des types numériques montrent comment ces types sont représentés de manière interne.

Types de données 32 bits, tailles et intervalles de valeurs

Type Taille Intervalle de valeurs Applications exemple


(bits)

unsigned char 8 0 <= X <= 255 Petits nombres, jeu de caractères


complet du PC
char 8 -128 <= X <= 127 Très petits nombres, caractères ASCII
short int 16 -32,768 <= X <= 32,767 Décomptes, petits nombres, boucles de
contrôle
unsigned int 32 0 <= X <= 4,294,967,295 Grands nombres et boucles de contrôle
int 32 -2 147 483 648 <= X <= Décomptes, petits nombres, boucles de
2 147 483 647 contrôle
3
unsigned long 32 0 <= X <= 4,294,967,295 Distances astronomiques
enum 32 -2 147 483 648 <= X <= Ensembles ordonnés de valeurs
2 147 483 647
long 32 -2 147 483 648 <= X <= Grands nombres, populations
2 147 483 647
float 32 1,18 ( 10^-38 < |X| < 3,40 ( 10^38 Scientifique (précision sur 7 chiffres)

677
Guide du langage C++ RAD Studio 3.1 Référence C++

double 64 2,23 ( 10^-308 < |X| < 1,79 ( 10^308 Scientifique (précision sur 15 chiffres)
long double 80 3,37 ( 10^-4932 < |X| < 1,18 ( Financière (précision sur 18 chiffres)
10^4932

Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)

Constantes caractère ( see page 669)

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)

Types entiers étendus __int8 ( see page 532)

Les trois types char ( see page 672)

Représentation interne des types numériques ( see page 682)

3.1.4.5.2.1.6 Constantes en virgule flottante


Les constantes en virgule flottante sont formées des éléments suivants :

• Entier décimal
• Séparateur décimal
• Fraction décimale
• e ou E et un exposant entier signé (facultatif)
• Suffixe de type : f, F, l ou L (facultatif)
Vous pouvez omettre l'entier décimal ou la fraction décimale, mais non les deux. Vous pouvez omettre le séparateur décimal ou
la lettre e (ou E) suivie de l'exposant entier signé, mais non les deux. Ces règles permettent des notations conventionnelles et
scientifiques (exposants).
Les constantes en virgule flottante négatives sont considérées comme des constantes positives avec l'opérateur unaire moins (-)
en préfixe.
3
Voici quelques exemples :

Constante Valeur
23.45e6 23.45 ( 10^6
.0 0
0. 0.0

678
3.1 Référence C++ RAD Studio Guide du langage C++

1. 1.0
-1.23 -1.23
2e-5 2.0 ( 10^-5
3E+10 3.0 ( 10^10
.09E34 0.09 ( 10^34

En l'absence de suffixe, les constantes en virgule flottante sont du type double.. Cependant, vous pouvez attribuer à une
constante en virgule flottante le type float en lui ajoutant le suffixe f ou F. De même, le suffixe l ou L attribue à la constante le
type de données long double. Le tableau suivant montre les intervalles disponibles pour les types float, double et long double.

Tailles et intervalles des constantes en virgule flottante

Type Taille Intervalle de valeurs


(bits)
float 32 3,4 ( 10^-38 à 3,4 ( 10^38
double 64 1,7 ( 10^-308 à 1,7 ( 10^308
long double 80 3,4 ( 10^-4932 à 1,1 ( 10^4932

Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes caractère ( see page 669)

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)

3.1.4.5.2.1.7 Constantes énumération


Cette section traite des constantes énumération.
3

679
Guide du langage C++ RAD Studio 3.1 Référence C++

Rubriques
Nom Description
Constantes énumération ( see page 680) Les constantes d'énumération sont des identificateurs définis dans des
déclarations de type enum. Les identificateurs sont généralement choisis comme
mnémoniques pour faciliter la lisibilité des textes. Les constantes d'énumération
sont de type entier. Elles peuvent apparaître dans toutes les expressions qui
admettent des constantes entières. Les identificateurs doivent être uniques dans
la portée de la déclaration enum. Les initialiseurs négatifs sont autorisés. Pour
de plus amples informations sur les déclarations enum, voir Enumérations et
enum (mot clé).
La valeur acquise par ces constantes d'énumération dépend du format de la
déclaration d'énumération et de la présence d'initialiseurs facultatifs.... suite (
see page 680)

3.1.4.5.2.1.7.1 Constantes énumération


Les constantes d'énumération sont des identificateurs définis dans des déclarations de type enum. Les identificateurs sont
généralement choisis comme mnémoniques pour faciliter la lisibilité des textes. Les constantes d'énumération sont de type
entier. Elles peuvent apparaître dans toutes les expressions qui admettent des constantes entières. Les identificateurs doivent
être uniques dans la portée de la déclaration enum. Les initialiseurs négatifs sont autorisés. Pour de plus amples informations
sur les déclarations enum, voir Enumérations et enum (mot clé).

La valeur acquise par ces constantes d'énumération dépend du format de la déclaration d'énumération et de la présence
d'initialiseurs facultatifs. Dans cet exemple,
enum équipe { géants, petits, roublards };
géants, petits et roublards sont des constantes d'énumération de type équipe, qui peuvent être affectées à n'importe quelle
variable de type équipe ou tout autre variable de type entier. Les valeurs acquises par les constantes d'énumération sont
géants = 0, petits = 1, roublards = 2
en l'absence d'initialisation explicite. Dans l'exemple suivant :
enum équipe { géants, petits=3, roublards = géants + 1 };
les constantes sont établies de la façon suivante :
géants = 0, petits = 3, roublards = 1
Il n'est pas nécessaire que les valeurs des constantes soient uniques :
enum équipe { géants, petits = 1, roublards = petits - 1 };
Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)

Constantes caractère ( see page 669)

3 Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

680
3.1 Référence C++ RAD Studio Guide du langage C++

Expressions constantes ( see page 676)

3.1.4.5.2.1.8 Constantes entières


Les constantes entières peuvent être décimales (base 10), octales (base 8) ou hexadécimales (base 16). En l'absence de suffixe
de redéfinition, le type de données d'une constante entière est issu de sa valeur, comme le montre la rubrique Constantes
entières sans L ni U. Remarquez bien que les règles diffèrent selon qu'il s'agit de constantes décimales ou non décimales.

Décimal

Les constantes décimales de 0 to 4 294 967 295 sont autorisées. Les constantes dépassant cette limite sont tronquées. Les
constantes décimales ne doivent pas comporter de zéro initial. Une constante entière qui commence par un zéro est interprétée
comme constante octale. Par conséquent,
int i = 10; /*décimal 10 */
int i = 010; /*décimal 8 */
int i = 0; /*décimal 0 = octal 0 */
Octal

Toutes les constantes qui commencent par un zéro sont considérées comme étant octales. Si une constante octale contient les
chiffres non autorisés 8 et 9, une erreur est signalée. Les constantes octales dépassant 037777777777 sont tronquées.

Hexadécimal

Toutes les constantes commençant par 0x (ou 0X) sont considérées comme étant hexadécimales. Les constantes
hexadécimales dépassant 0xFFFFFFFF sont tronquées.

Suffixes long et unsigned

Le suffixe L (ou l) attaché à n'importe quelle constante provoque sa représentation en type long. De même, le suffixe U (ou u)
qualifie la constante en unsigned. La constante sera unsigned long si la valeur du nombre lui-même est supérieure à 65 535,
quelle que soit la base utilisée. Vous pouvez associer les deux suffixes L et U à une même constante, dans l'ordre et la
distinction minuscules/majuscules que vous souhaitez : ul, lu, UL, etc.

Le type de données d'une constante en l'absence de suffixe (U, u, L ou l) correspond au premier des types suivants qui coïncide
avec sa valeur :

Décimal int, long int, unsigned long int


Octal int, unsigned int, long int, unsigned long int
Hexadécimal int, unsigned int, long int, unsigned long int

Si la constante est suivie du suffixe U ou u, son type de données sera le premier des types unsigned int, unsigned long int qui
admettra sa valeur.

Si la constante est suivie du suffixe L ou l, son type de données sera le premier des types long int, unsigned long int qui
admettra sa valeur.

Si la constante est suivie des deux suffixes u et l (ul, lu, Ul, lU, uL, Lu, LU ou UL), son type de données sera unsigned long int.

La table des constantes entières sans L ni U illustre la représentation des constantes entières dans les trois bases. Le type de 3
données indiqué suppose qu'aucun suffixe L ou U n'a été utilisé.

Voir aussi
Constantes ( see page 673)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)

681
Guide du langage C++ RAD Studio 3.1 Référence C++

Constantes caractère ( see page 669)

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)

Types entiers étendus __int8 ( see page 532)

3.1.4.5.2.1.9 Représentation interne des types numériques


Cette section traite de la représentation interne des types numériques.

Rubriques
Nom Description
Représentation interne des types numériques ( see page 682) Entiers 32 bits
Types virgule flottante, toujours

3.1.4.5.2.1.9.1 Représentation interne des types numériques


Entiers 32 bits

Types virgule flottante, toujours

s = Bit de signe ( 0 = positif, 1 = négatif) Domaine de l'exposant (valeurs normalisées) :


i = Position du point binaire implicite float : 127 (7FH)
1 = Bit entier de signification : double : 1 023 (3FFH)
Stocké dans long double, implicite dans float, double long double : 16 383 (3FFFH)

Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)


3
Constantes caractère ( see page 669)

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes chaîne ( see page 683)

682
3.1 Référence C++ RAD Studio Guide du langage C++

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)

Expressions constantes ( see page 676)

3.1.4.5.2.1.10 Constantes chaîne


Cette section traite des constantes chaîne.

Rubriques
Nom Description
Constantes chaîne ( see page 683) Les constantes chaîne, également appelées littéraux chaîne, constituent une
catégorie spéciale de constantes utilisée pour traiter des séquences fixes de
caractères. Un littéral chaîne est du type de données tableau-de-const char et
appartient à la classe de stockage static, écrite sous la forme d'une séquence de
plusieurs caractères délimitée par des guillemets :

3.1.4.5.2.1.10.1 Constantes chaîne


Les constantes chaîne, également appelées littéraux chaîne, constituent une catégorie spéciale de constantes utilisée pour
traiter des séquences fixes de caractères. Un littéral chaîne est du type de données tableau-de-const char et appartient à la
classe de stockage static, écrite sous la forme d'une séquence de plusieurs caractères délimitée par des guillemets :
"Ceci est littéralement une chaîne !"
La chaîne NULL (vide) s'écrit "".

Les caractères à l'intérieur des guillemets peuvent inclure des séquences d'échappement. Par exemple, ce code :
"\t\t\"Nom\"\\\tAdresse\n\n"
s'imprime comme suit :
"Nom"\ Adresse
"Nom" est précédé de deux tabulations ; Adresse d'une seule. La ligne est suivie de deux sauts de ligne. La séquence \" fournit
les guillemets intérieurs.

Si vous compilez avec l'option -A pour la compatibilité avec la norme ANSI, la séquence caractère d'échappement "\\" est
convertie en "\" par le compilateur.

Une chaîne littérale est stockée en interne sous la forme de la séquence de caractères indiquée plus un caractère NULL final
('\0'). Une chaîne NULL est stockée sous forme d'un simple caractère '\0'.

Les chaînes adjacentes séparées uniquement par des espaces sont concaténées durant la phase d'analyse. Dans l'exemple
suivant :
#include <stdio.h>
int main() {
char *p;
p = "Ceci est un exemple de la façon dont le compilateur " " effectue\nautomatiquement
pour vous la concaténation" " sur de très longues chaînes, \nce qui donne des programmes" "
plus agréables à lire.";
printf(p); 3
return(0);
}
Le programme produit l'affichage suivant :
Ceci est un exemple de la façon dont le compilateur effectue
automatiquement pour vous la concaténation sur de très longues chaînes,
ce qui donne des programmes plus agréables à lire.
La barre oblique inversée (\) peut aussi servir de caractère de prolongement afin d'étendre une chaîne littérale sur plusieurs

683
Guide du langage C++ RAD Studio 3.1 Référence C++

lignes :
puts("Ceci est en réalité \
une chaîne monoligne");
Voir aussi
Constantes ( see page 673)

Constantes entières ( see page 681)

Constante entière sans L ni U ( see page 675)

Constantes en virgule flottante ( see page 678)

Constantes caractère ( see page 669)

Les trois types char ( see page 672)

Séquences d'échappement ( see page 670)

Constantes à caractères larges et à caractères multiples ( see page 672)

Constantes énumération ( see page 680)

Constantes et représentation interne ( see page 677)

Représentation interne des types numériques ( see page 682)

Expressions constantes ( see page 676)

3.1.4.5.2.2 Tokens
Les tokens sont des unités reconnues par un langage de programmation (tels les mots d'une langue). Le compilateur reconnaît
six classes de tokens.

La définition formelle d'un token est la suivante :

• mot-clé
• identificateur
• constante
• littéral-chaîne
• opérateur
• ponctuation (appelé aussi séparateur)
Lors de l'analyse du code source, le système extrait les tokens en tentant de trouver le token le plus long possible à partir de la
séquence de caractères sélectionnée. Par exemple, l'analyse permettra d'extraire comme identificateur external au lieu
d'extraire le mot-clé extern suivi de l'identificateur al.
Pour de plus amples informations sur la fusion de tokens, voir la rubrique Fusion de tokens avec ##.
Voir aussi
Eléments lexicaux ( see page 666)
3
Caractère inerte ( see page 692)

3.1.4.5.2.3 Présentation des identificateurs


Cette section traite des identificateurs.

684
3.1 Référence C++ RAD Studio Guide du langage C++

Rubriques
Nom Description
Identificateurs ( see page 685) Voici la définition formelle d'un identificateur :
identificateur :

• nonchiffre
• nonchiffre identificateur
• chiffre identificateur
• nonchiffre : un parmi
• abcdefghijklmnopqrstuvwxyz_
• ABCDEFGHIJKLMNOPQRSTUVWXYZ
• chiffre : un parmi
• 0123456789
Restrictions de choix et de longueur des noms
Les identificateurs sont des noms arbitraires de n'importe
quelle longueur donnés... suite ( see page 685)

3.1.4.5.2.3.1 Identificateurs
Voici la définition formelle d'un identificateur :

identificateur :

• nonchiffre
• nonchiffre identificateur
• chiffre identificateur
• nonchiffre : un parmi
• abcdefghijklmnopqrstuvwxyz_
• ABCDEFGHIJKLMNOPQRSTUVWXYZ
• chiffre : un parmi
• 0123456789
Restrictions de choix et de longueur des noms
Les identificateurs sont des noms arbitraires de n'importe quelle longueur donnés aux classes, aux objets, aux fonctions, aux
variables, aux types de données définis par l'utilisateur, etc. Les identificateurs peuvent contenir les lettres de a à z et de A à
Z, le caractère de soulignement "_" et les chiffres de 0 à 9. Il n'y a que deux restrictions :
• Le premier caractère doit être une lettre ou un caractère de soulignement.
• Par défaut, le compilateur ne reconnaît que les 250 premiers caractères. Ce nombre de caractères significatifs peut être
réduit, mais non augmenté, par une option de menu ou de la ligne de commande. Pour modifier la longueur des caractères
significatifs, utilisez l'incrémenteur dans Projet|Options|Options avancées du compilateur|Source|Longueur d'ID.
Sensibilité à la casse
3
Les identificateurs en C et en C++ différencient les majuscules des minuscules, de sorte que Sum, sum et suM sont des
identificateurs différents.
Les identificateurs globaux importés depuis d'autres modules suivent les mêmes règles quant aux noms et aux caractères
significatifs. Cependant, une option permet d'annuler cette différenciation pour assurer la compatibilité avec des langages qui
ne la font pas. Avec cette option, les identificateurs globaux Sum et sum sont considérés comme identiques et l'avertissement
"Symbole dupliqué" risque d'apparaître lors des liaisons.
Une exception à ces règles : Les identificateurs de type __pascal sont toujours convertis en majuscules avant la liaison.

685
Guide du langage C++ RAD Studio 3.1 Référence C++

Unicité et portée
Bien que les noms d'identificateurs soient arbitraires (mais toujours conformes aux règles énoncées ci-dessus), des erreurs
apparaissent si le même nom est utilisé pour plusieurs identificateurs de même portée et partageant le même espace de
nommage. La duplication des noms est licite pour des espaces de nommage différents, indépendamment des règles de
portée.

3.1.4.5.2.4 Présentation des mots clés


Cette section traite des mots clés.

Rubriques
Nom Description
Mots clés ( see page 686) Les mots clés sont des mots réservés à des buts précis et ne doivent pas être
utilisés comme des noms d'identificateurs normaux.
Si vous utilisez des mots clés non ANSI dans un programme que vous souhaitez
conformer à la norme ANSI, utilisez toujours les versions des mots clés non
ANSI préfixés de deux caractères de soulignement. Certains d'entre eux peuvent
n'être précédés que d'un seul caractère de soulignement ; ils sont fournis pour
faciliter la portabilité du code développé avec d'autres compilateurs. Il n'existe
qu'une version pour les mots clés ANSI.
Remarque: Notez l'exception des mots clés __try
et try.... suite ( see page 686)
Extensions des mots clés ( see page 686) Borland C++ dispose de mots clés ne faisant pas partie des conventions ANSI.
Pour les listes alphabétique et thématique des routines de bibliothèque, voir le
sommaire de l'aide.
Mots clés spécifiques C++ ( see page 687) Certains mots clés sont spécifiques au C++ ; ils ne sont donc pas disponibles si
vous écrivez un programme uniquement en C. Pour les listes alphabétique et
thématique de ces mots clés et des autres, voir le sommaire de l'aide.
Tableau des pseudo variables de registre C++ de CodeGear ( see page 687) Ce tableau liste toutes les pseudovariables.

3.1.4.5.2.4.1 Mots clés


Les mots clés sont des mots réservés à des buts précis et ne doivent pas être utilisés comme des noms d'identificateurs
normaux.

Si vous utilisez des mots clés non ANSI dans un programme que vous souhaitez conformer à la norme ANSI, utilisez toujours
les versions des mots clés non ANSI préfixés de deux caractères de soulignement. Certains d'entre eux peuvent n'être précédés
que d'un seul caractère de soulignement ; ils sont fournis pour faciliter la portabilité du code développé avec d'autres
compilateurs. Il n'existe qu'une version pour les mots clés ANSI.

Remarque: Notez l'exception des mots clés __try

et try. Le mot clé try est nécessaire pour correspondre au mot clé catch dans le mécanisme de gestion des exceptions de C++.
try ne peut être remplacé par __try. Le mot clé __try ne peut être utilisé que pour correspondre au mot clé __except ou au mot
clé __finally. Pour de plus amples informations, voir la présentation de la gestion des exceptions en C++ et des exceptions
structurées du langage C sous Win32. Pour les listes alphabétique et thématique des mots clés, voir le sommaire de l'aide en
ligne.

Voir aussi
Liste alphabétique des mots clés ( see page 519)
3
Mots clés par catégorie ( see page 583)

3.1.4.5.2.4.2 Extensions des mots clés


Borland C++ dispose de mots clés ne faisant pas partie des conventions ANSI.

Pour les listes alphabétique et thématique des routines de bibliothèque, voir le sommaire de l'aide.

686
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.5.2.4.3 Mots clés spécifiques C++


Certains mots clés sont spécifiques au C++ ; ils ne sont donc pas disponibles si vous écrivez un programme uniquement en C.
Pour les listes alphabétique et thématique de ces mots clés et des autres, voir le sommaire de l'aide.

3.1.4.5.2.4.4 Tableau des pseudo variables de registre C++ de CodeGear


Ce tableau liste toutes les pseudovariables.

_AH _CL _EAX _ESP


_AL _CS _EBP _FLAGS
_AX _CX _EBX _FS
_BH _DH _ECX _GS
_BL _DI _EDI _SI
_BP _DL _EDX _SP
_BX _DS _ES _SS
_CH _DX _ESI

Toutes les pseudo variables de registre, excepté _FLAGS et _EFLAGS, sont associées à des registres segment, adresse ou à
usage particulier ou général.

Utilisez des pseudo variables de registre partout où vous pouvez utiliser une variable entière pour accéder directement au
registre 80x86 correspondant.

Les registres d'indicateurs contiennent des informations sur l'état du 80x86 ainsi que les résultats des instructions récentes.

3.1.4.5.2.5 Présentation des séparateurs


Cette section traite des séparateurs.

Rubriques
Nom Description
Séparateurs ( see page 688) Les séparateurs de C++ sont les suivants :

• []
• ()
• {}
• ,
• ;
• :
• ...
• = 3
• #
La plupart de ces séparateurs fonctionnent aussi comme des
opérateurs.
Crochets
Les crochets ouvrants ou fermants servent à spécifier un
indice d'accès à un tableau mono ou multidimensionnel :

687
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.5.2.5.1 Séparateurs
Les séparateurs de C++ sont les suivants :

• []
• ()
• {}
• ,
• ;
• :
• ...
• =
• #
La plupart de ces séparateurs fonctionnent aussi comme des opérateurs.
Crochets
Les crochets ouvrants ou fermants servent à spécifier un indice d'accès à un tableau mono ou multidimensionnel :
char ch, str[] = "Stan";
int mat[3][4]; /* matrice 3 x 4 */
ch = str[3]; /* 4me élément */
.
.
.
Parenthèses

Les parenthèses ouvrantes et fermantes ( ) permettent de grouper des expressions, d'isoler des expressions conditionnelles et
d'indiquer des appels et des paramètres de fonction :
d = c * (a + b);/* remplace la priorité normale */
if (d == z) ++x;/* essentiel avec une instruction conditionnelle */
func();/* appel de fonction, pas d'arguments */
int (*fptr)();/* déclaration de pointeur de fonction */
fptr = func;/* l'absence de () indique un pointeur de fonction */
void func2(int n);/* déclaration de fonction avec paramètres */
L'emploi de parenthèses est recommandé dans la définition de macros afin d'éviter des problèmes de priorité durant l'analyse :
#define CUBE(x) ((x) * (x) * (x))
L'utilisation des parenthèses pour modifier la priorité normale d'un opérateur et les règles d'associativité est abordée à la
rubrique Expressions.

Accolades

Les accolades ouvrantes et fermantes { } indiquent le début et la fin d'une instruction composée :
if (d == z)
3 {
++x;
func();
}
L'accolade fermante marque la fin de l'instruction composée, de sorte que le point-virgule (;) n'est pas indispensable après },
sauf dans les déclarations de structure ou de classe. Souvent, le point-virgule est illégal, comme dans
if (instruction)
{}; /* point-virgule illégal */
else

688
3.1 Référence C++ RAD Studio Guide du langage C++

Virgule

La virgule (,) sépare les éléments de la liste d'arguments d'une fonction :


void func(int n, float f, char ch);
La virgule sert aussi d'opérateur dans les expressions à virgules. L'association des deux emplois de la virgule est légal, mais
vous devez utiliser les parenthèses pour les distinguer. Notez que (exp1, exp2) évalue les deux arguments mais qu'elle est
équivalente à la seconde instruction :
func(i, j); /* appel de fonction avec deux arguments */
func((exp1, exp2), (exp3, exp4, exp5)); /* autre appel de fonction avec deux arguments */ */
Point-virgule

Le point-virgule (;) est le terminateur d'instruction. Toute expression légale en C ou en C++ (y compris l'expression vide) suivie
par un point-virgule est interprétée en tant qu'instruction, connue sous le nom d'instruction expression. L'expression est évaluée
et sa valeur est supprimée. Si l'expression n'a pas d'effet secondaire, le compilateur l'ignore.
a + b; /* évaluation probable de a + b, mais suppression de la valeur */
++a; /* effet secondaire sur a, mais suppression de la valeur de ++a */
; /* expression vide = instruction vide */
Les points-virgules permettent notamment de créer une instruction vide :
for (i = 0; i < n; i++)
{
;
}
Deux-points

Les deux-points (:) permettent d'indiquer une instruction avec étiquette :


démarrage: x=0;
...
goto démarrage;
Les étiquettes sont abordées à la rubrique Instructions à étiquettes.

Points de suspension

Les points de suspension (...) sont au nombre de trois, sans espace intermédiaire. Vous pouvez les utiliser dans une liste
formelle d'arguments d'un prototype de fonction, pour indiquer un nombre variable d'arguments, ou encore des arguments ayant
différents types. Par exemple :
void func(int n, char ch,...);
Cette déclaration dit que func est définie de telle manière que les appels doivent fournir au moins deux arguments, un de type
int et un de type char mais qu'ils peuvent aussi fournir des arguments supplémentaires.

En C++ uniquement, il est possible d'ignorer la virgule précédant les points de suspension.

Astérisque (déclaration de pointeur)

L'astérisque (*) dans une déclaration de variables indique la création d'un pointeur sur un type :
char *char_ptr; /* déclaration d'un pointeur sur char */ 3
Vous pouvez déclarer des pointeurs avec plusieurs niveaux d'indirection en indiquant le nombre adéquat d'astérisques :
int **int_ptr; /* pointeur sur un tableau d'entiers */
double ***double_ptr; /* pointeur sur une matrice de doubles */
L'astérisque s'utilise encore soit comme opérateur pour déréférencer un pointeur, soit pour la multiplication :
i = *int_ptr;
a = b * 3.14;

689
Guide du langage C++ RAD Studio 3.1 Référence C++

Signe égal (initialiseur)

Le signe égal (=) permet de séparer les déclarations de variables des listes d'initialisation :
char array[5] = { 1, 2, 3, 4, 5 };
int x = 5;
En C++, tout type de déclaration peut apparaître (avec certaines restrictions) en tout point du code. Dans une fonction C, les
déclarations de variables ne peuvent pas être précédées par du code.

Dans la liste des arguments d'une fonction en C++, le signe = indique la valeur par défaut du paramètre :
int f(int i = 0) { ... } /* paramètre i a la valeur zéro par défaut */
Le signe égal est utilisé aussi en tant qu'opérateur d'affectation dans les expressions :
int a, b, c;
a = b + c;
float *ptr = (float *) malloc(sizeof(float) * 100);
Signe dièse (directive du préprocesseur)

Le signe dièse (#) marque une directive pour le préprocesseur lorsqu'il apparaît sur une ligne, comme le premier caractère
différent de l'espace. Il indique une action de compilation, action qui n'est pas nécessairement en rapport avec la génération du
code. Pour de plus amples informations sur les directives du préprocesseur, voir Directives du préprocesseur.

# et ## (double dièse) sont également utilisés en tant qu'opérateurs pour réaliser des remplacements et des fusions de tokens
lors de la phase d'analyse effectuée par le préprocesseur. Voir Fusion de tokens.

3.1.4.5.3 Présentation des caractères inertes


Cette section présente les caractères inertes.

Rubriques
Nom Description
Commentaires ( see page 690) Les commentaires sont des bouts de texte utilisés pour annoter un programme.
Ceux-ci ne servent qu'au programmeur et sont supprimés du texte source avant
l'analyse.
Vous pouvez délimiter les commentaires de deux manières : en utilisant la
méthode C ou la méthode C++. Le compilateur supporte les deux méthodes et
offre en outre la possibilité supplémentaire d'imbriquer les commentaires. Si vous
ne compilez pas en vue de la compatibilité avec la norme ANSI, vous pouvez
utiliser l'un de ces types de commentaires dans les programmes en C et en C++.
Pour éviter d'autres problèmes de portabilité, il faut également suivre les... suite
( see page 690)
Caractère inerte ( see page 692) Un inerte est ici le nom collectif donné aux espaces (blancs), aux tabulations
horizontales et verticales, aux caractères de saut de ligne et aux commentaires .
C'est grâce aux inertes qu'il est possible de distinguer le début et la fin des
tokens. Mais une répétition d'inertes n'a aucune conséquence. Par exemple, les
deux séquences

3.1.4.5.3.1 Commentaires
Les commentaires sont des bouts de texte utilisés pour annoter un programme. Ceux-ci ne servent qu'au programmeur et sont
3 supprimés du texte source avant l'analyse.

Vous pouvez délimiter les commentaires de deux manières : en utilisant la méthode C ou la méthode C++. Le compilateur
supporte les deux méthodes et offre en outre la possibilité supplémentaire d'imbriquer les commentaires. Si vous ne compilez
pas en vue de la compatibilité avec la norme ANSI, vous pouvez utiliser l'un de ces types de commentaires dans les
programmes en C et en C++.

Pour éviter d'autres problèmes de portabilité, il faut également suivre les indications, données plus loin dans cette rubrique, sur
l'utilisation des inertes et des délimiteurs.

690
3.1 Référence C++ RAD Studio Guide du langage C++

Commentaires C

Un commentaire en C est n'importe quelle séquence de caractères placée après la paire de symboles /*. Le commentaire se
termine par la première occurrence de la paire */ qui suit la paire initiale /*. Après le développement des macros, la séquence
entière, y compris les quatre délimiteurs de commentaire, est remplacée par un espace. Notez que certaines implémentations de
C suppriment les commentaires sans les remplacer par des espaces.

Le compilateur ne supporte pas la méthode non portable de fusion de tokens dont la syntaxe est /**/. La fusion de tokens
s'effectue grâce à la paire de symboles ##, comme ci-dessous :
#define VAR(i,j) (i/**/j) /* ne fonctionnera pas */
#define VAR(i,j) (i##j) /* OK */
#define VAR(i,j) (i ## j) /* OK également */
Le compilateur analyse la déclaration,
int /* declaration */ i /* compteur */;
comme ces trois tokens :
int i;
Pour plus d'informations sur la fusion d'éléments, voir la rubrique Fusion de tokens avec ##.

Commentaires C++

C++ permet d'insérer une ligne de commentaire en utilisant deux barres obliques accolées (//). Le commentaire peut commencer
à n'importe quel endroit et s'étendre jusqu'à la ligne suivante :
class X { // ceci est un commentaire
... };
Vous pouvez aussi utiliser // pour créer des commentaires dans le code C. Cette fonctionnalité est spécifique au compilateur
Borland C++ et généralement non portable.

Commentaires imbriqués

Le langage C ANSI n'autorise pas les commentaires imbriqués. Un essai de commentaire de la ligne précédente avec :
/* int /* declaration */ i /* compteur */; */
échouera, puisque la portée du premier /* prend fin à la première séquence */ rencontrée. Ce qui donne :
i ; */
générant une erreur de syntaxe.

Par défaut, pour autoriser les commentaires imbriqués, cochez Projet|Options|Options avancées du
compilateur|Source|Commentaires imbriqués.

Délimiteurs et inertes

Dans de rares cas, des inertes avant /* et //, et après */ peuvent éviter des problèmes de portabilité. Ils ne sont toutefois pas
obligatoires. Par exemple, ce code C++ :
int i = j//* diviser par k*/k;
+m;
3
est analysé comme int i = j +m; et non comme
int i = j/k;
+m;
comme on pourrait s'y attendre avec la convention C. La forme suivante, plus lisible
int i = j//* diviser par k*/k;
+m;
évite ce problème.

691
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
Eléments lexicaux ( see page 666)

Caractère inerte ( see page 692)

Tokens ( see page 684)

3.1.4.5.3.2 Caractère inerte


Un inerte est ici le nom collectif donné aux espaces (blancs), aux tabulations horizontales et verticales, aux caractères de saut
de ligne et aux commentaires . C'est grâce aux inertes qu'il est possible de distinguer le début et la fin des tokens. Mais une
répétition d'inertes n'a aucune conséquence. Par exemple, les deux séquences
int i; float f;
et
int i;
float f;
sont lexicalement équivalentes et sont analysées de manière identique pour donner les six tokens ci-dessous :

• int
• i
• ;
• float
• f
• ;
Les caractères ASCII représentant l'inerte peuvent se trouver dans des chaînes littérales, auquel cas ils sont conservés par la
procédure d'analyse normale (ils font toujours partie de la chaîne). Par exemple,
char name[] = "CodeGear Corporation";
donne sept tokens, y compris le token chaîne littérale "CodeGear Corporation" qui compte pour un seul.

Poursuite de la ligne par \

Un cas particulier se présente lorsque le caractère de saut de ligne final est précédé par la barre oblique inversée (\). La barre
oblique comme le saut de ligne sont annulés et cela permet de traiter deux lignes physiques en une seule unité. Par exemple,
"CodeGear \
Corporation"
est analysé en "CodeGear Corporationl" (pour de plus amples informations, voir Constantes chaîne).

Voir aussi
Eléments lexicaux ( see page 666)

Tokens ( see page 684)


3
3.1.4.6 Le préprocesseur
Cette section traite du préprocesseur.

Rubriques
Nom Description
Présentation de la compilation conditionnelle ( see page 693) Cette section présente la compilation conditionnelle.

692
3.1 Référence C++ RAD Studio Guide du langage C++

Définition et annulation de la définition des macros ( see page 695) Cette section traite de la définition et de l'annulation de la définition des macros.
Directive de contrôle #error ( see page 697) Cette section traite de la directive de contrôle #error.
Fichiers inclus avec #include ( see page 698) Cette section traite des fichiers inclus avec #include.
Directive de contrôle #line ( see page 699) Cette section traite de la directive de contrôle #line.
Présentation des macros avec paramètres ( see page 699) Cette section présente les macros avec paramètres.
Présentation des directives pragma ( see page 701) Cette section présente les directives pragma.
Présentation des macros prédéfinies ( see page 714) Cette section présente les macros prédéfinies.
Directives du préprocesseur ( see page 716) Cette section traite des directives du préprocesseur.

3.1.4.6.1 Présentation de la compilation conditionnelle


Cette section présente la compilation conditionnelle.

Rubriques
Nom Description
Compilation conditionnelle ( see page 693) Le compilateur met en oeuvre la compilation conditionnelle en remplaçant les
lignes appropriées du code source par une ligne blanche. Les lignes ainsi
ignorées sont celles qui commencent par un signe # (à l'exception des directives
#if, #ifdef, #ifndef, #else, #elif et #endif), ainsi que les lignes qui ne sont pas à
compiler en conséquence des directives. Toutes les directives de compilation
conditionnelles doivent se terminer dans le fichier source ou le fichier inclus dans
lequel elles ont commencé.
#if, #elif, #else et #endif ( see page 693) Syntaxe
#ifdef et #ifndef ( see page 694) Syntaxe
Defined ( see page 695) Syntaxe

3.1.4.6.1.1 Compilation conditionnelle


Le compilateur met en oeuvre la compilation conditionnelle en remplaçant les lignes appropriées du code source par une ligne
blanche. Les lignes ainsi ignorées sont celles qui commencent par un signe # (à l'exception des directives #if, #ifdef, #ifndef,
#else, #elif et #endif), ainsi que les lignes qui ne sont pas à compiler en conséquence des directives. Toutes les directives de
compilation conditionnelles doivent se terminer dans le fichier source ou le fichier inclus dans lequel elles ont commencé.

3.1.4.6.1.2 #if, #elif, #else et #endif


Syntaxe
#if expression-constante-1
<section-1>
<#elif expression-constante-2 saut-de-ligne section-2>
.
.
.
<#elif expression-constante-n saut-de-ligne section-n>
<#else <saut-de-ligne> section-finale>
#endif
Description

Le compilateur met en oeuvre la compilation conditionnelle en remplaçant les lignes appropriées du code source par une ligne 3
blanche. Les lignes ainsi ignorées sont celles qui ne sont pas à compiler (ceci étant le résultat des directives). Toutes les
directives de compilation conditionnelles doivent se terminer dans le fichier source ou le fichier inclus dans lequel elles ont été
commencées.

Les directives conditionnelles #if, #elif, #else et #endif fonctionnent comme les opérateurs conditionnels normaux du C. Si
expression-constante-1 (soumise à un développement de macro) a une valeur différente de zéro (vrai), les lignes du code
(éventuellement vides) représentées par section-1 sont traitées, que ce soit des lignes de commande du préprocesseur ou des
lignes source normales et transmises au compilateur. Sinon, si expression-constante-1 a pour résultat zéro (faux), section-1 est

693
Guide du langage C++ RAD Studio 3.1 Référence C++

ignorée (pas de développement de macro, ni de compilation).

En cas de valeur vrai, après le traitement de section-1, le contrôle passe à #endif (qui termine la séquence conditionnelle), puis
continue avec la section-suivante. En cas de valeur fausse, le contrôle passe, le cas échéant, à la ligne #elif suivante (si elle
existe) où expression-constante-2 est évaluée. Si elle est vrai, section-2 est traitée puis le contrôle passe à #endif. Sinon, si
expression-constante-2 est fausse, le contrôle passe à la directive #elif suivante, et ainsi de suite jusqu'à ce que la directive
#else ou #endif soit atteinte. La directive facultative #else est utilisée comme alternative si tous les tests préalables se sont
avérés faux. #endif met fin à la séquence conditionnelle.

La section traitée peut contenir d'autres clauses conditionnelles imbriquées ; chaque #if doit être contrebalancé par une directive
de clôture #endif.

Le résultat du scénario précédent est qu'une seule section (qui peut être vide) est transmise au traitement ultérieur. Les sections
ignorées ne sont utiles que pour garder une trace des directives conditionnelles imbriquées, chaque #if étant associé à un
#endif.

Les expressions constantes à tester doivent avoir pour résultat une valeur entière.

Voir aussi
Defined ( see page 695)

#ifdef et #ifndef ( see page 694)

3.1.4.6.1.3 #ifdef et #ifndef


Syntaxe
#ifdef identificateur
#ifndef identificateur
Description

Les directives conditionnelles #ifdef et #ifndef permettent de tester si un identificateur est actuellement défini ou non,
c'est-à-dire si une commande #define a été exécutée pour cet identificateur et si celui-ci est encore actif. La ligne
#ifdef identificateur
équivaut exactement à
#if 1
si identificateur est actuellement défini, et équivaut à
#if 0
si identificateur est actuellement non défini.

#ifndef teste la véracité de la condition "non-défini", de sorte que la ligne


#ifndef identificateur
équivaut exactement à
#if 0
3
si identificateur est actuellement défini, et équivaut à
#if 1
si identificateur est actuellement non défini.

La syntaxe suit celle des directives #if, #elif, #else et #endif.

Un identificateur défini comme NULL est considéré comme étant défini.

694
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.6.1.4 Defined
Syntaxe
#if defined[(] <identificateur> [)]
#elif defined[(] <identificateur> [)]
Description

Utilisez l'opérateur defined pour tester si un identificateur a été préalablement défini avec #define. L'opérateur defined est
uniquement valide dans les expressions #if et #elif.

Defined vaut 1 (true) si un symbole précédemment défini n'a pas été indéfini (avec #undefPndSnundef) ; sinon, il vaut 0 (false).

La directive defined exécute la même fonction que #ifdef.


#if defined(mysym)
est identique à
#ifdef mysym
L'avantage est que vous pouvez utiliser defined plusieurs fois dans une expression complexe suivant la directive #if. Par
exemple,
#if defined(mysym) && !defined(yoursym)
Voir aussi
#ifdef et #ifndef ( see page 694)

3.1.4.6.2 Définition et annulation de la définition des macros


Cette section traite de la définition et de l'annulation de la définition des macros.

Rubriques
Nom Description
Utilisation des options de ligne de commande -D et -U ( see page 695) Il est possible de définir des identificateurs, ou d'annuler leur définition, en
utilisant les options du compilateur en ligne de commande -D et -U.
La ligne de commande
Mots clés et mots protégés dans les macros ( see page 696) Il est autorisé mais déconseillé d'utiliser les mots clés C++ comme identificateurs
de macros :
#define ( see page 696) Syntaxe
#undef ( see page 696) Syntaxe

3.1.4.6.2.1 Utilisation des options de ligne de commande -D et -U


Il est possible de définir des identificateurs, ou d'annuler leur définition, en utilisant les options du compilateur en ligne de
commande -D et -U.

La ligne de commande
BCC32 -Ddebug=1; paradox=0; X -Umysym myprog.cbc++ -Ddebug=1:paradox=0:X -Umysym myprog.c 3
bc++ -Ddebug=1:paradox=0:X -Umysym myprog.c
équivaut à introduire
#define debug 1
#define paradox 0
dans le programme.

695
Guide du langage C++ RAD Studio 3.1 Référence C++

Voir aussi
#define ( see page 696)

3.1.4.6.2.2 Mots clés et mots protégés dans les macros


Il est autorisé mais déconseillé d'utiliser les mots clés C++ comme identificateurs de macros :
#define int long /* légal mais probablement catastrophique */
#define INT long /* légal et probablement utile */
Les identificateurs globaux prédéfinis ci-après ne peuvent pas apparaître immédiatement après une directive #define ou
#undef :

• __DATE__ __FILE__ __LINE__


• __STDC__ __TIME__

3.1.4.6.2.3 #define
Syntaxe
#define identificateur_macro <séquence_tokens>
Description

La directive #define définit une macro. Les macros fournissent un mécanisme de remplacement des tokens par un ensemble de
paramètres fonction ou formels.

Chaque occurrence de identificateur_macro du code source suivant la ligne de contrôle sera remplacée à sa position d'origine
par séquence_tokens qui peut être vide (il existe certaines exceptions dont nous ferons état ultérieurement). Ces
remplacements constituent le développement de la macro. La séquence de tokens est parfois appelée corps de la macro.

Une séquence de tokens vide a pour résultat la suppression dans le code source de chaque identificateur de macro concerné.

Après chaque développement de macro individuelle, une analyse supplémentaire du texte résultant est effectuée. Cela permet
l'imbrication de macros. Le texte développé peut contenir des identificateurs de macros qui seront remplacés à leur tour.
Cependant, si la macro, après son développement, fournit un résultat qui ressemble à une directive pour le préprocesseur, cette
directive ne sera pas reconnue par le préprocesseur. Voici les restrictions du développement de macro :

• Toute occurrence de l'identificateur trouvée dans des chaînes littérales, des constantes caractère ou des commentaires dans
le code source n'est pas développée.
• Une macro ne se développera pas pendant son propre développement (ainsi #define A A ne se développera pas
indéfiniment).
Exemple
#define HI "Bonne journée!"
#define empty
Voir aussi
Mots clés et mots protégés dans les macros ( see page 696)
3
Macros avec paramètres ( see page 700)

#undef ( see page 696)

Utilisation des options de ligne de commande -D et -U ( see page 695)

3.1.4.6.2.4 #undef
Syntaxe

696
3.1 Référence C++ RAD Studio Guide du langage C++

#undef identificateur_macro
Description

Vous pouvez annuler la définition d'une macro en utilisant la directive #undef. #undef a pour effet de rompre l'association entre
l'identificateur et la séquence de tokens préalablement définie ; la définition de la macro est alors oubliée et l'identificateur de
macro indéfini. Aucun développement de macro n'est effectué après #undef.

L'état défini ou non défini d'un identificateur est une propriété importante au regard de la définition. Les directives conditionnelles
#ifdef et #ifndef, utilisées pour vérifier si un identificateur est défini ou non, constituent un moyen aisé de contrôler plusieurs des
aspects d'une compilation.

Une fois que la définition d'un identificateur a été annulée, il est possible de redéfinir celui-ci à l'aide de #define, en utilisant la
même séquence de tokens ou une autre.

La tentative de redéfinition d'un identificateur de macro déjà défini entraîne un avertissement, à moins que la nouvelle définition
ne soit exactement la même, token par token, que celle déjà existante. La stratégie à adopter lorsque des définitions peuvent
exister dans d'autres fichiers en-tête est la suivante :
#ifndef BLOCK_SIZE
#define BLOCK_SIZE 512
La ligne intermédiaire est ignorée si BLOCK_SIZE est actuellement défini ; s'il ne l'est pas, la ligne est appelée pour permettre la
définition.

Remarquez qu'aucun point-virgule (;) n'est nécessaire pour terminer une directive du préprocesseur. Tout caractère dans une
séquence de tokens, y compris les points-virgules, apparaît dans le développement de la macro. La séquence de tokens se
termine au niveau du premier saut de ligne sans barre inverse. Toute séquence de caractères inertes, y compris des
commentaires, dans la séquence de tokens est remplacée par un seul espace.

Voir aussi
#define ( see page 696)

Directives du préprocesseur ( see page 716)

3.1.4.6.3 Directive de contrôle #error


Cette section traite de la directive de contrôle #error.

Rubriques
Nom Description
#error ( see page 697) Syntaxe

3.1.4.6.3.1 #error
Syntaxe
#error errmsg
Description
3
La directive #error génère le message :
Erreur : nomfichier n°ligne : Erreur de directive : errmsg
Cette directive est généralement incluse dans une expression conditionnelle pour le préprocesseur destinée à détecter un
événement indésirable durant la compilation. Normalement, cette condition est fausse. Si elle est vrai, vous demandez au
compilateur qu'il imprime un message d'erreur et interrompre la compilation. Pour cela, intégrez une directive #error dans une
expression conditionnelle qui sera vraie lorsque le cas non souhaité se présentera.

697
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.6.4 Fichiers inclus avec #include


Cette section traite des fichiers inclus avec #include.

Rubriques
Nom Description
#include ( see page 698) Syntaxe
Recherche du fichier <nom_en_tête> ( see page 698) La variante <nom_en_tête> spécifie un fichier inclus standard ; le fichier est
recherché dans les répertoires des fichiers inclus, dans l'ordre où ils ont été
définis. Si le fichier ne figure dans aucun des répertoires par défaut, un message
d'erreur est généré.
Recherche du fichier "nom_en_tête" ( see page 699) La variante "nom_en_tête" spécifie un fichier inclus défini par l'utilisateur ; le
fichier est recherché dans l'ordre suivant :

1. 1. - dans le même répertoire que le fichier contenant


l'instruction #include
2. 2. - dans les répertoires de fichiers contenant (#include)
ce fichier
3. 3. - dans le répertoire actif
4. 4. - dans le chemin spécifié par l'option de compilation /I

3.1.4.6.4.1 #include
Syntaxe
#include <nom_en_tête>
#include "nom_en_tête"
Description

La directive #include intègre dans le code source d'autres fichiers appelés fichiers inclus, fichiers en-tête ou en-tête. La syntaxe
se présente sous trois formes :

• La première et la seconde variante impliquent qu'aucun développement de macro ne sera tenté, en d'autres termes
nom_en_tête ne sera jamais pris comme identificateur de macro. nom_en_tête doit être un nom de fichier DOS avec une
extension (généralement .h pour header), et éventuellement un nom de chemin.
• Dans la troisième variante, le premier caractère différent de l'espace après #include est différent de < ou de " . Cette variante
suppose l'existence d'une macro qui développera l'identificateur en un nom d'en-tête valide, délimité, au format
<nom_en_tête> ou "nom_en_tête".
Le préprocesseur efface la ligne #include et la remplace, au même endroit du code source, par le texte du fichier en-tête. Ce
texte source n'est pas modifié, mais le compilateur "voit" le code dans un contexte modifié : l'emplacement de #include peut
en effet influencer la portée et la durée de vie des identificateurs figurant dans le fichier inclus.
Si vous indiquez un chemin explicite dans nom_en_tête, seul ce répertoire sera soumis à la recherche du fichier.
La différence entre les formats <nom_en_tête> et "nom_en_tête" réside dans l'algorithme de recherche du fichier inclus.
Voir aussi

3 Recherche du fichier <nom_en_tête> ( see page 698)

Recherche du fichier "nom_en_tête" ( see page 699)

3.1.4.6.4.2 Recherche du fichier <nom_en_tête>


La variante <nom_en_tête> spécifie un fichier inclus standard ; le fichier est recherché dans les répertoires des fichiers inclus,
dans l'ordre où ils ont été définis. Si le fichier ne figure dans aucun des répertoires par défaut, un message d'erreur est généré.

698
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.6.4.3 Recherche du fichier "nom_en_tête"


La variante "nom_en_tête" spécifie un fichier inclus défini par l'utilisateur ; le fichier est recherché dans l'ordre suivant :

1. 1. - dans le même répertoire que le fichier contenant l'instruction #include


2. 2. - dans les répertoires de fichiers contenant (#include) ce fichier
3. 3. - dans le répertoire actif
4. 4. - dans le chemin spécifié par l'option de compilation /I

3.1.4.6.5 Directive de contrôle #line


Cette section traite de la directive de contrôle #line.

Rubriques
Nom Description
#line ( see page 699) Syntaxe

3.1.4.6.5.1 #line
Syntaxe
#line constante-entière <"fichier">
Description

Vous pouvez utiliser la commande #line pour indiquer comment numéroter les lignes d'un programme, afin de faciliter le
repérage des erreurs et des références croisées. Si votre programme est formé de sections extraites d'un autre fichier
programme, il est plus facile de les repérer avec les numéros de lignes du texte source qu'avec la numérotation issue du
programme composé.

La directive #line indique que la ligne suivante du texte source provient de la ligne constante-entière de fichier. Une fois que
fichier a été mentionné, vous pouvez l'omettre dans les autres commandes #line.

Le développement de macro est possible sur les arguments de #line comme cela se fait pour la directive #include.

La directive #line est essentiellement utilisée par les utilitaires générant du code C et non sur des sources écrits par des
programmeurs.

3.1.4.6.6 Présentation des macros avec paramètres


Cette section présente les macros avec paramètres.

Rubriques
Nom Description
Macros avec paramètres ( see page 700) La syntaxe suivante est utilisée pour définir une macro avec des paramètres :
Parenthèses imbriquées et virgules ( see page 700) La liste_arg_réels peut contenir des parenthèses, à condition qu'elles aillent par
paire. De même, les virgules à l'intérieur de guillemets ou de parenthèses ne
3
sont pas traitées comme des délimiteurs d'arguments.
Fusion de tokens avec ## ( see page 701) Vous pouvez coller (ou fusionner) deux tokens si ceux-ci sont séparés par ##
(plus un espace facultatif de part et d'autre). Le préprocesseur supprime l'espace
et les ##, combinant les tokens séparés en un seul. Cela permet de construire
des identificateurs.
Par exemple, avec la définition
Conversion en chaîne avec # ( see page 701) Le symbole # peut précéder un argument formel pour permettre, après
remplacement, la conversion d'un argument réel en chaîne.
Ainsi, avec la définition de macro ci-après :

699
Guide du langage C++ RAD Studio 3.1 Référence C++

Utilisation de la barre oblique inversée (\) de poursuite de ligne ( see page 701) Une longue séquence de tokens peut être répartie sur deux lignes à l'aide de la
barre oblique inversée (\). La barre oblique inversée et le saut de ligne sont
ensuite supprimés pour donner la séquence développée :
Effets secondaires et autres risques ( see page 701) Les similitudes entre les appels de fonction et les appels de macro masquent
souvent leur différence. Un appel de macro ne prévoit aucune vérification
intégrée de type, de sorte qu'une mauvaise correspondance des types des
arguments formels et des arguments réels risquent de donner des résultats
étranges, difficiles à déboguer, et sans aucun avertissement de la part du
système. Les appels de macro peuvent aussi avoir des effets secondaires
indésirables, notamment lorsqu'un argument réel est évalué plusieurs fois.
Comparez CUBE et cube dans l'exemple suivant :

3.1.4.6.6.1 Macros avec paramètres


La syntaxe suivante est utilisée pour définir une macro avec des paramètres :
#define identificateur_macro(<liste_arg>) séquence_tokens
Toute virgule entre parenthèses dans une liste d'arguments est traitée comme élément de l'argument et non comme un
délimiteur.

Notez qu'il ne faut pas mettre d'espace entre l'identificateur de macro et la parenthèse ouvrante (. List_arg est une séquence
facultative d'identificateurs séparés par des virgules, semblable à la liste des arguments d'une fonction C. Chaque identificateur
délimité par des virgules joue le rôle d'un argument formel ou marque de réservation.

De telles macros sont appelées en écrivant


identificateur_macro<espace>(<liste_arg_réels>)
dans le code source qui suit. La syntaxe est identique à celle d'un appel de fonction ; en réalité, de nombreuses fonctions de la
bibliothèque standard du C sont mises en oeuvre en tant que macros. Cependant, il existe des différences sémantiques
importantes et certains pièges.

La liste_arg_réels facultative doit contenir le même nombre de tokens délimités par des virgules, connus comme arguments
réels, que la liste des arguments formels liste_arg de la ligne #define : chaque argument formel nécessite un argument réel.
Une erreur est signalée si les deux listes ne comportent pas le même nombre d'arguments.

Un appel de macro a pour résultat deux séries de remplacement. Tout d'abord, l'identificateur de la macro et les arguments
entre parenthèses sont remplacés par la séquence de tokens. Ensuite, les arguments formels rencontrés dans la séquence de
tokens sont remplacés par les arguments réels correspondants figurant dans la liste_arg_réels.

Comme avec les définitions de macros simples, une deuxième analyse est effectuée pour détecter la présence éventuelle
d'identificateurs de macros imbriqués.

Voir aussi
Conversion en chaîne avec # ( see page 701)

Parenthèses imbriquées et virgules ( see page 700)

Effets secondaires et autres risques ( see page 701)

Utilisation de la barre oblique inversée (\) de poursuite de ligne ( see page 701)

3
3.1.4.6.6.2 Parenthèses imbriquées et virgules
La liste_arg_réels peut contenir des parenthèses, à condition qu'elles aillent par paire. De même, les virgules à l'intérieur de
guillemets ou de parenthèses ne sont pas traitées comme des délimiteurs d'arguments.
#define ERRMSG(x, str) showerr("Erreur:", x. str)
#define SUM(x,y) ((x) + (y))
:
ERRMSG(2, "Appuyez sur Entrée, puis Echap");
/* showerr("Erreur",2,"Appuyez sur Entrée, puis Echap"); */

700
3.1 Référence C++ RAD Studio Guide du langage C++

return SUM(f(i, j), g(k, l));


/* return ( (f(i, j)) + (g(k, l)) ); */

3.1.4.6.6.3 Fusion de tokens avec ##


Vous pouvez coller (ou fusionner) deux tokens si ceux-ci sont séparés par ## (plus un espace facultatif de part et d'autre). Le
préprocesseur supprime l'espace et les ##, combinant les tokens séparés en un seul. Cela permet de construire des
identificateurs.

Par exemple, avec la définition


#define VAR(i, j) (i##j)
l'appel de VAR(x, 6) se résout en (x6). Cette méthode remplace l'ancienne méthode (non portable) dont la syntaxe était (i/**/j).

3.1.4.6.6.4 Conversion en chaîne avec #


Le symbole # peut précéder un argument formel pour permettre, après remplacement, la conversion d'un argument réel en
chaîne.

Ainsi, avec la définition de macro ci-après :


#define TRACE(flag) printf(#flag "=%d\n", flag)
le fragment de code
int highval = 1024;
TRACE(highval);
devient
int highval = 1024;
printf("highval" "=%d\n", highval);
qui à son tour est traité comme
int highval = 1024;
printf("highval=%d\n", highval);

3.1.4.6.6.5 Utilisation de la barre oblique inversée (\) de poursuite de ligne


Une longue séquence de tokens peut être répartie sur deux lignes à l'aide de la barre oblique inversée (\). La barre oblique
inversée et le saut de ligne sont ensuite supprimés pour donner la séquence développée :
#define WARN "Ceci est une seule ligne -\
d'avertissement."

3.1.4.6.6.6 Effets secondaires et autres risques


Les similitudes entre les appels de fonction et les appels de macro masquent souvent leur différence. Un appel de macro ne
prévoit aucune vérification intégrée de type, de sorte qu'une mauvaise correspondance des types des arguments formels et des
arguments réels risquent de donner des résultats étranges, difficiles à déboguer, et sans aucun avertissement de la part du
système. Les appels de macro peuvent aussi avoir des effets secondaires indésirables, notamment lorsqu'un argument réel est
évalué plusieurs fois.
3
Comparez CUBE et cube dans l'exemple suivant :
int cube(int x) {
return x* x*x;

3.1.4.6.7 Présentation des directives pragma


Cette section présente les directives pragma.

701
Guide du langage C++ RAD Studio 3.1 Référence C++

Rubriques
Nom Description
#pragma ( see page 702) Syntaxe
#pragma alignment ( see page 704) Syntaxe
#pragma anon_struct ( see page 704) Syntaxe
#pragma argsused ( see page 704) Syntaxe
#pragma checkoption ( see page 705) Syntaxe
#pragma codeseg ( see page 705) Syntaxe
#pragma comment ( see page 705) Syntaxe
#pragma defineonoption et #pragma undefineonoption ( see page 705) Syntaxe
#pragma exit et #pragma startup ( see page 706) Syntaxe
#pragma hdrfile ( see page 706) Syntaxe
#pragma hdrstop ( see page 706) Syntaxe
#pragma inline ( see page 707) Syntaxe
#pragma intrinsic ( see page 707) Syntaxe
#pragma link ( see page 707) Syntaxe
#pragma message ( see page 708) Syntaxe
#pragma nopushoptwarn ( see page 708) Syntaxe
#pragma obsolete ( see page 708) Syntaxe
#pragma option ( see page 708) Syntaxe
#pragma pack ( see page 710) Syntaxe
#pragma package ( see page 712) Syntaxe
#pragma region et #pragma end_region ( see page 713) Syntaxe
#pragma resource ( see page 713) Syntaxe
#pragma warn ( see page 713) Syntaxe

3.1.4.6.7.1 #pragma
Syntaxe
#pragma nom-directive
Description

Avec #pragma, vous pouvez définir des directives pour le compilateur dans votre code source, sans interférer avec les autres
compilateurs supportant #pragma. Si le compilateur ne reconnaît pas nom-directive, il ignore la directive #pragma sans produire
de message d'erreur ni d'avertissement.

CodeGear C++ supporte les directives #pragma suivantes : Les liens à ces rubriques sont situés en bas de cette rubrique.

• #pragma alignment
• #pragma anon_struct
• #pragma argsused
• #pragma checkoption
• #pragma codeseg
3 • #pragma comment
• #pragma defineonoption
• #pragma exit
• #pragma hdrfile
• #pragma hdrstop
• #pragma inline

702
3.1 Référence C++ RAD Studio Guide du langage C++

• #pragma intrinsic
• #pragma link
• #pragma message
• #pragma nopushoptwarn
• #pragma obsolete
• #pragma option
• #pragma pack
• #pragma package
• #pragma resource
• #pragma startup
• #pragma undefineonoption
• #pragma warn
Voir aussi
#pragma alignment

#pragma anon_struct ( see page 704)

#pragma argsused ( see page 704)

#pragma checkoption ( see page 705)

#pragma codeseg ( see page 705)

#pragma comment ( see page 705)

#pragma curious_george

#pragma defineonoption ( see page 705)

#pragma exit ( see page 706)

#pragma hdrfile ( see page 706)

#pragma hdrstop ( see page 706)

#pragma inline ( see page 707)

#pragma intrinsic ( see page 707)

#pragma link ( see page 707)

#pragma message ( see page 708)

#pragma nopushoptwarn ( see page 708)

#pragma obsolete ( see page 708)

#pragma option ( see page 708)


3
#pragma pack ( see page 710)

#pragma package ( see page 712)

#pragma resource ( see page 713)

#pragma startup ( see page 706)

#pragma undefineonoption ( see page 705)

703
Guide du langage C++ RAD Studio 3.1 Référence C++

#pragma warn ( see page 713)

3.1.4.6.7.2 #pragma alignment


Syntaxe
#pragma alignment
Description

Ce pragma imprime l'alignement sur les octets, ainsi que la taille enum en cours.

Par exemple, le pragma


#pragma alignment
pourrait imprimer ce qui suit :

L'alignement est de 4 octets, la taille enum est de 4 octets

3.1.4.6.7.3 #pragma anon_struct


Syntaxe
#pragma anon_struct on
#pragma anon_struct off
Description

La directive anon_struct vous permet de compiler des structures anonymes imbriquées dans des classes.
#pragma anon_struct on
struct S {
int i;
struct { // Structure anonyme imbriquée
int j;
float x ;
};
class { // Classe anonyme imbriquée
public:
long double ld;
};
S() { i = 1; j = 2; x = 3.3; ld = 12345.5;}
};
#pragma anon_struct off
void main()
{
S mystruct;
mystruct.x = 1.2; // Affecte aux données imbriquées.
}

3.1.4.6.7.4 #pragma argsused


Syntaxe

3 #pragma argsused
Description

Le pragma argsused est uniquement autorisée entre les définitions de fonctions ; elle n'affecte que la fonction suivante. Elle
désactive le message d'avertissement :
"nomparamètre jamais utilisé dans la fonction nomfonction"

704
3.1 Référence C++ RAD Studio Guide du langage C++

3.1.4.6.7.5 #pragma checkoption


Syntaxe
#pragma checkoption <commutateurs>
où <commutateurs> représente les commutateurs de la ligne de commande.

Description

Ce pragma vérifie un ensemble d'options.

Par exemple, le pragma suivant


#pragma checkoption -w- -Vx
vérifie si les options -w- et -Vx sont actives. Si elles ne le sont pas, vous obtenez l'erreur :

Erreur E2471 nomfichier : pragma checkoption a échoué : les options ne sont pas celles attendues

3.1.4.6.7.6 #pragma codeseg


Syntaxe
#pragma codeseg <nom_seg> <"classe_seg"> <groupe>
Description

La directive codeseg vous permet de nommer le segment, la classe ou le groupe où les fonctions sont allouées. Si le pragma
est utilisé sans aucun de ses arguments facultatifs, le segment de code par défaut est utilisé pour l'allocation de la fonction.

3.1.4.6.7.7 #pragma comment


Syntaxe
#pragma comment (type_commentaire, "chaîne")
Description

La directive comment vous permet d'écrire un enregistrement de commentaire dans un fichier de sortie. L'argument
type_commentaire peut avoir une des valeurs suivantes :

Valeur Explication
exestr Le lieur écrit chaîne dans un fichier .obj. La chaîne spécifiée est placée dans le fichier exécutable. Une telle chaîne
n'est jamais chargée en mémoire mais peut être trouvée dans le fichier exécutable par utilisation d'un utilitaire de
recherche de fichier adéquat.
lib Ecrit un enregistrement de commentaire dans un fichier .obj. Un module bibliothèque qui n'est pas spécifié dans le
fichier réponse du lieur peut être spécifié par la directive comment LIB. Le lieur inclut le module bibliothèque dont le
nom est spécifié par chaîne comme dernière bibliothèque. Plusieurs modules peuvent être nommés et liés dans l'ordre
dans lequel ils sont nommés.
user Le compilateur écrit chaîne dans le fichier .obj. Le lieur ignore la chaîne spécifiée.
3

3.1.4.6.7.8 #pragma defineonoption et #pragma undefineonoption


Syntaxe
#pragma defineonoption <nommacro>
<commutateurs>
#pragma undefineonoption <nommacro>
<commutateurs>

705
Guide du langage C++ RAD Studio 3.1 Référence C++

où <nommacro> représente le nom de la macro à définir ou à annuler la définition, et <commutateurs> représente les
commutateurs de la ligne de commande.

Description

Le pragma #pragma defineonoption définit un nom de macro quand les options spécifiées sont définies. Le nom de macro
est défini si tous les commutateurs sont activés, à partir de la ligne de commande ou via un pragma.

Le pragma #pragma undefineonoption annule la définition d'un nom de macro quand les options spécifiées sont définies.

Par exemple, le pragma suivant


#pragma defineonoption DEBUG -v
entraîne la définition de la macro DEBUG quand l'option -v est définie.

A l'inverse, ce pragma
#pragma undefineonoption DEBUG -v
entraîne l'annulation de la définition de la macro DEBUG quand l'option -v est définie.

3.1.4.6.7.9 #pragma exit et #pragma startup


Syntaxe
#pragma startup nom-fonction <priorité>
#pragma exit nom-fonction <priorité>
Description

Ces deux pragmas permettent au programme de spécifier des fonctions qui doivent être appelées soit lors du lancement du
programme (avant l'appel de la fonction main), soit lors de la fin du programme (juste avant l'appel à _exit).

nom-fonction doit être une fonction déclarée précédemment ; elle ne doit pas accepter d'argument et doit renvoyer void ; en
d'autres mots, elle devrait être déclarée comme :
void func(void);
Le paramètre facultatif priorité doit être un entier compris entre 64 et 255. La plus haute priorité est 0. Au démarrage, l'appel des
fonctions se fait selon l'ordre des priorités, et selon l'ordre inverse pour la sortie. Si la priorité n'est pas spécifiée, la fonction se
voit attribuer le niveau 100.

Avertissement: N'utilisez pas de valeurs de priorité inférieures à 64. Les priorités de 0 à 63 sont réservées aux mécanismes de
démarrage et de d'arrêt ISO.

3.1.4.6.7.10 #pragma hdrfile


Syntaxe
#pragma hdrfile "nomfichier.csm"
Description

3 Cette directive spécifie le nom du fichier dans lequel sont stockés les en-têtes précompilés.

Si vous n'utilisez pas d'en-têtes précompilés, cette directive n'a pas d'effet. Vous pouvez utiliser l'option de ligne de commande
-H=nomfichier ou Utiliser des en-têtes précompilés pour modifier le nom du fichier utilisé pour le stockage des en-têtes
précompilés.

3.1.4.6.7.11 #pragma hdrstop


Syntaxe

706
3.1 Référence C++ RAD Studio Guide du langage C++

#pragma hdrstop
Description

Cette directive termine la liste des fichiers en-tête destinés à la précompilation. Vous pouvez utiliser cette option pour limiter
l'espace disque utilisé par les en-têtes précompilés.

Les fichiers en-tête précompilés peuvent être partagés par les fichiers source de votre projet uniquement si les directives
#include précédant #pragma hdrstop sont identiques. En conséquence, vous obtenez la meilleure performance de compilation
si vous incluez les fichiers en-tête communs de votre projet avant #pragma hdrstop et les fichiers spécifiques après.
Assurez-vous que les directives #include précédant #pragma hdrstop sont identiques dans tous les fichiers source ou qu'elles
différent très peu.

L'environnement de développement intégré génère du code pour améliorer la performance de la précompilation des en-têtes.
Par exemple, après une Nouvelle application, le fichier source "Unit1.cpp" ressemblera à ceci (commentaires ajoutés):
#include <clxvcl.h> // fichier en-tête commun
#pragma hdrstop // fin de la liste
Utilisez cette directive pragma seulement pour les fichiers sources. Pragma n'a pas d'effet lorsqu'il est utilisé dans un fichier
en-tête.

3.1.4.6.7.12 #pragma inline


Syntaxe
#pragma inline
Description

Cette directive est équivalente à l'option -B du compilateur en ligne de commande.

Il est préférable de la placer au début du fichier, car le compilateur s'initialise avec l'option -B lorsqu'il rencontre #pragma inline.

3.1.4.6.7.13 #pragma intrinsic


Syntaxe
#pragma intrinsic [-]nom-fonction
Description

Utilisez #pragma intrinsic pour remplacer les commutateurs de la ligne de commande ou les options du projet pour contrôler la
mise en ligne des fonctions.

Lors de la mise en ligne d'une fonction intrinsic, incorporez toujours un prototype de cette fonction avant de l'utiliser.

3.1.4.6.7.14 #pragma link


Syntaxe
#pragma link "[chemin]nommodule[.ext]"
3
Description

Cette directive indique au lieur de lier le fichier en un fichier exécutable.

Par défaut, le lieur recherche nommodule dans le répertoire local et n'importe quel chemin spécifié par l'option -L. Vous pouvez
utiliser l'argument chemin pour spécifier un répertoire.

Par défaut, le lieur génère une extension .obj.

707
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.6.7.15 #pragma message


Syntaxe
#pragma message ("texte" ["texte"["texte" ...]])
#pragma message texte
Description

Utilisez #pragma message pour spécifier un message défini par l'utilisateur dans le code de votre programme.

La première forme nécessite une ou plusieurs chaînes constante, et le message doit être entouré de parenthèses. (Cette forme
est compatible avec Microsoft C.) Cette forme génère la constante contenue entre les doubles guillemets, qu'il s'agisse ou non
d'une macro.

La seconde forme utilise le texte qui suit #pragma pour le message. Avec cette forme de #pragma, les références de macro
sont développées avant que le message ne soit affiché.

La troisième forme génère la valeur développée par la macro à partir du texte qui suit la directive #pragma, si figure #defined.
Si #defined est absent, vous obtenez un message de directive pragma incorrecte.

Les messages définis par l'utilisateur sont affichés comme des messages et non comme des avertissements.

L'affichage des messages définis par l'utilisateur est activé par défaut et peut être activé ou désactivé avec l'option Afficher
les messages. Cette option correspond à l'option -wmsg du compilateur.

Les messages ne sont affichés dans l'EDI que si l'option Afficher les messages généraux est cochée sur la page Propriétés
de projet C++ sous Projet Options Propriétés de projet.

Voir aussi
Directives du préprocesseur ( see page 716)

3.1.4.6.7.16 #pragma nopushoptwarn


Syntaxe
#pragma nopushoptwarn
Description

Le pragma nopushoptwarn permet l'utilisation de l'option pragma push sans pop et de l'option pragma pop sans push // dans
un fichier. Normalement, un avertissement devrait être donné.

3.1.4.6.7.17 #pragma obsolete


Syntaxe
#pragma obsolete identificateur
Description

3 Utilisez #pragma obsolete pour donner un avertissement l'attention dès que le préprocesseur rencontre la première utilisation
d'identificateur, rencontré après pragma, votre code source. Cet avertissement signale que identificateur est obsolète.

3.1.4.6.7.18 #pragma option


Syntaxe
#pragma option options
#pragma option push options
#pragma option pop

708
3.1 Référence C++ RAD Studio Guide du langage C++

#pragma nopushoptwarn
Description

Utilisez #pragma option pour inclure des options de la ligne de commande dans le code de votre programme. #pragma option
peut aussi être utilisée avec les arguments push ou pop.

#pragma option [options...]

options sont les options de la ligne de commande (à l'exception de celles énumérées ci-dessous). Une directive peut contenir un
nombre quelconque d'options. Les deux exemples suivants sont corrects :
#pragma option -C
#pragma option -C -A
Les options qui fonctionnent en bascule (par exemple -a ou -K) peuvent être activées et désactivées exactement comme au
niveau de la ligne de commande. Elles peuvent en outre apparaître suivies d'un point afin de restaurer l'option dans l'état qu'elle
avait dans la ligne de commande, dans le fichier de configuration ou dans l'option de menu. Cela permet de modifier
temporairement une option et revenir ensuite à sa valeur par défaut sans que vous ayez à vous rappeler (ni même à connaître)
celle-ci.

Les options suivantes ne peuvent pas apparaître dans pragma option :

B c dnom
Dnom=chaîne enomfichier E
Fx h Inomfichier
lexset M o
P Q S
T Unom V
X Y

• Les instructions #pragma, #include, #define, et certaines instructions #if, peuvent être utilisées dans les cas suivants :
• Avant l'utilisation d'un nom de macro commençant par deux caractères de soulignement (éventuellement une macro intégrée)
dans une directive #if, #ifdef, #ifndef ou #elif.
• Avant l'occurrence du premier élément réel du langage (la première déclaration C ou C++).
Certaines options de ligne de commande ne peuvent apparaître que dans une commande #pragma option précédant ces
événements. Ces options sont :

Enomfichier f i#
m* nchemin onomfichier
U W z

*
Les autres options peuvent être modifiées n'importe où. Les options suivantes ne vont affecter le compilateur que si elles sont
modifiées entre les déclarations de fonctions ou d'objets :
3
1 h r
2 k rd
A N v
Ff O y
G p Z

709
Guide du langage C++ RAD Studio 3.1 Référence C++

Les options suivantes sont modifiables à tout moment et prennent effet immédiatement :

A gn zE
b jn zF
C K zH
d wxxx

Les options peuvent être suivies d'un point (.) pour restaurer l'état de la ligne de commande.

#pragma option avec push ou pop

La directive #pragma option peut aussi être utilisée avec les arguments push et pop pour faciliter la modification des directives
de compilation.

Vous pouvez utiliser #pragma option push pour enregistrer la totalité ou un ensemble spécifié d'options avant d'inclure des
fichiers pouvant modifier de nombreux avertissements et options de compilation, puis, avec la seule instruction #pragma option
pop, revenir à l'état précédent. Par exemple :
#pragma option push
#include <theworld.h>
#pragma option pop
#include "mystuff.h"
La directive #pragma option push place dans un premier temps toutes les options de compilation et les paramètres
d'avertissement sur une pile puis traite les options (éventuellement fournies). Les exemples suivants illustrent l'utilisation de
#pragma option push avec ou sans options :
#pragma option push -C -A
#pragma option push
La directive #pragma option pop modifie les avertissements et les options de compilation en retirant de la pile le dernier
ensemble d'options et d'avertissements. Cela génère un avertissement, "Pragma option pop sans option push correspondante"
si la pile est vide, auquel cas rien ne se produit.

Le texte suivant génère un avertissement signalant une pile vide :


#pragma option push
#pragma option pop
#pragma option pop /* Avertissement */
Bien que cela ne soit pas recommandé, vous pouvez désactiver cet avertissement avec la directive : #pragma warn -nop.

Si vous tentez de spécifier des options après pop, vous obtenez le message d'erreur "Rien d'autorisé après pragma option pop".
Par exemple, le texte suivant génère un message d'erreur :
#pragma option pop -C/* ERREUR */
Si votre pile d'options poussées n'est pas la même au début et à la fin d'un fichier, vous obtenez l'avertissement : "Options et
avertissements précédents non restaurés". Pour désactiver cet avertissement, utilisez la directive #pragma nopushoptwarn.

3.1.4.6.7.19 #pragma pack


3
Syntaxe
#pragma pack([{push | pop}[,]] [identificateur[,]] [n])
Description

La directive #pragma pack(n) revient à utiliser #pragma option avec l'option de compilation -a. n représente l'alignement
d'octets qui détermine comment le compilateur aligne les données en mémoire. Pour de plus amples informations, voir l'option
de compilation -a. #pragma pack peut aussi être utilisée avec les arguments push et pop, offrant la même fonctionnalité que la

710
3.1 Référence C++ RAD Studio Guide du langage C++

directive #pragma option avec push et pop. Le tableau suivant compare l'utilisation de #pragma pack avec #pragma option.

#pragma pack #pragma option


#pragma pack(n) #pragma option -an
#pragma pack(push, n) #pragma option push -an
#pragma pack(pop) #pragma option pop

La directive #pragma pack accepte également un argument identificateur qui doit être utilisé en combinaison avec push ou pop.

#pragma pack sans arguments


#pragma pack()
L'utilisation de #pragma pack sans arguments définit la taille de package à l'alignement de départ –aX (qui a la valeur par
défaut 8). L'alignement de départ -aX est considéré comme l'alignement au départ de la compilation APRES le traitement de
toutes les options de la ligne de commande.

#pragma pack utilisant une valeur pour n


#pragma pack(8)
L'utilisation de #pragma pack avec une valeur pour 'n' définit l'alignement en cours à 'n'. Les valeurs autorisées pour 'n' sont :
1,2,4,8 et 16.

#pragma pack utilisant push


#pragma pack(push)
L'utilisation de #pragma pack avec push pousse l'alignement en cours dans la pile interne des alignements.

#pragma pack utilisant push, identifier


#pragma pack(push, ident)
L'utilisation de #pragma pack avec push et un identificateur associe l'alignement poussé avec 'ident'.

#pragma pack utilisant push et n


#pragma pack(push, 8)
#pragma pack(push, ident, 8)
L'utilisation de #pragma pack avec push et une valeur pour 'n', exécute le pragma pack push ou pragma pack push ident puis
définit ensuite l'alignement en cours à 'n'.

#pragma pack utilisant pop


#pragma pack(pop)
L'utilisation de #pragma pack avec pop extrait de la pile d'alignement et définit l'alignement en cours au dernier alignement
placé dans la pile. Si le pop n'a pas de push correspondant, toute la pile d'alignement est sortie, un avertissement est émis et
l'alignement revient à l'alignement de départ -aX.

#pragma pack utilisant pop, identifier


#pragma pop(pop, ident) 3
L'utilisation de #pragma pack avec pop et un identificateur extrait de la pile jusqu'à avoir trouvé l'identificateur et définit
l'alignement avec l'alignement placé par le #pragma pack(push, identifier) précédent correspondant. Si le pop avec un
identificateur ne trouve pas le push correspondant avec l'identificateur, toute la pile d'alignement est sortie, un avertissement est
émis :
W8083: Pragma pack pop sans pack push correspondant
Puis l'alignement revient à l'alignement de départ -aX.

711
Guide du langage C++ RAD Studio 3.1 Référence C++

#pragma pack utilisant pop et n


#pragma pack(pop, 8)
#pragma pack(pop, ident, 8)
L'utilisation de #pragma pack avec pop et une valeur pour 'n', exécute pragma pack pop ou pragma pack pop identificateur.
Ensuite l'alignement en cours est défini à 'n' sauf si pop n'a pas trouvé le push correspondant, dans ce cas 'n' n'est pas pris en
compte, un avertissement est émis et l'alignement revient à l'alignement de départ -aX.

Conditions d'erreur

Spécifier un 'identificateur' sans push ou pop est une erreur.

Spécifier un alignement différent de 1, 2, 4, 8 ou 16 est une erreur.

Conditions d'avertissement

L'utilisation de #pragma pop sans un push correspondant entraîne un avertissent.

3.1.4.6.7.20 #pragma package


Syntaxe
#pragma package(smart_init)
#pragma package(smart_init, weak)
Description : smart_init argument

#pragma package(smart_init) garantit l'initialisation des unités packagées dans l'ordre déterminé par leurs dépendances.
Incluse par défaut dans le fichier source d'un package. Typiquement, vous utilisez #pragma package pour les fichiers .CPP
construits comme des packages.

Cette directive pragma affecte l'ordre d'initialisation de l'unité de compilation. Pour les unités, l'initialisation se produit dans l'ordre
suivant :

• 1. Selon leur dépendances "d'usage". Ainsi, si l'unitéA dépend de l'unitéB, l'unitéB doit être initialisée avant l'unitéA.
• 2. Selon l'ordre de lien.
• 3. Selon l'ordre de priorité dans l'unité.
Pour les fichiers objet normaux (ceux non construits comme des unités), l'initialisation se produit d'abord en fonction de l'ordre
de priorité puis de l'ordre de lien. La modification de l'odre de lien des fichiers objet modifie l'ordre dans lequel les
constructeurs d'objets globaux sont appelés.
Les exemples suivants illustrent en quoi l'initialisation des unités diffère de celle des fichiers objet normaux.
Supposons trois fichiers unité, A, B et C, initialisés de façon "intelligente" avec #pragma package(smart_init) et ont les valeurs
de priorité (définies par le paramètre de priorité de #pragma startup) 10, 20 et 30. Les noms des fonctions sont déterminés
par leur valeur de priorité et le fichier objet parent : a10, a20, a30, b10, etc.
Puisque les trois fichiers sont des unités, et en supposant que A utilise B et C et que l'ordre de lien est A, B puis C, l'ordre
d'initialisation est :
B10 B20 B30 C10 C20 C30 A10 A20 A30
3 S'il s'agissait de fichiers objet, et non d'unités, l'ordre serait :
A10 B10 C10 A20 B20 C20 A30 B30 C30
Toutes les références #pragma link à d'autres fichiers objet à partir d'un fichier .cpp utilisant et déclarant #pragma
package(smart_init) doivent aussi être résolues par une unité. Les références #pragma link à des fichiers non objet peuvent
néanmoins être résolues par des bibliothèques, etc.
Description : weak packages
La directive #pragma package(smart_init, weak) affecte la manière dont un fichier objet est stocké dans les fichiers .bpi et .bpl
d'un package. Si #pragma package(smart_init, weak) apparaît dans un fichier d'unité, le compilateur ne place pas l'unité

712
3.1 Référence C++ RAD Studio Guide du langage C++

dans les fichiers bpl si c'est possible, et il crée une copie locale non empaquetée de l'unité si elle est nécessaire à une autre
application ou un autre package. Une unité compilée avec cette directive est dite faiblement empaquetée.
#pragma package(smart_init, weak) est utilisée pour éliminer les conflits entre packages pouvant dépendre de la même
bibliothèque externe.
Les fichiers d'unités contenant la directive #pragma package(smart_init, weak) ne doivent pas contenir de variables globales.
Pour de plus amples informations, voir la rubrique Faible packaging.
Voir aussi
Directives du préprocesseur ( see page 716)

3.1.4.6.7.21 #pragma region et #pragma end_region


Syntaxe
#pragma region <nom> #pragma end_region
Description

Ces deux pragmas permettent au programme de spécifier une région qui peut être réduite et développée (similaire à la
fonctionnalité fournie automatiquement pour les fonctions).

Utilisez ces pragmas en entourant la section code comme suit :


#pragma region nom code à réduire/développer ... #pragma
end_region
Le nom est facultatif.

3.1.4.6.7.22 #pragma resource


Syntaxe
#pragma resource "*.xdfm"
Description

Ce pragma marque le fichier comme unité d'une fiche et nécessite les fichiers .dfm et en-tête correspondants. Ces fichiers sont
gérés par l'EDI.

Si votre fiche nécessite des variables, elles doivent être déclarées immédiatement après l'utilisation de la ressource pragma. La
déclaration doit être de la forme :

TFormName *Formname;

3.1.4.6.7.23 #pragma warn


Syntaxe
#pragma warn [+|-|.]xxx
Description
3
Le pragma warn permet de modifier des options spécifiques de la ligne de commande -wxxx ou les paramètres d'affichage des
avertissements. xxx est l'identificateur de message sur trois lettres ou quatre chiffres utilisé par l'option de ligne de commande.
+ active un avertissement tandis que - désactive l'avertissement. Le '.' restaure un avertissement sur les paramètres Options
de projet.

713
Guide du langage C++ RAD Studio 3.1 Référence C++

3.1.4.6.8 Présentation des macros prédéfinies


Cette section présente les macros prédéfinies.

Rubriques
Nom Description
Macros prédéfinies ( see page 714) Le compilateur prédéfinit certains identificateurs globaux connus comme
constantes manifestes. La plupart des identificateurs commencent et se
terminent par deux caractères de soulignement (__).
Remarque: Pour plus de lisibilité, les caractères de soulignement sont souvent
séparés par un espace. Dans votre code source, vous ne devez pas insérer cet
espace entre les caractères de soulignement.

3.1.4.6.8.1 Macros prédéfinies


Le compilateur prédéfinit certains identificateurs globaux connus comme constantes manifestes. La plupart des identificateurs
commencent et se terminent par deux caractères de soulignement (__).

Remarque: Pour plus de lisibilité, les caractères de soulignement sont souvent séparés par un espace. Dans votre code
source, vous ne devez pas insérer cet espace entre les caractères de soulignement.

Macro Valeur Description


__BCOPT__ 1 Définie dans n'importe quel compilateur avec un optimisateur.
__BCPLUSPLUS__ • 0x0570 pour BDS Définie si vous avez sélectionné la compilation C++. Cette valeur
2006 augmentera dans les prochaines versions.

• 0x0590 pour
C++Builder 2007
• 0x0591 pour la Mise
à jour 1 de
C++Builder 2007
• 0x0592 pour RAD
Studio 2007
• 0x0593 pour la Mise
à jour Décembre de
RAD Studio 2007

__BORLANDC__ • 0x0570 pour BDS Numéro de version.


2006
• 0x0590 pour
C++Builder 2007
• 0x0591 pour la Mise
à jour 1 de
3 C++Builder 2007
• 0x0592 pour RAD
Studio 2007
• 0x0593 pour la Mise
à jour Décembre de
RAD Studio 2007

714
3.1 Référence C++ RAD Studio Guide du langage C++

__CDECL__ 1 Définie si les conventions d'appel sont initialisées à cdecl ; sinon,


elle est non définie.
_CHAR_UNSIGNED 1 Définie par défaut pour indiquer que le char par défaut est
unsigned char. Utilisez l'option de compilation –K pour annuler la
définition de cette macro.
__CODEGUARD__ Définie lorsque l'une des options CodeGuard du compilateur est
utilisée ; sinon, elle est non définie.
__CONSOLE__ 1 Lorsqu'elle est définie, la macro indique que l'application est une
application console.
_CPPUNWIND 1 Autorise le déroulement de la pile. La valeur est true par défaut.
Utilisez -xd- pour désactiver cette possibilité.
__cplusplus 1 Définie en mode C++ ; sinon, elle est non définie.
__DATE__ Littéral chaîne Donne la date du début du traitement du fichier en cours.
__DLL__ 1 Définie lorsque l'option -WD du compilateur est utilisée ; sinon, elle
est non définie.
__FILE__ Littéral chaîne Nom du fichier en cours de traitement.
__FLAT__ 1 définie lors de la compilation dans un modèle de mémoire linéaire
32 bits.
__FUNC__ Littéral chaîne Nom de la fonction en cours de traitement. Plus d'informations.
__LINE__ Constante décimale Numéro de ligne du fichier en cours de traitement.
_M_IX86 0x12c Toujours définie. La valeur par défaut est 300. Vous pouvez
modifier cette valeur en 400 ou en 500 en utilisant l'option de
compilateur /4 ou /5.
__MT__ 1 Définie uniquement si l'option -tWM est utilisée. Indique que la
bibliothèque multithread doit être liée.
__PASCAL__ 1 Définie si les conventions d'appel sont initialisées à Pascal ; sinon,
elle est non définie.
__STDC__ 1 Définie si vous compilez avec l'option de compilateur -A ; sinon, elle
est non définie.
__TCPLUSPLUS__ 0x0570 Numéro de version.
__TEMPLATES__ 1 Définie à 1 pour les fichiers C++ (ce qui signifie que les templates
sont supportés) ; sinon, elle est non définie.
__TIME__ Littéral chaîne Donne l'heure du début du traitement du fichier en cours.
__TLS__ 1 Stockage local thread. Toujours définie.

715
Guide du langage C++ RAD Studio 3.1 Référence C++

__TURBOC__ • 0x0570 pour BDS Valeur qui augmentera dans les prochaines versions.
2006
• 0x0590 pour
C++Builder 2007
• 0x0591 pour la Mise
à jour 1 de
C++Builder 2007
• 0x0592 pour RAD
Studio 2007
• 0x0593 pour la Mise
à jour Décembre de
RAD Studio 2007

_WCHAR_T Définie seulement pour les programmes C++ pour indiquer que
wchar_t est un type de données intrinsèque.
_WCHAR_T_DEFINED Définie seulement pour les programmes C++ pour indiquer que
wchar_t est un type de données intrinsèque.
_Windows Définie lors de la compilation sur la plate-forme Windows.
__WIN32__ 1 Toujours définie pour les applications console et GUI sur la
plate-forme Windows.
__linux__ Définie lors de la compilation sur la plate-forme Linux.

Remarque: __DATE__

, __FILE__ , __FUNC__, __LINE__, __STDC__ et __TIME__ ne peuvent pas être redéfinies et leur définition ne peut pas être
annulée.

Voir aussi
Effets secondaires et autres risques ( see page 701)

Utilisation de la barre oblique inversée (\) de poursuite de ligne ( see page 701)

Conversion en chaîne avec # ( see page 701)

3.1.4.6.9 Directives du préprocesseur


Cette section traite des directives du préprocesseur.

Rubriques
Nom Description
Directives du préprocesseur ( see page 716) Les directives du préprocesseur sont habituellement placées au début du code
source, mais elles peuvent apparaître en tout point du programme. Le
préprocesseur détecte les directives du préprocesseur (appelées aussi lignes de
contrôle) et analyse les jetons qui y sont incorporés. Le préprocesseur supporte
3 les directives suivantes :
# (directive nulle) ( see page 717) Syntaxe

3.1.4.6.9.1 Directives du préprocesseur


Les directives du préprocesseur sont habituellement placées au début du code source, mais elles peuvent apparaître en tout
point du programme. Le préprocesseur détecte les directives du préprocesseur (appelées aussi lignes de contrôle) et analyse
les jetons qui y sont incorporés. Le préprocesseur supporte les directives suivantes :

716
3.1 Référence C++ RAD Studio C Runtime Library Reference

# (directive nulle) #ifdef


#define #ifndef
#elif #undef
#else #include
#endif #line
#error #pragma
#if #import

Toute ligne commençant par un # est considérée comme une directive de préprocesseur, à moins que le # ne soit inclus dans
un littéral chaîne, dans une constante caractère ou incorporé à un commentaire. Le # initial peut être précédé ou suivi de
caractères inertes (à l'exclusion des caractères de nouvelle ligne).

3.1.4.6.9.2 # (directive nulle)


Syntaxe
#
Description

La directive nulle consiste en une ligne contenant le caractère #. Cette ligne est toujours ignorée.

3.1.5 C Runtime Library Reference


RAD Studio has several hundred functions, macros, and classes that you call from within your C and C++ programs to perform a
wide variety of tasks, including low- and high-level I/O, string and file manipulation, memory allocation, process control, data
conversion, mathematical calculations, and more.

Note: In the online help, each function, macro, and class in the C Runtime Library is listed only once . However, some functions,
macros, and classes are defined in more than one header file.

For example, _strerror is defined in both string.h and stdio.h. For functions that are defined in several header files, the online
help assigns the function to the first header file in alphabetic order. Thus, you will find _strerror listed in the help in stdio.h but
not in string.h.

To find a function, macro, or class that is not listed in a header file in which you expect it, please use the help Index.

Rubriques
Nom Description
alloc.h ( see page 718) The following functions, macros, and classes are provided in alloc.h:
assert.h ( see page 736) The following functions, macros, and classes are provided in assert.h:
conio.h ( see page 738) The following functions, macros, and classes are provided in conio.h:
3
ctype.h ( see page 772) The following functions, macros, and classes are provided in ctype.h:
delayimp.h ( see page 793) The following functions, macros, and classes are provided in delayimp.h:
direct.h ( see page 796) The following functions, macros, and classes are provided in direct.h:
dirent.h ( see page 798) The following functions, macros, and classes are provided in dirent.h:
dir.h ( see page 805) The following functions, macros, and classes are provided in dir.h:
dos.h ( see page 824) The following functions, macros, and classes are provided in dos.h:
errno.h ( see page 837) The following functions, macros, and classes are provided in errno.h:
except.h ( see page 844) The following functions, macros, and classes are provided in except.h:

717
C Runtime Library Reference RAD Studio 3.1 Référence C++

fastmath.h ( see page 848) The following functions, macros, and classes are provided in fastmath.h:
fcntl.h ( see page 850) The following functions, macros, and classes are provided in fcntl.h:
float.h ( see page 859) The following functions, macros, and classes are provided in float.h:
io.h ( see page 870) The following functions, macros, and classes are provided in io.h:
limits.h ( see page 922) The following functions, macros, and classes are provided in limits.h:
locale.h ( see page 924) The following functions, macros, and classes are provided in locale.h:
malloc.h ( see page 929) The following functions, macros, and classes are provided in malloc.h:
math.h ( see page 930) The following functions, macros, and classes are provided in math.h:
mem.h ( see page 968) The following functions, macros, and classes are provided in mem.h:
new.h ( see page 977) The following functions, macros, and classes are provided in new.h:
process.h ( see page 980) The following functions, macros, and classes are provided in process.h:
setjmp.h ( see page 1002) The following functions, macros, and classes are provided in setjmp.h:
share.h ( see page 1005) The following functions, macros, and classes are provided in share.h:
signal.h ( see page 1006) The following functions, macros, and classes are provided in signal.h:
stdarg.h ( see page 1012) The following functions, macros, and classes are provided in stdarg.h:
stddef.h ( see page 1013) The following functions, macros, and classes are provided in stddef.h:
stdio.h ( see page 1015) The following functions, macros, and classes are provided in stdio.h:
stdlib.h ( see page 1087) The following functions, macros, and classes are provided in stdlib.h:
string.h ( see page 1146) The following functions, macros, and classes are provided in string.h:
sys\stat.h ( see page 1193) The following functions, macros, and classes are provided in sys\stat.h:
sys\timeb.h ( see page 1197) The following functions, macros, and classes are provided in sys\timeb.h:
sys\types.h ( see page 1199) The following functions, macros, and classes are provided in sys\types.h:
time.h ( see page 1200) The following functions, macros, and classes are provided in time.h:
typeinfo.h ( see page 1218) The following functions, macros, and classes are provided in typeinfo.h:
utime.h ( see page 1220) The following functions, macros, and classes are provided in utime.h:
values.h ( see page 1221) The following functions, macros, and classes are provided in values.h:

3.1.5.1 alloc.h
The following functions, macros, and classes are provided in alloc.h:

Rubriques
Nom Description
_heapchk ( see page 722) Header File
malloc.h
Category
Memory Routines
Syntax
int _heapchk(void);
Description
Checks and verifies the heap.
_heapchk walks through the heap and examines each block, checking its
pointers, size, and other critical attributes.
Return Value
One of the following values:

718
3.1 Référence C++ RAD Studio C Runtime Library Reference

_heapmin ( see page 723) Header File


malloc.h
Category
Memory Routines
Prototype
int _heapmin(void);
Description
Release unused heap areas.
The _heapmin function returns unused areas of the heap to the operating
system. This allows other processes to use blocks that have been allocated and
then freed. Due to fragmentation of the heap, _heapmin might not always be able
to return unused memory to the operating system; this is not an error.
Return Value
_heapmin returns 0 if it is successful, or -1 if an error occurs.
Portability
_heapset ( see page 723) Header File
malloc.h
Category
Memory Routines
Prototype
int _heapset(unsigned int fillvalue);
Description
Fills the free blocks on the heap with a constant value.
_heapset checks the heap for consistency using the same methods as
_heapchk. It then fills each free block in the heap with the value contained in the
least significant byte of fillvalue. This function can be used to find heap-related
problems. It does not guarantee that subsequently allocated blocks will be filled
with the specified value.
Return Value
One of the following values:
_msize ( see page 726) Header File
malloc.h
Category
Memory Routines
Prototype
size_t _msize(void *block);
Description
Returns the size of a heap block.
_msize returns the size of the allocated heap block whose address is block. The
block must have been allocated with malloc, calloc, or realloc. The returned size
can be larger than the number of bytes originally requested when the block was
allocated.
Return Value
_msize returns the size of the block in bytes.
Example
_rtl_heapwalk ( see page 726) Header File
malloc.h
Category
Memory Routines
Prototype
int _rtl_heapwalk(_HEAPINFO *hi);
Description
Inspects the heap node by node.
Remarque: This function replaces _heapwalk which is obsolete.
_rtl_heapwalk assumes the heap is correct. Use _heapchk to verify the heap
before using _rtl_heapwalk. _HEAPOK is returned with the last block on the 3
heap. _HEAPEND will be returned on the next call to _rtl_heapwalk.
_rtl_heapwalk receives a pointer to a structure of type _HEAPINFO (declared in
malloc.h). Note that the _HEAPINFO structure must be allocated on the heap
(using malloc()). You can’t pass the address of a variable declared on the stack.
For the... suite ( see page 726)

719
C Runtime Library Reference RAD Studio 3.1 Référence C++

calloc ( see page 727) Header File


alloc.h, stdlib.h
Category
Memory Routines
Prototype
void *calloc(size_t nitems, size_t size);
Description
Allocates main memory.
calloc provides access to the C memory heap. The heap is available for dynamic
allocation of variable-sized blocks of memory. Many data structures, such as
trees and lists, naturally employ heap memory allocation.
calloc allocates a block of size nitems * size. The block is initialized to 0.
Return Value
calloc returns a pointer to the newly allocated block. If not enough space exists
for the new block or if nitems or size is 0, calloc returns NULL.
Example
free ( see page 728) Header File
alloc.h, stdlib.h
Category
Memory Routines
Prototype
void free(void *block);
Description
Frees allocated block.
free deallocates a memory block allocated by a previous call to calloc, malloc, or
realloc.
Return Value
None.
Example
heapcheck ( see page 729) Header File
alloc.h
Category
Memory Routines
Prototype
int heapcheck(void);
Description
Checks and verifies the heap.
heapcheck walks through the heap and examines each block, checking its
pointers, size, and other critical attributes.
Return Value
The return value is less than 0 for an error and greater than 0 for success. The
return values and their meaning are as follows:
heapcheckfree ( see page 730) Header File
alloc.h
Category
Memory Routines
Prototype
int heapcheckfree(unsigned int fillvalue);
Description
Checks the free blocks on the heap for a constant value.
Return Value
The return value is less then 0 for an error and greater than 0 for success. The
return values and their meaning are as follows:

720
3.1 Référence C++ RAD Studio C Runtime Library Reference

heapchecknode ( see page 731) Header File


alloc.h
Category
Memory Routines
Prototype
int heapchecknode(void *node);
Description
Checks and verifies a single node on the heap.
If a node has been freed and heapchecknode is called with a pointer to the freed
block, heapchecknode can return _BADNODE rather than the expected
_FREEENTRY. This is because adjacent free blocks on the heap are merged,
and the block in question no longer exists.
Return Value
One of the following values:
heapfillfree ( see page 732) Header File
alloc.h
Category
Memory Routines
Prototype
int heapfillfree(unsigned int fillvalue);
Description
Fills the free blocks on the heap with a constant value.
Return Value
One of the following values:
heapwalk ( see page 733) Header File
alloc.h
Category
Memory Routines
Prototype
int heapwalk(struct heapinfo *hi);
Description
heapwalk is used to “walk” through the heap, node by node.
heapwalk assumes the heap is correct. Use heapcheck to verify the heap before
using heapwalk. _HEAPOK is returned with the last block on the heap.
_HEAPEND will be returned on the next call to heapwalk.
heapwalk receives a pointer to a structure of type heapinfo (declared in alloc.h).
For the first call to heapwalk, set the hi.ptr field to null. heapwalk returns with
hi.ptr containing the address of the first block. hi.size holds the size of the... suite
( see page 733)
malloc ( see page 734) Header File
alloc.h, stdlib.h
Category
Memory Routines
Prototype
void *malloc(size_t size);
Description
malloc allocates a block of size bytes from the memory heap. It allows a program
to allocate memory explicitly as it’s needed, and in the exact amounts needed.
Allocates main memory.The heap is used for dynamic allocation of variable-sized
blocks of memory. Many data structures, for example, trees and lists, naturally
employ heap memory allocation.
In the large data models, all the space beyond the program stack to the end of
available memory is available for the heap.
Return Value
On success, malloc returns a pointer to the... suite ( see page 734)
3

721
C Runtime Library Reference RAD Studio 3.1 Référence C++

realloc ( see page 735) Header File


alloc.h, stdlib.h
Category
Memory Routines
Prototype
void *realloc(void *block, size_t size);
Description
Reallocates main memory.
realloc attempts to shrink or expand the previously allocated block to size bytes.
If size is zero, the memory block is freed and NULL is returned. The block
argument points to a memory block previously obtained by calling malloc, calloc,
or realloc. If block is a NULL pointer, realloc works just like malloc.
realloc adjusts the size of the allocated block to size, copying the contents to a
new location if necessary.
Return Value
realloc returns the address of the reallocated block, which... suite ( see page
735)
stackavail ( see page 735) Header File
malloc.h
Category
Memory Routines
Prototype
size_t stackavail(void);
Description
Gets the amount of available stack memory.
stackavail returns the number of bytes available on the stack. This is the amount
of dynamic memory that alloca can access.
Return Value
stackavail returns a size_t value indicating the number of bytes available.
Example

3.1.5.1.1 _heapchk
Header File

malloc.h

Category

Memory Routines

Syntax
int _heapchk(void);

Description

Checks and verifies the heap.

_heapchk walks through the heap and examines each block, checking its pointers, size, and other critical attributes.

Return Value

One of the following values:


3
_HEAPBADNODE A corrupted heap block has been found
_HEAPEMPTY No heap exists
_HEAPOK The heap appears to be uncorrupted

Portability

722
3.1 Référence C++ RAD Studio C Runtime Library Reference

POSIX Win32 ANSI C ANSI C++


+

3.1.5.1.2 _heapmin
Header File

malloc.h

Category

Memory Routines

Prototype
int _heapmin(void);

Description

Release unused heap areas.

The _heapmin function returns unused areas of the heap to the operating system. This allows other processes to use blocks that
have been allocated and then freed. Due to fragmentation of the heap, _heapmin might not always be able to return unused
memory to the operating system; this is not an error.

Return Value

_heapmin returns 0 if it is successful, or -1 if an error occurs.

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.1.3 _heapset
Header File

malloc.h

Category

Memory Routines

Prototype
int _heapset(unsigned int fillvalue);

Description 3
Fills the free blocks on the heap with a constant value.

_heapset checks the heap for consistency using the same methods as _heapchk. It then fills each free block in the heap with the
value contained in the least significant byte of fillvalue. This function can be used to find heap-related problems. It does not
guarantee that subsequently allocated blocks will be filled with the specified value.

Return Value

One of the following values:

723
C Runtime Library Reference RAD Studio 3.1 Référence C++

_HEAPOK The heap appears to be uncorrupted


_HEAPEMPTY No heap exists
_HEAPBADNODE A corrupted heap block has been found

Example
#include <windowsx.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
BOOL InitApplication(HINSTANCE hInstance);
HWND InitInstance(HINSTANCE hInstance, int nCmdShow);
LRESULT FAR PASCAL _export MainWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam);
void ExampleHeapSet(HWND hWnd);
#pragma argsused
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg; // message
if (!InitApplication(hInstance)) // Initialize shared things
return (FALSE); // Exits if unable to initialize
/* Perform initializations that apply to a specific instance */
if (!(InitInstance(hInstance, nCmdShow)))
return (FALSE);
/* Acquire and dispatch messages until a WM_QUIT message is received. */
while (GetMessage(&msg, // message structure
NULL, // handle of window receiving the message
NULL, // lowest message to examine
NULL)) // highest message to examine
{
TranslateMessage(&msg); // Translates virtual key codes
DispatchMessage(&msg); // Dispatches message to window
}
return (msg.wParam); // Returns the value from PostQuitMessage
}
BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS wc;
// Fill in window class structure with parameters that describe the
// main window.
wc.style = CS_HREDRAW | CS_VREDRAW; // Class style(s).
wc.lpfnWndProc = (long (FAR PASCAL*)(void *,unsigned int,unsigned int, long ))MainWndProc;
// Function to retrieve messages for
// windows of this class.
wc.cbClsExtra = 0; // No per-class extra data.
wc.cbWndExtra = 0; // No per-window extra data.
wc.hInstance = hInstance; // Application that owns the class.
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL; // Name of menu resource in .RC file.
wc.lpszClassName = "Example"; // Name used in call to CreateWindow.
3 /* Register the window class and return success/failure code. */
return (RegisterClass(&wc));
}
HWND InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd; // Main window handle.
/* Create a main window for this application instance. */
hWnd = CreateWindow(
"Example", // See RegisterClass() call.
"Example _heapset 32 bit only", // Text for window title bar.

724
3.1 Référence C++ RAD Studio C Runtime Library Reference

WS_OVERLAPPEDWINDOW, // Window style.


CW_USEDEFAULT, // Default horizontal position.
CW_USEDEFAULT, // Default vertical position.
CW_USEDEFAULT, // Default width.
CW_USEDEFAULT, // Default height.
NULL, // Overlapped windows have no parent.
NULL, // Use the window class menu.
hInstance, // This instance owns this window.
NULL // Pointer not needed.
);
/* If window could not be created, return "failure" */
if (!hWnd)
return (FALSE);
/* Make the window visible; update its client area; and return "success" */
ShowWindow(hWnd, nCmdShow); // Show the window
UpdateWindow(hWnd); // Sends WM_PAINT message
return (hWnd); // Returns the value from PostQuitMessage
}
void ExampleHeapSet(HWND hWnd)
{
int hsts;
char *buffer;
if ( (buffer = (char *)malloc( 1 )) == NULL )
exit(0);
hsts = _heapset( 'Z' );
switch (hsts)
{
case _HEAPOK:
MessageBox(hWnd,"Heap is OK","Heap",MB_OK|MB_ICONINFORMATION);
break;
case _HEAPEMPTY:
MessageBox(hWnd,"Heap is empty","Heap",MB_OK|MB_ICONINFORMATION);
break;
case _HEAPBADNODE:
MessageBox(hWnd,"Bad node in heap","Heap",MB_OK|MB_ICONINFORMATION);
break;
default:
break;
}
free (buffer);
}
#pragma argsused
LRESULT FAR PASCAL _export MainWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_CREATE:
{
//Example _heapset
ExampleHeapSet(hWnd);
return NULL;
}
case WM_QUIT:
case WM_DESTROY: // message: window being destroyed
PostQuitMessage(0);
break;
default: // Passes it on if unprocessed 3
return (DefWindowProc(hWnd, message, wParam, lParam));
}
}
Portability

POSIX Win32 ANSI C ANSI C++


+

725
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.1.4 _msize
Header File

malloc.h

Category

Memory Routines

Prototype
size_t _msize(void *block);

Description

Returns the size of a heap block.

_msize returns the size of the allocated heap block whose address is block. The block must have been allocated with malloc,
calloc, or realloc. The returned size can be larger than the number of bytes originally requested when the block was allocated.

Return Value

_msize returns the size of the block in bytes.

Example
#include <malloc.h> /* malloc() _msize() */
#include <stdio.h> /* printf() */
int main( )
{
int size;
int *buffer;
buffer = malloc(100 * sizeof(int));
size = _msize(buffer);
printf("Allocated %d bytes for 100 integers\n", size);
return(0);
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.1.5 _rtl_heapwalk
Header File

malloc.h

Category
3 Memory Routines

Prototype
int _rtl_heapwalk(_HEAPINFO *hi);

Description

Inspects the heap node by node.

Remarque: This function replaces _heapwalk which is obsolete.

726
3.1 Référence C++ RAD Studio C Runtime Library Reference

_rtl_heapwalk assumes the heap is correct. Use _heapchk to verify the heap before using _rtl_heapwalk. _HEAPOK is returned
with the last block on the heap. _HEAPEND will be returned on the next call to _rtl_heapwalk.

_rtl_heapwalk receives a pointer to a structure of type _HEAPINFO (declared in malloc.h). Note that the _HEAPINFO structure
must be allocated on the heap (using malloc()). You can’t pass the address of a variable declared on the stack.

For the first call to _rtl_heapwalk, set the hi._pentry field to NULL. _rtl_heapwalk returns with hi._pentry containing the address of
the first block.

hi._size holds the size of the block in bytes.


hi._useflag is a flag that is set to _USEDENTRY if the block is currently in use. If the block is free, hi._useflag is
set to _FREEENTRY.

Return Value

This function returns one of the following values:

_HEAPBADNODE A corrupted heap block has been found


_HEAPBADPTR The _pentry field does not point to a valid heap block
_HEAPEMPTY No heap exists
_HEAPEND The end of the heap has been reached
_HEAPOK The _heapinfo block contains valid information about the next heap block

Example
#include <stdio.h>
#include <malloc.h>
#include <alloc.h>
#define NUM_PTRS 10
#define NUM_BYTES 16
int main( void )
{
_HEAPINFO *hi;
char *array[ NUM_PTRS ];
int i;
hi = (_HEAPINFO *) malloc( sizeof(_HEAPINFO) );
for( i = 0; i < NUM_PTRS; i++ )
array[ i ] = (char *) malloc( NUM_BYTES );
for( i = 0; i < NUM_PTRS; i += 2 )
free( array[ i ] );
hi->_pentry = NULL;
printf( " Size Status\n" );
printf( " ---- ------\n" );
while( _rtl_heapwalk( hi ) == _HEAPOK )
printf( "%7u %s\n", hi->_size, hi->_useflag ? "used" : "free" );
free( hi );
return 0;
}
Portability
3
POSIX Win32 ANSI C ANSI C++
+

3.1.5.1.6 calloc
Header File

727
C Runtime Library Reference RAD Studio 3.1 Référence C++

alloc.h, stdlib.h

Category

Memory Routines

Prototype
void *calloc(size_t nitems, size_t size);

Description

Allocates main memory.

calloc provides access to the C memory heap. The heap is available for dynamic allocation of variable-sized blocks of memory.
Many data structures, such as trees and lists, naturally employ heap memory allocation.

calloc allocates a block of size nitems * size. The block is initialized to 0.

Return Value

calloc returns a pointer to the newly allocated block. If not enough space exists for the new block or if nitems or size is 0, calloc
returns NULL.

Example
#include <stdio.h>
#include <alloc.h>
#include <string.h>
int main(void)
{
char *str = NULL;
/* allocate memory for string */
str = (char *) calloc(10, sizeof(char));
/* copy "Hello" into string */
strcpy(str, "Hello");
/* display string */
printf("String is %s\n", str);
/* free memory */
free(str);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.1.7 free
Header File

alloc.h, stdlib.h
3
Category

Memory Routines

Prototype
void free(void *block);

Description

728
3.1 Référence C++ RAD Studio C Runtime Library Reference

Frees allocated block.

free deallocates a memory block allocated by a previous call to calloc, malloc, or realloc.

Return Value

None.

Example
#include <string.h>
#include <stdio.h>
#include <alloc.h>
int main(void)
{
char *str;
/* allocate memory for string */
str = (char *) malloc(10);
/* copy "Hello" to string */
strcpy(str, "Hello");
/* display string */
printf("String is %s\n", str);
/* free memory */
free(str);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.1.8 heapcheck
Header File

alloc.h

Category

Memory Routines

Prototype
int heapcheck(void);

Description

Checks and verifies the heap.

heapcheck walks through the heap and examines each block, checking its pointers, size, and other critical attributes.

Return Value

The return value is less than 0 for an error and greater than 0 for success. The return values and their meaning are as follows: 3
_HEAPCORRUPT Heap has been corrupted
_HEAPEMPTY No heap
_HEAPOK Heap is verified

Example

729
C Runtime Library Reference RAD Studio 3.1 Référence C++

#include <stdio.h>
#include <alloc.h>
#define NUM_PTRS 10
#define NUM_BYTES 16
int main(void)
{
char *array[ NUM_PTRS ];
int i;
for( i = 0; i < NUM_PTRS; i++ )
array[ i ] = (char *) malloc( NUM_BYTES );
for( i = 0; i < NUM_PTRS; i += 2 )
free( array[ i ] );
if( heapcheck() == _HEAPCORRUPT )
printf( "Heap is corrupted.\n" );
else
printf( "Heap is OK.\n" );
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.1.9 heapcheckfree
Header File

alloc.h

Category

Memory Routines

Prototype
int heapcheckfree(unsigned int fillvalue);

Description

Checks the free blocks on the heap for a constant value.

Return Value

The return value is less then 0 for an error and greater than 0 for success. The return values and their meaning are as follows:

_BADVALUE A value other than the fill value was found


_HEAPCORRUPT Heap has been corrupted
_HEAPEMPTY No heap
_HEAPOK Heap is accurate

3
Portability

POSIX Win32 ANSI C ANSI C++


+

730
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.1.10 heapchecknode
Header File

alloc.h

Category

Memory Routines

Prototype
int heapchecknode(void *node);

Description

Checks and verifies a single node on the heap.

If a node has been freed and heapchecknode is called with a pointer to the freed block, heapchecknode can return _BADNODE
rather than the expected _FREEENTRY. This is because adjacent free blocks on the heap are merged, and the block in question
no longer exists.

Return Value

One of the following values:

_BADNODE Node could not be found


_FREEENTRY Node is a free block
_HEAPCORRUPT Heap has been corrupted
_HEAPEMPTY No heap
_USEDENTRY Node is a used block

Example
#include <stdio.h>
#include <alloc.h>
#define NUM_PTRS 10
#define NUM_BYTES 16
int main(void)
{
char *array[ NUM_PTRS ];
int i;
for( i = 0; i < NUM_PTRS; i++ )
array[ i ] = (char *) malloc( NUM_BYTES );
for( i = 0; i < NUM_PTRS; i += 2 )
free( array[ i ] );
for( i = 0; i < NUM_PTRS; i++ )
{
printf( "Node %2d ", i );
switch( heapchecknode( array[ i ] ) )
{ 3
case _HEAPEMPTY:
printf( "No heap.\n" );
break;
case _HEAPCORRUPT:
printf( "Heap corrupt.\n" );
break;
case _BADNODE:
printf( "Bad node.\n" );
break;
case _FREEENTRY:

731
C Runtime Library Reference RAD Studio 3.1 Référence C++

printf( "Free entry.\n" );


break;
case _USEDENTRY:
printf( "Used entry.\n" );
break;
default:
printf( "Unknown return code.\n" );
break;
}
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.1.11 heapfillfree
Header File

alloc.h

Category

Memory Routines

Prototype
int heapfillfree(unsigned int fillvalue);

Description

Fills the free blocks on the heap with a constant value.

Return Value

One of the following values:

_HEAPCORRUPT Heap has been corrupted


_HEAPEMPTY No heap
_HEAPOK Heap is accurate

Example
#include <stdio.h>
#include <alloc.h>
#include <mem.h>
#define NUM_PTRS 10
#define NUM_BYTES 16
3 int main(void)
{
char *array[ NUM_PTRS ];
int i;
int res;
for( i = 0; i < NUM_PTRS; i++ )
array[ i ] = (char *) malloc( NUM_BYTES );
for( i = 0; i < NUM_PTRS; i += 2 )
free( array[ i ] );
if( heapfillfree( 1 ) < 0 )
{

732
3.1 Référence C++ RAD Studio C Runtime Library Reference

printf( "Heap corrupted.\n" );


return 1;
}
for( i = 1; i < NUM_PTRS; i += 2 )
memset( array[ i ], 0, NUM_BYTES );
res = heapcheckfree( 1 );
if( res < 0 )
switch( res )
{
case _HEAPCORRUPT:
printf( "Heap corrupted.\n" );
return 1;
case _BADVALUE:
printf( "Bad value in free space.\n" );
return 1;
default:
printf( "Unknown error.\n" );
return 1;
}
printf( "Test successful.\n" );
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.1.12 heapwalk
Header File

alloc.h

Category

Memory Routines

Prototype
int heapwalk(struct heapinfo *hi);

Description

heapwalk is used to “walk” through the heap, node by node.

heapwalk assumes the heap is correct. Use heapcheck to verify the heap before using heapwalk. _HEAPOK is returned with the
last block on the heap. _HEAPEND will be returned on the next call to heapwalk.

heapwalk receives a pointer to a structure of type heapinfo (declared in alloc.h). For the first call to heapwalk, set the hi.ptr field
to null. heapwalk returns with hi.ptr containing the address of the first block. hi.size holds the size of the block in bytes. hi.in_use
is a flag that’s set if the block is currently in use.

Return Value
3

One of the following values:

_HEAPEMPTY No heap exists


_HEAPEND The end of the heap has been reached
_HEAPOK The heapinfo block contains valid information about the next heap block

733
C Runtime Library Reference RAD Studio 3.1 Référence C++

Example
Portability
<table htmltable<tr><th>POSIX<th>Win32<th>ANSI C<th>ANSI C++<tr><td> <td>+<td> <td> </table

3.1.5.1.13 malloc
Header File

alloc.h, stdlib.h

Category

Memory Routines

Prototype
void *malloc(size_t size);

Description

malloc allocates a block of size bytes from the memory heap. It allows a program to allocate memory explicitly as it’s needed,
and in the exact amounts needed.

Allocates main memory.The heap is used for dynamic allocation of variable-sized blocks of memory. Many data structures, for
example, trees and lists, naturally employ heap memory allocation.

In the large data models, all the space beyond the program stack to the end of available memory is available for the heap.

Return Value

On success, malloc returns a pointer to the newly allocated block of memory. If not enough space exists for the new block, it
returns NULL. The contents of the block are left unchanged. If the argument size == 0, malloc returns NULL.

Example
#include <stdio.h>
#include <string.h>
#include <alloc.h>
#include <process.h>
int main(void)
{
char *str;
/* allocate memory for string */
if ((str = (char *) malloc(10)) == NULL)
{
printf("Not enough memory to allocate buffer\n");
exit(1); /* terminate program if out of memory */
}
/* copy "Hello" into string */
strcpy(str, "Hello");
/* display string */
printf("String is %s\n", str);
/* free memory */
free(str);
3 return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

734
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.1.14 realloc
Header File

alloc.h, stdlib.h

Category

Memory Routines

Prototype
void *realloc(void *block, size_t size);

Description

Reallocates main memory.

realloc attempts to shrink or expand the previously allocated block to size bytes. If size is zero, the memory block is freed and
NULL is returned. The block argument points to a memory block previously obtained by calling malloc, calloc, or realloc. If block
is a NULL pointer, realloc works just like malloc.

realloc adjusts the size of the allocated block to size, copying the contents to a new location if necessary.

Return Value

realloc returns the address of the reallocated block, which can be different than the address of the original block.

If the block cannot be reallocated, realloc returns NULL.

If the value of size is 0, the memory block is freed and realloc returns NULL.

Example
#include <stdio.h>
#include <alloc.h>
#include <string.h>
int main(void)
{
char *str;
/* allocate memory for string */
str = (char *) malloc(10);
/* copy "Hello" into string */
strcpy(str, "Hello");
printf("String is %s\n Address is %p\n", str, str);
str = (char *) realloc(str, 20);
printf("String is %s\n New address is %p\n", str, str);
/* free memory */
free(str);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++ 3


+ + + +

3.1.5.1.15 stackavail
Header File

malloc.h

735
C Runtime Library Reference RAD Studio 3.1 Référence C++

Category

Memory Routines

Prototype
size_t stackavail(void);

Description

Gets the amount of available stack memory.

stackavail returns the number of bytes available on the stack. This is the amount of dynamic memory that alloca can access.

Return Value

stackavail returns a size_t value indicating the number of bytes available.

Example
#include <malloc.h>
#include <stdio.h>

int main(void)
{
char *buf;

printf("\nThe stack: %u\tstack pointer: %u", stackavail(), _SP);


buf = (char *) alloca(100 * sizeof(char));
printf("\nNow, the stack: %u\tstack pointer: %u", stackavail(), _SP);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.2 assert.h
The following functions, macros, and classes are provided in assert.h:

Rubriques
Nom Description
NDEBUG #define ( see page 737) Header File
assert.h
Description
NDEBUG means "Use #define to treat assert as a macro or a true function".
Can be defined in a user program. If defined, assert is a true function; otherwise
assert is a macro.

736
3.1 Référence C++ RAD Studio C Runtime Library Reference

assert ( see page 737) Header File


assert.h
Category
Diagnostic Routines
Prototype
void assert(int test);
Description
Tests a condition and possibly aborts.
assert is a macro that expands to an if statement; if test evaluates to zero, the
assert macro calls the _assert function
void _RTLENTRY _EXPFUNC _assert(char * __cond, char *
__file, int __line);
and aborts the program. The _assert function calls abort and asserts the
following a message on stderr:
Assertion failed: test, file filename, line linenum
The filename and linenum listed in the message are the source file name and line
number where the assert macro appears.
If you place the #define... suite ( see page 737)

3.1.5.2.1 NDEBUG #define


Header File

assert.h

Description

NDEBUG means "Use #define to treat assert as a macro or a true function".

Can be defined in a user program. If defined, assert is a true function; otherwise assert is a macro.

3.1.5.2.2 assert
Header File

assert.h

Category

Diagnostic Routines

Prototype
void assert(int test);

Description

Tests a condition and possibly aborts.

assert is a macro that expands to an if statement; if test evaluates to zero, the assert macro calls the _assert function
void _RTLENTRY _EXPFUNC _assert(char * __cond, char * __file, int __line);

and aborts the program. The _assert function calls abort and asserts the following a message on stderr:
3
Assertion failed: test, file filename, line linenum

The filename and linenum listed in the message are the source file name and line number where the assert macro appears.

If you place the #define NDEBUG directive ("no debugging") in the source code before the #include <assert.h> directive, the
macro expands to a no-op, the effect is to comment out the assert statement.

Return Value

None.

737
C Runtime Library Reference RAD Studio 3.1 Référence C++

Example
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
struct ITEM {
int key;
int value;
};
/* add item to list, make sure list is not null */
void additem(struct ITEM *itemptr) {
assert(itemptr != NULL);
/* add item to list */
}
int main(void)
{
additem(NULL);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.3 conio.h
The following functions, macros, and classes are provided in conio.h:

Rubriques
Nom Description
_setcursortype ( see page 746) Header File
conio.h
Category
Console I/O Routines
Prototype
void _setcursortype(int cur_t);
Description
Selects cursor appearance.
Sets the cursor type to
cgets ( see page 747) Header File
conio.h
Category
Console I/O Routines
Prototype
char *cgets(char *str);
Description
Reads a string from the console.
cgets reads a string of characters from the console, storing the string (and the
string length) in the location pointed to by str.
3 cgets reads characters until it encounters a carriage-return/linefeed (CR/LF)
combination, or until the maximum allowable number of characters have been
read. If cgets reads a CR/LF combination, it replaces the combination with a \0
(null terminator) before storing the string.
Before cgets is called, set str[0] to the maximum length of the string to be read.
On return, str[1]... suite ( see page 747)

738
3.1 Référence C++ RAD Studio C Runtime Library Reference

clreol ( see page 748) Header File


conio.h
Category
Console I/O Routines
Prototype
void clreol(void);
Description
Clears to end of line in text window.
clreol clears all characters from the cursor position to the end of the line within
the current text window, without moving the cursor.
Remarque: This function should not be used in Win32 GUI applications.
Return Value
None.
Example
clrscr ( see page 749) Header File
conio.h
Category
Console I/O Routines
Prototype
void clrscr(void);
Description
Clears the text-mode window.
clrscr clears the current text window and places the cursor in the upper left corner
(at position 1,1).
Remarque: Do not use this function in Win32 GUI applications.
Return Value
None.
Example
cprintf ( see page 750) Header File
conio.h
Category
Console I/O Routines
Prototype
int cprintf(const char *format[, argument, ...]);
Description
Writes formatted output to the screen.
cprintf accepts a series of arguments, applies to each a format specifier
contained in the format string pointed to by format, and outputs the formatted
data directly to the current text window on the screen. There must be the same
number of format specifiers as arguments.
For details details on format specifiers, see printf Format Specifiers.
The string is written either directly to screen memory or by way of a BIOS call,
depending on the value of the global... suite ( see page 750)
cputs ( see page 751) Header File
conio.h
Category
Console I/O Routines
Prototype
int cputs(const char *str);
Description
Writes a string to the screen.
cputs writes the null-terminated string str to the current text window. It does not
append a newline character.
The string is written either directly to screen memory or by way of a BIOS call,
depending on the value of the global variable _directvideo. Unlike puts, cputs 3
does not translate linefeed characters (\n) into carriage-return/linefeed character
pairs (\r\n).
Remarque: Do not use this function in Win32 GUI applications.
Return Value
cputs returns the last character printed.
Example

739
C Runtime Library Reference RAD Studio 3.1 Référence C++

cscanf ( see page 752) Header File


conio.h
Category
Console I/O Routines
Prototype
int cscanf(char *format[, address, ...]);
Description
Scans and formats input from the console.
cscanf scans a series of input fields one character at a time, reading directly from
the console. Then each field is formatted according to a format specifier passed
to cscanf in the format string pointed to by format. Finally, cscanf stores the
formatted input at an address passed to it as an argument following format, and
echoes the input directly to the screen. There must be the same number of
format specifiers and addresses as there are input fields.... suite ( see page
752)
delline ( see page 753) Header File
conio.h
Category
Console I/O Routines
Prototype
void delline(void);
Description
Deletes line in text window.
delline deletes the line containing the cursor and moves all lines below it one line
up. delline operates within the currently active text window.
Remarque: Do not use this function in Win32 GUI applications.
Return Value
None.
Example
getch ( see page 753) Header File
conio.h
Category
Console I/O Routines
Prototype
int getch(void);
Description
Gets character from keyboard, does not echo to screen.
getch reads a single character directly from the keyboard, without echoing to the
screen.
Remarque: Do not use this function in Win32 GUI applications.
Return Value
getch returns the character read from the keyboard.
Example
getche ( see page 754) Header File
conio.h
Category
Console I/O Routines
Prototype
int getche(void);
Description
Gets character from the keyboard, echoes to screen.
getche reads a single character from the keyboard and echoes it to the current
text window using direct video or BIOS.
Remarque: Do not use this function in Win32 GUI applications.
3 Return Value
getche returns the character read from the keyboard.
Example

740
3.1 Référence C++ RAD Studio C Runtime Library Reference

getpass ( see page 755) Header File


conio.h
Category
Console I/O Routines
Prototype
char *getpass(const char *prompt);
Description
Reads a password.
getpass reads a password from the system console after prompting with the
null-terminated string prompt and disabling the echo. A pointer is returned to a
null-terminated string of up to eight characters (not counting the null-terminator).
Remarque: Do not use this function in Win32 GUI applications.
Return Value
The return value is a pointer to a static string that is overwritten with each call.
Example
gettext ( see page 756) Header File
conio.h
Category
Console I/O Routines
Prototype
int gettext(int left, int top, int right, int bottom, void
*destin);
Description
Copies text from text mode screen to memory.
gettext stores the contents of an onscreen text rectangle defined by left, top,
right, and bottom into the area of memory pointed to by destin.
All coordinates are absolute screen coordinates not window-relative. The upper
left corner is (1,1). gettext reads the contents of the rectangle into memory
sequentially from left to right and top to bottom.
Each position onscreen takes 2 bytes of memory: The first byte is the character
in... suite ( see page 756)
gettextinfo ( see page 757) Header File
conio.h
Category
Console I/O Routines
Prototype
void gettextinfo(struct text_info *r);
Description
Gets text mode video information.
gettextinfo fills in the text_info structure pointed to by r with the current text video
information.
The text_info structure is defined in conio.h as follows:
struct text_info {
unsigned char winleft; /* left window coordinate */
unsigned char wintop; /* top window coordinate */
unsigned char winright; /* right window coordinate */
unsigned char winbottom; /* bottom window coordinate */
unsigned char attribute; /* text attribute */
unsigned char normattr; /* normal attribute */
unsigned char currmode; /* BW40, BW80, C40, C80,... suite
( see page 757)

741
C Runtime Library Reference RAD Studio 3.1 Référence C++

gotoxy ( see page 758) Header File


conio.h
Category
Console I/O Routines
Prototype
void gotoxy(int x, int y);
Description
Positions cursor in text window.
gotoxy moves the cursor to the given position in the current text window. If the
coordinates are in any way invalid the call to gotoxy is ignored. An example of
this is a call to gotoxy(40,30) when (35,25) is the bottom right position in the
window. Neither argument to gotoxy can be zero.
Note:Do not use this function in Win32 GUI applications.
Return Value
None.
Example
highvideo ( see page 758) Header File
conio.h
Category
Console I/O Routines
Prototype
void highvideo(void);
Description
Selects high-intensity characters.
highvideo selects high-intensity characters by setting the high-intensity bit of the
currently selected foreground color.
This function does not affect any characters currently onscreen, but does affect
those displayed by functions (such as cprintf) that perform direct video, text mode
output after highvideo is called.
Remarque: Do not use this function in Win32 GUI applications.
Return Value
None.
Example
insline ( see page 759) Header File
conio.h
Category
Console I/O Routines
Prototype
void insline(void);
Description
Inserts a blank line in the text window.
insline inserts an empty line in the text window at the cursor position using the
current text background color. All lines below the empty one move down one line,
and the bottom line scrolls off the bottom of the window.
Remarque: Do not use this function in Win32 GUI applications.
Return Value
None.
Example
kbhit ( see page 760) Header File
conio.h
Category
Console I/O Routines
Prototype
int kbhit(void);
3 Description
Checks for currently available keystrokes.
kbhit checks to see if a keystroke is currently available. Any available keystrokes
can be retrieved with getch or getche.
Remarque: Do not use this function in Win32 GUI applications.
Return Value
If a keystroke is available, kbhit returns a nonzero value. Otherwise, it returns 0.
Example

742
3.1 Référence C++ RAD Studio C Runtime Library Reference

lowvideo ( see page 761) Header File


conio.h
Category
Console I/O Routines
Prototype
void lowvideo(void);
Description
Selects low-intensity characters.
lowvideo selects low-intensity characters by clearing the high-intensity bit of the
currently selected foreground color.
This function does not affect any characters currently onscreen. It affects only
those characters displayed by functions that perform text mode, direct console
output after this function is called.
Remarque: Do not use this function in Win32 GUI applications.
Return Value
None.
Example
movetext ( see page 761) Header File
conio.h
Category
Console I/O Routines
Prototype
int movetext(int left, int top, int right, int bottom, int
destleft, int desttop);
Description
Copies text onscreen from one rectangle to another.
movetext copies the contents of the onscreen rectangle defined by left, top, right,
and bottom to a new rectangle of the same dimensions. The new rectangle’s
upper left corner is position (destleft, desttop).
All coordinates are absolute screen coordinates. Rectangles that overlap are
moved correctly.
movetext is a text mode function performing direct video output.
Note:Do not use this function in Win32 GUI applications.
Return Value
On success, movetext... suite ( see page 761)
normvideo ( see page 762) Header File
conio.h
Category
Console I/O Routines
Prototype
void normvideo(void);
Description
Selects normal-intensity characters.
normvideo selects normal characters by returning the text attribute (foreground
and background) to the value it had when the program started.
This function does not affect any characters currently on the screen, only those
displayed by functions (such as cprintf) performing direct console output
functions after normvideo is called.
Remarque: Do not use this function in Win32 GUI applications.
Return Value
None.
Example

743
C Runtime Library Reference RAD Studio 3.1 Référence C++

putch ( see page 763) Header File


conio.h
Category
Console I/O Routines
Prototype
int putch(int c);
Description
Outputs character to screen.
putch outputs the character c to the current text window. It is a text mode function
performing direct video output to the console. putch does not translate linefeed
characters (\n) into carriage-return/linefeed pairs.
The string is written either directly to screen memory or by way of a BIOS call,
depending on the value of the global variable _directvideo.
Remarque: This function should not be used in Win32 GUI applications.
Return Value
On success, putch returns the character printed, c. On error, it returns EOF....
suite ( see page 763)
puttext ( see page 764) Header File
conio.h
Category
Console I/O Routines
Prototype
int puttext(int left, int top, int right, int bottom, void
*source);
Description
Copies text from memory to the text mode screen.
puttext writes the contents of the memory area pointed to by source out to the
onscreen rectangle defined by left, top, right, and bottom.
All coordinates are absolute screen coordinates, not window-relative. The upper
left corner is (1,1).
puttext places the contents of a memory area into the defined rectangle
sequentially from left to right and top to bottom.
Each position onscreen takes 2 bytes of memory: The first byte is... suite ( see
page 764)
textattr ( see page 765) Header File
conio.h
Category
Console I/O Routines
Prototype
void textattr(int newattr);
Description
Sets text attributes.
Remarque: Do not use this function in Win32 GUI applications.
textattr lets you set both the foreground and background colors in a single call.
(Normally, you set the attributes with textcolor and textbackground.)
This function does not affect any characters currently onscreen; it affects only
those characters displayed by functions (such as cprintf) performing text mode,
direct video output after this function is called.
The color information is encoded in the newattr parameter as follows:
In this 8-bit newattr parameter:

• bits 0-3 contain the 4-bit... suite ( see page 765)

744
3.1 Référence C++ RAD Studio C Runtime Library Reference

textbackground ( see page 766) Header File


conio.h
Category
Console I/O Routines
Prototype
void textbackground(int newcolor);
Description
Selects new text background color.
Remarque: Do not use this function in Win32 GUI applications.
textbackground selects the background color. This function works for functions
that produce output in text mode directly to the screen. newcolor selects the new
background color. You can set newcolor to an integer from 0 to 7, or to one of the
symbolic constants defined in conio.h. If you use symbolic constants, you must
include conio.h.
Once you have called textbackground, all subsequent functions using direct
video output (such as cprintf) will use... suite ( see page 766)
textcolor ( see page 767) Header File
conio.h
Category
Console I/O Routines
Prototype
void textcolor(int newcolor);
Description
Selects new character color in text mode.
Remarque: Do not use this function in Win32 GUI applications.
textcolor selects the foreground character color. This function works for the
console output functions. newcolor selects the new foreground color. You can set
newcolor to an integer as given in the table below, or to one of the symbolic
constants defined in conio.h. If you use symbolic constants, you must include
conio.h.
Once you have called textcolor, all subsequent functions using direct video
output (such as cprintf) will use newcolor. textcolor... suite ( see page 767)
textmode ( see page 768) Header File
conio.h
Category
Console I/O Routines
Prototype
void textmode(int newmode);
Description
Puts screen in text mode.
Remarque: Do not use this function in Win32 GUI applications.
textmode selects a specific text mode.
You can give the text mode (the argument newmode) by using a symbolic
constant from the enumeration type text_modes (defined in conio.h).
The most commonly used text_modes type constants and the modes they
specify are given in the following table. Some additional values are defined in
conio.h.
ungetch ( see page 770) Header File
conio.h
Category
Console I/O Routines
Prototype
int ungetch(int ch);
Description
Pushes a character back to the keyboard buffer.
Remarque: Do not use this function in Win32 GUI applications. 3
ungetch pushes the character ch back to the console, causing ch to be the next
character read. The ungetch function fails if it is called more than once before the
next read.
Return Value
On success, ungetch returns the character ch.
On error, it returns EOF.
Example

745
C Runtime Library Reference RAD Studio 3.1 Référence C++

wherex ( see page 770) Header File


conio.h
Category
Console I/O Routines
Prototype
int wherex(void);
Description
Gives horizontal cursor position within window.
Remarque: Do not use this function in Win32 GUI applications.
wherex returns the x-coordinate of the current cursor position (within the current
text window).
Return Value
wherex returns an integer in the range 1 to the number of columns in the current
video mode.
Example
wherey ( see page 771) Header File
conio.h
Category
Console I/O Routines
Prototype
int wherey(void);
Description
Gives vertical cursor position within window.
Remarque: Do not use this function in Win32 GUI applications.
wherey returns the y-coordinate of the current cursor position (within the current
text window).
Return Value
wherey returns an integer in the range 1 to the number of rows in the current
video mode.
Portability
window ( see page 772) Header File
conio.h
Category
Console I/O Routines
Prototype
void window(int left, int top, int right, int bottom);
Description
Defines active text mode window.
Remarque: Do not use this function in Win32 GUI applications.
window defines a text window onscreen. If the coordinates are in any way invalid,
the call to window is ignored.
left and top are the screen coordinates of the upper left corner of the window.
right and bottom are the screen coordinates of the lower right corner.
The minimum size of the text window is one column by one line. The default
window is full screen, with... suite ( see page 772)

3.1.5.3.1 _setcursortype
Header File

conio.h

Category
3
Console I/O Routines

Prototype
void _setcursortype(int cur_t);

Description

Selects cursor appearance.

746
3.1 Référence C++ RAD Studio C Runtime Library Reference

Sets the cursor type to

_NOCURSOR Turns off the cursor


_NORMALCURSOR Normal underscore cursor
_SOLIDCURSOR Solid block cursor

Remarque: Do not use this function in Win32 GUI applications.

Return Value

None.

Example
#include <conio.h>
int main( )
{
// tell the user what to do
clrscr();
cputs("Press any key three times.\n\r");
cputs("Each time the cursor will change shape.\n\r");
gotoxy(1,5); // show a solid cursor
cputs("Now the cursor is solid.\n\r");
_setcursortype(_SOLIDCURSOR);
while(!kbhit()) {}; // wait to proceed
getch();
gotoxy(1,5); // remove the cursor
cputs("Now the cursor is gone.");
clreol();
gotoxy(1,6);
_setcursortype(_NOCURSOR);
while(!kbhit()) {}; // wait to proceed
getch();
gotoxy(1,5); // show a normal cursor
cputs("Now the cursor is normal.");
clreol();
gotoxy(1,6);
_setcursortype(_NORMALCURSOR);
while(!kbhit()) {}; // wait to proceed
getch();
clrscr();
return(0);
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.2 cgets
Header File 3
conio.h

Category

Console I/O Routines

Prototype
char *cgets(char *str);

747
C Runtime Library Reference RAD Studio 3.1 Référence C++

Description

Reads a string from the console.

cgets reads a string of characters from the console, storing the string (and the string length) in the location pointed to by str.

cgets reads characters until it encounters a carriage-return/linefeed (CR/LF) combination, or until the maximum allowable
number of characters have been read. If cgets reads a CR/LF combination, it replaces the combination with a \0 (null terminator)
before storing the string.

Before cgets is called, set str[0] to the maximum length of the string to be read. On return, str[1] is set to the number of
characters actually read. The characters read start at str[2] and end with a null terminator. Thus, str must be at least str[0] plus 2
bytes long.

Remarque: Do not use this function for Win32 GUI applications.

Return Value

On success, cgets returns a pointer to str[2].

Example
#include <stdio.h>
#include <conio.h>
int main(void)
{
char buffer[83];
char *p;
/* There is space for 80 characters plus the NULL terminator */
buffer[0] = 81;
printf("Input some chars:");
p = cgets(buffer);
printf("\ncgets read %d characters: \"%s\"\n", buffer[1], p);
printf("The returned pointer is %p, buffer[0] is at %p\n", p, &buffer);
/* Leave room for 5 characters plus the NULL terminator */
buffer[0] = 6;
printf("Input some chars:");
p = cgets(buffer);
printf("\ncgets read %d characters: \"%s\"\n", buffer[1], p);
printf("The returned pointer is %p, buffer[0] is at %p\n", p, &buffer);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.3 clreol
Header File
3 conio.h

Category

Console I/O Routines

Prototype
void clreol(void);

Description

748
3.1 Référence C++ RAD Studio C Runtime Library Reference

Clears to end of line in text window.

clreol clears all characters from the cursor position to the end of the line within the current text window, without moving the cursor.

Remarque: This function should not be used in Win32 GUI applications.

Return Value

None.

Example
#include <conio.h>
int main(void)
{
clrscr();
cprintf("The function CLREOL clears all characters from the\r\n");
cprintf("cursor position to the end of the line within the\r\n");
cprintf("current text window, without moving the cursor.\r\n");
cprintf("Press any key to continue . . .");
gotoxy(14, 4);
getch();
clreol();
getch();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.4 clrscr
Header File

conio.h

Category

Console I/O Routines

Prototype
void clrscr(void);

Description

Clears the text-mode window.

clrscr clears the current text window and places the cursor in the upper left corner (at position 1,1).

Remarque: Do not use this function in Win32 GUI applications.

Return Value 3
None.

Example
#include <conio.h>
int main(void)
{
int i;
clrscr();

749
C Runtime Library Reference RAD Studio 3.1 Référence C++

for (i = 0; i < 20; i++)


cprintf("%d\r\n", i);
cprintf("\r\nPress any key to clear screen");
getch();
clrscr();
cprintf("The screen has been cleared!");
getch();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.5 cprintf
Header File

conio.h

Category

Console I/O Routines

Prototype
int cprintf(const char *format[, argument, ...]);

Description

Writes formatted output to the screen.

cprintf accepts a series of arguments, applies to each a format specifier contained in the format string pointed to by format, and
outputs the formatted data directly to the current text window on the screen. There must be the same number of format specifiers
as arguments.

For details details on format specifiers, see printf Format Specifiers.

The string is written either directly to screen memory or by way of a BIOS call, depending on the value of the global variable
_directvideo.

Unlike fprintf and printf, cprintf does not translate linefeed characters (\n) into carriage-return/linefeed character pairs (\r\n). Tab
characters (specified by \t) are not expanded into spaces.

Remarque: Do not use this function in Win32 GUI applications.

Return Value

cprintf returns the number of characters output.

Example
3 #include <conio.h>
int main(void)
{
/* clear the screen */
clrscr();
/* create a text window */
window(10, 10, 80, 25);
/* output some text in the window */
cprintf("Hello world\r\n");
/* wait for a key */

750
3.1 Référence C++ RAD Studio C Runtime Library Reference

getch();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.6 cputs
Header File

conio.h

Category

Console I/O Routines

Prototype
int cputs(const char *str);

Description

Writes a string to the screen.

cputs writes the null-terminated string str to the current text window. It does not append a newline character.

The string is written either directly to screen memory or by way of a BIOS call, depending on the value of the global variable
_directvideo. Unlike puts, cputs does not translate linefeed characters (\n) into carriage-return/linefeed character pairs (\r\n).

Remarque: Do not use this function in Win32 GUI applications.

Return Value

cputs returns the last character printed.

Example
#include <conio.h>
int main(void)
{
/* clear the screen */
clrscr();
/* create a text window */
window(10, 10, 80, 25);
/* output some text in the window */
cputs("This is within the window\r\n");
/* wait for a key */
getch();
return 0;
}
Portability 3

POSIX Win32 ANSI C ANSI C++


+

751
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.3.7 cscanf
Header File

conio.h

Category

Console I/O Routines

Prototype
int cscanf(char *format[, address, ...]);

Description

Scans and formats input from the console.

cscanf scans a series of input fields one character at a time, reading directly from the console. Then each field is formatted
according to a format specifier passed to cscanf in the format string pointed to by format. Finally, cscanf stores the formatted
input at an address passed to it as an argument following format, and echoes the input directly to the screen. There must be the
same number of format specifiers and addresses as there are input fields.

Remarque: For details on format specifiers, see scanf Format Specifiers.

cscanf might stop scanning a particular field before it reaches the normal end-of-field (whitespace) character, or it might
terminate entirely for a number of reasons. See scanf for a discussion of possible causes.

Remarque: Do not use this function in Win32 GUI applications.

Return Value

cscanf returns the number of input fields successfully scanned, converted, and stored; the return value does not include scanned
fields that were not stored. If no fields were stored, the return value is 0.

If cscanf attempts to read at end-of-file , the return value is EOF.

Example
#include <conio.h>
int main(void)
{
char string[80];
/* clear the screen */
clrscr();
/* Prompt the user for input */
cprintf("Enter a string with no spaces:");
/* read the input */
cscanf("%s", string);
/* display what was read */
cprintf("\r\nThe string entered is: %s", string);
return 0;
}
3 Portability

POSIX Win32 ANSI C ANSI C++


+

752
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.3.8 delline
Header File

conio.h

Category

Console I/O Routines

Prototype
void delline(void);

Description

Deletes line in text window.

delline deletes the line containing the cursor and moves all lines below it one line up. delline operates within the currently active
text window.

Remarque: Do not use this function in Win32 GUI applications.

Return Value

None.

Example
#include <conio.h>
int main(void)
{
clrscr();
cprintf("The function DELLINE deletes the line containing the\r\n");
cprintf("cursor and moves all lines below it one line up.\r\n");
cprintf("DELLINE operates within the currently active text\r\n");
cprintf("window. Press any key to continue . . .");
gotoxy(1,2); /* Move the cursor to the second line and first column */
getch();
delline();
getch();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.9 getch
Header File 3
conio.h

Category

Console I/O Routines

Prototype
int getch(void);

753
C Runtime Library Reference RAD Studio 3.1 Référence C++

Description

Gets character from keyboard, does not echo to screen.

getch reads a single character directly from the keyboard, without echoing to the screen.

Remarque: Do not use this function in Win32 GUI applications.

Return Value

getch returns the character read from the keyboard.

Example
#include <conio.h>
#include <stdio.h>
int main(void)
{
int c;
int extended = 0;
c = getch();
if (!c)
extended = getch();
if (extended)
printf("The character is extended\n");
else
printf("The character isn't extended\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.10 getche
Header File

conio.h

Category

Console I/O Routines

Prototype
int getche(void);

Description

Gets character from the keyboard, echoes to screen.

getche reads a single character from the keyboard and echoes it to the current text window using direct video or BIOS.
3
Remarque: Do not use this function in Win32 GUI applications.

Return Value

getche returns the character read from the keyboard.

Example
#include <stdio.h>
#include <conio.h>

754
3.1 Référence C++ RAD Studio C Runtime Library Reference

int main(void)
{
char ch;
printf("Input a character:");
ch = getche();
printf("\nYou input a '%c'\n", ch);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.11 getpass
Header File

conio.h

Category

Console I/O Routines

Prototype
char *getpass(const char *prompt);

Description

Reads a password.

getpass reads a password from the system console after prompting with the null-terminated string prompt and disabling the
echo. A pointer is returned to a null-terminated string of up to eight characters (not counting the null-terminator).

Remarque: Do not use this function in Win32 GUI applications.

Return Value

The return value is a pointer to a static string that is overwritten with each call.

Example
#include <conio.h>

int main(void)
{
char *password;

password = getpass("Input a password:");


cprintf("The password is: %s\r\n", password);
return 0;
}
Portability 3

POSIX Win32 ANSI C ANSI C++


+

755
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.3.12 gettext
Header File

conio.h

Category

Console I/O Routines

Prototype
int gettext(int left, int top, int right, int bottom, void *destin);

Description

Copies text from text mode screen to memory.

gettext stores the contents of an onscreen text rectangle defined by left, top, right, and bottom into the area of memory pointed to
by destin.

All coordinates are absolute screen coordinates not window-relative. The upper left corner is (1,1). gettext reads the contents of
the rectangle into memory sequentially from left to right and top to bottom.

Each position onscreen takes 2 bytes of memory: The first byte is the character in the cell and the second is the cell's video
attribute. The space required for a rectangle w columns wide by h rows high is defined as

bytes = (h rows) x (w columns) x 2

Remarque: Do not use this function in Win32 GUI applications.

Return Value

gettext returns 1 if the operation succeeds.

On error, it returns 0 (for example, if it fails because you gave coordinates outside the range of the current screen mode).

Example
#include <conio.h>

char buffer[4096];
int main(void)
{
int i;
clrscr();
for (i = 0; i <= 20; i++)
cprintf("Line #%d\r\n", i);
gettext(1, 1, 80, 25, buffer);
gotoxy(1, 25);
cprintf("Press any key to clear screen...");
getch();
clrscr();
gotoxy(1, 25);
3 cprintf("Press any key to restore screen...");
getch();
puttext(1, 1, 80, 25, buffer);
gotoxy(1, 25);
cprintf("Press any key to quit...");
getch();
return 0;
}
Portability

756
3.1 Référence C++ RAD Studio C Runtime Library Reference

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.13 gettextinfo
Header File

conio.h

Category

Console I/O Routines

Prototype
void gettextinfo(struct text_info *r);

Description

Gets text mode video information.

gettextinfo fills in the text_info structure pointed to by r with the current text video information.

The text_info structure is defined in conio.h as follows:


struct text_info {
unsigned char winleft; /* left window coordinate */
unsigned char wintop; /* top window coordinate */
unsigned char winright; /* right window coordinate */
unsigned char winbottom; /* bottom window coordinate */
unsigned char attribute; /* text attribute */
unsigned char normattr; /* normal attribute */
unsigned char currmode; /* BW40, BW80, C40, C80, or C4350 */
unsigned char screenheight; /* text screen's height */
unsigned char screenwidth; /* text screen's width */
unsigned char curx; /* x-coordinate in current window */
unsigned char cury; /* y-coordinate in current window */
};

Remarque: Do not use this function in Win32 GUI applications.

Return Value

None. Results are returned in the structure pointed to by r. 3


Example
#include <conio.h>
int main(void)
{
struct text_info ti;
gettextinfo(&ti);
cprintf("window left %2d\r\n",ti.winleft);
cprintf("window top %2d\r\n",ti.wintop);

757
C Runtime Library Reference RAD Studio 3.1 Référence C++

cprintf("window right %2d\r\n",ti.winright);


cprintf("window bottom %2d\r\n",ti.winbottom);
cprintf("attribute %2d\r\n",ti.attribute);
cprintf("normal attribute %2d\r\n",ti.normattr);
cprintf("current mode %2d\r\n",ti.currmode);
cprintf("screen height %2d\r\n",ti.screenheight);
cprintf("screen width %2d\r\n",ti.screenwidth);
cprintf("current x %2d\r\n",ti.curx);
cprintf("current y %2d\r\n",ti.cury);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.14 gotoxy
Header File

conio.h

Category

Console I/O Routines

Prototype
void gotoxy(int x, int y);

Description

Positions cursor in text window.

gotoxy moves the cursor to the given position in the current text window. If the coordinates are in any way invalid the call to
gotoxy is ignored. An example of this is a call to gotoxy(40,30) when (35,25) is the bottom right position in the window. Neither
argument to gotoxy can be zero.

Note:Do not use this function in Win32 GUI applications.

Return Value

None.

Example
#include <conio.h>
int main(void)
{
clrscr();
gotoxy(35, 12);
cprintf("Hello world");
3 getch();
return 0;
}

3.1.5.3.15 highvideo
Header File

conio.h

758
3.1 Référence C++ RAD Studio C Runtime Library Reference

Category

Console I/O Routines

Prototype
void highvideo(void);

Description

Selects high-intensity characters.

highvideo selects high-intensity characters by setting the high-intensity bit of the currently selected foreground color.

This function does not affect any characters currently onscreen, but does affect those displayed by functions (such as cprintf)
that perform direct video, text mode output after highvideo is called.

Remarque: Do not use this function in Win32 GUI applications.

Return Value

None.

Example
#include <conio.h>
int main(void)
{
clrscr();
lowvideo();
cprintf("Low Intensity text\r\n");
highvideo();
gotoxy(1,2);
cprintf("High Intensity Text\r\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.16 insline
Header File

conio.h

Category

Console I/O Routines

Prototype
void insline(void); 3
Description

Inserts a blank line in the text window.

insline inserts an empty line in the text window at the cursor position using the current text background color. All lines below the
empty one move down one line, and the bottom line scrolls off the bottom of the window.

Remarque: Do not use this function in Win32 GUI applications.

759
C Runtime Library Reference RAD Studio 3.1 Référence C++

Return Value

None.

Example
#include <conio.h>
int main(void)
{
clrscr();
cprintf("INSLINE inserts an empty line in the text window\r\n");
cprintf("at the cursor position using the current text\r\n");
cprintf("background color. All lines below the empty one\r\n");
cprintf("move down one line and the bottom line scrolls\r\n");
cprintf("off the bottom of the window.\r\n");
cprintf("\r\nPress any key to continue:");
gotoxy(1, 3);
getch();
insline();
getch();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.17 kbhit
Header File

conio.h

Category

Console I/O Routines

Prototype
int kbhit(void);

Description

Checks for currently available keystrokes.

kbhit checks to see if a keystroke is currently available. Any available keystrokes can be retrieved with getch or getche.

Remarque: Do not use this function in Win32 GUI applications.

Return Value

If a keystroke is available, kbhit returns a nonzero value. Otherwise, it returns 0.


3 Example
#include <conio.h>
int main(void)
{
cprintf("Press any key to continue:");
while (!kbhit()) /* do nothing */ ;
cprintf("\r\nA key was pressed...\r\n");
return 0;
}

760
3.1 Référence C++ RAD Studio C Runtime Library Reference

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.18 lowvideo
Header File

conio.h

Category

Console I/O Routines

Prototype
void lowvideo(void);

Description

Selects low-intensity characters.

lowvideo selects low-intensity characters by clearing the high-intensity bit of the currently selected foreground color.

This function does not affect any characters currently onscreen. It affects only those characters displayed by functions that
perform text mode, direct console output after this function is called.

Remarque: Do not use this function in Win32 GUI applications.

Return Value

None.

Example
#include <conio.h>
int main(void)
{
clrscr();
highvideo();
cprintf("High Intensity Text\r\n");
lowvideo();
gotoxy(1,2);
cprintf("Low Intensity Text\r\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+
3

3.1.5.3.19 movetext
Header File

conio.h

Category

761
C Runtime Library Reference RAD Studio 3.1 Référence C++

Console I/O Routines

Prototype
int movetext(int left, int top, int right, int bottom, int destleft, int desttop);

Description

Copies text onscreen from one rectangle to another.

movetext copies the contents of the onscreen rectangle defined by left, top, right, and bottom to a new rectangle of the same
dimensions. The new rectangle’s upper left corner is position (destleft, desttop).

All coordinates are absolute screen coordinates. Rectangles that overlap are moved correctly.

movetext is a text mode function performing direct video output.

Note:Do not use this function in Win32 GUI applications.

Return Value

On success, movetext returns nonzero.

On error (for example, if it failed because you gave coordinates outside the range of the current screen mode), movetext returns
0.

Example
#include <conio.h>
#include <string.h>
int main(void)
{
char *str = "This is a test string";
clrscr();
cputs(str);
getch();
movetext(1, 1, strlen(str), 2, 10, 10);
getch();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.20 normvideo
Header File

conio.h

Category
3
Console I/O Routines

Prototype
void normvideo(void);

Description

Selects normal-intensity characters.

762
3.1 Référence C++ RAD Studio C Runtime Library Reference

normvideo selects normal characters by returning the text attribute (foreground and background) to the value it had when the
program started.

This function does not affect any characters currently on the screen, only those displayed by functions (such as cprintf)
performing direct console output functions after normvideo is called.

Remarque: Do not use this function in Win32 GUI applications.

Return Value

None.

Example
#include <conio.h>
int main(void)
{
normvideo();
cprintf("NORMAL Intensity Text\r\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.21 putch
Header File

conio.h

Category

Console I/O Routines

Prototype
int putch(int c);

Description

Outputs character to screen.

putch outputs the character c to the current text window. It is a text mode function performing direct video output to the console.
putch does not translate linefeed characters (\n) into carriage-return/linefeed pairs.

The string is written either directly to screen memory or by way of a BIOS call, depending on the value of the global variable
_directvideo.

Remarque: This function should not be used in Win32 GUI applications.

Return Value 3
On success, putch returns the character printed, c. On error, it returns EOF.

Example
#include <stdio.h>
#include <conio.h>
int main(void)
{

763
C Runtime Library Reference RAD Studio 3.1 Référence C++

char ch = 0;
printf("Input a string:");
while ((ch != '\r'))
{
ch = getch();
putch(ch);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.22 puttext
Header File

conio.h

Category

Console I/O Routines

Prototype
int puttext(int left, int top, int right, int bottom, void *source);

Description

Copies text from memory to the text mode screen.

puttext writes the contents of the memory area pointed to by source out to the onscreen rectangle defined by left, top, right, and
bottom.

All coordinates are absolute screen coordinates, not window-relative. The upper left corner is (1,1).

puttext places the contents of a memory area into the defined rectangle sequentially from left to right and top to bottom.

Each position onscreen takes 2 bytes of memory: The first byte is the character in the cell, and the second is the cell’s video
attribute. The space required for a rectangle w columns wide by h rows high is defined as

bytes = (h rows) x (w columns) x 2

puttext is a text mode function performing direct video output.

Note:This function should not be used in Win32 GUI applications.

Return Value

puttext returns a nonzero value if the operation succeeds; it returns 0 if it fails (for example, if you gave coordinates outside the
range of the current screen mode).
3
Example
#include <conio.h>
int main(void)
{
char buffer[512];
/* put some text to the console */
clrscr();
gotoxy(20, 12);
cprintf("This is a test. Press any key to continue ...");

764
3.1 Référence C++ RAD Studio C Runtime Library Reference

getch();
/* grab screen contents */
gettext(20, 12, 36, 21,buffer);
clrscr();
/* put selected characters back to the screen */
gotoxy(20, 12);
puttext(20, 12, 36, 21, buffer);
getch();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.23 textattr
Header File

conio.h

Category

Console I/O Routines

Prototype
void textattr(int newattr);

Description

Sets text attributes.

Remarque: Do not use this function in Win32 GUI applications.

textattr lets you set both the foreground and background colors in a single call. (Normally, you set the attributes with textcolor
and textbackground.)

This function does not affect any characters currently onscreen; it affects only those characters displayed by functions (such as
cprintf) performing text mode, direct video output after this function is called.

The color information is encoded in the newattr parameter as follows:

In this 8-bit newattr parameter:

• bits 0-3 contain the 4-bit foreground color (0 to 15).


• bits 4-6 contain the 3-bit background color (0 to 7).
• bit 8 is the blink-enable bit.
If the blink-enable bit is on, the character blinks. This can be accomplished by adding the constant BLINK to the attribute.
• If you use the symbolic color constants defined in conio.h for creating text attributes with textattr, note the following limitations 3
on the color you select for the background:
• You can select only one of the first eight colors for the background.
• You must shift the selected background color left by 4 bits to move it into the correct bit positions.
These symbolic constants are listed in the following table:
Return Value
None.

765
C Runtime Library Reference RAD Studio 3.1 Référence C++

Example
#include <conio.h>
int main(void)
{
int i;
clrscr();
for (i=0; i<9; i++)
{
textattr(i + ((i+1) << 4));
cprintf("This is a test\r\n");
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.24 textbackground
Header File

conio.h

Category

Console I/O Routines

Prototype
void textbackground(int newcolor);

Description

Selects new text background color.

Remarque: Do not use this function in Win32 GUI applications.

textbackground selects the background color. This function works for functions that produce output in text mode directly to the
screen. newcolor selects the new background color. You can set newcolor to an integer from 0 to 7, or to one of the symbolic
constants defined in conio.h. If you use symbolic constants, you must include conio.h.

Once you have called textbackground, all subsequent functions using direct video output (such as cprintf) will use newcolor.
textbackground does not affect any characters currently onscreen.

The following table lists the symbolic constants and the numeric values of the allowable colors:

BLACK 0
BLUE 1
3 GREEN 2
CYAN 3
RED 4
MAGENTA 5
BROWN 6
LIGHTGRAY 7

766
3.1 Référence C++ RAD Studio C Runtime Library Reference

Return Value

None.

Example
#include <conio.h>
int main(void)
{
int i, j;
clrscr();
for (i=0; i<9; i++)
{
for (j=0; j<80; j++)
cprintf("C");
cprintf("\r\n");
textcolor(i+1);
textbackground(i);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.25 textcolor
Header File

conio.h

Category

Console I/O Routines

Prototype
void textcolor(int newcolor);

Description

Selects new character color in text mode.

Remarque: Do not use this function in Win32 GUI applications.

textcolor selects the foreground character color. This function works for the console output functions. newcolor selects the new
foreground color. You can set newcolor to an integer as given in the table below, or to one of the symbolic constants defined in
conio.h. If you use symbolic constants, you must include conio.h.

Once you have called textcolor, all subsequent functions using direct video output (such as cprintf) will use newcolor. textcolor
does not affect any characters currently onscreen.
3
The following table lists the allowable colors (as symbolic constants) and their numeric values:

BLACK 0
BLUE 1
GREEN 2
CYAN 3

767
C Runtime Library Reference RAD Studio 3.1 Référence C++

RED 4
MAGENTA 5
BROWN 6
LIGHTGRAY 7
DARKGRAY 8
LIGHTBLUE 9
LIGHTGREEN 10
LIGHTCYAN 11
LIGHTRED 12
LIGHTMAGENTA 13
YELLOW 14
WHITE 15
BLINK 128

You can make the characters blink by adding 128 to the foreground color. The predefined constant BLINK exists for this purpose.

For example:
textcolor(CYAN + BLINK);

Remarque: Some monitors do not recognize the intensity signal used to create the eight “light” colors (8-15). On such monitors,
the light colors are displayed as their “dark” equivalents (0-7). Also, systems that do not display in color can treat these numbers
as shades of one color, special patterns, or special attributes (such as underlined, bold, italics, and so on). Exactly what you’ll
see on such systems depends on your hardware.

Return Value

None.

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.26 textmode
Header File

conio.h

Category

3 Console I/O Routines

Prototype
void textmode(int newmode);

Description

Puts screen in text mode.

Remarque: Do not use this function in Win32 GUI applications.

768
3.1 Référence C++ RAD Studio C Runtime Library Reference

textmode selects a specific text mode.

You can give the text mode (the argument newmode) by using a symbolic constant from the enumeration type text_modes
(defined in conio.h).

The most commonly used text_modes type constants and the modes they specify are given in the following table. Some
additional values are defined in conio.h.

LASTMODE Previous text mode


BW40 Black and white, 40 columns
C40 Color, 40 columns
BW80 Black and white, 80 columns
C80 Color, 80 columns
MONO Monochrome, 80 columns
C4350 EGA 43-line and VGA 50-line modes

When textmode is called, the current window is reset to the entire screen, and the current text attributes are reset to normal,
corresponding to a call to normvideo.

Specifying LASTMODE to textmode causes the most recently selected text mode to be reselected.

textmode should be used only when the screen or window is in text mode (presumably to change to a different text mode). This
is the only context in which textmode should be used. When the screen is in graphics mode, use restorecrtmode instead to
escape temporarily to text mode.

Return Value

None.

Example
#include <conio.h>
int main(void)
{
textmode(BW40);
cprintf("ABC");
getch();
textmode(C40);
cprintf("ABC");
getch();
textmode(BW80);
cprintf("ABC");
getch();
textmode(C80);
cprintf("ABC");
getch();
textmode(MONO);
cprintf("ABC");
getch();
return 0;
} 3
Portability

POSIX Win32 ANSI C ANSI C++


+

769
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.3.27 ungetch
Header File

conio.h

Category

Console I/O Routines

Prototype
int ungetch(int ch);

Description

Pushes a character back to the keyboard buffer.

Remarque: Do not use this function in Win32 GUI applications.

ungetch pushes the character ch back to the console, causing ch to be the next character read. The ungetch function fails if it is
called more than once before the next read.

Return Value

On success, ungetch returns the character ch.

On error, it returns EOF.

Example
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
int main( void )
{
int i=0;
char ch;
puts("Input an integer followed by a char:");
/* read chars until non digit or EOF */
while((ch = getche()) != EOF && isdigit(ch))
i = 10 * i + ch - 48; /* convert ASCII into int value */
/* if non digit char was read, push it back into input buffer */
if (ch != EOF)
ungetch(ch);
printf("\n\ni = %d, next char in buffer = %c\n", i, getch());
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+
3
3.1.5.3.28 wherex
Header File

conio.h

Category

770
3.1 Référence C++ RAD Studio C Runtime Library Reference

Console I/O Routines

Prototype
int wherex(void);

Description

Gives horizontal cursor position within window.

Remarque: Do not use this function in Win32 GUI applications.

wherex returns the x-coordinate of the current cursor position (within the current text window).

Return Value

wherex returns an integer in the range 1 to the number of columns in the current video mode.

Example
#include <conio.h>
int main(void)
{
clrscr();
gotoxy(10,10);
cprintf("Current location is X: %d Y: %d\r\n", wherex(), wherey());
getch();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.29 wherey
Header File

conio.h

Category

Console I/O Routines

Prototype
int wherey(void);

Description

Gives vertical cursor position within window.

Remarque: Do not use this function in Win32 GUI applications.


3
wherey returns the y-coordinate of the current cursor position (within the current text window).

Return Value

wherey returns an integer in the range 1 to the number of rows in the current video mode.

Portability

771
C Runtime Library Reference RAD Studio 3.1 Référence C++

POSIX Win32 ANSI C ANSI C++


+

3.1.5.3.30 window
Header File

conio.h

Category

Console I/O Routines

Prototype
void window(int left, int top, int right, int bottom);

Description

Defines active text mode window.

Remarque: Do not use this function in Win32 GUI applications.

window defines a text window onscreen. If the coordinates are in any way invalid, the call to window is ignored.

left and top are the screen coordinates of the upper left corner of the window.

right and bottom are the screen coordinates of the lower right corner.

The minimum size of the text window is one column by one line. The default window is full screen, with the coordinates:

1,1,C,R

where C is the number of columns in the current video mode, and R is the number of rows.

Return Value

None.

Example
#include <conio.h>
int main(void)
{
window(10,10,40,11);
textcolor(BLACK);
textbackground(WHITE);
cprintf("This is a test\r\n");
return 0;
}
Portability
3 POSIX Win32 ANSI C ANSI C++
+

3.1.5.4 ctype.h
The following functions, macros, and classes are provided in ctype.h:

772
3.1 Référence C++ RAD Studio C Runtime Library Reference

Rubriques
Nom Description
_ctype ( see page 778) Header File
ctype.h
Syntax
extern char _ctype[];
Description
_ctype is an array of character attribute information indexed by ASCII value + 1.
Each entry is a set of bits describing the character. This array is used by isdigit,
isprint, and so on.
_IS_xxx #defines ( see page 778) Header File
ctype.h
Description
Bit settings in the _ctype[] used by the is... character macros.
_tolower ( see page 778) Header File
ctype.h
Category
Conversion Routines
Prototype
int _tolower(int ch);
Description
_tolower is a macro that does the same conversion as tolower, except that it
should be used only when ch is known to be uppercase (AZ).
To use _tolower, you must include ctype.h.
Return Value
_tolower returns the converted value of ch if it is uppercase; otherwise, the result
is undefined.
Example
_toupper ( see page 779) Header File
ctype.h
Category
Conversion Routines
Prototype
int _toupper(int ch);
Description
Translates characters to uppercase.
_toupper is a macro that does the same conversion as toupper, except that it
should be used only when ch is known to be lowercase (a to z).
To use _toupper, you must include ctype.h.
Return Value
_toupper returns the converted value of ch if it is lowercase; otherwise, the result
is undefined.
Example
isalnum, __iscsym, iswalnum, _ismbcalnum ( see page 780) Header File
ctype.h, mbstring.h
Category
Classification Routines
Prototype
int isalnum(int c);
int __iscsym(int c);
int iswalnum(wint_t c);
int _ismbcalnum(unsigned int c);
Description
Tests for an alphanumeric character. 3
isalnum is a macro that classifies ASCII-coded integer values by table lookup.
The macro is affected by the current locale’s LC_CTYPE category. For the
default C locale, c is a letter (A to Z or a to z) or a digit (0 to 9).
You can make this macro available as a function by undefining (#undef) it.
Return Value
It is a predicate returning nonzero for true and 0 for false.... suite ( see page
780)

773
C Runtime Library Reference RAD Studio 3.1 Référence C++

isalpha, __iscsymf, iswalpha, _ismbcalpha ( see page 781) Header File


ctype.h, mbstring.h
Category
Classification Routines
Prototype
int isalpha(int c);
int __iscsymf(int c);
int iswalpha(wint_t c);
int _ismbcalpha(unsigned int c);
Description
Classifies an alphabetical character.
isalpha is a macro that classifies ASCII-coded integer values by table lookup.
The macro is affected by the current locale’s LC_CTYPE category. For the
default C locale, c is a letter (A to Z or a to z).
You can make this macro available as a function by undefining (#undef) it.
Return Value
isalpha returns nonzero if c is a letter.
__iscsymf returns true if and only if the argument c is... suite ( see page 781)
isascii, iswascii ( see page 782) Header File
ctype.h, wctype.h
Category
Classification Routines
Prototype
int isascii(int c);
int iswascii(wint_t c);
Description
Character classification macro.
These functions depend on the LC_CTYPE
isascii is a macro that classifies ASCII-coded integer values by table lookup. It is
a predicate returning nonzero for true and 0 for false.
isascii is defined on all integer values.
Return Value
isascii returns nonzero if c is in the range 0 to 127 (0x00-0x7F).
iswascii returns nonzero if c is is a wide-character representation of an ASCII
character.
Each of these routines returns 0 if c does not satisfy the test condition.
Example... suite ( see page 782)
iscntrl, iswcntrl ( see page 783) Header File
ctype.h
Category
Classification Routines
Prototype
int iscntrl(int c);
int iswcntrl(wint_t c);
Description
Tests for a control character.
iscntrl is a macro that classifies ASCII-coded integer values by table lookup. The
macro is affected by the current locale’s LC_CTYPE category. For the default C
locale, c is a delete character or control character (0x7F or 0x00 to 0x1F).
You can make this macro available as a function by undefining (#undef) it.
Return Value
iscntrl returns nonzero if c is a delete character or ordinary control character.
Example

774
3.1 Référence C++ RAD Studio C Runtime Library Reference

isdigit, iswdigit, _ismbcdigit ( see page 784) Header File


ctype.h, mbstring.h
Category
Classification Routines
Prototype
int isdigit(int c);
int iswdigit(wint_t c);
int _ismbcdigit(unsigned int c);
Description
Tests for decimal-digit character.
isdigit is a macro that classifies ASCII-coded integer values by table lookup. The
macro is affected by the current locale’s LC_CTYPE category. For the default C
locale, c is a digit (0 to 9).
You can make this macro available as a function by undefining (#undef) it.
Return Value
isdigit returns nonzero if c is a digit.
_ismbcdigit returns true if and only if the argument c is a single-byte
representation of an ASCII digit.... suite ( see page 784)
isgraph, iswgraph, _ismbcgraph ( see page 785) Header File
ctype.h, mbstring.h
Category
Classification Routines
Prototype
int isgraph(int c);
int iswgraph(wint_t c);
int _ismbcgraph( unsigned int c);
Description
Tests for printing character.
isgraph is a macro that classifies ASCII-coded integer values by table lookup.
The macro is affected by the current locale’s LC_CTYPE category. For the
default C locale, c is a printing character except blank space (‘ ‘).
You can make this macro available as a function by undefining (#undef) it.
Return Value
isgraph returns nonzero if c is a printing character.
Example
islower, iswlower, _ismbclower ( see page 785) Header File
ctype.h, mbstring.h
Category
Classification Routines
Prototype
int islower(int c);
int iswlower(wint_t c);
int _ismbclower(unsigned int c);
Description
Tests for lowercase character.
islower is a macro that classifies ASCII-coded integer values by table lookup. The
macro is affected by the current locale’s LC_CTYPE category. For the default C
locale, c is a lowercase letter (a to z).
You can make this macro available as a function by undefining (#undef) it.
Return Value
islower returns nonzero if c is a lowercase letter.
Example

775
C Runtime Library Reference RAD Studio 3.1 Référence C++

isprint, iswprint, _ismbcprint ( see page 786) Header File


ctype.h, wctype.h, mbstring.h
Category
Classification Routines
Prototype
int isprint(int c);
int iswprint(wint_t c);
int _ismbcprint(unsigned int c);
Description
Tests for printing character.
isprint is a macro that classifies ASCII-coded integer values by table lookup. The
macro is affected by the current locale’s LC_CTYPE category. For the default C
locale, c is a printing character including the blank space (‘ ‘).
You can make this macro available as a function by undefining (#undef) it.
Return Value
isprint returns nonzero if c is a printing character.
Example
ispunct, iswpunct, _ismbcpunct ( see page 787) Header File
ctype.h, wctype.h, mbstring.h
Category
Classification Routines
Prototype
int ispunct(int c);
int iswpunct(wint_t c);
int _ismbcpunct(unsigned int c);
Description
Tests for punctuation character.
ispunct is a macro that classifies ASCII-coded integer values by table lookup.
The macro is affected by the current locale’s LC_CTYPE category. For the
default C locale, c is any printing character that is neither an alphanumeric nor a
blank space (‘ ‘).
You can make this macro available as a function by undefining (#undef) it.
Return Value
ispunct returns nonzero if c is a punctuation character.
Example
isspace, iswspace, _ismbcspace ( see page 788) Header File
ctype.h, wctype.h, mbstring.h
Category
Classification Routines
Prototype
int isspace(int c);
int iswspace(wint_t c);
int _ismbcspace(unsigned int c);
Description
Tests for space character.
isspace is a macro that classifies ASCII-coded integer values by table lookup.
The macro is affected by the current locale’s LC_CTYPE category.
You can make this macro available as a function by undefining (#undef) it.
Return Value
isspace returns nonzero if c is a space, tab, carriage return, new line, vertical tab,
formfeed (0x09 to 0x0D, 0x20), or any other locale-defined space character.
Example

776
3.1 Référence C++ RAD Studio C Runtime Library Reference

isupper, iswupper, _ismbcupper ( see page 789) Header File


ctype.h, wctype.h, mbstring.h
Category
Classification Routines
Prototype
int isupper(int c);
int iswupper(wint_t c);
int _ismbcupper(unsigned int c);
Description
Tests for uppercase character.
isupper is a macro that classifies ASCII-coded integer values by table lookup.
The macro is affected by the current locale’s LC_CTYPE category. For the
default C locale, c is an uppercase letter (A to Z).
You can make this macro available as a function by undefining (#undef) it.
Return Value
isupper returns nonzero if c is an uppercase letter.
Example
isxdigit, iswxdigit ( see page 790) Header File
ctype.h, wctype.h
Category
Classification Routines
Prototype
int isxdigit(int c);
int iswxdigit(wint_t c);
Description
Tests for hexadecimal character.
isxdigit is a macro that classifies ASCII-coded integer values by table lookup. The
macro is affected by the current locale’s LC_CTYPE category.
You can make this macro available as a function by undefining (#undef) it.
Return Value
isxdigit returns nonzero if c is a hexadecimal digit (0 to 9, A to F, a to f) or any
other hexadecimal digit defined by the locale.
Example
toascii ( see page 790) Header File
ctype.h
Category
Conversion Routines
Prototype
int toascii(int c);
Description
Translates characters to ASCII format.
toascii is a macro that converts the integer c to ASCII by clearing all but the lower
7 bits; this gives a value in the range 0 to 127.
Return Value
toascii returns the converted value of c.
Portability
tolower, _mbctolower, towlower ( see page 791) Header File
ctype.h, mbstring.h
Category
Conversion Routines
Prototype
int tolower(int ch);
int towlower(wint_t ch); // Unicode version
unsigned int _mbctolower(unsigned int c);
Description 3
Translates characters to lowercase.
tolower is a function that converts an integer ch (in the range EOF to 255) to its
lowercase value (a to z; if it was uppercase, A to Z). All others are left unchanged.
Return Value
tolower returns the converted value of ch if it is uppercase; it returns all others
unchanged.
Example

777
C Runtime Library Reference RAD Studio 3.1 Référence C++

toupper, _mbctoupper, towupper ( see page 792) Header File


ctype.h, mbstring.h
Category
Conversion Routines
Prototype
int toupper(int ch);
int towupper(wint_t ch); // Unicode version
unsigned int _mbctoupper(unsigned int c);
Description
Translates characters to uppercase.
toupper is a function that converts an integer ch (in the range EOF to 255) to its
uppercase value (A to Z; if it was lowercase, a to z). All others are left unchanged.
towupper is the Unicode version of toupper. It is available when Unicode is
defined.
Return Value
toupper returns the converted value of ch if it is lowercase; it returns all others
unchanged.
Example

3.1.5.4.1 _ctype
Header File

ctype.h

Syntax
extern char _ctype[];

Description

_ctype is an array of character attribute information indexed by ASCII value + 1. Each entry is a set of bits describing the
character. This array is used by isdigit, isprint, and so on.

3.1.5.4.2 _IS_xxx #defines


Header File

ctype.h

Description

Bit settings in the _ctype[] used by the is... character macros.

Name Meaning
_IS_SP Is space
_IS_DIG Is digit
_IS_UPP Is uppercase
_IS_LOW Is lowercase
3 _IS_HEX [A-F] or [a-f]
_IS_CTL Control
_IS_PUN Punctuation

3.1.5.4.3 _tolower
Header File

778
3.1 Référence C++ RAD Studio C Runtime Library Reference

ctype.h

Category

Conversion Routines

Prototype
int _tolower(int ch);

Description

_tolower is a macro that does the same conversion as tolower, except that it should be used only when ch is known to be
uppercase (AZ).

To use _tolower, you must include ctype.h.

Return Value

_tolower returns the converted value of ch if it is uppercase; otherwise, the result is undefined.

Example
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int length, i;
char *string = "THIS IS A STRING.";
length = strlen(string);
for (i = 0; i < length; i++) {
if ((string[i] >= 'A') && (string[i] <= 'Z')){
string[i] = _tolower(string[i]);
}
}
printf("%s\n",string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.4.4 _toupper
Header File

ctype.h

Category

Conversion Routines 3
Prototype
int _toupper(int ch);

Description

Translates characters to uppercase.

_toupper is a macro that does the same conversion as toupper, except that it should be used only when ch is known to be

779
C Runtime Library Reference RAD Studio 3.1 Référence C++

lowercase (a to z).

To use _toupper, you must include ctype.h.

Return Value

_toupper returns the converted value of ch if it is lowercase; otherwise, the result is undefined.

Example
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int length, i;
char *string = "this is a string.";
length = strlen(string);
for (i = 0; i < length; i++) {
if ((string[i] >= 'a') && (string[i] <= 'z')){
string[i] = _toupper(string[i]);
}
}
printf("%s\n",string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.4.5 isalnum, __iscsym, iswalnum, _ismbcalnum


Header File

ctype.h, mbstring.h

Category

Classification Routines

Prototype
int isalnum(int c);
int __iscsym(int c);
int iswalnum(wint_t c);
int _ismbcalnum(unsigned int c);

Description

3 Tests for an alphanumeric character.

isalnum is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s
LC_CTYPE category. For the default C locale, c is a letter (A to Z or a to z) or a digit (0 to 9).

You can make this macro available as a function by undefining (#undef) it.

Return Value

It is a predicate returning nonzero for true and 0 for false.

780
3.1 Référence C++ RAD Studio C Runtime Library Reference

isalnum returns nonzero if c is a letter or a digit.

__iscsym returns nonzero if c is a letter, underscore, or digit.

iswalnum returns nonzero if iswalpha or iswdigit return true for c.

_ismbcalnum returns true if and only if the argument c is a single-byte ASCII English letter.

Example
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';

if (isalnum(c))
printf("%c is alphanumeric\n",c);
else
printf("%c is not alphanumeric\n",c);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


isalnum + + + +
__iscsym +
_ismbcalnum +
iswalnum + + +

3.1.5.4.6 isalpha, __iscsymf, iswalpha, _ismbcalpha


Header File

ctype.h, mbstring.h

Category

Classification Routines

Prototype
int isalpha(int c);
int __iscsymf(int c);
int iswalpha(wint_t c);
int _ismbcalpha(unsigned int c);

Description
3
Classifies an alphabetical character.

isalpha is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s
LC_CTYPE category. For the default C locale, c is a letter (A to Z or a to z).

You can make this macro available as a function by undefining (#undef) it.

Return Value

isalpha returns nonzero if c is a letter.

781
C Runtime Library Reference RAD Studio 3.1 Référence C++

__iscsymf returns true if and only if the argument c is a letter or an underscore.

iswalpha returns nonzero if c is a wchar_t in the character set defined by the implementation.

_ismbcalpha returns true if and only if the argument c is a single-byte ASCII English letter.

Example
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';

if (isalpha(c))
printf("%c is alphabetical\n",c);
else
printf("%c is not alphabetical\n",c);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


isalpha + + + +
__iscsymf +
_ismbcalpha +
iswalpha + + +

3.1.5.4.7 isascii, iswascii


Header File

ctype.h, wctype.h

Category

Classification Routines

Prototype
int isascii(int c);
int iswascii(wint_t c);

Description

Character classification macro.

These functions depend on the LC_CTYPE

isascii is a macro that classifies ASCII-coded integer values by table lookup. It is a predicate returning nonzero for true and 0 for
3
false.

isascii is defined on all integer values.

Return Value

isascii returns nonzero if c is in the range 0 to 127 (0x00-0x7F).

iswascii returns nonzero if c is is a wide-character representation of an ASCII character.

782
3.1 Référence C++ RAD Studio C Runtime Library Reference

Each of these routines returns 0 if c does not satisfy the test condition.

Example
#include <stdio.h>
#include <ctype.h>
#include <stdio.h>
int main(void)
{
char c = 'C';
if (isascii(c))
printf("%c is ascii\n",c);
else
printf("%c is not ascii\n",c);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


isascii +
iswascii +

3.1.5.4.8 iscntrl, iswcntrl


Header File

ctype.h

Category

Classification Routines

Prototype
int iscntrl(int c);
int iswcntrl(wint_t c);

Description

Tests for a control character.

iscntrl is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s
LC_CTYPE category. For the default C locale, c is a delete character or control character (0x7F or 0x00 to 0x1F).

You can make this macro available as a function by undefining (#undef) it.

Return Value

iscntrl returns nonzero if c is a delete character or ordinary control character.

Example
3
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';
if (iscntrl(c))
printf("%c is a control character\n",c);
else
printf("%c is not a control character\n",c);
return 0;

783
C Runtime Library Reference RAD Studio 3.1 Référence C++

}
Portability

POSIX Win32 ANSI C ANSI C++


iscntrl + + + +
iswcntrl + + +

3.1.5.4.9 isdigit, iswdigit, _ismbcdigit


Header File

ctype.h, mbstring.h

Category

Classification Routines

Prototype
int isdigit(int c);
int iswdigit(wint_t c);
int _ismbcdigit(unsigned int c);

Description

Tests for decimal-digit character.

isdigit is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s
LC_CTYPE category. For the default C locale, c is a digit (0 to 9).

You can make this macro available as a function by undefining (#undef) it.

Return Value

isdigit returns nonzero if c is a digit.

_ismbcdigit returns true if and only if the argument c is a single-byte representation of an ASCII digit.

Example
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';
if (isdigit(c))
printf("%c is a digit\n",c);
else
printf("%c is not a digit\n",c);
return 0;
3 }
Portability

POSIX Win32 ANSI C ANSI C++


isdigit + + + +
_ismbcdigit +
iswdigit + + +

784
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.4.10 isgraph, iswgraph, _ismbcgraph


Header File

ctype.h, mbstring.h

Category

Classification Routines

Prototype
int isgraph(int c);
int iswgraph(wint_t c);
int _ismbcgraph( unsigned int c);

Description

Tests for printing character.

isgraph is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s
LC_CTYPE category. For the default C locale, c is a printing character except blank space (‘ ‘).

You can make this macro available as a function by undefining (#undef) it.

Return Value

isgraph returns nonzero if c is a printing character.

Example
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';
if (isgraph(c))
printf("%c is a graphic character\n",c);
else
printf("%c is not a graphic character\n",c);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


isgraph + + + +
_ismbcgraph +
iswgraph + + +

3
3.1.5.4.11 islower, iswlower, _ismbclower
Header File

ctype.h, mbstring.h

Category

Classification Routines

785
C Runtime Library Reference RAD Studio 3.1 Référence C++

Prototype
int islower(int c);
int iswlower(wint_t c);
int _ismbclower(unsigned int c);

Description

Tests for lowercase character.

islower is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s
LC_CTYPE category. For the default C locale, c is a lowercase letter (a to z).

You can make this macro available as a function by undefining (#undef) it.

Return Value

islower returns nonzero if c is a lowercase letter.

Example
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';
if (islower(c))
printf("%c is a lowercase character\n",c);
else
printf("%c is not a lowercase character\n",c);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


islower + + + +
_ismbclower +
iswlower + + +

3.1.5.4.12 isprint, iswprint, _ismbcprint


Header File

ctype.h, wctype.h, mbstring.h

Category

Classification Routines

3 Prototype
int isprint(int c);
int iswprint(wint_t c);
int _ismbcprint(unsigned int c);

Description

Tests for printing character.

786
3.1 Référence C++ RAD Studio C Runtime Library Reference

isprint is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s
LC_CTYPE category. For the default C locale, c is a printing character including the blank space (‘ ‘).

You can make this macro available as a function by undefining (#undef) it.

Return Value

isprint returns nonzero if c is a printing character.

Example
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';
if (isprint(c))
printf("%c is a printable character\n",c);
else
printf("%c is not a printable character\n",c);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


isprint + + + +
_ismbcprint +
iswprint +

3.1.5.4.13 ispunct, iswpunct, _ismbcpunct


Header File

ctype.h, wctype.h, mbstring.h

Category

Classification Routines

Prototype
int ispunct(int c);
int iswpunct(wint_t c);
int _ismbcpunct(unsigned int c);

Description

Tests for punctuation character.

ispunct is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s 3
LC_CTYPE category. For the default C locale, c is any printing character that is neither an alphanumeric nor a blank space (‘ ‘).

You can make this macro available as a function by undefining (#undef) it.

Return Value

ispunct returns nonzero if c is a punctuation character.

Example

787
C Runtime Library Reference RAD Studio 3.1 Référence C++

#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';
if (ispunct(c))
printf("%c is a punctuation character\n",c);
else
printf("%c is not a punctuation character\n",c);

return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


ispunct + + + +
_ismbcpunt +
iswpunct + + +

3.1.5.4.14 isspace, iswspace, _ismbcspace


Header File

ctype.h, wctype.h, mbstring.h

Category

Classification Routines

Prototype
int isspace(int c);
int iswspace(wint_t c);
int _ismbcspace(unsigned int c);

Description

Tests for space character.

isspace is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s
LC_CTYPE category.

You can make this macro available as a function by undefining (#undef) it.

Return Value

isspace returns nonzero if c is a space, tab, carriage return, new line, vertical tab, formfeed (0x09 to 0x0D, 0x20), or any other
locale-defined space character.
3 Example
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';
if (isspace(c))
printf("%c is white space\n",c);
else
printf("%c is not white space\n",c);

788
3.1 Référence C++ RAD Studio C Runtime Library Reference

return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


isspace + + + +
_ismbcspace +
iswspace + + +

3.1.5.4.15 isupper, iswupper, _ismbcupper


Header File

ctype.h, wctype.h, mbstring.h

Category

Classification Routines

Prototype
int isupper(int c);
int iswupper(wint_t c);
int _ismbcupper(unsigned int c);

Description

Tests for uppercase character.

isupper is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s
LC_CTYPE category. For the default C locale, c is an uppercase letter (A to Z).

You can make this macro available as a function by undefining (#undef) it.

Return Value

isupper returns nonzero if c is an uppercase letter.

Example
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';
if (isupper(c))
printf("%c is an uppercase character\n",c);
else
printf("%c is not an uppercase character\n",c);
return 0; 3
}
Portability

POSIX Win32 ANSI C ANSI C++


isupper + + + +
_ismbcupper +
iswupper + + +

789
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.4.16 isxdigit, iswxdigit


Header File

ctype.h, wctype.h

Category

Classification Routines

Prototype
int isxdigit(int c);
int iswxdigit(wint_t c);

Description

Tests for hexadecimal character.

isxdigit is a macro that classifies ASCII-coded integer values by table lookup. The macro is affected by the current locale’s
LC_CTYPE category.

You can make this macro available as a function by undefining (#undef) it.

Return Value

isxdigit returns nonzero if c is a hexadecimal digit (0 to 9, A to F, a to f) or any other hexadecimal digit defined by the locale.

Example
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char c = 'C';
if (isxdigit(c))
printf("%c is a hexadecimal digit\n",c);
else
printf("%c is not a hexadecimal digit\n",c);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


isxdigit + + + +
iswxdigit + + +

3.1.5.4.17 toascii
3 Header File

ctype.h

Category

Conversion Routines

Prototype
int toascii(int c);

790
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

Translates characters to ASCII format.

toascii is a macro that converts the integer c to ASCII by clearing all but the lower 7 bits; this gives a value in the range 0 to 127.

Return Value

toascii returns the converted value of c.

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.4.18 tolower, _mbctolower, towlower


Header File

ctype.h, mbstring.h

Category

Conversion Routines

Prototype
int tolower(int ch);
int towlower(wint_t ch); // Unicode version
unsigned int _mbctolower(unsigned int c);

Description

Translates characters to lowercase.

tolower is a function that converts an integer ch (in the range EOF to 255) to its lowercase value (a to z; if it was uppercase, A to
Z). All others are left unchanged.

Return Value

tolower returns the converted value of ch if it is uppercase; it returns all others unchanged.

Example
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int length, i;
char *string = "THIS IS A STRING";
length = strlen(string);
for (i=0; i<length; i++) 3
{
string[i] = tolower(string[i]);
}
printf("%s\n",string);
return 0;
}
Portability

791
C Runtime Library Reference RAD Studio 3.1 Référence C++

POSIX Win32 ANSI C ANSI C++


tolower + + + +
_mbctolower +
towlower + + +

3.1.5.4.19 toupper, _mbctoupper, towupper


Header File

ctype.h, mbstring.h

Category

Conversion Routines

Prototype
int toupper(int ch);
int towupper(wint_t ch); // Unicode version
unsigned int _mbctoupper(unsigned int c);

Description

Translates characters to uppercase.

toupper is a function that converts an integer ch (in the range EOF to 255) to its uppercase value (A to Z; if it was lowercase, a to
z). All others are left unchanged.

towupper is the Unicode version of toupper. It is available when Unicode is defined.

Return Value

toupper returns the converted value of ch if it is lowercase; it returns all others unchanged.

Example
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int length, i;
char *string = "this is a string";
length = strlen(string);
for (i=0; i<length; i++)
{
string[i] = toupper(string[i]);
}
printf("%s\n",string);
3 return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


toupper + + + +
_mbctoupper +
towupper + + +

792
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.5 delayimp.h
The following functions, macros, and classes are provided in delayimp.h:

Rubriques
Nom Description
__pfnDliNotifyHook, __pfnDliFailureHook ( see page 793) Header File
delayimp.h
Category
Delay load hook notification Routines
Prototype
typedef FARPROC (WINAPI *DelayedLoadHook)(dliNotification
dliNotify,
DelayLoadInfo * pdli);
Description
The delay load mechanism provides two hooks for you to modify the runtime
behavior of a delay loaded DLL. By writing your own hook functions using the
function signature below and assigning this to the two hooks you can modify the
delay load process.
DelayLoadProc structure
typedef struct DelayLoadProc
{
BOOL fImportByName;
union
{
LPCSTR szProcName;
DWORD dwOrdinal;
};
} DelayLoadProc;
ImgDelayDescr structure
typedef struct ImgDelayDescr
{
DWORD grAttrs; /* attributes */
LPCSTR szName; /* pointer to dll name */
HMODULE... suite ( see page 793)
__FUnloadDelayLoadedDLL ( see page 796) Header File
delayimp.h
Prototype
BOOL WINAPI __FUnloadDelayLoadedDLL(LPCSTR szDll);
Description
Unloads a delay loaded DLL.
szDll is pointer to a name to unload, or NULL to unload all the delay load DLLs in
the list.
Return Value
On successful completion __FUnloadDelayLoadedDLL returns true.
On error it returns false.

3.1.5.5.1 __pfnDliNotifyHook, __pfnDliFailureHook


Header File

delayimp.h 3
Category

Delay load hook notification Routines

Prototype
typedef FARPROC (WINAPI *DelayedLoadHook)(dliNotification dliNotify,
DelayLoadInfo * pdli);

793
C Runtime Library Reference RAD Studio 3.1 Référence C++

Description

The delay load mechanism provides two hooks for you to modify the runtime behavior of a delay loaded DLL. By writing your
own hook functions using the function signature below and assigning this to the two hooks you can modify the delay load
process.

DelayLoadProc structure
typedef struct DelayLoadProc
{
BOOL fImportByName;
union
{
LPCSTR szProcName;
DWORD dwOrdinal;
};
} DelayLoadProc;

ImgDelayDescr structure
typedef struct ImgDelayDescr
{
DWORD grAttrs; /* attributes */
LPCSTR szName; /* pointer to dll name */
HMODULE hmod; /* address of module handle */
IMAGE_THUNK_DATA * pIAT; /* address of the IAT */
IMAGE_THUNK_DATA * pINT; /* address of the INT */
IMAGE_THUNK_DATA * pBoundIAT; /* address of the optional bound IAT */
IMAGE_THUNK_DATA * pUnloadIAT; /* address of optional copy of
original IAT */
DWORD dwTimeStamp; /* 0 if not bound, */
/* O.W. date/time stamp of DLL bound
to (Old BIND) */
} ImgDelayDescr;

DelayLoadInfo structure
typedef struct DelayLoadInfo

3 {
DWORD cb; /* size of structure */
const ImgDelayDescr * pidd; /* raw form of data (everything is
there) */
FARPROC * ppfn; /* points to address of function to
load */

794
3.1 Référence C++ RAD Studio C Runtime Library Reference

LPCSTR szDll; /* name of dll */


DelayLoadProc dlp; /* name or ordinal of procedure */
HMODULE hmodCur; /* the hInstance of the library we
have loaded */
FARPROC pfnCur; /* the actual function that will be
called */
DWORD dwLastError;/* error received (if an error
notification) */
} DelayLoadInfo, *PDelayLoadInfo;

Delay load import hook notifications

The following structure is the enumerations that are defined for the hook notification events:
typedef enum
{
dliNoteStartProcessing, /* used to bypass or note helper only */
dliNotePreLoadLibrary, /* called just before LoadLibrary, can */
/* override w/ new HMODULE return val */
dliNotePreGetProcAddress, /* called just before GetProcAddress, can */
/* override w/ new FARPROC return value */
dliFailLoadLibrary, /* failed to load library, fix it by */
/* returning a valid HMODULE */
dliFailGetProcAddress, /* failed to get proc address, fix it by */
/* returning a valid FARPROC */
dliNoteEndProcessing, /* called after all processing is done, */
/* no bypass possible at this point */
/* except by longjmp(), throw(), or
RaiseException. */
} dliNotification;

Hook pointers

The “notify hook” gets called for every call to the delay load helper. This allows a user to hook every call and skip the delay load
helper entirely.
extern DelayedLoadHook _EXPDATA __pfnDliNotifyHook;
dliNotify == 3
{
dliNoteStartProcessing |
dliNotePreLoadLibrary |
dliNotePreGetProcAddress |
dliNoteEndProcessing

795
C Runtime Library Reference RAD Studio 3.1 Référence C++

Remarque: The “failure” hook is assigned to:


extern DelayedLoadHook _EXPDATA __pfnDliFailureHook;

This hook is called with the following notification flags:


dliNotify ==
{
dliFailLoadLibrary |
dliFailGetProcAddress
}

For further information on when this notify eventsd occur during the delay load process, please see delayhlp.c

3.1.5.5.2 __FUnloadDelayLoadedDLL
Header File

delayimp.h

Prototype
BOOL WINAPI __FUnloadDelayLoadedDLL(LPCSTR szDll);

Description

Unloads a delay loaded DLL.

szDll is pointer to a name to unload, or NULL to unload all the delay load DLLs in the list.

Return Value

On successful completion __FUnloadDelayLoadedDLL returns true.

On error it returns false.

3.1.5.6 direct.h
The following functions, macros, and classes are provided in direct.h:

Rubriques
Nom Description
_chdrive ( see page 797) Header File
direct.h
Category
Directory Control Routines
3 Prototype
int _chdrive(int drive);
Description
Sets current disk drive.
_chdrive sets the current drive to the one associated with drive: 1 for A, 2 for B, 3
for C, and so on.
This function changes the current drive of the parent process.
Return Value
_chdrive returns 0 if the current drive was changed successfully; otherwise, it
returns -1.
Example

796
3.1 Référence C++ RAD Studio C Runtime Library Reference

_getdcwd, _wgetdcwd ( see page 797) Header File


direct.h
Category
Directory Control Routines
Prototype
char * _getdcwd(int drive, char *buffer, int buflen);
wchar_t * _wgetdcwd(int drive, wchar_t *buffer, int buflen);
Description
Gets current directory for specified drive.
_getdcwd gets the full path name of the working directory of the specified drive
(including the drive name), up to buflen bytes long, and stores it in buffer. If the
full path name length (including the null-terminator) is longer than buflen, an error
occurs. The drive is 0 for the default drive, 1=A, 2=B, and so on.
If the working directory is the root directory, the terminating character for... suite
( see page 797)

3.1.5.6.1 _chdrive
Header File

direct.h

Category

Directory Control Routines

Prototype
int _chdrive(int drive);

Description

Sets current disk drive.

_chdrive sets the current drive to the one associated with drive: 1 for A, 2 for B, 3 for C, and so on.

This function changes the current drive of the parent process.

Return Value

_chdrive returns 0 if the current drive was changed successfully; otherwise, it returns -1.

Example
#include <stdio.h>
#include <direct.h>
int main(void)
{
if (_chdrive(3) == 0)
printf("Successfully changed to drive C:\n");
else
printf("Cannot change to drive C:\n");
return 0;
}
Portability
3
POSIX Win32 ANSI C ANSI C++
+

3.1.5.6.2 _getdcwd, _wgetdcwd


Header File

797
C Runtime Library Reference RAD Studio 3.1 Référence C++

direct.h

Category

Directory Control Routines

Prototype
char * _getdcwd(int drive, char *buffer, int buflen);
wchar_t * _wgetdcwd(int drive, wchar_t *buffer, int buflen);

Description

Gets current directory for specified drive.

_getdcwd gets the full path name of the working directory of the specified drive (including the drive name), up to buflen bytes
long, and stores it in buffer. If the full path name length (including the null-terminator) is longer than buflen, an error occurs. The
drive is 0 for the default drive, 1=A, 2=B, and so on.

If the working directory is the root directory, the terminating character for the full path is a backslash. If the working directory is a
subdirectory, there is no terminating backslash after the subdirectory name.

If buffer is NULL, _getdcwd allocates a buffer at least buflen bytes long. You can later free the allocated buffer by passing the
_getdcwd return value to the free function.

Return Value

If successful, _getdcwd returns a pointer to the buffer containing the current directory for the specified drive.

Otherwise it returns NULL, and sets the global variable errno to one of the following values:

ENOMEM Not enough memory to allocate a buffer (buffer is NULL)


ERANGE Directory name longer than buflen (buffer is not NULL)

Example
#include <direct.h>
#include <stdio.h>
char buf[65];
void main()
{
if (_getdcwd(3, buf, sizeof(buf)) == NULL)
perror("Unable to get current directory of drive C");
else
printf("Current directory of drive C is %s\n",buf);
}
Portability

POSIX Win32 ANSI C ANSI C++


_getdcwd +
_wgetdcwd NT only
3

3.1.5.7 dirent.h
The following functions, macros, and classes are provided in dirent.h:

798
3.1 Référence C++ RAD Studio C Runtime Library Reference

Rubriques
Nom Description
closedir, wclosedir ( see page 800) Header File
dirent.h
Category
Directory Control Routines
Prototype
void closedir(DIR *dirp);
void wclosedir(wDIR *dirp);
Description
Closes a directory stream.
closedir is available on POSIX-compliant UNIX systems.
The closedir function closes the directory stream dirp, which must have been
opened by a previous call to opendir. After the stream is closed, dirp no longer
points to a valid directory stream.
wclosedir is the Unicode version of closedir.
Return Value
If closedir is successful, it returns 0. Otherwise, closedir returns -1 and sets the
global variable errno to
opendir, wopendir ( see page 801) Header File
dirent.h
Category
Directory Control Routines
Prototype
DIR *opendir(const char *dirname);
wDIR *wopendir(const wchar_t *dirname);
Description
Opens a directory stream for reading.
opendir is available on POSIX-compliant UNIX systems.
The opendir function opens a directory stream for reading. The name of the
directory to read is dirname. The stream is set to read the first entry in the
directory.
A directory stream is represented by the DIR structure, defined in dirent.h. This
structure contains no user-accessible fields. Multiple directory streams can be
opened and read simultaneously. Directory entries can be created or deleted
while a directory stream is being... suite ( see page 801)
readdir, wreaddir ( see page 802) Header File
dirent.h
Category
Directory Control Routines
Prototype
struct dirent *readdir(DIR *dirp);
struct wdirent *wreaddir(wDIR *dirp)
Description
Reads the current entry from a directory stream.
readdir is available on POSIX-compliant UNIX systems.
The readdir function reads the current directory entry in the directory stream
pointed to by dirp. The directory stream is advanced to the next entry.
The readdir function returns a pointer to a dirent structure that is overwritten by
each call to the function on the same directory stream. The structure is not
overwritten by a readdir call on a different directory stream.
The dirent structure corresponds to... suite ( see page 802)

799
C Runtime Library Reference RAD Studio 3.1 Référence C++

rewinddir, wrewinddir ( see page 803) Header File


dirent.h
Category
Directory Control Routines
Prototype
void rewinddir(DIR *dirp);
void wrewinddir(wDIR *dirp);
Description
Resets a directory stream to the first entry.
rewinddir is available on POSIX-compliant UNIX systems.
The rewinddir function repositions the directory stream dirp at the first entry in the
directory. It also ensures that the directory stream accurately reflects any
directory entries that might have been created or deleted since the last opendir or
rewinddir on that directory stream.
wrewinddir is the Unicode version of rewinddir.
Return Value
None.
Example

3.1.5.7.1 closedir, wclosedir


Header File

dirent.h

Category

Directory Control Routines

Prototype
void closedir(DIR *dirp);
void wclosedir(wDIR *dirp);

Description

Closes a directory stream.

closedir is available on POSIX-compliant UNIX systems.

The closedir function closes the directory stream dirp, which must have been opened by a previous call to opendir. After the
stream is closed, dirp no longer points to a valid directory stream.

wclosedir is the Unicode version of closedir.

Return Value

If closedir is successful, it returns 0. Otherwise, closedir returns -1 and sets the global variable errno to

EBADF The dirp argument does not point to a valid open directory stream

Example

3 /* opendir.c - test opendir(), readdir(), closedir() */

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>

void scandir(char *dirname)


{
DIR *dir;
struct dirent *ent;

800
3.1 Référence C++ RAD Studio C Runtime Library Reference

printf("First pass on '%s':\n",dirname);


if ((dir = opendir(dirname)) == NULL)
{
perror("Unable to open directory");
exit(1);
}
while ((ent = readdir(dir)) != NULL)
printf("%s\n",ent->d_name);

printf("Second pass on '%s':\n",dirname);


rewinddir(dir);
while ((ent = readdir(dir)) != NULL)
printf("%s\n",ent->d_name);
if (closedir(dir) != 0)
perror("Unable to close directory");
}

void main(int argc,char *argv[])


{
if (argc != 2)
{
printf("usage: opendir dirname\n");
exit(1);
}
scandir(argv[1]);
exit(0);
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

3.1.5.7.2 opendir, wopendir


Header File

dirent.h

Category

Directory Control Routines

Prototype
DIR *opendir(const char *dirname);
wDIR *wopendir(const wchar_t *dirname);

Description

Opens a directory stream for reading.

opendir is available on POSIX-compliant UNIX systems. 3


The opendir function opens a directory stream for reading. The name of the directory to read is dirname. The stream is set to
read the first entry in the directory.

A directory stream is represented by the DIR structure, defined in dirent.h. This structure contains no user-accessible fields.
Multiple directory streams can be opened and read simultaneously. Directory entries can be created or deleted while a directory
stream is being read.

Use the readdir function to read successive entries from a directory stream. Use the closedir function to remove a directory

801
C Runtime Library Reference RAD Studio 3.1 Référence C++

stream when it is no longer needed.

Return Value

On success, opendir returns a pointer to a directory stream that can be used in calls to readdir, rewinddir, and closedir.

On error (If the directory cannot be opened), the functino returns NULL and sets the global variable errno to

ENOENT The directory does not exist


ENOMEM Not enough memory to allocate a DIR object

Example
/* opendir.c - test opendir(), readdir(), closedir() */

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>

void scandir(char *dirname)


{
DIR *dir;
struct dirent *ent;

printf("First pass on '%s':\n",dirname);


if ((dir = opendir(dirname)) == NULL)
{
perror("Unable to open directory");
exit(1);
}
while ((ent = readdir(dir)) != NULL)
printf("%s\n",ent->d_name);

printf("Second pass on '%s':\n",dirname);


rewinddir(dir);
while ((ent = readdir(dir)) != NULL)
printf("%s\n",ent->d_name);
if (closedir(dir) != 0)
perror("Unable to close directory");
}

void main(int argc,char *argv[])


{
if (argc != 2)
{
printf("usage: opendir dirname\n");
exit(1);
}
scandir(argv[1]);
exit(0);
}
Portability

3 POSIX Win32 ANSI C ANSI C++


opendir + +
wopendir

3.1.5.7.3 readdir, wreaddir


Header File

802
3.1 Référence C++ RAD Studio C Runtime Library Reference

dirent.h

Category

Directory Control Routines

Prototype
struct dirent *readdir(DIR *dirp);
struct wdirent *wreaddir(wDIR *dirp)

Description

Reads the current entry from a directory stream.

readdir is available on POSIX-compliant UNIX systems.

The readdir function reads the current directory entry in the directory stream pointed to by dirp. The directory stream is advanced
to the next entry.

The readdir function returns a pointer to a dirent structure that is overwritten by each call to the function on the same directory
stream. The structure is not overwritten by a readdir call on a different directory stream.

The dirent structure corresponds to a single directory entry. It is defined in dirent.h and contains (in addition to other
non-accessible members) the following member:

char d_name[];

where d_name is an array of characters containing the null-terminated file name for the current directory entry. The size of the
array is indeterminate; use strlen to determine the length of the file name.

All valid directory entries are returned, including subdirectories, “.” and “..” entries, system files, hidden files, and volume labels.
Unused or deleted directory entries are skipped.

A directory entry can be created or deleted while a directory stream is being read, but readdir might or might not return the
affected directory entry. Rewinding the directory with rewinddir or reopening it with opendir ensures that readdir will reflect the
current state of the directory.

The wreaddir function is the Unicode version of readdir. It uses the wdirent structure but otherwise is similar to readdir.

Return Value

On success, readdir returns a pointer to the current directory entry for the directory stream.

If the end of the directory has been reached, or dirp does not refer to an open directory stream, readdir returns NULL.

Portability

POSIX Win32 ANSI C ANSI C++


readdir + +
wreaddir +

3
3.1.5.7.4 rewinddir, wrewinddir
Header File

dirent.h

Category

Directory Control Routines

803
C Runtime Library Reference RAD Studio 3.1 Référence C++

Prototype
void rewinddir(DIR *dirp);
void wrewinddir(wDIR *dirp);

Description

Resets a directory stream to the first entry.

rewinddir is available on POSIX-compliant UNIX systems.

The rewinddir function repositions the directory stream dirp at the first entry in the directory. It also ensures that the directory
stream accurately reflects any directory entries that might have been created or deleted since the last opendir or rewinddir on
that directory stream.

wrewinddir is the Unicode version of rewinddir.

Return Value

None.

Example
/* opendir.c - test opendir(), readdir(), closedir() */

#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>

void scandir(char *dirname)


{
DIR *dir;
struct dirent *ent;

printf("First pass on '%s':\n",dirname);


if ((dir = opendir(dirname)) == NULL)
{
perror("Unable to open directory");
exit(1);
}
while ((ent = readdir(dir)) != NULL)
printf("%s\n",ent->d_name);

printf("Second pass on '%s':\n",dirname);


rewinddir(dir);
while ((ent = readdir(dir)) != NULL)
printf("%s\n",ent->d_name);
if (closedir(dir) != 0)
perror("Unable to close directory");
}

void main(int argc,char *argv[])


{
if (argc != 2)
{
3 printf("usage: opendir dirname\n");
exit(1);
}
scandir(argv[1]);
exit(0);
}
Portability

804
3.1 Référence C++ RAD Studio C Runtime Library Reference

POSIX Win32 ANSI C ANSI C++


rewind + +
wrewinddir +

3.1.5.8 dir.h
The following functions, macros, and classes are provided in dir.h:

Rubriques
Nom Description
chdir ( see page 809) Header File
dir.h
Category
Directory Control Routines
Prototype
int chdir(const char *path);
int _wchdir(const wchar_t *path);
Description
Changes current directory.
chdir causes the directory specified by path to become the current working
directory; path must specify an existing directory.
A drive can also be specified in the path argument, such as
chdir("a:\\BC")
but this method changes only the current directory on that drive; it does not
change the active drive.

• Under Windows, only the current process is affected.


Return Value
Upon successful completion, chdir returns a value of 0.
Otherwise, it returns a value of -1, and the global
variable... suite ( see page 809)
MAXxxxx #defines (fnsplit) ( see page 810) Header File
dir.h
Description
These symbols define the maximum number of characters in a file specification
for fnsplit (including room for a terminating NULL).
findclose, _wfindclose ( see page 810) Header File
dir.h
Category
Directory Control Routines
Prototype
int findclose(struct ffblk *ffblk );
int _wfindclose(struct _wffblk *ffblk );
Description
findclose closes any handles and frees up any dynamic memory associated with
previous calls to findfirst and findnext.
Return Value
findclose returns 0 on successfully closing the handle. On failure: 3
• -1 is returned
• errno is set to

805
C Runtime Library Reference RAD Studio 3.1 Référence C++

findfirst, _wfindfirst ( see page 811) Header File


dir.h
Category
Directory Control Routines
Prototype
int findfirst(const char *pathname, struct ffblk *ffblk,
int attrib);
int _wfindfirst( const wchar_t *pathname, struct _wffblk
*ffblk, int attrib);
Description
Searches a disk directory.
findfirst begins a search of a disk directory for files specified by attributes or
wildcards.
pathname is a string with an optional drive specifier path and file name of the file
to be found. Only the file name portion can contain wildcard match characters
(such as ? or *). If a matching file is found the ffblk structure is filled with the
file-directory information.
When Unicode is defined,... suite ( see page 811)
findnext, _wfindnext ( see page 813) Header File
dir.h
Category
Directory Control Routines
Prototype
int findnext(struct ffblk *ffblk );
int _wfindnext(struct _wffblk *ffblk );
Description
Continues findfirst search.
findnext is used to fetch subsequent files that match the pathname given in
findfirst. ffblk is the same block filled in by the findfirst call. This block contains
necessary information for continuing the search. One file name for each call to
findnext will be returned until no more files are found in the directory matching the
pathname.
Return Value
findnext returns 0 on successfully finding a file matching the search pathname.
When no more files can be found... suite ( see page 813)
fnmerge, _wfnmerge ( see page 814) Header File
dir.h
Category
Directory Control Routines
Prototype
void fnmerge(char *path, const char *drive, const char
*dir, const char *name, const char *ext);
void _wfnmerge(wchar_t *path, const wchar_t *drive, const
wchar_t *dir, const wchar_t *name, const wchar_t *ext );
Description
Builds a path from component parts.
fnmerge makes a path name from its components. The new path name is
X:\DIR\SUBDIR\NAME.EXT
where:
fnsplit, _wfnsplit ( see page 816) Header File
dir.h
Category
Directory Control Routines
Prototype
int fnsplit(const char *path, char *drive, char *dir, char
*name, char *ext);
3 int _wfnsplit(const wchar_t *path, wchar_t *drive, wchar_t
*dir, wchar_t *name, wchar_t *ext );
Description
Splits a full path name into its components.
fnsplit takes a file's full path name (path) as a string in the form
X:\DIR\SUBDIR\NAME.EXT and splits path into its four components. It then
stores those components in the strings pointed to by drive, dir, name, and ext. All
five components must be passed but any of them can be a null which means the
corresponding component will... suite ( see page 816)

806
3.1 Référence C++ RAD Studio C Runtime Library Reference

Bit Definitions for fnsplit ( see page 817) Header File


dir.h
Description
Bit definitions returned from fnsplit to identify which pieces of a file name were
found during the split.
getcurdir, _wgetcurdir ( see page 817) Header File
dir.h
Category
Directory Control Routines
Prototype
int getcurdir(int drive, char *directory);
int _wgetcurdir(int drive, wchar_t *directory );
Description
Gets current directory for specified drive.
getcurdir gets the name of the current working directory for the drive indicated by
drive. drive specifies a drive number (0 for default, 1 for A, and so on). directory
points to an area of memory of length MAXDIR where the null-terminated
directory name will be placed. The name does not contain the drive specification
and does not begin with a backslash.
Return Value
getcurdir returns 0 on success or -1 in the event... suite ( see page 817)
getcwd, _wgetcwd ( see page 818) Header File
dir.h
Category
Directory Control Routines
Prototype
char *getcwd(char *buf, int buflen);
wchar_t *_wgetcwd(wchar_t *buf, int buflen);
Description
Gets current working directory.
getcwd gets the full path name (including the drive) of the current working
directory, up to buflen bytes long and stores it in buf. If the full path name length
(including the null terminator) is longer than buflen bytes, an error occurs.
If buf is NULL, a buffer buflen bytes long is allocated for you with malloc. You can
later free the allocated buffer by passing the return value of getcwd to the
function free.
Return Value... suite ( see page 818)
getdisk, setdisk ( see page 819) Header File
dir.h
Category
Directory Control Routines
Prototype
int getdisk(void);
int setdisk(int drive);
Description
Gets or sets the current drive number.
getdisk gets the current drive number. It returns an integer: 0 for A, 1 for B, 2 for
C, and so on.
setdisk sets the current drive to the one associated with drive: 0 for A, 1 for B, 2
for C, and so on.
The setdisk function changes the current drive of the parent process.
Return Value
getdisk returns the current drive number. setdisk returns the total number of
drives available.
Example
3

807
C Runtime Library Reference RAD Studio 3.1 Référence C++

mkdir, _wmkdir ( see page 820) Header File


dir.h
Category
Directory Control Routines
Prototype
int mkdir(const char *path);
int _wmkdir(const wchar_t *path);
Description
Creates a directory.
mkdir is available on UNIX, though it then takes an additional parameter.
mkdir creates a new directory from the given path name path.
Return Value
mkdir returns the value 0 if the new directory was created.
A return value of -1 indicates an error, and the global variable errno is set to one
of the following values:
_mktemp, _wmktemp ( see page 821) Header File
dir.h
Category
Directory Control Routines
Prototype
char *_mktemp(char *template);
wchar_t *_wmktemp(wchar_t *template);
Description
Makes a unique file name.
_mktemp replaces the string pointed to by template with a unique file name and
returns template.
template should be a null-terminated string with six trailing Xs. These Xs are
replaced with a unique collection of letters plus a period, so that there are two
letters, a period, and three suffix letters in the new file name.
Starting with AA.AAA, the new file name is assigned by looking up the name on
the disk and avoiding pre-existing names of the same... suite ( see page 821)
_rmdir, _wrmdir ( see page 822) Header File
dir.h
Category
Directory Control Routines
Prototype
int _rmdir(const char *path);
int _wrmdir(const wchar_t *path);
Description
Removes a directory.
_rmdir deletes the directory whose path is given by path. The directory named by
path

• must be empty
• must not be the current working directory
• must not be the root directory
Return Value
_rmdir returns 0 if the directory is successfully deleted. A
return value of -1 indicates an error, and the global
variable errno is set to one of the following values:

808
3.1 Référence C++ RAD Studio C Runtime Library Reference

searchpath, wsearchpath ( see page 823) Header File


dir.h
Category
Miscellaneous Routines
Prototype
char *searchpath(const char *file);
wchar_t *wsearchpath( const wchar_t *file );
Description
Searches the operating system path for a file.
searchpath attempts to locate file, searching along the operating system path,
which is the PATH=... string in the environment. A pointer to the complete
path-name string is returned as the function value.
searchpath searches for the file in the current directory of the current drive first. If
the file is not found there, the PATH environment variable is fetched, and each
directory in the path is searched in turn until the file is found,... suite ( see page
823)

3.1.5.8.1 chdir
Header File

dir.h

Category

Directory Control Routines

Prototype
int chdir(const char *path);
int _wchdir(const wchar_t *path);

Description

Changes current directory.

chdir causes the directory specified by path to become the current working directory; path must specify an existing directory.

A drive can also be specified in the path argument, such as


chdir("a:\\BC")

but this method changes only the current directory on that drive; it does not change the active drive.

• Under Windows, only the current process is affected.


Return Value
Upon successful completion, chdir returns a value of 0. Otherwise, it returns a value of -1, and the global variable errno is set to

ENOENT Path or file name not found

Example
#include <stdio.h>
#include <stdlib.h> 3
#include <dir.h>
char old_dir[MAXDIR];
char new_dir[MAXDIR];
int main(void)
{
if (getcurdir(0, old_dir))
{
perror("getcurdir()");
exit(1);

809
C Runtime Library Reference RAD Studio 3.1 Référence C++

}
printf("Current directory is: \\%s\n", old_dir);
if (chdir("\\"))
{
perror("chdir()");
exit(1);
}
if (getcurdir(0, new_dir))
{
perror("getcurdir()");
exit(1);
}
printf("Current directory is now: \\%s\n", new_dir);
printf("\nChanging back to original directory: \\%s\n", old_dir);
if (chdir(old_dir))
{
perror("chdir()");
exit(1);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


chdir + +
_wchdir NT only

3.1.5.8.2 MAXxxxx #defines (fnsplit)


Header File

dir.h

Description

These symbols define the maximum number of characters in a file specification for fnsplit (including room for a terminating
NULL).

Name Meaning
MAXPATH Complete file name with path
MAXDRIVE Disk drive (e.g., "A:")
MAXDIR File subdirectory specification
MAXFILE File name without extension
MAXEXT File extension

3 3.1.5.8.3 findclose, _wfindclose


Header File

dir.h

Category

Directory Control Routines

810
3.1 Référence C++ RAD Studio C Runtime Library Reference

Prototype
int findclose(struct ffblk *ffblk );
int _wfindclose(struct _wffblk *ffblk );

Description

findclose closes any handles and frees up any dynamic memory associated with previous calls to findfirst and findnext.

Return Value

findclose returns 0 on successfully closing the handle. On failure:

• -1 is returned
• errno is set to

EINVDAT Invalid data

Portability

POSIX Win32 ANSI C ANSI C++


findclose +
_wfindclose NT only

Voir aussi
findfirst ( see page 811)

findnext ( see page 813)

3.1.5.8.4 findfirst, _wfindfirst


Header File

dir.h

Category

Directory Control Routines

Prototype
int findfirst(const char *pathname, struct ffblk *ffblk, int attrib);
int _wfindfirst( const wchar_t *pathname, struct _wffblk *ffblk, int attrib);

Description

Searches a disk directory.

findfirst begins a search of a disk directory for files specified by attributes or wildcards.
3
pathname is a string with an optional drive specifier path and file name of the file to be found. Only the file name portion can
contain wildcard match characters (such as ? or *). If a matching file is found the ffblk structure is filled with the file-directory
information.

When Unicode is defined, the _wfindfirst function uses the following _wffblk structure.
struct _wffblk {

811
C Runtime Library Reference RAD Studio 3.1 Référence C++

long ff_reserved;
long ff_fsize;
unsigned long ff_attrib;
unsigned short ff_ftime;
unsigned short ff_fdate;
wchar_t ff_name[256];
};

For Win32, the format of the structure ffblk is as follows:


struct ffblk {
long ff_reserved;
long ff_fsize; /* file size */
unsigned long ff_attrib; /* attribute found */
unsigned short ff_ftime; /* file time */
unsigned short ff_fdate; /* file date */
char ff_name[256]; /* found file name */
};

attrib is a file-attribute byte used in selecting eligible files for the search. attrib should be selected from the following constants
defined in dos.h:

FA_RDONLY Read-only attribute


FA_HIDDEN Hidden file
FA_SYSTEM System file
FA_LABEL Volume label
FA_DIREC Directory
FA_ARCH Archive

A combination of constants can be OR'ed together.

For more detailed information about these attributes refer to your operating system documentation.

ff_ftime and ff_fdate contain bit fields for referring to the current date and time. The structure of these fields was established by
the operating system. Both are 16-bit structures divided into three fields.

ff_ftime:

Bits 0 to 4 The result of seconds divided by 2 (for example 10 here means 20 seconds)
Bits 5 to 10 Minutes
3 Bits 11 to 15 Hours

ff_fdate:

Bits 0-4 Day


Bits 5-8 Month
Bits 9-15 Years since 1980 (for example 9 here means 1989)

812
3.1 Référence C++ RAD Studio C Runtime Library Reference

The structure ftime declared in io.h uses time and date bit fields similar in structure to ff_ftime and ff_fdate.

Return Value

findfirst returns 0 on successfully finding a file matching the search pathname.

When no more files can be found, or if there is an error in the file name:

• -1 is returned
• errno is set to

ENOENT Path or file name not found

• _doserrno is set to one of the following values:

ENMFILE No more files


ENOENT Path or file name not found

Example
/* findfirst and findnext example */
#include <stdio.h>
#include <dir.h>
int main(void)
{
struct ffblk ffblk;
int done;
printf("Directory listing of *.*\n");
done = findfirst("*.*",&ffblk,0);
while (!done)
{
printf(" %s\n", ffblk.ff_name);
done = findnext(&ffblk);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


findfirst +
_wfindfirst NT only

Voir aussi
findclose ( see page 810)

findnext ( see page 813)


3
3.1.5.8.5 findnext, _wfindnext
Header File

dir.h

Category

Directory Control Routines

813
C Runtime Library Reference RAD Studio 3.1 Référence C++

Prototype
int findnext(struct ffblk *ffblk );
int _wfindnext(struct _wffblk *ffblk );

Description

Continues findfirst search.

findnext is used to fetch subsequent files that match the pathname given in findfirst. ffblk is the same block filled in by the findfirst
call. This block contains necessary information for continuing the search. One file name for each call to findnext will be returned
until no more files are found in the directory matching the pathname.

Return Value

findnext returns 0 on successfully finding a file matching the search pathname. When no more files can be found or if there is an
error in the file name

-1 is returned

errno is set to

ENOENT Path or file name not found

_doserrno is set to one of the following values:

ENMFILE No more files


ENOENT Path or file name not found

Portability

POSIX Win32 ANSI C ANSI C++


findnext +
_wfindnext NT only

Voir aussi
findfirst ( see page 811)

findnext

3.1.5.8.6 fnmerge, _wfnmerge


Header File

dir.h

Category
3 Directory Control Routines

Prototype
void fnmerge(char *path, const char *drive, const char *dir, const char *name, const char
*ext);
void _wfnmerge(wchar_t *path, const wchar_t *drive, const wchar_t *dir, const wchar_t *name,
const wchar_t *ext );

814
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

Builds a path from component parts.

fnmerge makes a path name from its components. The new path name is
X:\DIR\SUBDIR\NAME.EXT

where:

drive = X
dir = \\DIR\\SUBDIR\\
name = NAME
ext = .EXT

If drive is empty or NULL, no drive is inserted in the path name. If it is missing a trailing colon (:), a colon is inserted in the path
name.

If dir is empty or NULL, no directory is inserted in the path name. If it is missing a trailing slash (\ or /), a backslash is inserted in
the path name.

If name is empty or NULL, no file name is inserted in the path name.

If ext is empty or NULL, no extension is inserted in the path name. If it is missing a leading period (.), a period is inserted in the
path name.

fnmerge assumes there is enough space in path for the constructed path name. The maximum constructed length is MAXPATH.
MAXPATH is defined in dir.h.

fnmerge and fnsplit are invertible; if you split a given path with fnsplit then merge the resultant components with fnmerge you end
up with path.

Return Value

None.

Example
#include <string.h>
#include <stdio.h>
#include <dir.h>
int main(void)
{
char s[MAXPATH];
char drive[MAXDRIVE];
char dir[MAXDIR];
char file[MAXFILE];
char ext[MAXEXT];
getcwd(s,MAXPATH); /* get the current working directory */
strcat(s,"\\"); /* append on a trailing character */
fnsplit(s,drive,dir,file,ext); /* split the string to separate elems */
strcpy(file,"DATA");
strcpy(ext,".TXT"); 3
fnmerge(s,drive,dir,file,ext); /* merge everything into one string */
puts(s); /* display resulting string */
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


fnmerge +

815
C Runtime Library Reference RAD Studio 3.1 Référence C++

_wfnmerge NT only

3.1.5.8.7 fnsplit, _wfnsplit


Header File

dir.h

Category

Directory Control Routines

Prototype
int fnsplit(const char *path, char *drive, char *dir, char *name, char *ext);
int _wfnsplit(const wchar_t *path, wchar_t *drive, wchar_t *dir, wchar_t *name, wchar_t *ext );

Description

Splits a full path name into its components.

fnsplit takes a file's full path name (path) as a string in the form X:\DIR\SUBDIR\NAME.EXT and splits path into its four
components. It then stores those components in the strings pointed to by drive, dir, name, and ext. All five components must be
passed but any of them can be a null which means the corresponding component will be parsed but not stored. If any path
component is null, that component corresponds to a non-NULL, empty string.

The maximum sizes for these strings are given by the constants MAXDRIVE, MAXDIR, MAXPATH, MAXFILE, and MAXEXT
(defined in dir.h) and each size includes space for the null-terminator.

fnsplit assumes that there is enough space to store each non-null component.

• When fnsplit splits path it treats the punctuation as follows:


• drive includes the colon (C:, A:, and so on)
• dir includes the leading and trailing backslashes (\BC\include\, \source\ ,and so on)
• name includes the file name
• ext includes the dot preceding the extension (.C, .EXE, and so on).
fnmerge and fnsplit are invertible; if you split a given path with fnsplit then merge the resultant components with fnmerge you end
up with path.
Return Value
fnsplit returns an integer (composed of five flags defined in dir.h) indicating which of the full path name components were present
in path. These flags and the components they represent are

EXTENSION An extension
FILENAME A file name
DIRECTORY A directory (and possibly subdirectories)
3
DRIVE A drive specification (see dir.h)
WILDCARDS Wildcards (* or ?)

Example
#include <stdlib.h>
#include <stdio.h>
#include <dir.h>

816
3.1 Référence C++ RAD Studio C Runtime Library Reference

int main(void)
{
char *s;
char drive[MAXDRIVE];
char dir[MAXDIR];
char file[MAXFILE];
char ext[MAXEXT];
int flags;
s=getenv("COMSPEC"); /* get the comspec environment parameter */
flags=fnsplit(s,drive,dir,file,ext);
printf("Command processor info:\n");
if(flags & DRIVE)
printf("\tdrive: %s\n",drive);
if(flags & DIRECTORY)
printf("\tdirectory: %s\n",dir);
if(flags & FILENAME)
printf("\tfile: %s\n",file);
if(flags & EXTENSION)
printf("\textension: %s\n",ext);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


fnsplit +
_wfnsplit NT only

3.1.5.8.8 Bit Definitions for fnsplit


Header File

dir.h

Description

Bit definitions returned from fnsplit to identify which pieces of a file name were found during the split.

Flag Component
DIRECTORY Path includes a directory (and possibly subdirectories)
DRIVE Path includes a drive specification (see DIR.H)
EXTENSION Path includes an extension
FILENAME Path includes a file name
WILDCARDS Path contains wildcards (* or ?)

3.1.5.8.9 getcurdir, _wgetcurdir


3
Header File

dir.h

Category

Directory Control Routines

Prototype

817
C Runtime Library Reference RAD Studio 3.1 Référence C++

int getcurdir(int drive, char *directory);


int _wgetcurdir(int drive, wchar_t *directory );

Description

Gets current directory for specified drive.

getcurdir gets the name of the current working directory for the drive indicated by drive. drive specifies a drive number (0 for
default, 1 for A, and so on). directory points to an area of memory of length MAXDIR where the null-terminated directory name
will be placed. The name does not contain the drive specification and does not begin with a backslash.

Return Value

getcurdir returns 0 on success or -1 in the event of error.

Example
#include <dir.h>
#include <stdio.h>
#include <string.h>
char *current_directory(char *path)
{
strcpy(path, "X:\\"); /* fill string with form of response: X:\ */
path[0] = 'A' + getdisk(); /* replace X with current drive letter */
getcurdir(0, path+3); /* fill rest of string with current directory */
return(path);
}
int main(void)
{
char curdir[MAXPATH];
current_directory(curdir);
printf("The current directory is %s\n", curdir);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


getcurdir +
_wgetcurdir NT only

3.1.5.8.10 getcwd, _wgetcwd


Header File

dir.h

Category

Directory Control Routines

3 Prototype
char *getcwd(char *buf, int buflen);
wchar_t *_wgetcwd(wchar_t *buf, int buflen);

Description

Gets current working directory.

getcwd gets the full path name (including the drive) of the current working directory, up to buflen bytes long and stores it in buf. If

818
3.1 Référence C++ RAD Studio C Runtime Library Reference

the full path name length (including the null terminator) is longer than buflen bytes, an error occurs.

If buf is NULL, a buffer buflen bytes long is allocated for you with malloc. You can later free the allocated buffer by passing the
return value of getcwd to the function free.

Return Value

• getcwd returns the following values:


• If buf is not NULL on input, getcwd returns buf on success, NULL on error.
• If buf is NULL on input, getcwd returns a pointer to the allocated buffer.
In the event of an error return, the global variable errno is set to one of the following values:

ENODEV No such device


ENOMEM Not enough memory to allocate a buffer (buf is NULL)
ERANGE Directory name longer than buflen (buf is not NULL)

Example
#include <stdio.h>
#include <dir.h>
int main(void)
{
char buffer[MAXPATH];
getcwd(buffer, MAXPATH);
printf("The current directory is: %s\n", buffer);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


getcwd + +
_wgetcwd NT only

3.1.5.8.11 getdisk, setdisk


Header File

dir.h

Category

Directory Control Routines

Prototype
int getdisk(void);
int setdisk(int drive); 3
Description

Gets or sets the current drive number.

getdisk gets the current drive number. It returns an integer: 0 for A, 1 for B, 2 for C, and so on.

setdisk sets the current drive to the one associated with drive: 0 for A, 1 for B, 2 for C, and so on.

The setdisk function changes the current drive of the parent process.

819
C Runtime Library Reference RAD Studio 3.1 Référence C++

Return Value

getdisk returns the current drive number. setdisk returns the total number of drives available.

Example
#include <stdio.h>
#include <dir.h>
int main(void)
{
int disk, maxdrives = setdisk(2);
disk = getdisk() + 'A';
printf("\nThe number of logical drives is:%d\n", maxdrives);
printf("The current drive is: %c\n", disk);
return 0;
}

3.1.5.8.12 mkdir, _wmkdir


Header File

dir.h

Category

Directory Control Routines

Prototype
int mkdir(const char *path);
int _wmkdir(const wchar_t *path);

Description

Creates a directory.

mkdir is available on UNIX, though it then takes an additional parameter.

mkdir creates a new directory from the given path name path.

Return Value

mkdir returns the value 0 if the new directory was created.

A return value of -1 indicates an error, and the global variable errno is set to one of the following values:

EACCES Permission denied


ENOENT No such file or directory

Example
#include <stdio.h>
#include <process.h>
#include <dir.h>
3 #define DIRNAME "testdir.$$$"
int main(void)
{
int stat;
stat = mkdir(DIRNAME);
if (!stat)
printf("Directory created\n");
else
{
printf("Unable to create directory\n");

820
3.1 Référence C++ RAD Studio C Runtime Library Reference

exit(1);
}
getchar();
system("dir/p");
getchar();
stat = rmdir(DIRNAME);
if (!stat)
printf("\nDirectory deleted\n");
else
{
perror("\nUnable to delete directory\n");
exit(1);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


mkdir + +
_wmkdir NT only

3.1.5.8.13 _mktemp, _wmktemp


Header File

dir.h

Category

Directory Control Routines

Prototype
char *_mktemp(char *template);
wchar_t *_wmktemp(wchar_t *template);

Description

Makes a unique file name.

_mktemp replaces the string pointed to by template with a unique file name and returns template.

template should be a null-terminated string with six trailing Xs. These Xs are replaced with a unique collection of letters plus a
period, so that there are two letters, a period, and three suffix letters in the new file name.

Starting with AA.AAA, the new file name is assigned by looking up the name on the disk and avoiding pre-existing names of the
same format.

Return Value

If a unique name can be created and template is well formed, _mktemp returns the address of the template string. Otherwise, it 3
returns null.

Example
#include <dir.h>
#include <stdio.h>
int main(void)
{
/* fname defines the template for the
temporary file. */

821
C Runtime Library Reference RAD Studio 3.1 Référence C++

char *fname = "TXXXXXX", *ptr;


ptr = mktemp(fname);
printf("%s\n",ptr);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


mktemp + +
_wmktemp +

3.1.5.8.14 _rmdir, _wrmdir


Header File

dir.h

Category

Directory Control Routines

Prototype
int _rmdir(const char *path);
int _wrmdir(const wchar_t *path);

Description

Removes a directory.

_rmdir deletes the directory whose path is given by path. The directory named by path

• must be empty
• must not be the current working directory
• must not be the root directory
Return Value
_rmdir returns 0 if the directory is successfully deleted. A return value of -1 indicates an error, and the global variable errno is set
to one of the following values:

EACCES Permission denied


ENOENT Path or file function not found

Example
#include <stdio.h>
#include <process.h>
#include <dir.h>
3 #define DIRNAME "testdir.$$$"
int main(void)
{
int stat;
stat = mkdir(DIRNAME);
if (!stat)
printf("Directory created\n");
else
{
printf("Unable to create directory\n");

822
3.1 Référence C++ RAD Studio C Runtime Library Reference

exit(1);
}
getchar();
system("dir/p");
getchar();
stat = rmdir(DIRNAME);
if (!stat)
printf("\nDirectory deleted\n");
else
{
perror("\nUnable to delete directory\n");
exit(1);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_rmdir + +
_wrmdir NT only

3.1.5.8.15 searchpath, wsearchpath


Header File

dir.h

Category

Miscellaneous Routines

Prototype
char *searchpath(const char *file);
wchar_t *wsearchpath( const wchar_t *file );

Description

Searches the operating system path for a file.

searchpath attempts to locate file, searching along the operating system path, which is the PATH=... string in the environment. A
pointer to the complete path-name string is returned as the function value.

searchpath searches for the file in the current directory of the current drive first. If the file is not found there, the PATH
environment variable is fetched, and each directory in the path is searched in turn until the file is found, or the path is exhausted.

When the file is located, a string is returned containing the full path name. This string can be used in a call to access the file (for
example, with fopen or exec...).

The string returned is located in a static buffer and is overwritten on each subsequent call to searchpath.
3
Return Value

searchpath returns a pointer to a file name string if the file is successfully located; otherwise, searchpath returns null.

Example
#include <stdio.h>
#include <dir.h>
int main(void)
{

823
C Runtime Library Reference RAD Studio 3.1 Référence C++

char *p;
/* Looks for ILINK32 and returns a pointer
to the path */
p = searchpath("ILINK32.EXE");
printf("Search for ILINK32.EXE : %s\n", p);
/* Looks for nonexistent file */
p = searchpath("NOTEXIST.FIL");
printf("Search for NOTEXIST.FIL : %s\n", p);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


searchpath +
wsearchpath NT only

3.1.5.9 dos.h
The following functions, macros, and classes are provided in dos.h:

Rubriques
Nom Description
FA_xxxx #defines ( see page 828) Header File
dos.h
Description
File attributes
NFDS #define ( see page 828) Header File
dos.h
Description
Maximum number of file descriptors.
_getdrive ( see page 828) Header File
dos.h
Category
Directory Control Routines
Prototype
int _getdrive(void);
Description
Gets the current drive.
_getdrive gets the the current drive number. It returns an integer: 0 for A, 1 for B,
2 for C, and so on.
Return Value
_getdrive returns the current drive number on success or -1 in the event of error.
Example
_osmajor ( see page 829) Header File
dos.h
Syntax
extern unsigned char _osmajor;
Description
3 The major version number of the operating system is available individually
through _osmajor. For example, if you are running DOS version 3.2, _osmajor
will be 3.
This variable can be useful when you want to write modules that will run on DOS
versions 2.x and 3.x. Some library routines behave differently depending on the
DOS version number, while others only work under DOS 3.x and higher. For
example, refer to creatnew and _rtl_open.

824
3.1 Référence C++ RAD Studio C Runtime Library Reference

_osminor ( see page 829) Header File


dos.h
Syntax
extern unsigned char _osminor;
Description
The minor version number of the operating system is available individually
through _osminor. For example, if you are running DOS version 3.2, _osminor
will be 20.
This variables can be useful when you want to write modules that will run on
DOS versions 2.x and 3.x. Some library routines behave differently depending on
the DOS version number, while others only work under DOS 3.x and higher. For
example, refer to creatnew and _rtl_open.
_osversion ( see page 829) Header File
dos.h
Syntax
extern unsigned _osversion;
Description
_osversion contains the operating system version number, with the major version
number in the low byte and the minor version number in the high byte. (For DOS
version x.y, the x is the major version number, and y is the minor version
number.)
_osversion is functionally identical to _version.
_sleep ( see page 830) Header File
dos.h
Category
Process Control Routines
Prototype
void _sleep(unsigned seconds);
Description
Suspends execution for an interval (seconds).
With a call to _sleep, the current program is suspended from execution for the
number of seconds specified by the argument seconds. The interval is accurate
only to the nearest hundredth of a second or to the accuracy of the operating
system clock, whichever is less accurate.
Return Value
None.
Example
_version ( see page 830) Header File
dos.h
Syntax
extern unsigned _version;
Description
_version contains the operating system version number, with the major version
number in the low byte and the minor version number in the high byte. (For DOS
version x.y, the x is the major version number, and y is the minor version
number.)
disable, _disable, enable, _enable ( see page 831) Header File
dos.h
Category
Miscellaneous Routines
Prototype
void disable(void);
void _disable(void);
void enable(void);
void _enable(void);
Description
Disables and enables interrupts.
3
These macros are designed to provide a programmer with flexible hardware
interrupt control.
disable and _disable macros disable interrupts. Only the NMI (non-maskable
interrupt) is allowed from any external device.
enable and _enable macros enable interrupts, allowing any device interrupts to
occur.
Return Value
None.
Portability

825
C Runtime Library Reference RAD Studio 3.1 Référence C++

dostounix ( see page 831) Header File


dos.h
Category
Time and Date Routines
Prototype
long dostounix(struct date *d, struct time *t);
Description
Converts date and time to UNIX time format.
dostounix converts a date and time as returned from getdate and gettime
into UNIX time format. d points to a date structure, and t points to a time
structure containing valid date and time information.
The date and time must not be earlier than or equal to Jan 1 1980 00:00:00.
Return Value
Returns UNIX version of current date and time parameters: number of seconds
since 00:00:00 on January 1, 1970 (GMT).
Example
geninterrupt ( see page 832) Header File
Category
Prototype
void geninterrupt(int intr_num);
Description
Return Value
Portability
getdate, setdate ( see page 832) Header File
dos.h
Category
Time and Date Routines
Prototype
void getdate(struct date *datep);
void setdate(struct date *datep);
Description
Gets and sets system date.
getdate fills in the date structure (pointed to by datep) with the system's current
date.
setdate sets the system date (month, day, and year) to that in the date structure
pointed to by datep. Note that a request to set a date might fail if you do not have
the privileges required by the operating system.
The date structure is defined as follows:
struct date{
int da_year; /* current year */
char da_day; /* day of the... suite ( see page 832)
getdfree ( see page 833) Header File
dos.h
Category
Directory Control Routines, Miscellaneous Routines
Prototype
void getdfree(unsigned char drive, struct dfree *dtable);
Description
Gets disk free space.
getdfree accepts a drive specifier in drive (0 for default, 1 for A, and so on) and
fills the dfree structure pointed to by dtable with disk attributes.
The dfree structure is defined as follows:
struct dfree {
unsigned df_avail; /* available clusters */
3 unsigned df_total; /* total clusters */
unsigned df_bsec; /* bytes per sector */
unsigned df_sclus; /* sectors per cluster */
};
Return Value
getdfree returns no value. In the event of an error, df_sclus... suite ( see page
833)

826
3.1 Référence C++ RAD Studio C Runtime Library Reference

gettime, settime ( see page 834) Header File


dos.h
Category
Time and Date Routines
Prototype
void gettime(struct time *timep);
void settime(struct time *timep);
Description
Gets and sets the system time.
gettime fills in the time structure pointed to by timep with the system's current
time.

• settime sets the system time to the values in the time


structure pointed to by timep.
The time structure is defined as follows:
struct time {
unsigned char ti_min; /* minutes */
unsigned char ti_hour; /* hours */
unsigned char ti_hund; /* hundredths of
seconds */
unsigned char ti_sec; /* seconds */
};
Return Value
None.
Example
unixtodos ( see page 835) Header File
dos.h
Category
Time and Date Routines
Prototype
void unixtodos(long time, struct date *d, struct time *t);
Description
Converts date and time from UNIX to DOS format.
unixtodos converts the UNIX-format time given in time to DOS format and fills in
the date and time structures pointed to by d and t.
time must not represent a calendar time earlier than Jan. 1, 1980 00:00:00.
Return Value
None.
Example
_unlink, _wunlink ( see page 836) Header File
dos.h
Category
Input/output Routines
Prototype
int _unlink(const char *filename);
int _wunlink(const wchar_t *filename);
Description
Deletes a file.
_unlink deletes a file specified by filename. Any drive, path, and file name can be
3
used as a filename. Wildcards are not allowed.
Read-only files cannot be deleted by this call. To remove read-only files, first use
chmod or _rtl_chmod to change the read-only attribute.
Remarque: If the file is open, it must be closed before unlinking it.
_wunlink is the Unicode version of _wunlink. The Unicode version accepts a
filename that is a wchar_t character string. Otherwise, the functions perform...
suite ( see page 836)

827
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.9.1 FA_xxxx #defines


Header File

dos.h

Description

File attributes

Constant Description
FA_RDONLY Read-only attribute
FA_HIDDEN Hidden file
FA_SYSTEM System file
FA_LABEL Volume label
FA_DIREC Directory
FA_ARCH Archive

3.1.5.9.2 NFDS #define


Header File

dos.h

Description

Maximum number of file descriptors.

3.1.5.9.3 _getdrive
Header File

dos.h

Category

Directory Control Routines

Prototype
int _getdrive(void);

Description

Gets the current drive.

3 _getdrive gets the the current drive number. It returns an integer: 0 for A, 1 for B, 2 for C, and so on.

Return Value

_getdrive returns the current drive number on success or -1 in the event of error.

Example
#include <stdio.h>
#include <direct.h>
int main(void)

828
3.1 Référence C++ RAD Studio C Runtime Library Reference

{
int disk;
disk = _getdrive() + 'A' - 1;
printf("The current drive is: %c\n", disk);
return 0;
}

3.1.5.9.4 _osmajor
Header File

dos.h

Syntax
extern unsigned char _osmajor;

Description

The major version number of the operating system is available individually through _osmajor. For example, if you are running
DOS version 3.2, _osmajor will be 3.

This variable can be useful when you want to write modules that will run on DOS versions 2.x and 3.x. Some library routines
behave differently depending on the DOS version number, while others only work under DOS 3.x and higher. For example, refer
to creatnew and _rtl_open.

3.1.5.9.5 _osminor
Header File

dos.h

Syntax
extern unsigned char _osminor;

Description

The minor version number of the operating system is available individually through _osminor. For example, if you are running
DOS version 3.2, _osminor will be 20.

This variables can be useful when you want to write modules that will run on DOS versions 2.x and 3.x. Some library routines
behave differently depending on the DOS version number, while others only work under DOS 3.x and higher. For example, refer
to creatnew and _rtl_open.

3.1.5.9.6 _osversion
Header File

dos.h

Syntax
3
extern unsigned _osversion;

Description

_osversion contains the operating system version number, with the major version number in the low byte and the minor version
number in the high byte. (For DOS version x.y, the x is the major version number, and y is the minor version number.)

_osversion is functionally identical to _version.

829
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.9.7 _sleep
Header File

dos.h

Category

Process Control Routines

Prototype
void _sleep(unsigned seconds);

Description

Suspends execution for an interval (seconds).

With a call to _sleep, the current program is suspended from execution for the number of seconds specified by the argument
seconds. The interval is accurate only to the nearest hundredth of a second or to the accuracy of the operating system clock,
whichever is less accurate.

Return Value

None.

Example
#include <dos.h>
#include <stdio.h>
int main(void)
{
int i;
for (i=1; i<5; i++)
{
printf("Sleeping for %d seconds\n", i);
_sleep(i);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.9.8 _version
Header File

dos.h
3
Syntax
extern unsigned _version;

Description

_version contains the operating system version number, with the major version number in the low byte and the minor version
number in the high byte. (For DOS version x.y, the x is the major version number, and y is the minor version number.)

830
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.9.9 disable, _disable, enable, _enable


Header File

dos.h

Category

Miscellaneous Routines

Prototype
void disable(void);
void _disable(void);
void enable(void);
void _enable(void);

Description

Disables and enables interrupts.

These macros are designed to provide a programmer with flexible hardware interrupt control.

disable and _disable macros disable interrupts. Only the NMI (non-maskable interrupt) is allowed from any external device.

enable and _enable macros enable interrupts, allowing any device interrupts to occur.

Return Value

None.

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.9.10 dostounix
Header File

dos.h

Category

Time and Date Routines

Prototype
long dostounix(struct date *d, struct time *t);

Description
3
Converts date and time to UNIX time format.

dostounix converts a date and time as returned from getdate and gettime into UNIX time format. d points to a date
structure, and t points to a time structure containing valid date and time information.

The date and time must not be earlier than or equal to Jan 1 1980 00:00:00.

Return Value

831
C Runtime Library Reference RAD Studio 3.1 Référence C++

Returns UNIX version of current date and time parameters: number of seconds since 00:00:00 on January 1, 1970 (GMT).

Example
#include <time.h>
#include <stddef.h>
#include <dos.h>
#include <stdio.h>
int main(void)
{
time_t t;
struct time d_time;
struct date d_date;
struct tm *local;
getdate(&d_date);
gettime(&d_time);
t = dostounix(&d_date, &d_time);
local = localtime(&t);
printf("Time and Date: %s\n", asctime(local));
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.9.11 geninterrupt
Header File

Category

Prototype
void geninterrupt(int intr_num);

Description

Return Value

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.9.12 getdate, setdate


Header File
3 dos.h

Category

Time and Date Routines

Prototype
void getdate(struct date *datep);
void setdate(struct date *datep);

832
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

Gets and sets system date.

getdate fills in the date structure (pointed to by datep) with the system's current date.

setdate sets the system date (month, day, and year) to that in the date structure pointed to by datep. Note that a request to set a
date might fail if you do not have the privileges required by the operating system.

The date structure is defined as follows:


struct date{
int da_year; /* current year */
char da_day; /* day of the month */
char da_mon; /* month (1 = Jan) */
};

Return Value

getdate and setdate do not return a value.

Example
#include <dos.h>
#include <stdio.h>
int main(void)
{
struct date d;
getdate(&d);
printf("The current year is: %d\n", d.da_year);
printf("The current day is: %d\n", d.da_day);
printf("The current month is: %d\n", d.da_mon);
return 0;
}

3.1.5.9.13 getdfree
Header File

dos.h

Category

Directory Control Routines, Miscellaneous Routines

Prototype
void getdfree(unsigned char drive, struct dfree *dtable);

Description

Gets disk free space.

getdfree accepts a drive specifier in drive (0 for default, 1 for A, and so on) and fills the dfree structure pointed to by dtable with 3
disk attributes.

The dfree structure is defined as follows:


struct dfree {
unsigned df_avail; /* available clusters */
unsigned df_total; /* total clusters */

833
C Runtime Library Reference RAD Studio 3.1 Référence C++

unsigned df_bsec; /* bytes per sector */


unsigned df_sclus; /* sectors per cluster */
};

Return Value

getdfree returns no value. In the event of an error, df_sclus in the dfree structure is set to (unsigned) -1.

Example
#include <stdio.h>
#include <dos.h>
#include <process.h>
int main(void)
{
struct dfree free;
long avail;
getdfree(0, &free);
if ( free.df_sclus == -1)
{
printf("Error in getdfree() call\n");
exit(1);
}
avail = (long) free.df_avail
* (long) free.df_bsec
* (long) free.df_sclus;
printf("The current drive has %ld bytes available\n", avail);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.9.14 gettime, settime


Header File

dos.h

Category

Time and Date Routines

Prototype
void gettime(struct time *timep);
void settime(struct time *timep);

Description
3
Gets and sets the system time.

gettime fills in the time structure pointed to by timep with the system's current time.

• settime sets the system time to the values in the time structure pointed to by timep.
The time structure is defined as follows:
struct time {
unsigned char ti_min; /* minutes */

834
3.1 Référence C++ RAD Studio C Runtime Library Reference

unsigned char ti_hour; /* hours */


unsigned char ti_hund; /* hundredths of seconds */
unsigned char ti_sec; /* seconds */
};
Return Value
None.
Example
#include <stdio.h>
#include <dos.h>
int main(void)
{
struct time t;
gettime(&t);
printf("The current time is: %2d:%02d:%02d.%02d\n",
t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);
return 0;
}

3.1.5.9.15 unixtodos
Header File

dos.h

Category

Time and Date Routines

Prototype
void unixtodos(long time, struct date *d, struct time *t);

Description

Converts date and time from UNIX to DOS format.

unixtodos converts the UNIX-format time given in time to DOS format and fills in the date and time structures pointed to by d and
t.

time must not represent a calendar time earlier than Jan. 1, 1980 00:00:00.

Return Value

None.

Example
#include <stdio.h>
#include <dos.h>
char *month[] = {"---", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
#define SECONDS_PER_DAY 86400L /* the number of seconds in one day */ 3
struct date dt;
struct time tm;
int main(void)
{
unsigned long val;
/* get today's date and time */
getdate(&dt);
gettime(&tm);
printf("today is %d %s %d\n", dt.da_day, month[dt.da_mon], dt.da_year);
/*convert date and time to unix format (num of seconds since Jan 1, 1970*/

835
C Runtime Library Reference RAD Studio 3.1 Référence C++

val = dostounix(&dt, &tm);


/* subtract 42 days worth of seconds */
val -= (SECONDS_PER_DAY * 42);
/* convert back to dos time and date */
unixtodos(val, &dt, &tm);
printf("42 days ago it was %d %s %d\n",
dt.da_day, month[dt.da_mon], dt.da_year);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.9.16 _unlink, _wunlink


Header File

dos.h

Category

Input/output Routines

Prototype
int _unlink(const char *filename);
int _wunlink(const wchar_t *filename);

Description

Deletes a file.

_unlink deletes a file specified by filename. Any drive, path, and file name can be used as a filename. Wildcards are not allowed.

Read-only files cannot be deleted by this call. To remove read-only files, first use chmod or _rtl_chmod to change the read-only
attribute.

Remarque: If the file is open, it must be closed before unlinking it.

_wunlink is the Unicode version of _wunlink. The Unicode version accepts a filename that is a wchar_t character string.
Otherwise, the functions perform identically.

Return Value

On success, _unlink returns 0.

On error, it returns -1 and sets the global variable errno to one of the following values:

EACCES Permission denied

3 ENOENT Path or file name not found

Example
#include <stdio.h>
#include <io.h>
int main(void)
{
FILE *fp = fopen("junk.jnk","w");
int status;
fprintf(fp,"junk");

836
3.1 Référence C++ RAD Studio C Runtime Library Reference

status = access("junk.jnk",0);
if (status == 0)
printf("File exists\n");
else
printf("File doesn't exist\n");
fclose(fp);
unlink("junk.jnk");
status = access("junk.jnk",0);
if (status == 0)
printf("File exists\n");
else
printf("File doesn't exist\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_unlink + +
_wunlink NT only

3.1.5.10 errno.h
The following functions, macros, and classes are provided in errno.h:

Rubriques
Nom Description
EDOM, ERANGE, #defines ( see page 838) Header File
errno.h, math.h
Description
These are the mnemonics and meanings for the error numbers found in math.h
and errno.
_doserrno ( see page 839) Header File
errno.h
Syntax
extern int _doserrno;
Description
_doserrno is a variable that maps many operating system error codes to errno;
however, perror does not use _doserrno directly.
When an operating system call results in an error, _doserrno is set to the actual
operating system error code. errno is a parallel error variable inherited from UNIX.
The following list gives mnemonics for the actual DOS error codes to which
_doserrno can be set. (This value of _doserrno may or may not be mapped
(through errno) to an equivalent error message string in _sys_errlist.
errno (C Runtime Library Reference) ( see page 839) Header File
errno.h
Syntax
extern int errno;
Description
errno is used by perror to print error messages when certain library routines fail
to accomplish their appointed tasks. 3
When an error in a math or system call occurs, errno is set to indicate the type of
error. Sometimes errno and _doserrno are equivalent. At other times, errno does
not contain the actual operating system error code, which is contained in
_doserrno. Still other errors might occur that set only errno, not _doserrno.

837
C Runtime Library Reference RAD Studio 3.1 Référence C++

Error Numbers in errno ( see page 840) Header File


errno.h
Description
These are the mnemonics and meanings for the error numbers found in errno.
Each value listed can be used to index into the sys_errlist array for displaying
messages.
Also, perror will display messages.
perror,_wperror ( see page 841) Header File
errno.h, stdio.h
Category
Diagnostic Routines, Input/output Routines
Prototype
void perror(const char *s);
void _wperror(const wchar_t *s);
Description
Prints a system error message.
perror prints to the stderr stream (normally the console) the system error
message for the last library routine that set the global variable errno.
It prints the argument s followed by a colon (:) and the message corresponding to
the current value of the global variable errno and finally a new line. The
convention is to pass the file name of the program as the argument string.
The array of error message strings is accessed through... suite ( see page 841)
_sys_errlist ( see page 843) Header File
errno.h
Syntax
extern char * _sys_errlist[ ];
Description
_sys_errlist is used by perror to print error messages when certain library
routines fail to accomplish their appointed tasks.
To provide more control over message formatting, the array of message strings is
provided in _sys_errlist. You can use errno as an index into the array to find the
string corresponding to the error number. The string does not include any newline
character.
Example
printf("%s\n", _sys_errlist[ENOPATH]);
This code statement that uses the Mnemonic ENOPATH will output the string
"Path not found".
The following table gives mnemonics and their meanings for the... suite ( see
page 843)
_sys_nerr ( see page 844) Header File
errno.h
Syntax
extern int _sys_nerr;
Description
_sys_nerr is used by perror to print error messages when certain library routines
fail to accomplish their appointed tasks.
This variable is defined as the number of error message strings in _sys_errlist.

3.1.5.10.1 EDOM, ERANGE, #defines


Header File

errno.h, math.h

3 Description

These are the mnemonics and meanings for the error numbers found in math.h and errno.

Name Meaning
EDOM Error code for math domain error
ERANGE Error code for result out of range

838
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.10.2 _doserrno
Header File

errno.h

Syntax
extern int _doserrno;

Description

_doserrno is a variable that maps many operating system error codes to errno; however, perror does not use _doserrno directly.

When an operating system call results in an error, _doserrno is set to the actual operating system error code. errno is a parallel
error variable inherited from UNIX.

The following list gives mnemonics for the actual DOS error codes to which _doserrno can be set. (This value of _doserrno may
or may not be mapped (through errno) to an equivalent error message string in _sys_errlist.

E2BIG Bad environ


EACCES Access denied
EACCES Bad access
EACCES Is current dir
EBADF Bad handle
EFAULT Reserved
EINVAL Bad data
EINVAL Bad function
EMFILE Too many open
ENOENT No such file or directory
ENOEXEC Bad format
ENOMEM Mcb destroyed
ENOMEM Out of memory
ENOMEM Bad block
EXDEV Bad drive
EXDEV Not same device

3.1.5.10.3 errno (C Runtime Library Reference)


Header File

errno.h 3
Syntax
extern int errno;

Description

errno is used by perror to print error messages when certain library routines fail to accomplish their appointed tasks.

When an error in a math or system call occurs, errno is set to indicate the type of error. Sometimes errno and _doserrno are

839
C Runtime Library Reference RAD Studio 3.1 Référence C++

equivalent. At other times, errno does not contain the actual operating system error code, which is contained in _doserrno. Still
other errors might occur that set only errno, not _doserrno.

3.1.5.10.4 Error Numbers in errno


Header File

errno.h

Description

These are the mnemonics and meanings for the error numbers found in errno.

Each value listed can be used to index into the sys_errlist array for displaying messages.

Also, perror will display messages.

Mnemonic Meaning
EZERO Error 0
EINVFNC Invalid function number
ENOFILE File not found
ENOPATH Path not found
ECONTR Memory blocks destroyed
EINVMEM Invalid memory block address
EINVENV Invalid environment
EINVFMT Invalid format
EINVACC Invalid access code
EINVDAT Invalid data
EINVDRV Invalid drive specified
ECURDIR Attempt to remove CurDir
ENOTSAM Not same device
ENMFILE No more files
ENOENT No such file or directory
EMFILE Too many open files
EACCES Permission denied
EBADF Bad file number
ENOMEM Not enough memory
EFAULT Unknown error
ENODEV No such device
3
EINVAL Invalid argument
E2BIG Arg list too long
ENOEXEC Exec format error
EXDEV Cross-device link
ENFILE Too many open files
ECHILD No child process

840
3.1 Référence C++ RAD Studio C Runtime Library Reference

ENOTTY Terminal control function attempted on a file that is not a terminal. (POSIX – Not used in Win32
applications.)
ETXTBSY Not used in Win32 applications
EFBIG An attempt was made to write to a file, beyond the maximum file size. (POSIX – Not used in Win32
applications.)
ESOSPC No space left on device
ESPIPE Illegal seek
EROFS Read-only file system
EMLINK The number of links exceeds LINK_MAX. (POSIX – Not used in Win32 applications.)
EPIPE Broken pipe
EDOM Math argument
ERANGE Result too large
EEXIST File already exists
EDEADLOCK Locking violation
EPERM Operation not permitted
ESRCH No such process id. (POSIX – Not used in Win32 applications.)
EINTR Interrupted function call
EIO Input/output error
ENXIO No such device or address
EAGAIN Resource temporarily unavailable
ENOTBLK Not used in Win32 applications
EBUSY Resource busy
ENOTDIR A pathname component is not a directory. (POSIX – Not used in Win32 applications.)
EISDIR An attempt was made to open a directory for writing, or to rename a file with the same name as an
existing directory. (POSIX – Not used in Win32 applications.)
EUCLEAN Not used in Win32 console applications

3.1.5.10.5 perror,_wperror
Header File

errno.h, stdio.h

Category

Diagnostic Routines, Input/output Routines

Prototype 3
void perror(const char *s);
void _wperror(const wchar_t *s);

Description

Prints a system error message.

perror prints to the stderr stream (normally the console) the system error message for the last library routine that set the global

841
C Runtime Library Reference RAD Studio 3.1 Référence C++

variable errno.

It prints the argument s followed by a colon (:) and the message corresponding to the current value of the global variable errno
and finally a new line. The convention is to pass the file name of the program as the argument string.

The array of error message strings is accessed through the global variable _sys_errlist. The global variable errno can be used as
an index into the array to find the string corresponding to the error number. None of the strings include a newline character.

The global variable _sys_nerr contains the number of entries in the array.

The following messages are generated by perror:

Remarque: For Win32 GUI applications, stderr must be redirected.

Arg list too big

Attempted to remove current directory

Bad address

Bad file number

Block device required

Broken pipe

Cross-device link

Error 0

Exec format error

Executable file in use

File already exists

File too large

Illegal seek

Inappropriate I/O control operation

Input/output error

Interrupted function call

Invalid access code

Invalid argument Resource busy

Invalid dataResource temporarily unavailable

Invalid environment

Invalid format

Invalid function number


3
Invalid memory block address

Is a directory

Math argument

Memory arena trashed

Name too long

842
3.1 Référence C++ RAD Studio C Runtime Library Reference

No child processes

No more files

No space left on device

No such device

No such device or address

No such file or directory

No such process

Not a directory

Not enough memory

Not same device

Operation not permitted

Path not found

Permission denied

Possible deadlock

Read-only file system

Resource busy

Resource temporarily unavailable

Result too large

Too many links

Too many open files

Example
#include <stdio.h>
int main(void)
{
FILE *fp;
fp = fopen("perror.dat", "r");
if (!fp)
perror("Unable to open file for reading");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


perror + + + +
_wperror + 3

3.1.5.10.6 _sys_errlist
Header File

errno.h

843
C Runtime Library Reference RAD Studio 3.1 Référence C++

Syntax
extern char * _sys_errlist[ ];

Description

_sys_errlist is used by perror to print error messages when certain library routines fail to accomplish their appointed tasks.

To provide more control over message formatting, the array of message strings is provided in _sys_errlist. You can use errno as
an index into the array to find the string corresponding to the error number. The string does not include any newline character.

Example
printf("%s\n", _sys_errlist[ENOPATH]);

This code statement that uses the Mnemonic ENOPATH will output the string "Path not found".

The following table gives mnemonics and their meanings for the values stored in _sys_errlist. The list is alphabetically ordered
for ease your reading convenience. For the numerical ordering, see the header file errno.h.

3.1.5.10.7 _sys_nerr
Header File

errno.h

Syntax
extern int _sys_nerr;

Description

_sys_nerr is used by perror to print error messages when certain library routines fail to accomplish their appointed tasks.

This variable is defined as the number of error message strings in _sys_errlist.

3.1.5.11 except.h
The following functions, macros, and classes are provided in except.h:

Rubriques
Nom Description
__throwExceptionName ( see page 846) Header File
except.h
Syntax
extern char * _RTLENTRY __ThrowExceptionName();
#define __throwExceptionName __ThrowExceptionName()
Description
Use this global variable to get the name of a thrown exception. The output for this
variable is a printable character string.
__throwFileName ( see page 846) Header File
3 except.h
Syntax
extern char * _RTLENTRY __ThrowFileName();
#define __throwFileName __ThrowFileName()
Description
Use this global variable to get the name of a thrown exception. The output for this
variable is a printable character string.
To get the file name for a thrown exception with __throwFileName, you must
compile the module with the -xp compiler option.

844
3.1 Référence C++ RAD Studio C Runtime Library Reference

__throwLineNumber ( see page 846) Header File


except.h
Syntax
extern unsigned _RTLENTRY __ThrowLineNumber();
#define __throwLineNumber __ThrowLineNumber()
Description
Use this global variable to get the name of a thrown exception. The output for this
variable is a printable character string.
To get the line number for a thrown exception with __throwLineNumber, you
must compile the module with the -xp compiler option.
set_terminate ( see page 846) Header File
except.h
Syntax
typedef void (*terminate_handler)();
terminate_handler set_terminate(terminate_handler t_func);
Description
set_terminate lets you install a function that defines the program's termination
behavior when a handler for the exception cannot be found. The actions are
defined in t_func, which is declared to be a function of type terminate_handler. A
terminate_handler type, defined in except.h, is a function that takes no
arguments, and returns void.
By default, an exception for which no handler can be found results in the program
calling the terminate function. This will normally result in a call to abort. The
program then ends with the message Abnormal... suite ( see page 846)
set_unexpected ( see page 847) Header File
except.h
Syntax
typedef void ( * unexpected_handler )();
unexpected_handler set_unexpected(unexpected_handler
unexpected_func);
Description
set_unexpected lets you install a function that defines the program's behavior
when a function throws an exception not listed in its exception specification. The
actions are defined in unexpected_func, which is declared to be a function of
type unexpected_handler. An unexpected_handler type, defined in except.h, is a
function that takes no arguments, and returns void.
By default, an unexpected exception causes unexpected to be called. If is
defined, it is subsequently called by unexpected. Program control is then turned
over to the user-defined unexpected_func. Otherwise, terminate... suite ( see
page 847)
terminate ( see page 847) Header File
except.h
Syntax
void terminate();
Description
The function terminate can be called by unexpected or by the program when a
handler for an exception cannot be found. The default action by terminate is to
call abort. Such a default action causes immediate program termination.
You can modify the way that your program will terminate when an exception is
generated that is not listed in the exception specification. If you do not want the
program to terminate with a call to abort, you can instead define a function to be
called. Such a function (called a terminate_handler) will be called... suite ( see
page 847)
unexpected ( see page 848) Header File
except.h
Syntax
void unexpected();
Description 3
The unexpected function is called when a function throws an exception not listed
in its exception specification. The program calls unexpected, which by default
calls any user-defined function registered by set_unexpected. If no function is
registered with set_unexpected, the unexpected function then calls terminate.
Return Value
None, although unexpected may throw an exception.

845
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.11.1 __throwExceptionName
Header File

except.h

Syntax
extern char * _RTLENTRY __ThrowExceptionName();
#define __throwExceptionName __ThrowExceptionName()

Description

Use this global variable to get the name of a thrown exception. The output for this variable is a printable character string.

3.1.5.11.2 __throwFileName
Header File

except.h

Syntax
extern char * _RTLENTRY __ThrowFileName();
#define __throwFileName __ThrowFileName()

Description

Use this global variable to get the name of a thrown exception. The output for this variable is a printable character string.

To get the file name for a thrown exception with __throwFileName, you must compile the module with the -xp compiler option.

3.1.5.11.3 __throwLineNumber
Header File

except.h

Syntax
extern unsigned _RTLENTRY __ThrowLineNumber();
#define __throwLineNumber __ThrowLineNumber()

Description

Use this global variable to get the name of a thrown exception. The output for this variable is a printable character string.

To get the line number for a thrown exception with __throwLineNumber, you must compile the module with the -xp compiler
option.
3

3.1.5.11.4 set_terminate
Header File

except.h

Syntax

846
3.1 Référence C++ RAD Studio C Runtime Library Reference

typedef void (*terminate_handler)();


terminate_handler set_terminate(terminate_handler t_func);

Description

set_terminate lets you install a function that defines the program's termination behavior when a handler for the exception cannot
be found. The actions are defined in t_func, which is declared to be a function of type terminate_handler. A terminate_handler
type, defined in except.h, is a function that takes no arguments, and returns void.

By default, an exception for which no handler can be found results in the program calling the terminate function. This will
normally result in a call to abort. The program then ends with the message Abnormal program termination. If you want some
function other than abort to be called by the terminate function, you should define your own t_func function. Your t_func function
is installed by set_terminate as the termination function. The installation of t_func lets you implement any actions that are not
taken by abort.

Return Value

The previous function given to set_terminate will be the return value.

The definition of t_func must terminate the program. Such a user-defined function must not return to its caller, the terminate
function. An attempt to return to the caller results in undefined program behavior. It is also an error for t_func to throw an
exception.

3.1.5.11.5 set_unexpected
Header File

except.h

Syntax
typedef void ( * unexpected_handler )();
unexpected_handler set_unexpected(unexpected_handler unexpected_func);

Description

set_unexpected lets you install a function that defines the program's behavior when a function throws an exception not listed in
its exception specification. The actions are defined in unexpected_func, which is declared to be a function of type
unexpected_handler. An unexpected_handler type, defined in except.h, is a function that takes no arguments, and returns void.

By default, an unexpected exception causes unexpected to be called. If is defined, it is subsequently called by unexpected.
Program control is then turned over to the user-defined unexpected_func. Otherwise, terminate is called.

Return Value

The previous function given to set_unexpected will be the return value.

The definition of unexpected_func must not return to its caller, the unexpected function. An attempt to return to the caller results
in undefined program behavior.

unexpected_func can also call abort, exit, or terminate. 3

3.1.5.11.6 terminate
Header File

except.h

Syntax

847
C Runtime Library Reference RAD Studio 3.1 Référence C++

void terminate();

Description

The function terminate can be called by unexpected or by the program when a handler for an exception cannot be found. The
default action by terminate is to call abort. Such a default action causes immediate program termination.

You can modify the way that your program will terminate when an exception is generated that is not listed in the exception
specification. If you do not want the program to terminate with a call to abort, you can instead define a function to be called. Such
a function (called a terminate_handler) will be called by terminate if it is registered with set_terminate.

Return Value

None.

3.1.5.11.7 unexpected
Header File

except.h

Syntax
void unexpected();

Description

The unexpected function is called when a function throws an exception not listed in its exception specification. The program calls
unexpected, which by default calls any user-defined function registered by set_unexpected. If no function is registered with
set_unexpected, the unexpected function then calls terminate.

Return Value

None, although unexpected may throw an exception.

3.1.5.12 fastmath.h
The following functions, macros, and classes are provided in fastmath.h:

Rubriques
Nom Description
Using fastmath math routines ( see page 848) Header File
fastmath.h
Category
Math Routines
Description
The FastMath routines are high performance math routines that don't check for
most error conditions and never call matherr. They are coded for maximum
speed. These functions are never exported from the RTLDLL, which means that
they always get linked directly into the PE file that is being created.
3 When you include fastmath.h, the following math functions are remapped to
these fastmath functions.

3.1.5.12.1 Using fastmath math routines


Header File

fastmath.h

848
3.1 Référence C++ RAD Studio C Runtime Library Reference

Category

Math Routines

Description

The FastMath routines are high performance math routines that don't check for most error conditions and never call matherr.
They are coded for maximum speed. These functions are never exported from the RTLDLL, which means that they always get
linked directly into the PE file that is being created.

When you include fastmath.h, the following math functions are remapped to these fastmath functions.

Math Routine Fastmath Routine Math Routine Fastmath Routine


acos _fm_acos asin _fm_asin
atan _fm_atan atan2 _fm_atan2
cos _fm_cos cosh _fm_cosh
exp _fm_exp fabs _fm_fabs
asin _fm_asin atan _fm_atan
atan2 _fm_atan2 cos _fm_cos
cosh _fm_cosh exp _fm_exp
fabs _fm_fabs frexp _fm_frexp
hypot _fm_hypot ldexp _fm_ldexp
log _fm_log log10 _fm_log10
sin _fm_sin sinh _fm_sinh
sqrt _fm_sqr tan _fm_tan
tanh _fm_tanh sincos _fm_sincos
acosl _fm_acosl asinl _fm_asinl
atan2l _fm_atan2l atanl _fm_atanl
coshl _fm_coshl cosl _fm_cosl
expl _fm_expl fabsl _fm_fabsl
frexpl _fm_frexpl hypotl _fm_hypotl
ldexpl _fm_ldexpl log10l _fm_log10l
logl _fm_logl sinhl _fm_sinhl
sinl _fm_sinl sqrtl _fm_sqrtl
tanhl _fm_tanhl tanl _fm_tanl
sincosl _fm_sincosl atanhl _fm_atanhl
acoshl _fm_acoshl asinhl _fm_asinhl

If you don't want the standard C function names remapped to the FastMath versions, then define _FM_NO_REMAP. The 3
FastMath routines can still be called with their _fm_xxx names.

The following additional functions are available in FastMath; they are not directly supported in the regular RTL:
void _FMAPI _fm_sincos(double __a, double *__x, double *__y);
void _FMAPI _fm_sincosl(long double __a, long double *__x, long double *__y);
long double _FMAPI _fm_atanhl (long double __x);

849
C Runtime Library Reference RAD Studio 3.1 Référence C++

long double _FMAPI _fm_acoshl (long double __x);


long double _FMAPI _fm_asinhl (long double __x);
__inline void _fm_fwait(void)
unsigned int _FMAPI _fm_init(void);

_fm_fwait is a special inline function that performs an intrinsic FWAIT instruction.

_Fm_init is a function that can be called to mask all fpu exceptions prior to using the FastMath routines.

3.1.5.13 fcntl.h
The following functions, macros, and classes are provided in fcntl.h:

Rubriques
Nom Description
O_xxxx #defines ( see page 851) Header File
fcntl.h
Description
These #defines are bit definitions for a file-access argument.
These RTL file-open functions use some (not all) of these definitions:

• fdopen
• fopen
• freopen
• _fsopen
• open
• _rtl_open
• sopen
sopen also uses file-sharing symbolic constants in the
file-access argument.
_fmode ( see page 853) Header File
fcntl.h
Syntax
extern int _fmode;
Description
_fmode determines in which mode (text or binary) files will be opened and
translated. The value of _fmode is O_TEXT by default, which specifies that files
will be read in text mode. If _fmode is set to O_BINARY, the files are opened and
read in binary mode. (O_TEXT and O_BINARY are defined in fcntl.h.)
In text mode, carriage-return/linefeed (CR/LF) combinations are translated to a
single linefeed character (LF) on input. On output, the reverse is true: LF
characters are translated to CR/LF combinations.
In binary mode, no such translation occurs.
You can... suite ( see page 853)

850
3.1 Référence C++ RAD Studio C Runtime Library Reference

_pipe ( see page 853) Header File


io.h, fcntl.h
Category
Input/output Routines
Syntax
int _pipe(int *handles, unsigned int size, int mode);
Description
Creates a read/write pipe.
The _pipe function creates an anonymous pipe that can be used to pass
information between processes. The pipe is opened for both reading and writing.
Like a disk file, a pipe can be read from and written to, but it does not have a
name or permanent storage associated with it; data written to and from the pipe
exist only in a memory buffer managed by the operating system.
The read handle is returned to handles[0], and the write... suite ( see page 853)
open, _wopen ( see page 855) Header File
io.h, fcntl.h
Category
Input/output Routines
Prototype
int open(const char *path, int access [, unsigned mode]);
int _wopen(const wchar_t *path, int access [, unsigned
mode]);
Description
Opens a file for reading or writing.
open opens the file specified by path, then prepares it for reading and/or writing
as determined by the value of access.
To create a file in a particular mode, you can either assign to the global variable
_fmode or call open with the O_CREAT and O_TRUNC options ORed with the
translation mode desired.
open("XMP",O_CREAT|O_TRUNC|O_BINARY,S_IREAD)
creates a binary-mode, read-only file named XMP, truncating its length to 0...
suite ( see page 855)
_sopen, _wsopen ( see page 856) Header File
fcntl.h, sys\stat.h, share.h, io.h, stdio.h
Category
Input/output Routines
Prototype
int _sopen(char *path, int access, int shflag[, int mode]);
int _wsopen(wchar_t *path, int access, int shflag[, int
mode]);
Description
Opens a shared file.
_sopen opens the file given by path and prepares it for shared reading or writing,
as determined by access, shflag, and mode.
_wsopen is the Unicode version of _sopen. The Unicode version accepts a
filename that is a wchar_t character string. Otherwise, the functions perform
identically.
For _sopen, access is constructed by ORing flags bitwise from the following lists:
Read/write flags
You can use only one... suite ( see page 856)

3.1.5.13.1 O_xxxx #defines


Header File

fcntl.h 3
Description

These #defines are bit definitions for a file-access argument.

These RTL file-open functions use some (not all) of these definitions:

• fdopen
• fopen

851
C Runtime Library Reference RAD Studio 3.1 Référence C++

• freopen
• _fsopen
• open
• _rtl_open
• sopen
sopen also uses file-sharing symbolic constants in the file-access argument.

Constant Description
Read/Write flag

O_RDONLY Open for reading only


O_WRONLY Open for writing only
O_RDWR Open for reading and writing
Other access flags

O_NDELAY Not used; for UNIX compatibility.


O_APPEND Append to end of file
If set, the file pointer is set to the end of the file prior to each write.
O_CREAT Create and open file
If the file already exists, has no effect.
If the file does not exist, the file is created.
O_EXCL Exclusive open: Used only with O_CREAT.
If the file already exists, an error is returned.
O_TRUNC Open with truncation
If the file already exists, its length is truncated to 0. The file attributes remain
unchanged.
Binary-mode/Text-mode
flags
O_BINARY No translation: Explicitly opens the file in binary mode
O_TEXT CR-LF translation: Explicitly opens the file in text mode
Additional values
available using
_rtl_open
O_NOINHERIT Child processes inherit file
O_DENYALL Error if opened for read/write
3 O_DENYWRITE Error if opened for write
O_DENYREAD Error if opened for read
O_DENYNONE Allow concurrent access

Note: Only one of the O_DENYxxx options can be included in a single open. These file-sharing attributes are in addition to any
locking performed on the files.

852
3.1 Référence C++ RAD Studio C Runtime Library Reference

Do not modify
O_CHANGED Special DOS read-only bit
O_DEVICE Special DOS read-only bit

3.1.5.13.2 _fmode
Header File

fcntl.h

Syntax
extern int _fmode;

Description

_fmode determines in which mode (text or binary) files will be opened and translated. The value of _fmode is O_TEXT by
default, which specifies that files will be read in text mode. If _fmode is set to O_BINARY, the files are opened and read in binary
mode. (O_TEXT and O_BINARY are defined in fcntl.h.)

In text mode, carriage-return/linefeed (CR/LF) combinations are translated to a single linefeed character (LF) on input. On
output, the reverse is true: LF characters are translated to CR/LF combinations.

In binary mode, no such translation occurs.

You can override the default mode as set by _fmode by specifying a t (for text mode) or b (for binary mode) in the argument type
in the library functions fopen, fdopen, and freopen. Also, in the function open, the argument access can include either
O_BINARY or O_TEXT, which will explicitly define the file being opened (given by the path argument to the open function) to be
in either binary or text mode.

3.1.5.13.3 _pipe
Header File

io.h, fcntl.h

Category

Input/output Routines

Syntax
int _pipe(int *handles, unsigned int size, int mode);

Description

Creates a read/write pipe.

The _pipe function creates an anonymous pipe that can be used to pass information between processes. The pipe is opened for
3
both reading and writing. Like a disk file, a pipe can be read from and written to, but it does not have a name or permanent
storage associated with it; data written to and from the pipe exist only in a memory buffer managed by the operating system.

The read handle is returned to handles[0], and the write handle is returned to handles[1]. The program can use these handles in
subsequent calls to read, write, dup, dup2, or close. When all pipe handles are closed, the pipe is destroyed.

The size of the internal pipe buffer is size. A recommended minimum value is 512 bytes.

The translation mode is specified by mode, as follows:

853
C Runtime Library Reference RAD Studio 3.1 Référence C++

O_BINARY The pipe is opened in binary mode


O_TEXT The pipe is opened in text mode

If mode is zero, the translation mode is determined by the external variable _fmode.

Return Value

On success, _pipe returns 0 and returns the pipe handles to handles[0] and handles[1].

On error, it returns -1 and sets errno to one of the following values:

EMFILE Too many open files


ENOMEM Out of memory

Example
/*
There are two short programs here. SEND spawns a child
process, RECEIVE. Each process holds one end of a
pipe. The parent transmits its command-line argument
to the child, which prints the string and exits.
IMPORTANT: The parent process must be linked with
the \32bit\fileinfo.obj file. The code in fileinfo
enables a parent to share handles with a child.
Without this extra information, the child cannot use
the handle it receives.
*/
/* SEND */
#include <fcntl.h> // _pipe()
#include <io.h> // write()
#include <process.h> // spawnl() cwait()
#include <stdio.h> // puts() perror()
#include <stdlib.h> // itoa()
#include <string.h> // strlen()
#define DECIMAL_RADIX 10 // for atoi()
enum PIPE_HANDLES { IN, OUT }; // to index the array of handles
int main(int argc, char *argv[])
{
int handles[2]; // in- and
//outbound pipe handles
char handleStr[10]; // a handle
//stored as a string
int pid;
// system's ID for child process
if (argc <= 1)
{
puts("No message to send.");
return(1);
}
if (_pipe(handles, 256, O_TEXT) != 0)
{
perror("Cannot create the pipe");
3 return(1);
}
// store handle as a string for passing on the command line
itoa(handles[IN], handleStr, DECIMAL_RADIX);
// create the child process, passing it the inbound pipe handle
spawnl(P_NOWAIT, "receive.exe", "receive.exe", handleStr, NULL);
// transmit the message
write(handles[OUT], argv[1], strlen(argv[1])+1);
// when done with the pipe, close both handles
close(handles[IN]);
close(handles[OUT]);

854
3.1 Référence C++ RAD Studio C Runtime Library Reference

// wait for the child to finish


wait(NULL);
return(0);
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.13.4 open, _wopen


Header File

io.h, fcntl.h

Category

Input/output Routines

Prototype
int open(const char *path, int access [, unsigned mode]);
int _wopen(const wchar_t *path, int access [, unsigned mode]);

Description

Opens a file for reading or writing.

open opens the file specified by path, then prepares it for reading and/or writing as determined by the value of access.

To create a file in a particular mode, you can either assign to the global variable _fmode or call open with the O_CREAT and
O_TRUNC options ORed with the translation mode desired.
open("XMP",O_CREAT|O_TRUNC|O_BINARY,S_IREAD)

creates a binary-mode, read-only file named XMP, truncating its length to 0 bytes if it already existed.

For open, access is constructed by bitwise ORing flags from the following lists. Only one flag from the first list can be used (and
one must be used); the remaining flags can be used in any logical combination.

These symbolic constants are defined in fcntl.h.

O_RDONLY Open for reading only.


O_WRONLY Open for writing only.
O_RDWR Open for reading and writing.
3

O_NDELAY Not used; for UNIX compatibility.


O_APPEND If set, the file pointer will be set to the end of the file prior to each write.
O_CREAT If the file exists, this flag has no effect. If the file does not exist, the file is created, and the bits of
mode are used to set the file attribute bits as in chmod.
O_TRUNC If the file exists, its length is truncated to 0. The file attributes remain unchanged.

855
C Runtime Library Reference RAD Studio 3.1 Référence C++

O_EXCL Used only with O_CREAT. If the file already exists, an error is returned.
O_BINARY Can be given to explicitly open the file in binary mode.
O_TEXT Can be given to explicitly open the file in text mode.

If neither O_BINARY nor O_TEXT is given, the file is opened in the translation mode set by the global variable _fmode.

If the O_CREAT flag is used in constructing access, you need to supply the mode argument to open from the following symbolic
constants defined in sys\stat.h.

S_IWRITE Permission to write


S_IREAD Permission to read
S_IREAD|S_IWRITE Permission to read and write

Return Value

On success, open returns a nonnegative integer (the file handle). The file pointer, which marks the current position in the file, is
set to the beginning of the file.

On error, open returns -1 and the global variable errno is set to one of the following values:

EACCES Permission denied


EINVACC Invalid access code
EMFILE Too many open files
ENOENT No such file or directory

Example
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
char msg[] = "Hello world";
if ((handle = open("TEST.$$$", O_CREAT | O_TEXT)) == -1)
{
perror("Error:");
return 1;
}
write(handle, msg, strlen(msg));
close(handle);
return 0;
}
Portability

3 POSIX Win32 ANSI C ANSI C++


open + +
_wopen NT only

3.1.5.13.5 _sopen, _wsopen


Header File

856
3.1 Référence C++ RAD Studio C Runtime Library Reference

fcntl.h, sys\stat.h, share.h, io.h, stdio.h

Category

Input/output Routines

Prototype
int _sopen(char *path, int access, int shflag[, int mode]);
int _wsopen(wchar_t *path, int access, int shflag[, int mode]);

Description

Opens a shared file.

_sopen opens the file given by path and prepares it for shared reading or writing, as determined by access, shflag, and mode.

_wsopen is the Unicode version of _sopen. The Unicode version accepts a filename that is a wchar_t character string.
Otherwise, the functions perform identically.

For _sopen, access is constructed by ORing flags bitwise from the following lists:

Read/write flags

You can use only one of the following flags:

O_RDONLY Open for reading only.


O_WRONLY Open for writing only.
O_RDWR Open for reading and writing.

Other access flags

You can use any logical combination of the following flags:

O_NDELAY Not used; for UNIX compatibility.


O_APPEND If set, the file pointer is set to the end of the file prior to each write.
O_CREA If the file exists, this flag has no effect. If the file does not exist, the file is created, and the bits of
mode are used to set the file attribute bits as in chmod.
O_TRUNC If the file exists, its length is truncated to 0. The file attributes remain unchanged.
O_EXCL Used only with O_CREAT. If the file already exists, an error is returned.
O_BINARY This flag can be given to explicitly open the file in binary mode.
O_TEXT This flag can be given to explicitly open the file in text mode.
O_NOINHERIT The file is not passed to child programs.

Remarque: These O_... symbolic constants are defined in fcntl.h.

If neither O_BINARY nor O_TEXT is given, the file is opened in the translation mode set by the global variable _fmode.

If the O_CREAT flag is used in constructing access, you need to supply the mode argument to _sopen from the following 3
symbolic constants defined in sys\stat.h.

S_IWRITE Permission to write


S_IREAD Permission to read
S_IREAD|S_IWRITE Permission to read/write

shflag specifies the type of file-sharing allowed on the file path. Symbolic constants for shflag are defined in share.h.

857
C Runtime Library Reference RAD Studio 3.1 Référence C++

SH_COMPAT Sets compatibility mode.


SH_DENYRW Denies read/write access
SH_DENYWR Denies write access
SH_DENYRD Denies read access
SH_DENYNONE Permits read/write access
SH_DENYNO Permits read/write access

Return Value

On success, _sopen returns a nonnegative integer (the file handle), and the file pointer (that marks the current position in the file)
is set to the beginning of the file.

On error, it returns -1, and the global variable errno is set to

EACCES Permission denied


EINVACC Invalid access code
EMFILE Too many open files
ENOENT Path or file function not found

Example
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <process.h>
#include <share.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int handle,
handle1;
handle = sopen("c:\\autoexec.bat", O_RDONLY, SH_DENYWR, S_IREAD);
if (handle == -1)
{
perror (sys_errlist[errno]);
exit (1);
}
if (!handle)
{
printf("sopen failed\n");
exit(1);
}
/* Attempt sopen for write.
*/
handle1 = sopen("c:\\autoexec.bat", O_RDONLY, SH_DENYWR, S_IREAD);
if (handle1 == -1)
{
3 perror (sys_errlist[errno]);
exit (1);
}
if (!handle1)
{
printf("sopen failed\n");
exit(1);
}
close (handle);
close (handle1);

858
3.1 Référence C++ RAD Studio C Runtime Library Reference

return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_sopen +
_wsopen +

3.1.5.14 float.h
The following functions, macros, and classes are provided in float.h:

Rubriques
Nom Description
CW_DEFAULT #define ( see page 862) Header File
float.h
Description
Default control word for 80x87 math coprocessor.
_chgsign, _chgsignl ( see page 862) Header File
float.h
Category
Math Routintes
Prototype
double _chgsign(double d);
long double _chgsignl(long double ld);
Description
Reverses the sign of a double-precision floating-point argument, d.
_chgsignl is the long double version; it takes a long double argument and
returns a long double result.
Return Value
Returns a value of the same magnitude and exponent as the argument, but with
the opposite sign. There is no error return value.
Portability
_clear87, _clearfp ( see page 863) Header File
float.h
Category
Math Routines
Prototype
unsigned int _clear87 (void);
unsigned int _clearfp (void);
Description
Clears the floating-point status word.
_clear87 clears the floating-point status word, which is a combination of the
80x87 status word and other conditions detected by the 80x87 exception handler.
_clearfp is identical to _clear87 and is for Microsoft compatibility.
Return Value
The bits in the value returned indicate the floating-point status before it was
cleared. For information on the status word, refer to the constants defined in
float.h.
Example
3

859
C Runtime Library Reference RAD Studio 3.1 Référence C++

_control87, _controlfp ( see page 864) Header File


float.h
Category
Math Routines
Prototype
unsigned int _control87(unsigned int newcw, unsigned int
mask);
unsigned int _controlfp(unsigned int newcw, unsigned int
mask);
Description
Manipulates the floating-point control word.
_control87 retrieves or changes the floating-point control word.
The floating-point control word is an unsigned int that, bit by bit, specifies certain
modes in the floating-point package; namely, the precision, infinity, and rounding
modes. Changing these modes lets you mask or unmask floating-point
exceptions.
_control87 matches the bits in mask to the bits in newcw. If a mask bit equals 1,
the corresponding bit in newcw contains the new value... suite ( see page 864)
_copysign, _copysignl ( see page 865) Header File
float.h
Category
Math Routines
Prototype
double _copysign(double da, double db);
long double _copysignl(long double lda, long double ldb);
Description
Returns the double-precision floating point argument da, with the same sign as
the double-precision floating-point argument db.
_copysignl is the long double version; it takes a long double argument and
returns a long double result.
Return Value
Returns the first value with the same magnitude and exponent, but with the sign
of the second value. There is no error value returned.
Portability
_finite, _finitel ( see page 865) Header File
float.h
Category
Math Routines
Prototype
int _finite(double d);
int _finitel(long double ld);
Description
Determines whether a given double-precision floating point value d is finite.
_finitel is the long double version; it takes a long double argument.
Return Value
Returns non-zero if the argument is finite, and 0 if it is not.
Portability
_fpclass, _fpclassl ( see page 866) Header File
float.h
Category
Math Routines
Prototype
int _fpclass(double d);
int _fpclassl(long double ld);
Description
3 Returns an integer value representing the type (class) of an IEEE real for
doubles. This value contains information on the floating-point class of the
argument.
_fpclassl is the long double version; it takes a long double argument and
returns the type (class) of an IEEE real for long doubles.
Return Value
Returns an integer value that indicates the floating-point class of its argument.
The possible values, which are listed in the table below, are defined in FLOAT.H.
Portability

860
3.1 Référence C++ RAD Studio C Runtime Library Reference

_fpreset ( see page 866) Header File


float.h
Category
Math Routines
Prototype
void _fpreset(void);
Description
Reinitializes floating-point math package.
_fpreset reinitializes the floating-point math package. This function is usually
used in conjunction with system or the exec... or spawn... functions. It is also
used to recover from floating-point errors before calling longjmp.
Remarque: If an 80x87 coprocessor is used in a program a child process
(executed by the system, or by an exec... or spawn... function) might alter the
parent process' floating-point state.

• If you use an 80x87 take the following precautions:


• Do not call system or an exec... or spawn... function while
a... suite ( see page 866)
_isnan, _isnanl ( see page 867) Header File
float.h
Category
Classification Routines, Math Routines
Prototype
int _isnan(double d);
int _isnanl(long double ld);
Description
Tests whether a given double-precision floating-point value d is a NaN.
_isnanl is the long double version; it takes a long double argument.
Return Value
Returns a nonzero value (TRUE) if the value passed in is a NaN; otherwise it
returns 0 (FALSE). The non-zero return value corresponds to either
_FPCLASS_SNAN, if the NaN is of the signaling type, or _FPCLASS_QNAN, if
the NaN is of the quiet type. The values for _FPCLASS_SNAN and
_FPCLASS_QNAN are in float.h.
Portability
_logb, _logbl ( see page 868) Header File
float.h
Category
Math Routines
Prototype
double _logb(double d);
long double _logbl(long double ld);
Description
Extracts the exponential value of a double-precision floating-point argument. If
the argument is denormalized, it is treated as if it were normalized.
_logbl is the long double version; it takes a long double argument and returns a
long double result.
Return Value
Returns the unbiased exponent of the value passed in.
Portability

861
C Runtime Library Reference RAD Studio 3.1 Référence C++

_nextafter, _nextafterl ( see page 868) Header File


float.h
Category
Math Routines
Prototype
double _nextafter(double da, double db);
long double _nextafterl(long double lda, long double ldb);
Description
Takes two doubles (da and db) and returns the closest representable neighbor of
da in the direction toward db.
If da == db, _nextafter returns da, with no exception triggered. If either da or db is
a quiet NaN, then the return value is one or the other of the input NaNs.
_nextafterl is the long double version; it takes a long double argument and
returns a long double result.
Return Value
Returns the closest representable neighbor of... suite ( see page 868)
_scalb, _scalbl ( see page 869) Header File
float.h
Category
Math Routines
Prototype
double _scalb(double d, long exp);
long double _scalbl(long double ld, long exp);
Description
Scales the argument d by a power of 2.
_scalbl is the long double version; it takes a long double argument and returns
a long double result.
Return Value
Returns an exponential value if successful. On overflow (depending on the sign
of the argument), the function returns +/– HUGE_VAL; the ERRNO variable is set
to ERANGE.
Portability
_status87, _statusfp ( see page 869) Header File
float.h
Category
Math Routines
Prototype
unsigned int _status87(void);
unsigned int _statusfp(void);
Description
Gets floating-point status.
_status87 gets the floating-point status word, which is a combination of the 80x87
status word and other conditions detected by the 80x87 exception handler.
_statusfp is identical to _status87 and is for Microsoft compatibility.
Return Value
The bits in the return value give the floating-point status. See float.h for a
complete definition of the bits returned by _status87 and _status87.
Portability

3.1.5.14.1 CW_DEFAULT #define


Header File

3 float.h

Description

Default control word for 80x87 math coprocessor.

3.1.5.14.2 _chgsign, _chgsignl


Header File

862
3.1 Référence C++ RAD Studio C Runtime Library Reference

float.h

Category

Math Routintes

Prototype
double _chgsign(double d);
long double _chgsignl(long double ld);

Description

Reverses the sign of a double-precision floating-point argument, d.

_chgsignl is the long double version; it takes a long double argument and returns a long double result.

Return Value

Returns a value of the same magnitude and exponent as the argument, but with the opposite sign. There is no error return value.

Portability

POSIX Win32 ANSI C ANSI C++


_chgsign +
_chgsignl +

3.1.5.14.3 _clear87, _clearfp


Header File

float.h

Category

Math Routines

Prototype
unsigned int _clear87 (void);
unsigned int _clearfp (void);

Description

Clears the floating-point status word.

_clear87 clears the floating-point status word, which is a combination of the 80x87 status word and other conditions detected by
the 80x87 exception handler.

_clearfp is identical to _clear87 and is for Microsoft compatibility.

Return Value 3
The bits in the value returned indicate the floating-point status before it was cleared. For information on the status word, refer to
the constants defined in float.h.

Example
#include <stdio.h>
#include <float.h>
int main(void)
{

863
C Runtime Library Reference RAD Studio 3.1 Référence C++

float x;
double y = 1.5e-100;
printf("\nStatus 87 before error: %X\n", _status87());
x = y; /* create underflow and precision loss */
printf("Status 87 after error: %X\n", _status87());
_clear87();
printf("Status 87 after clear: %X\n", _status87());
y = x;
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.14.4 _control87, _controlfp


Header File

float.h

Category

Math Routines

Prototype
unsigned int _control87(unsigned int newcw, unsigned int mask);
unsigned int _controlfp(unsigned int newcw, unsigned int mask);

Description

Manipulates the floating-point control word.

_control87 retrieves or changes the floating-point control word.

The floating-point control word is an unsigned int that, bit by bit, specifies certain modes in the floating-point package; namely,
the precision, infinity, and rounding modes. Changing these modes lets you mask or unmask floating-point exceptions.

_control87 matches the bits in mask to the bits in newcw. If a mask bit equals 1, the corresponding bit in newcw contains the
new value for the same bit in the floating-point control word, and _control87 sets that bit in the control word to the new value.

Here is a simple illustration:

Original control word: 0100 0011 0110 0011


mask: 1000 0001 0100 1111
newcw: 1110 1001 0000 0101
Changing bits: 1xxx xxx1 x0xx 0101
3
If mask equals 0, _control87 returns the floating-point control word without altering it.

_controlfp is for Microsoft compatibility. _controlfp is identical to _control87 except that it always removes (turns off) the
EM_DEMORMAL bit from the mask parameter.

Return Value

The bits in the value returned reflect the new floating-point control word. For a complete definition of the bits returned by
_control87, see the header file float.h.

864
3.1 Référence C++ RAD Studio C Runtime Library Reference

Portability

POSIX Win32 ANSI C ANSI C++


_control87 +
_controlfp +

3.1.5.14.5 _copysign, _copysignl


Header File

float.h

Category

Math Routines

Prototype
double _copysign(double da, double db);
long double _copysignl(long double lda, long double ldb);

Description

Returns the double-precision floating point argument da, with the same sign as the double-precision floating-point argument db.

_copysignl is the long double version; it takes a long double argument and returns a long double result.

Return Value

Returns the first value with the same magnitude and exponent, but with the sign of the second value. There is no error value
returned.

Portability

POSIX Win32 ANSI C ANSI C++


_copysign +
_copysignl +

3.1.5.14.6 _finite, _finitel


Header File

float.h

Category

Math Routines
3
Prototype
int _finite(double d);
int _finitel(long double ld);

Description

Determines whether a given double-precision floating point value d is finite.

_finitel is the long double version; it takes a long double argument.

865
C Runtime Library Reference RAD Studio 3.1 Référence C++

Return Value

Returns non-zero if the argument is finite, and 0 if it is not.

Portability

POSIX Win32 ANSI C ANSI C++


_finite +
_finitel +

3.1.5.14.7 _fpclass, _fpclassl


Header File

float.h

Category

Math Routines

Prototype
int _fpclass(double d);
int _fpclassl(long double ld);

Description

Returns an integer value representing the type (class) of an IEEE real for doubles. This value contains information on the
floating-point class of the argument.

_fpclassl is the long double version; it takes a long double argument and returns the type (class) of an IEEE real for long
doubles.

Return Value

Returns an integer value that indicates the floating-point class of its argument. The possible values, which are listed in the table
below, are defined in FLOAT.H.

Portability

POSIX Win32 ANSI C ANSI C++


_fpclass +
_fpclassl +

3.1.5.14.8 _fpreset
Header File
3
float.h

Category

Math Routines

Prototype
void _fpreset(void);

866
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

Reinitializes floating-point math package.

_fpreset reinitializes the floating-point math package. This function is usually used in conjunction with system or the exec... or
spawn... functions. It is also used to recover from floating-point errors before calling longjmp.

Remarque: If an 80x87 coprocessor is used in a program a child process (executed by the system, or by an exec... or spawn...
function) might alter the parent process' floating-point state.

• If you use an 80x87 take the following precautions:


• Do not call system or an exec... or spawn... function while a floating-point expression is being evaluated.
Call _fpreset to reset the floating-point state after using system exec... or spawn... if there is any chance that the child process
performed a floating-point operation with the 80x87.
Return Value
None.
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.14.9 _isnan, _isnanl


Header File

float.h

Category

Classification Routines, Math Routines

Prototype
int _isnan(double d);
int _isnanl(long double ld);

Description

Tests whether a given double-precision floating-point value d is a NaN.

_isnanl is the long double version; it takes a long double argument.

Return Value

Returns a nonzero value (TRUE) if the value passed in is a NaN; otherwise it returns 0 (FALSE). The non-zero return value
corresponds to either _FPCLASS_SNAN, if the NaN is of the signaling type, or _FPCLASS_QNAN, if the NaN is of the quiet
type. The values for _FPCLASS_SNAN and _FPCLASS_QNAN are in float.h.

Portability 3
POSIX Win32 ANSI C ANSI C++
_isnan +
_isnanl +

867
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.14.10 _logb, _logbl


Header File

float.h

Category

Math Routines

Prototype
double _logb(double d);
long double _logbl(long double ld);

Description

Extracts the exponential value of a double-precision floating-point argument. If the argument is denormalized, it is treated as if it
were normalized.

_logbl is the long double version; it takes a long double argument and returns a long double result.

Return Value

Returns the unbiased exponent of the value passed in.

Portability

POSIX Win32 ANSI C ANSI C++


_logb +
_logbl +

3.1.5.14.11 _nextafter, _nextafterl


Header File

float.h

Category

Math Routines

Prototype
double _nextafter(double da, double db);
long double _nextafterl(long double lda, long double ldb);

Description

3 Takes two doubles (da and db) and returns the closest representable neighbor of da in the direction toward db.

If da == db, _nextafter returns da, with no exception triggered. If either da or db is a quiet NaN, then the return value is one or the
other of the input NaNs.

_nextafterl is the long double version; it takes a long double argument and returns a long double result.

Return Value

Returns the closest representable neighbor of the first argument in the direction toward the second argument.

868
3.1 Référence C++ RAD Studio C Runtime Library Reference

Portability

POSIX Win32 ANSI C ANSI C++


_nextafter +
_nextafterl +

3.1.5.14.12 _scalb, _scalbl


Header File

float.h

Category

Math Routines

Prototype
double _scalb(double d, long exp);
long double _scalbl(long double ld, long exp);

Description

Scales the argument d by a power of 2.

_scalbl is the long double version; it takes a long double argument and returns a long double result.

Return Value

Returns an exponential value if successful. On overflow (depending on the sign of the argument), the function returns +/–
HUGE_VAL; the ERRNO variable is set to ERANGE.

Portability

POSIX Win32 ANSI C ANSI C++


_scalb +
_scalbl +

3.1.5.14.13 _status87, _statusfp


Header File

float.h

Category

Math Routines
3
Prototype
unsigned int _status87(void);
unsigned int _statusfp(void);

Description

Gets floating-point status.

_status87 gets the floating-point status word, which is a combination of the 80x87 status word and other conditions detected by

869
C Runtime Library Reference RAD Studio 3.1 Référence C++

the 80x87 exception handler.

_statusfp is identical to _status87 and is for Microsoft compatibility.

Return Value

The bits in the return value give the floating-point status. See float.h for a complete definition of the bits returned by _status87
and _status87.

Portability

POSIX Win32 ANSI C ANSI C++


_status87 +
_statusfp +

3.1.5.15 io.h
The following functions, macros, and classes are provided in io.h:

Rubriques
Nom Description
_findclose ( see page 880) Header File
io.h
Category
Directory Control Routines
Prototype
int _findclose(long handle);
Description
Closes the specified search handle and releases associated resources
associated with previous calls to findfirst/findnext. The handle parameter is the
search handle returned by the previous call to _findfirst.
This function is provided for Microsoft compatibility.
Return Value
On success, returns 0.
Otherwise, returns –1 and sets errno to:
ENOENTFile specification that could not be matched
Portability
_findfirst, __wfindfirst ( see page 881) Header File
io.h, wchar.h
Category
Directory Control Routines
Prototype
long _findfirst(char *filter, struct _finddata_t *fileinfo);
long __wfindfirst(wchar_t *filter, struct _wfinddata_t
*fileinfo);
Description
Begins a search of a disk directory to find information about the first instance of a
filename that matches a specified filter. The filter parameter is a string that
specifies which files to return. Wildcards may be used in the filter. The fileinfo
parameter is the file information buffer. If a matching file is found, the fileinfo
3 structure is filled with the file-directory information.
These functions are provided for Microsoft compatibility.
Return Value
On success, returns a unique... suite ( see page 881)

870
3.1 Référence C++ RAD Studio C Runtime Library Reference

_findfirsti64, _wfindfirsti64 ( see page 882) Header File


io.h, wchar.h
Category
Directory Control Routines
Prototype
long _findfirsti64(char *filter, struct _finddatai64_t
*fileinfo);
long _wfindfirsti64(wchar_t *filter, struct _wfinddatai64_t
*fileinfo);
Description
Begins a search of a disk directory to find information about the first instance of a
filename that matches a specified filter. The filter parameter is a string that
specifies which files to return. Wildcards may be used in the filter. The fileinfo
parameter is the file information buffer. If a matching file is found, the fileinfo
structure is filled with the file-directory information.
These i64 versions are for 64 bit filesize use and are provided for Microsoft...
suite ( see page 882)
_findnext, __wfindnext ( see page 882) Header File
io.h, wchar.h
Category
Directory Control Routines
Prototype
long _findnext(long handle, struct _finddata_t *fileinfo);
long __wfindnext(long handle, struct _wfinddata_t
*fileinfo);
Description
Finds subsequent files, if any, that match the filter argument in a previous call to
_findfirst/__wfindfirst. Then, _findnext/__wfindnext updates the fileinfo structure
with the necessary information for continuing the search. One file name for each
call to _tfindnext is returned until no more files are found in the directory matching
the pathname (filter).
The handle parameter is the search handle returned by a previous call to
_findfirst. The fileinfo parameter is the file information buffer.
These functions are... suite ( see page 882)
_findnexti64, _wfindnexti64 ( see page 883) Header File
io.h, wchar.h
Category
Directory Control Routines
Prototype
long _findnexti64(long handle, struct _finddatai64_t
*fileinfo);
__int64 _wfindnexti64(long handle, struct _wfinddata_t
*fileinfo);
Description
Finds subsequent files, if any, that match the filter argument in a previous call to
_findfirsti64/_wfindfirsti64. Then, _findnexti64/_wfindnexti64 updates the fileinfo
structure with the necessary information for continuing the search. One file name
for each call to _tfindnext is returned until no more files are found in the directory
matching the pathname (filter).
The handle parameter is the search handle returned by a previous call to
_findfirst. The fileinfo parameter is the file information buffer.
These i64 versions... suite ( see page 883)
_get_osfhandle ( see page 884) Header File
io.h
Category
Input/output Routines
Prototype
long _get_osfhandle(int filehandle); 3
Description
Associates file handles.
The _get_osfhandle function associates an operating system file handle with an
existing runtime file handle. The variable filehandle is the file handle of your
program.
Return value
On success, _get_osfhandle returns an operating system file handle
corresponding to the variable filehandle.
On error, the function returns -1 and sets the global variable errno to

871
C Runtime Library Reference RAD Studio 3.1 Référence C++

_open_osfhandle ( see page 886) Header File


io.h
Category
Input/output Routines
Prototype
int _open_osfhandle(long osfhandle, int flags);
Description
Associates file handles.
The _open_osfhandle function allocates a runtime file handle and sets it to point
to the operating system file handle specified by osfhandle.
The value flags is a bitwise OR combination of one or more of the following
manifest constants (defined in fcntl.h):
_pclose ( see page 887) Header File
stdio.h
Category
Input/output Routines, Process Control Routines
Prototype
int _pclose(FILE * stream);
Description
Waits for piped command to complete.
_pclose closes a pipe stream created by a previous call to _popen, and then
waits for the associated child command to complete.
Return Value
On success, _pclose returns the termination status of the child command. This is
the same value as the termination status returned by cwait, except that the high
and low order bytes of the low word are swapped.
On error, it returns -1.
Portability
_rtl_chmod, _wrtl_chmod ( see page 887) Header File
io.h
Category
Input/output Routines
Prototype
int _rtl_chmod(const char *path, int func [, int attrib]);
int _wrtl_chmod(const wchar_t *path, int func, ... );
Description
Gets or sets file attributes.
Remarque: The _rtl_chmod function replaces _chmod
which is obsolete_rtl_chmod can either fetch or set file attributes. If func is 0,
_rtl_chmod returns the current attributes for the file. If func is 1, the attribute is set
to attrib.
attrib can be one of the following symbolic constants (defined in dos.h):
_rtl_close ( see page 889) Header File
io.h
Category
Input/output Routines
Prototype
int _rtl_close(int handle);
Description
Closes a file.
Remarque: This function replaces _close which is obsolete
The _rtl_close function closes the file associated with handle, a file handle
obtained from a call to creat, creatnew, creattemp, dup, dup2, open, _rtl_creat, or
_rtl_open.
It does not write a Ctrl-Z character at the end of the file. If you want to terminate
3 the file with a Ctrl-Z, you must explicitly output one.
Return Value
On success, _rtl_close returns 0.
On error (if it fails because handle is not the handle of a valid, open file),
_rtl_close... suite ( see page 889)

872
3.1 Référence C++ RAD Studio C Runtime Library Reference

_rtl_creat, _wrtl_creat ( see page 890) Header File


io.h
Category
Input/output Routines
Prototype
int _rtl_creat(const char *path, int attrib);
int _wrtl_creat(const wchar_t *path, int attrib);
Description
Creates a new file or overwrites an existing one.
Remarque: The _rtl_creat function replaces _creat,
which is obsolete_rtl_creat opens the file specified by path. The file is always
opened in binary mode. Upon successful file creation, the file pointer is set to the
beginning of the file. The file is opened for both reading and writing.
If the file already exists its size is reset to 0. (This is essentially the same as
deleting the file and creating a new... suite ( see page 890)
_rtl_open, _wrtl_open ( see page 891) Header File
io.h
Category
Input/output Routines
Prototype
int _rtl_open(const char *filename, int oflags);
int _wrtl_open(const wchar_t *path, int oflags);
Description
Opens a file for reading or writing.
Remarque: The _rtl_open function replaces _open which is obsolete.
_rtl_open opens the file specified by filename, then prepares it for reading or
writing, as determined by the value of oflags. The file is always opened in binary
mode.
oflags uses the flags from the following two lists. Only one flag from List 1 can be
used (and one must be used) and the flags in List 2 can be used in any logical...
suite ( see page 891)
_rtl_read ( see page 893) Header File
io.h
Category
Input/output Routines
Prototype
int _rtl_read(int handle, void *buf, unsigned len);
Description
Reads from file.
Remarque: This function replaces _read which is obsolete.
This function reads len bytes from the file associated with handle into the buffer
pointed to by buf. When a file is opened in text mode, _rtl_read does not remove
carriage returns.
The argument handle is a file handle obtained from a creat, open, dup, or dup2
call.
On disk files, _rtl_read begins reading at the current file pointer. When the
reading is complete, it increments the file pointer by the number of bytes... suite
( see page 893)
_rtl_write ( see page 894) Header File
io.h
Category
Input/output Routines
Prototype
int _rtl_write(int handle, void *buf, unsigned len);
Description
Writes to a file. 3
Remarque: This function replaces _write which is obsolete.
_rtl_write attempts to write len bytes from the buffer pointed to by buf to the file
associated with handle.
The maximum number of bytes that _rtl_write can write is UINT_MAX -1
(because UINT_MAX is the same as -1), which is the error return indicator for
_rtl_write. UINT_MAX is defined in limits.h. _rtl_write does not translate a
linefeed character (LF) to a CR/LF pair because all its files are binary files.
If the number... suite ( see page 894)

873
C Runtime Library Reference RAD Studio 3.1 Référence C++

_snprintf;_snwprintf ( see page 895) Header File


stdio.h
Category
Memory and String Manipulation Routines
Syntax
int _snprintf(char* buffer, size_t nsize, const char*
format, ...);
int _snwprintf(wchar_t* buffer, size_t nsize, const
wchar_t* format, ...);
Description
Sends formatted output to a string of a maximum length specified by nsize.
_snprintf and _snwprintf are Microsoft compatible with the _snprintf and
_snprintfw functions, respectively.
If the number of bytes to output is:

• < nsize, then all of the characters have been written,


including the terminating ‘\0’ character.
• == nsize, then nsize characters are written with no
terminating ‘\0’ character.
If nsize is 0, then the string will not be... suite ( see page
895)
access, _waccess ( see page 896) Header File
io.h
Category
Input/output Routines
Prototype
int access(const char *filename, int amode);
int _waccess(const wchar_t *filename, int amode);
Description
Determines accessibility of a file.
access checks the file named by filename to determine if it exists, and whether it
can be read, written to, or executed.
The list of amode values is as follows:
chmod, _wchmod ( see page 897) Header File
io.h
Category
Input/output Routines
Prototype
int chmod(const char *path, int amode);
int _wchmod(const wchar_t *path, int amode);
Description
Changes file access mode.
chmod sets the file-access permissions of the file given by path according to the
mask given by amode. path points to a string.
amode can contain one or both of the symbolic constants S_IWRITE and
S_IREAD (defined in sys\stat.h).
chsize ( see page 898) Header File
io.h
Category
Input/output Routines
Prototype
int chsize(int handle, long size);
Description
3 Changes the file size.
chsize changes the size of the file associated with handle. It can truncate or
extend the file, depending on the value of size compared to the file's original size.
The mode in which you open the file must allow writing.
If chsize extends the file, it will append null characters (\0). If it truncates the file,
all data beyond the new end-of-file indicator is lost.
Return Value
On success, chsize returns 0. On failure, it returns -1 and the global variable
errno is... suite ( see page 898)

874
3.1 Référence C++ RAD Studio C Runtime Library Reference

close ( see page 899) Header File


io.h
Category
Input/output Routines
Prototype
int close(int handle);
Description
Closes a file.
The close function closes the file associated with handle, a file handle obtained
from a call to creat, creatnew, creattemp, dup, dup2, open, _rtl_creat, or
_rtl_open.
It does not write a Ctrl-Z character at the end of the file. If you want to terminate
the file with a Ctrl-Z, you must explicitly output one.
Return Value
Upon successful completion, close returns 0.
On error (if it fails because handle is not the handle of a valid, open file), close
returns a value of -1 and the... suite ( see page 899)
_creat, _wcreat ( see page 900) Header File
io.h
Category
Input/output Routines
Prototype
int creat(const char *path, int amode);
int _wcreat(const wchar_t *path, int amode);
Description
Creates a new file or overwrites an existing one.
Remarque: Remember that a backslash in a path requires '\\'.
creat creates a new file or prepares to rewrite an existing file given by path.
amode applies only to newly created files.
A file created with creat is always created in the translation mode specified by the
global variable _fmode (O_TEXT or O_BINARY).
If the file exists and the write attribute is set, creat truncates the file to a length
of... suite ( see page 900)
creatnew ( see page 901) Header File
io.h
Category
Input/output Routines
Prototype
int creatnew(const char *path, int mode);
Description
Creates a new file.
creatnew is identical to _rtl_creat with one exception: If the file exists, creatnew
returns an error and leaves the file untouched.
The mode argument to creatnew can be zero or an OR-combination of any one
of the following constants (defined in dos.h):
creattemp ( see page 902) Header File
io.h
Category
Input/output Routines
Prototype
int creattemp(char *path, int attrib);
Description
Creates a unique file in the directory associated with the path name.
A file created with creattemp is always created in the translation mode specified
by the global variable _fmode (O_TEXT or O_BINARY).
path is a path name ending with a backslash (\). A unique file name is selected in 3
the directory given by path. The newly created file name is stored in the path
string supplied. path should be long enough to hold the resulting file name. The
file is not automatically deleted when the program... suite ( see page 902)

875
C Runtime Library Reference RAD Studio 3.1 Référence C++

dup ( see page 903) Header File


io.h
Category
Input/output Routines
Prototype
int dup(int handle);
Description
Duplicates a file handle.

• dup creates a new file handle that has the following in


common with the original file handle:
• Same open file or device
• Same file pointer (that is, changing the file pointer of one
changes the other)
• Same access mode (read, write, read/write)
handle is a file handle obtained from a call to creat, open,
dup, dup2, _rtl_creat, or _rtl_open.
Return Value
Upon successful completion, dup returns the new file handle,
a nonnegative integer; otherwise, dup returns -1.
In the event of error, the global variable... suite ( see page
903)
dup2 ( see page 905) Header File
io.h
Category
Input/output Routines
Prototype
int dup2(int oldhandle, int newhandle);
Description
Duplicates a file handle (oldhandle) onto an existing file handle (newhandle).

• dup2 creates a new file handle that has the following in


common with the original file handle:
• Same open file or device
• Same file pointer (that is, changing the file pointer of one
changes the other)
• Same access mode (read, write, read/write)
dup2 creates a new handle with the value of newhandle. If
the file associated with newhandle is open when dup2 is
called, the file is closed.
newhandle and oldhandle are file handles obtained from...
suite ( see page 905)
eof ( see page 906) Header File
io.h
Category
3 Input/output Routines
Prototype
int eof(int handle);
Description
Checks for end-of-file.
eof determines whether the file associated with handle has reached end-of-file.
Return Value
If the current position is end-of-file, eof returns the value 1; otherwise, it returns 0.
A return value of -1 indicates an error; the global variable errno is set to

876
3.1 Référence C++ RAD Studio C Runtime Library Reference

filelength ( see page 907) Header File


io.h
Category
Input/output Routines
Prototype
long filelength(int handle);
Description
Gets file size in bytes.
filelength returns the length (in bytes) of the file associated with handle.
Return Value
On success filelength returns a long value the file length in bytes. On error it
returns -1 and the global variable errno is set to
_fileno ( see page 908) Header File
stdio.h
Category
Input/output Routines
Prototype
int _fileno(FILE *stream);
Description
Gets the file handle.
_fileno is a macro that returns the file handle for the given stream. If stream has
more than one handle _fileno returns the handle assigned to the stream when it
was first opened.
Return Value
_fileno returns the integer file handle associated with stream.
Example
getftime, setftime ( see page 908) Header File
io.h
Category
Input/output Routines
Prototype
int getftime(int handle, struct ftime *ftimep);
int setftime(int handle, struct ftime *ftimep);
Description
Gets and sets the file date and time.
getftime retrieves the file time and date for the disk file associated with the open
handle. The ftime structure pointed to by ftimep is filled in with the file's time and
date.
setftime sets the file date and time of the disk file associated with the open
handle to the date and time in the ftime structure pointed to by ftimep. The file
must not be written to after the setftime call... suite ( see page 908)

877
C Runtime Library Reference RAD Studio 3.1 Référence C++

isatty ( see page 910) Header File


io.h
Category
Input/output Routines
Prototype
int isatty(int handle);
Description
Checks for device type.
isatty determines whether handle is associated with any one of the following
character devices:

• a terminal
• a console
• a printer
• a serial port
Return Value
If the device is one of the four character devices listed
above, isatty returns a nonzero integer. If it is not such a
device, isatty returns 0.
Example
lock ( see page 910) Header File
io.h
Category
Input/output Routines
Prototype
int lock(int handle, long offset, long length);
Description
Sets file-sharing locks.
lock provides an interface to the operating system file-sharing mechanism.
A lock can be placed on arbitrary, nonoverlapping regions of any file. A program
attempting to read or write into a locked region will retry the operation three
times. If all three retries fail, the call fails with an error.
Return Value
lock returns 0 on success. On error, lock returns -1 and sets the global variable
errno to
locking ( see page 911) Header File
io.h, sys\locking.h
Category
Input/output Routines
Prototype
int locking(int handle, int cmd, long length);
Description
Sets or resets file-sharing locks.
locking provides an interface to the operating system file-sharing mechanism.
The file to be locked or unlocked is the open file specified by handle. The region
to be locked or unlocked starts at the current file position, and is length bytes
long.
Locks can be placed on arbitrary, nonoverlapping regions of any file. A program
attempting to read or write into a locked region will retry the operation three
times. If all three retries fail, the call fails with... suite ( see page 911)
lseek ( see page 913) Header File
3 io.h
Category
Input/output Routines
Prototype
long lseek(int handle, long offset, int fromwhere);
Description
Moves file pointer.
lseek sets the file pointer associated with handle to a new position offset bytes
beyond the file location given by fromwhere. fromwhere must be one of the
following symbolic constants (defined in io.h):

878
3.1 Référence C++ RAD Studio C Runtime Library Reference

read ( see page 914) Header File


io.h
Category
Input/output Routines
Prototype
int read(int handle, void *buf, unsigned len);
Description
Reads from file.
read attempts to read len bytes from the file associated with handle into the
buffer pointed to by buf.
For a file opened in text mode, read removes carriage returns and reports
end-of-file when it reaches a Ctrl-Z.
The file handle handle is obtained from a creat, open, dup, or dup2 call.
On disk files, read begins reading at the current file pointer. When the reading is
complete, it increments the file pointer by the number of bytes read. On devices,
the... suite ( see page 914)
setmode ( see page 915) Header File
io.h
Category
Input/output Routines
Prototype
int setmode(int handle, int amode);
Description
Sets mode of an open file.
setmode sets the mode of the open file associated with handle to either binary or
text. The argument amode must have a value of either O_BINARY or O_TEXT,
never both. (These symbolic constants are defined in fcntl.h.)
Return Value
setmode returns the previous translation mode if successful. On error it returns -1
and sets the global variable errno to
tell ( see page 916) Header File
io.h
Category
Input/output Routines
Prototype
long tell(int handle);
Description
Gets the current position of a file pointer.
tell gets the current position of the file pointer associated with handle and
expresses it as the number of bytes from the beginning of the file.
Return Value
tell returns the current file pointer position. A return of -1 (long) indicates an
error, and the global variable errno is set to
umask ( see page 917) Header File
io.h, sys\stat.h
Category
Input/output Routines
Prototype
unsigned umask(unsigned mode);
Description
Sets file read/write permission mask.
The umask function sets the access permission mask used by open and creat.
Bits that are set in mode will be cleared in the access permission of files
subsequently created by open and creat.
The mode can have one of the following values, defined in sys\stat.h:
3

879
C Runtime Library Reference RAD Studio 3.1 Référence C++

unlock ( see page 918) Header File


io.h
Category
Input/output Routines
Prototype
int unlock(int handle, long offset, long length);
Description
Releases file-sharing locks.
unlock provides an interface to the operating system file-sharing mechanism.
unlock removes a lock previously placed with a call to lock. To avoid error, all
locks must be removed before a file is closed. A program must release all locks
before completing.
Return Value
On success, unlock returns 0
O error, it returns -1.
Example
vsscanf ( see page 919) Header File
io.h
Category
Memory and String Manipulation Routines
Prototype
int vsscanf(const char *buffer, const char *format, va_list
arglist);
Description
Scans and formats input from a stream.
The v...scanf functions are known as alternate entry points for the ...scanf
functions. They behave exactly like their ...scanf counterparts, but they accept a
pointer to a list of arguments instead of an argument list.
Remarque: For details on format specifiers, see Scanf Format Specifiers.
vsscanf scans a series of input fields, one character at a time, reading from a
stream. Then each field is formatted according to a format specifier passed to...
suite ( see page 919)
write ( see page 920) Header File
io.h
Category
Input/output Routines
Prototype
int write(int handle, void *buf, unsigned len);
Description
Writes to a file.
write writes a buffer of data to the file or device named by the given handle.
handle is a file handle obtained from a creat, open, dup, or dup2 call.
This function attempts to write len bytes from the buffer pointed to by buf to the
file associated with handle. Except when write is used to write to a text file, the
number of bytes written to the file will be no more than the number requested.
The maximum number of... suite ( see page 920)

3.1.5.15.1 _findclose
Header File

io.h

Category
3
Directory Control Routines

Prototype
int _findclose(long handle);

Description

Closes the specified search handle and releases associated resources associated with previous calls to findfirst/findnext. The
handle parameter is the search handle returned by the previous call to _findfirst.

880
3.1 Référence C++ RAD Studio C Runtime Library Reference

This function is provided for Microsoft compatibility.

Return Value

On success, returns 0.

Otherwise, returns –1 and sets errno to:

ENOENTFile specification that could not be matched

Portability

POSIX Win32 ANSI C ANSI C++


_findclose +

Voir aussi
_findfirst ( see page 881)

_findnext ( see page 882)

3.1.5.15.2 _findfirst, __wfindfirst


Header File

io.h, wchar.h

Category

Directory Control Routines

Prototype
long _findfirst(char *filter, struct _finddata_t *fileinfo);
long __wfindfirst(wchar_t *filter, struct _wfinddata_t *fileinfo);

Description

Begins a search of a disk directory to find information about the first instance of a filename that matches a specified filter. The
filter parameter is a string that specifies which files to return. Wildcards may be used in the filter. The fileinfo parameter is the file
information buffer. If a matching file is found, the fileinfo structure is filled with the file-directory information.

These functions are provided for Microsoft compatibility.

Return Value

On success, returns a unique search handle to a file or group of files matching the filter specification.

Otherwise, returns –1 and sets errno to one of the following values:

ENOENTPath or file name not found

EINVALInvalid filename specification


3
Portability

POSIX Win32 ANSI C ANSI C++


_findfirst +
__wfindfirst NT only

881
C Runtime Library Reference RAD Studio 3.1 Référence C++

Voir aussi
_findclose ( see page 880)

_findnext ( see page 882)

3.1.5.15.3 _findfirsti64, _wfindfirsti64


Header File

io.h, wchar.h

Category

Directory Control Routines

Prototype
long _findfirsti64(char *filter, struct _finddatai64_t *fileinfo);
long _wfindfirsti64(wchar_t *filter, struct _wfinddatai64_t *fileinfo);

Description

Begins a search of a disk directory to find information about the first instance of a filename that matches a specified filter. The
filter parameter is a string that specifies which files to return. Wildcards may be used in the filter. The fileinfo parameter is the file
information buffer. If a matching file is found, the fileinfo structure is filled with the file-directory information.

These i64 versions are for 64 bit filesize use and are provided for Microsoft compatibility.

Return Value

On success, returns a unique search handle identifying the file or group of files matching the filter specification.

Otherwise, returns –1 and sets errno to one of the following values:

ENOENTFile specification that could not be matched

EINVALInvalid filename specification

Portability

POSIX Win32 ANSI C ANSI C++


_findfirsti64 +
_wfindfirsti64 NT only

3.1.5.15.4 _findnext, __wfindnext


Header File

3 io.h, wchar.h

Category

Directory Control Routines

Prototype
long _findnext(long handle, struct _finddata_t *fileinfo);
long __wfindnext(long handle, struct _wfinddata_t *fileinfo);

882
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

Finds subsequent files, if any, that match the filter argument in a previous call to _findfirst/__wfindfirst. Then,
_findnext/__wfindnext updates the fileinfo structure with the necessary information for continuing the search. One file name for
each call to _tfindnext is returned until no more files are found in the directory matching the pathname (filter).

The handle parameter is the search handle returned by a previous call to _findfirst. The fileinfo parameter is the file information
buffer.

These functions are provided for Microsoft compatibility.

Return Value

On success, returns 0.

Otherwise, returns –1 and sets errno to:

ENOENTFile specification that could not be matched

Portability

POSIX Win32 ANSI C ANSI C++


_findnext +
__wfindnext NT only

Voir aussi
_findclose ( see page 880)

_findfirst ( see page 881)

3.1.5.15.5 _findnexti64, _wfindnexti64


Header File

io.h, wchar.h

Category

Directory Control Routines

Prototype
long _findnexti64(long handle, struct _finddatai64_t *fileinfo);
__int64 _wfindnexti64(long handle, struct _wfinddata_t *fileinfo);

Description

Finds subsequent files, if any, that match the filter argument in a previous call to _findfirsti64/_wfindfirsti64. Then,
_findnexti64/_wfindnexti64 updates the fileinfo structure with the necessary information for continuing the search. One file name
for each call to _tfindnext is returned until no more files are found in the directory matching the pathname (filter).
3
The handle parameter is the search handle returned by a previous call to _findfirst. The fileinfo parameter is the file information
buffer.

These i64 versions are for 64 bit filesize use and are provided for Microsoft compatibility.

Return Value

On success, returns 0.

883
C Runtime Library Reference RAD Studio 3.1 Référence C++

Otherwise, returns –1 and sets errno to:

ENOENTFile specification that could not be matched

Portability

POSIX Win32 ANSI C ANSI C++


_findnexti64 +
_wfindnexti64 NT only

3.1.5.15.6 _get_osfhandle
Header File

io.h

Category

Input/output Routines

Prototype
long _get_osfhandle(int filehandle);

Description

Associates file handles.

The _get_osfhandle function associates an operating system file handle with an existing runtime file handle. The variable
filehandle is the file handle of your program.

Return value

On success, _get_osfhandle returns an operating system file handle corresponding to the variable filehandle.

On error, the function returns -1 and sets the global variable errno to

EBADF an invalid file handle

Example
#include <windows.h>
#include <fcntl.h>
#include <stdio.h>
#include <io.h>
//Example for _get_osfhandle() and _open_osfhandle()
BOOL InitApplication(HINSTANCE hInstance);
HWND InitInstance(HINSTANCE hInstance, int nCmdShow);
LRESULT FAR PASCAL _export MainWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam);
Example_get_osfhandle(HWND hWnd);
#pragma argsused
3 int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg; // message
if (!InitApplication(hInstance)) // Initialize shared things
return (FALSE); // Exits if unable to initialize
/* Perform initializations that apply to a specific instance */
if (!(InitInstance(hInstance, nCmdShow)))
return (FALSE);
/* Acquire and dispatch messages until a WM_QUIT message is received. */

884
3.1 Référence C++ RAD Studio C Runtime Library Reference

while (GetMessage(&msg, // message structure


NULL, // handle of window receiving the message
NULL, // lowest message to examine
NULL)) // highest message to examine
{
TranslateMessage(&msg); // Translates virtual key codes
DispatchMessage(&msg); // Dispatches message to window
}
return (msg.wParam); // Returns the value from PostQuitMessage
}
BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS wc;
// Fill in window class structure with parameters that describe the
// main window.
wc.style = CS_HREDRAW | CS_VREDRAW; // Class style(s).
wc.lpfnWndProc = (long (FAR PASCAL*)(void *,unsigned int,unsigned int, long ))MainWndProc;
// Function to retrieve messages for
// windows of this class.
wc.cbClsExtra = 0; // No per-class extra data.
wc.cbWndExtra = 0; // No per-window extra data.
wc.hInstance = hInstance; // Application that owns the class.
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL; // Name of menu resource in .RC file.
wc.lpszClassName = "Example"; // Name used in call to CreateWindow.
/* Register the window class and return success/failure code. */
return (RegisterClass(&wc));
}
HWND InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd; // Main window handle.
/* Create a main window for this application instance. */
hWnd = CreateWindow(
"Example", // See RegisterClass() call.
"Example _get_osfhandle _open_osfhandle (32 bit)", // Text for window title bar.
WS_OVERLAPPEDWINDOW, // Window style.
CW_USEDEFAULT, // Default horizontal position.
CW_USEDEFAULT, // Default vertical position.
CW_USEDEFAULT, // Default width.
CW_USEDEFAULT, // Default height.
NULL, // Overlapped windows have no parent.
NULL, // Use the window class menu.
hInstance, // This instance owns this window.
NULL // Pointer not needed.
);
/* If window could not be created, return "failure" */
if (!hWnd)
return (FALSE);
/* Make the window visible; update its client area; and return "success" */
ShowWindow(hWnd, nCmdShow); // Show the window
UpdateWindow(hWnd); // Sends WM_PAINT message
return (hWnd); // Returns the value from PostQuitMessage
}
#pragma argsused
LRESULT FAR PASCAL _export MainWndProc(HWND hWnd, UINT message, 3
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
Example_get_osfhandle(hWnd);
return NULL;
}

885
C Runtime Library Reference RAD Studio 3.1 Référence C++

case WM_QUIT:
case WM_DESTROY: // message: window being destroyed
PostQuitMessage(0);
break;
default: // Passes it on if unprocessed
return (DefWindowProc(hWnd, message, wParam, lParam));
}
}
Example_get_osfhandle(HWND hWnd)
{
long osfHandle;
char str[128];
int fHandle = open("file1.c", O_CREAT|O_TEXT);
if(fHandle != -1)
{
osfHandle = _get_osfhandle(fHandle);
sprintf(str, "file handle = %lx OS file handle = %lx", fHandle, osfHandle);
MessageBox(hWnd,str,"_get_osfhandle",MB_OK|MB_ICONINFORMATION);
close(fHandle);
fHandle = _open_osfhandle(osfHandle, O_TEXT );
sprintf(str, "file handle = %lx OS file handle = %lx", fHandle, osfHandle);
MessageBox(hWnd,str,"_open_osfhandle",MB_OK|MB_ICONINFORMATION);
close(fHandle);
}
else
MessageBox(hWnd,"File Open Error","WARNING",MB_OK|MB_ICONSTOP);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.7 _open_osfhandle
Header File

io.h

Category

Input/output Routines

Prototype
int _open_osfhandle(long osfhandle, int flags);

Description

Associates file handles.

The _open_osfhandle function allocates a runtime file handle and sets it to point to the operating system file handle specified by
3 osfhandle.

The value flags is a bitwise OR combination of one or more of the following manifest constants (defined in fcntl.h):

O_APPEND Repositions the file pointer to the end of the file before every write operation.
O_RDONLY Opens the file for reading only.
O_TEXT Opens the file in text (translated) mode.

886
3.1 Référence C++ RAD Studio C Runtime Library Reference

Return Value

On success, _open_osfhandle returns a C runtime file handle. Otherwise, it returns -1.

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.8 _pclose
Header File

stdio.h

Category

Input/output Routines, Process Control Routines

Prototype
int _pclose(FILE * stream);

Description

Waits for piped command to complete.

_pclose closes a pipe stream created by a previous call to _popen, and then waits for the associated child command to complete.

Return Value

On success, _pclose returns the termination status of the child command. This is the same value as the termination status
returned by cwait, except that the high and low order bytes of the low word are swapped.

On error, it returns -1.

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.9 _rtl_chmod, _wrtl_chmod


Header File

io.h

Category

Input/output Routines
3
Prototype
int _rtl_chmod(const char *path, int func [, int attrib]);
int _wrtl_chmod(const wchar_t *path, int func, ... );

Description

Gets or sets file attributes.

887
C Runtime Library Reference RAD Studio 3.1 Référence C++

Remarque: The _rtl_chmod function replaces _chmod

which is obsolete_rtl_chmod can either fetch or set file attributes. If func is 0, _rtl_chmod returns the current attributes for the file.
If func is 1, the attribute is set to attrib.

attrib can be one of the following symbolic constants (defined in dos.h):

FA_RDONLY Read-only attribute


FA_HIDDEN Hidden file
FA_SYSTEM System file
FA_LABEL Volume label
FA_DIREC Directory
FA_ARCH Archive

Return Value

On success, _rtl_chmod returns the file attribute word.

On error, it returns a value of -1 and sets the global variable errno to one of the following values:

ENOENT Path or filename not found


EACCES Permission denied

Example
#include <errno.h>
#include <stdio.h>
#include <dir.h>
#include <io.h>
int get_file_attrib(char *filename);
int main(void)
{
char filename[128];
int attrib;
printf("Enter a filename:");
scanf("%s", filename);
attrib = get_file_attrib(filename);
if (attrib == -1)
switch(errno)
{
case ENOENT : printf("Path or file not found.\n");
break;
case EACCES : printf("Permission denied.\n");
break;
default: printf("Error number: %d", errno);
break;
}
else
{
if (attrib & FA_RDONLY)
3 printf("%s is read-only.\n", filename);
if (attrib & FA_HIDDEN)
printf("%s is hidden.\n", filename);
if (attrib & FA_SYSTEM)
printf("%s is a system file.\n", filename);
if (attrib & FA_DIREC)
printf("%s is a directory.\n", filename);
if (attrib & FA_ARCH)
printf("%s is an archive file.\n", filename);
}
return 0;

888
3.1 Référence C++ RAD Studio C Runtime Library Reference

}
/* returns the attributes of a DOS file */
int get_file_attrib(char *filename)
{
return(_rtl_chmod(filename, 0));
}
Portability

POSIX Win32 ANSI C ANSI C++


_rtl_chmod +
_wrtl_chmod NT only

3.1.5.15.10 _rtl_close
Header File

io.h

Category

Input/output Routines

Prototype
int _rtl_close(int handle);

Description

Closes a file.

Remarque: This function replaces _close which is obsolete

The _rtl_close function closes the file associated with handle, a file handle obtained from a call to creat, creatnew, creattemp,
dup, dup2, open, _rtl_creat, or _rtl_open.

It does not write a Ctrl-Z character at the end of the file. If you want to terminate the file with a Ctrl-Z, you must explicitly output
one.

Return Value

On success, _rtl_close returns 0.

On error (if it fails because handle is not the handle of a valid, open file), _rtl_close returns a value of -1 and the global variable
errno is set to

EBADF Bad file number

Example
#include <string.h>
#include <stdio.h> 3
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
char msg[] = "Hello world";
if ((handle = _rtl_open("TEST.$$$", O_RDWR)) == -1)
{
perror("Error:");
return 1;

889
C Runtime Library Reference RAD Studio 3.1 Référence C++

}
_rtl_write(handle, msg, strlen(msg));
_rtl_close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.11 _rtl_creat, _wrtl_creat


Header File

io.h

Category

Input/output Routines

Prototype
int _rtl_creat(const char *path, int attrib);
int _wrtl_creat(const wchar_t *path, int attrib);

Description

Creates a new file or overwrites an existing one.

Remarque: The _rtl_creat function replaces _creat,

which is obsolete_rtl_creat opens the file specified by path. The file is always opened in binary mode. Upon successful file
creation, the file pointer is set to the beginning of the file. The file is opened for both reading and writing.

If the file already exists its size is reset to 0. (This is essentially the same as deleting the file and creating a new file with the
same name.)

The attrib argument is an OR’ed combination of one or more of the following constants (defined in dos.h):

FA_RDONLY Read-only attribute


FA_HIDDEN Hidden file
FA_SYSTEM System file

Return Value

On success, _rtl_creat returns the new file handle (a non-negative integer).

On error, it returns -1 and sets the global variable errno to one of the following values:

3 EACCESPermission denied

EMFILEToo many open files

ENOENTPath or file name not found

Example
#include <string.h>
#include <stdio.h>
#include <io.h>

890
3.1 Référence C++ RAD Studio C Runtime Library Reference

int main() {
unsigned count;
int handle;
char buf[11] = "0123456789";
/* Create a 10-byte file using _rtl_creat. */
if ((handle = _rtl_creat("DUMMY2.FIL", 0)) < 0) {
perror("Unable to _rtl_create DUMMY2.FIL");
return 1;
}
if (_rtl_write(handle, buf, strlen(buf)) < 0) {
perror("Unable to _rtl_write to DUMMY2.FIL");
return 1;
}
_rtl_close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_rtl_crea +
_wrtl_creat NT only

3.1.5.15.12 _rtl_open, _wrtl_open


Header File

io.h

Category

Input/output Routines

Prototype
int _rtl_open(const char *filename, int oflags);
int _wrtl_open(const wchar_t *path, int oflags);

Description

Opens a file for reading or writing.

Remarque: The _rtl_open function replaces _open which is obsolete.

_rtl_open opens the file specified by filename, then prepares it for reading or writing, as determined by the value of oflags. The
file is always opened in binary mode.

oflags uses the flags from the following two lists. Only one flag from List 1 can be used (and one must be used) and the flags in
List 2 can be used in any logical combination.

O_RDONLY Open for reading.


3
O_WRONLY Open for writing.
O_RDWR Open for reading and writing.

The following additional values can be included in oflags (using an OR operation):

891
C Runtime Library Reference RAD Studio 3.1 Référence C++

O_NOINHERIT The file is not passed to child programs.


SH_COMPAT Allow other opens with SH_COMPAT. All other openings of a file with the SH_COMPAT flag must be
opened using SH_COMPAT flag. You can request a file open that uses SH_COMPAT logically OR’ed
with some other flag (for example, SH_COMPAT | SH_DENWR is allowed). The call will fail if the file
has already been opened in any other shared mode.
SH_DENYRW Only the current handle can have access to the file.
SH_DENWR Allow only reads from any other open to the file.
SH_DENYRD Allow only writes from any other open to the file.
SH_DENYNO Allow other shared opens to the file, but not other SH_COMPAT opens.

Remarque: These symbolic constants are defined in fcntl.h and share.h.

Only one of the SH_DENYxx values can be included in a single _rtl_open routine. These file-sharing attributes are in addition to
any locking performed on the files.

The maximum number of simultaneously open files is defined by HANDLE_MAX.

Return Value

On success:_rtl_open returns a non-negative integer (the file handle). The file pointer, which marks the current position in the
file, is set to the beginning of the file.

On error, it returns -1 and sets the global variable errno to one of the following values:

EACCES Permission denied


EINVACC Invalid access code
EMFILE Too many open files
ENOENT Path or file not found

Example
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
char msg[] = "Hello world";
if ((handle = _rtl_open("TEST.$$$", O_RDWR)) == -1)
{
perror("Error:");
return 1;
}
_rtl_write(handle, msg, strlen(msg));
_rtl_close(handle);
return 0;
3 }
Portability

POSIX Win32 ANSI C ANSI C++


_rtl_open +
_wrtl_open NT only

892
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.15.13 _rtl_read
Header File

io.h

Category

Input/output Routines

Prototype
int _rtl_read(int handle, void *buf, unsigned len);

Description

Reads from file.

Remarque: This function replaces _read which is obsolete.

This function reads len bytes from the file associated with handle into the buffer pointed to by buf. When a file is opened in text
mode, _rtl_read does not remove carriage returns.

The argument handle is a file handle obtained from a creat, open, dup, or dup2 call.

On disk files, _rtl_read begins reading at the current file pointer. When the reading is complete, it increments the file pointer by
the number of bytes read. On devices, the bytes are read directly from the device.

The maximum number of bytes it can read is UINT_MAX -1 (because UINT_MAX is the same as -1, the error return indicator).
UINT_MAX is defined in limits.h.

Return Value

On success, _rtl_read returns either

• a positive integer, indicating the number of bytes placed in the buffer


• zero, indicating end-of-file
On error, it returns -1 and sets the global variable errno to one of the following values:

EACCES Permission denied


EBADF Bad file number

Example
#include <stdio.h>
#include <io.h>
#include <alloc.h>
#include <fcntl.h>
#include <process.h>
#include <sys\stat.h>
int main(void)
{ 3
void *buf;
int handle, bytes;
buf = malloc(10);
/*
Looks for a file in the current directory named TEST.$$$ and attempts to read 10 bytes from
it. To use this example you should create the file TEST.$$$
*/
if ((handle =
open("TEST.$$$", O_RDONLY | O_BINARY, S_IWRITE | S_IREAD)) == -1)
{

893
C Runtime Library Reference RAD Studio 3.1 Référence C++

printf("Error Opening File\n");


exit(1);
}
if ((bytes = _rtl_read(handle, buf, 10)) == -1) {
printf("Read Failed.\n");
exit(1);
}
else {
printf("_rtl_read: %d bytes read.\n", bytes);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.14 _rtl_write
Header File

io.h

Category

Input/output Routines

Prototype
int _rtl_write(int handle, void *buf, unsigned len);

Description

Writes to a file.

Remarque: This function replaces _write which is obsolete.

_rtl_write attempts to write len bytes from the buffer pointed to by buf to the file associated with handle.

The maximum number of bytes that _rtl_write can write is UINT_MAX -1 (because UINT_MAX is the same as -1), which is the
error return indicator for _rtl_write. UINT_MAX is defined in limits.h. _rtl_write does not translate a linefeed character (LF) to a
CR/LF pair because all its files are binary files.

If the number of bytes actually written is less than that requested the condition should be considered an error and probably
indicates a full disk.

For disk files, writing always proceeds from the current file pointer. On devices, bytes are directly sent to the device.

For files opened with the O_APPEND option, the file pointer is not positioned to EOF before writing the data.

Return Value
3 On success, _rtl_write returns number of bytes written.

On error, it returns -1 and sets the global variable errno to one of the following values:

EACCES Permission denied


EBADF Bad file number

Example

894
3.1 Référence C++ RAD Studio C Runtime Library Reference

#include <stdio.h>
#include <io.h>
#include <alloc.h>
#include <fcntl.h>
#include <process.h>
#include <sys\stat.h>
int main(void)
{
void *buf;
int handle, bytes;
buf = malloc(200);
/*
Create a file name TEST.$$$ in the current directory and writes 200 bytes to it. If TEST.$$$
already exists, it's overwritten.
*/
if ((handle = open("TEST.$$$", O_CREAT | O_WRONLY | O_BINARY,
S_IWRITE | S_IREAD)) == -1)
{
printf("Error Opening File\n");
exit(1);
}
if ((bytes = _rtl_write(handle, buf, 200)) == -1) {
printf("Write Failed.\n");
exit(1);
}
printf("_rtl_write: %d bytes written.\n",bytes);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.15 _snprintf;_snwprintf
Header File

stdio.h

Category

Memory and String Manipulation Routines

Syntax
int _snprintf(char* buffer, size_t nsize, const char* format, ...);
int _snwprintf(wchar_t* buffer, size_t nsize, const wchar_t* format, ...);

Description

Sends formatted output to a string of a maximum length specified by nsize. _snprintf and _snwprintf are Microsoft compatible
with the _snprintf and _snprintfw functions, respectively. 3
If the number of bytes to output is:

• < nsize, then all of the characters have been written, including the terminating ‘\0’ character.
• == nsize, then nsize characters are written with no terminating ‘\0’ character.
If nsize is 0, then the string will not be written to (and may be NULL).
If nsize is too small, then return value is -1, and only nsize characters are written, with no terminating ‘\0’ character.

895
C Runtime Library Reference RAD Studio 3.1 Référence C++

Return Value
Number of bytes output or –1 if nsize is too small.

3.1.5.15.16 access, _waccess


Header File

io.h

Category

Input/output Routines

Prototype
int access(const char *filename, int amode);
int _waccess(const wchar_t *filename, int amode);

Description

Determines accessibility of a file.

access checks the file named by filename to determine if it exists, and whether it can be read, written to, or executed.

The list of amode values is as follows:

06 Check for read and write permission


04 Check for read permission
02 Check for write permission
01 Execute (ignored)
00 Check for existence of file

All existing files have read access (amode equals 04), so 00 and 04 give the same result. Similarly, amode values of 06 and 02
are equivalent because under Win32 write access implies read access.

If filename refers to a directory, access simply determines whether the directory exists.

Return Value

If the requested access is allowed, access returns 0; otherwise, it returns a value of -1, and the global variable errno is set to one
of the following values:

ENOENT Path or file name not found


EACCES Permission denied

Example
#include <stdio.h>
3 #include <io.h>
int file_exists(char *filename);
int main(void)
{
printf("Does NOTEXIST.FIL exist: %s\n",
file_exists("NOTEXISTS.FIL") ? "YES" : "NO");
return 0;
}
int file_exists(char *filename)
{
return (access(filename, 0) == 0);

896
3.1 Référence C++ RAD Studio C Runtime Library Reference

}
Portability

POSIX Win32 ANSI C ANSI C++


access + +
_waccess NT only

3.1.5.15.17 chmod, _wchmod


Header File

io.h

Category

Input/output Routines

Prototype
int chmod(const char *path, int amode);
int _wchmod(const wchar_t *path, int amode);

Description

Changes file access mode.

chmod sets the file-access permissions of the file given by path according to the mask given by amode. path points to a string.

amode can contain one or both of the symbolic constants S_IWRITE and S_IREAD (defined in sys\stat.h).

S_IWRITE Permission to write


S_IREAD Permission to read
S_IREAD | S_IWRITE Permission to read and write (write permission implies read permission)

Return Value

Upon successfully changing the file access mode, chmod returns 0. Otherwise, chmod returns a value of -1.

In the event of an error, the global variable errno is set to one of the following values:

EACCES Permission denied


ENOENT Path or file name not found

Example
#include <errno.h>
#include <stdio.h>
#include <io.h> 3
#include <process.h>
#include <sys\stat.h>
void main(void)
{
char filename[64];
struct stat stbuf;
int amode;
printf("Enter name of file: ");
scanf("%s", filename);
if (stat(filename, &stbuf) != 0)

897
C Runtime Library Reference RAD Studio 3.1 Référence C++

{
perror("Unable to get file information");
exit(1);
}
if (stbuf.st_mode & S_IWRITE)
{
printf("Changing to read-only\n");
amode = S_IREAD;
}
else
{
printf("Changing to read-write\n");
amode = S_IREAD|S_IWRITE;
}
if (chmod(filename, amode) != 0)
{
perror("Unable to change file mode");
exit(1);
}
exit(0);
}
Portability

POSIX Win32 ANSI C ANSI C++


chmod + +
_wchmod NT only

3.1.5.15.18 chsize
Header File

io.h

Category

Input/output Routines

Prototype
int chsize(int handle, long size);

Description

Changes the file size.

chsize changes the size of the file associated with handle. It can truncate or extend the file, depending on the value of size
compared to the file's original size.

The mode in which you open the file must allow writing.

If chsize extends the file, it will append null characters (\0). If it truncates the file, all data beyond the new end-of-file indicator is
3 lost.

Return Value

On success, chsize returns 0. On failure, it returns -1 and the global variable errno is set to one of the following values:

EACCES Permission denied


EBADF Bad file number
ENOSPC No space left on device

898
3.1 Référence C++ RAD Studio C Runtime Library Reference

Example
#include <string.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
char buf[11] = "0123456789";
/* create text file containing 10 bytes */
handle = open("DUMMY.FIL", O_CREAT);
write(handle, buf, strlen(buf));
/* truncate the file to 5 bytes in size */
chsize(handle, 5);
/* close the file */
close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.19 close
Header File

io.h

Category

Input/output Routines

Prototype
int close(int handle);

Description

Closes a file.

The close function closes the file associated with handle, a file handle obtained from a call to creat, creatnew, creattemp, dup,
dup2, open, _rtl_creat, or _rtl_open.

It does not write a Ctrl-Z character at the end of the file. If you want to terminate the file with a Ctrl-Z, you must explicitly output
one.

Return Value

Upon successful completion, close returns 0.

On error (if it fails because handle is not the handle of a valid, open file), close returns a value of -1 and the global variable errno
is set to 3

EBADF Bad file number

Example
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>

899
C Runtime Library Reference RAD Studio 3.1 Référence C++

main()
{
int handle;
char buf[11] = "0123456789";
/* create a file containing 10 bytes */
handle = open("NEW.FIL", O_CREAT);
if (handle > -1)
{
write(handle, buf, strlen(buf));
close(handle); /* close the file */
}
else
{
printf("Error opening file\n");
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

3.1.5.15.20 _creat, _wcreat


Header File

io.h

Category

Input/output Routines

Prototype
int creat(const char *path, int amode);
int _wcreat(const wchar_t *path, int amode);

Description

Creates a new file or overwrites an existing one.

Remarque: Remember that a backslash in a path requires '\\'.

creat creates a new file or prepares to rewrite an existing file given by path. amode applies only to newly created files.

A file created with creat is always created in the translation mode specified by the global variable _fmode (O_TEXT or
O_BINARY).

If the file exists and the write attribute is set, creat truncates the file to a length of 0 bytes, leaving the file attributes unchanged. If
the existing file has the read-only attribute set, the creat call fails and the file remains unchanged.

3 The creat call examines only the S_IWRITE bit of the access-mode word amode. If that bit is 1, the file can be written to. If the bit
is 0, the file is marked as read-only. All other operating system attributes are set to 0.

amode can be one of the following (defined in sys\stat.h):

S_IWRITE Permission to write


S_IREAD Permission to read
S_IREAD / S_IWRITE Permission to read and write (write permission implies read permission)

900
3.1 Référence C++ RAD Studio C Runtime Library Reference

Return Value

Upon successful completion, _creat returns the new file handle, a nonnegative integer; otherwise, it returns -1.

In the event of error, the global variable errno is set to one of the following:

EACCES Permission denied


ENOENT Path or file name not found
EMFILE Too many open files

Example
#include <sys\stat.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
char buf[11] = "0123456789";
/* change the default file mode from text to binary */
_fmode = O_BINARY;
/* create a binary file for reading and writing */
handle = creat("DUMMY.FIL", S_IREAD |S_IWRITE);
/* write 10 bytes to the file */
write(handle, buf, strlen(buf));
/* close the file */
close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


creat + +
_wcreat NT only

3.1.5.15.21 creatnew
Header File

io.h

Category

Input/output Routines

Prototype
int creatnew(const char *path, int mode);
3
Description

Creates a new file.

creatnew is identical to _rtl_creat with one exception: If the file exists, creatnew returns an error and leaves the file untouched.

The mode argument to creatnew can be zero or an OR-combination of any one of the following constants (defined in dos.h):

901
C Runtime Library Reference RAD Studio 3.1 Référence C++

FA_HIDDEN Hidden file


FA_RDONLY Read-only attribute
FA_SYSTEM System file

Return Value

Upon successful completion, creatnew returns the new file handle, a nonnegative integer; otherwise, it returns -1.

In the event of error, the global variable errno is set to one of the following values:

EACCES Permission denied


EEXIST File already exists
EMFILE Too many open files
ENOENT Path or file name not found

Example
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <io.h>
int main(void)
{
int handle;
char buf[11] = "0123456789";
/* attempt to create a file that doesn't already exist */
handle = creatnew("DUMMY.FIL", 0);
if (handle == -1)
printf("DUMMY.FIL already exists.\n");
else
{
printf("DUMMY.FIL successfully created.\n");
write(handle, buf, strlen(buf));
close(handle);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.22 creattemp
Header File

3 io.h

Category

Input/output Routines

Prototype
int creattemp(char *path, int attrib);

Description

902
3.1 Référence C++ RAD Studio C Runtime Library Reference

Creates a unique file in the directory associated with the path name.

A file created with creattemp is always created in the translation mode specified by the global variable _fmode (O_TEXT or
O_BINARY).

path is a path name ending with a backslash (\). A unique file name is selected in the directory given by path. The newly created
file name is stored in the path string supplied. path should be long enough to hold the resulting file name. The file is not
automatically deleted when the program terminates.

The attrib argument to creattemp can be zero or an OR-combination of any one of the following constants (defined in dos.h):

FA_HIDDEN Hidden file


FA_RDONLY Read-only attribute
FA_SYSTEM System file

Upon successful file creation, the file pointer is set to the beginning of the file. The file is opened for both reading and writing.

Return Value

Upon successful completion, the new file handle, a nonnegative integer, is returned; otherwise, -1 is returned.

In the event of error, the global variable errno is set to one of the following values:

EACCES Permission denied


EMFILE Too many open files
ENOENT Path or file name not found

Example
#include <string.h>
#include <stdio.h>
#include <io.h>
int main(void)
{
int handle;
char pathname[128];
strcpy(pathname, "\\");
/* create a unique file in the root directory */
handle = creattemp(pathname, 0);
printf("%s was the unique file created.\n", pathname);
close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3
3.1.5.15.23 dup
Header File

io.h

Category

Input/output Routines

903
C Runtime Library Reference RAD Studio 3.1 Référence C++

Prototype
int dup(int handle);

Description

Duplicates a file handle.

• dup creates a new file handle that has the following in common with the original file handle:
• Same open file or device
• Same file pointer (that is, changing the file pointer of one changes the other)
• Same access mode (read, write, read/write)
handle is a file handle obtained from a call to creat, open, dup, dup2, _rtl_creat, or _rtl_open.
Return Value
Upon successful completion, dup returns the new file handle, a nonnegative integer; otherwise, dup returns -1.
In the event of error, the global variable errno is set to one of the following values:

EBADF Bad file number


EMFILE Too many open files

Example
#include <string.h>
#include <stdio.h>
#include <io.h>
void flush(FILE *stream);
int main(void)
{
FILE *fp;
char msg[] = "This is a test";
/* create a file */
fp = fopen("DUMMY.FIL", "w");
/* write some data to the file */
fwrite(msg, strlen(msg), 1, fp);
printf("Press ENTER to flush DUMMY.FIL:");
getchar();
/* flush the data to DUMMY.FIL without closing it */
flush(fp);
printf("\nFile was flushed, Press ENTER to quit:");
getchar();
return 0;
}
void flush(FILE *stream)
{
int duphandle;
/* flush TC's internal buffer */
fflush(stream);
/* make a duplicate file handle */
duphandle = dup(fileno(stream));
/* close the duplicate handle to flush the DOS buffer */
3 close(duphandle);
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

904
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.15.24 dup2
Header File

io.h

Category

Input/output Routines

Prototype
int dup2(int oldhandle, int newhandle);

Description

Duplicates a file handle (oldhandle) onto an existing file handle (newhandle).

• dup2 creates a new file handle that has the following in common with the original file handle:
• Same open file or device
• Same file pointer (that is, changing the file pointer of one changes the other)
• Same access mode (read, write, read/write)
dup2 creates a new handle with the value of newhandle. If the file associated with newhandle is open when dup2 is called, the
file is closed.
newhandle and oldhandle are file handles obtained from a creat, open, dup, or dup2 call.
Return Value
dup2 returns 0 on successful completion, -1 otherwise.
In the event of error, the global variable errno is set to one of the following values:
EBADF Bad file number
EMFILE Too many open files
Example
#include <sys\stat.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#define STDOUT 1
int main(void)
{
int nul, oldstdout;
char msg[] = "This is a test";
/* create a file */
nul = open("DUMMY.FIL", O_CREAT | O_RDWR,
S_IREAD | S_IWRITE);
/* create a duplicate handle for standard output */
oldstdout = dup(STDOUT);
/*
redirect standard output to DUMMY.FIL 3
by duplicating the file handle onto
the file handle for standard output.
*/
dup2(nul, STDOUT);
/* close the handle for DUMMY.FIL */
close(nul);
/* will be redirected into DUMMY.FIL */
write(STDOUT, msg, strlen(msg));
/* restore original standard output handle */
dup2(oldstdout, STDOUT);

905
C Runtime Library Reference RAD Studio 3.1 Référence C++

/* close duplicate handle for STDOUT */


close(oldstdout);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

3.1.5.15.25 eof
Header File

io.h

Category

Input/output Routines

Prototype
int eof(int handle);

Description

Checks for end-of-file.

eof determines whether the file associated with handle has reached end-of-file.

Return Value

If the current position is end-of-file, eof returns the value 1; otherwise, it returns 0. A return value of -1 indicates an error; the
global variable errno is set to

EBADF Bad file number

Example
#include <sys\stat.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
char msg[] = "This is a test";
char ch;
/* create a file */
handle = open("DUMMY.FIL",
O_CREAT | O_RDWR,
3 S_IREAD | S_IWRITE);
/* write some data to the file */
write(handle, msg, strlen(msg));
/* seek to the beginning of the file */
lseek(handle, 0L, SEEK_SET);
/* reads chars from the file until it reaches EOF */
do
{
read(handle, &ch, 1);
printf("%c", ch);
} while (!eof(handle));

906
3.1 Référence C++ RAD Studio C Runtime Library Reference

close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.26 filelength
Header File

io.h

Category

Input/output Routines

Prototype
long filelength(int handle);

Description

Gets file size in bytes.

filelength returns the length (in bytes) of the file associated with handle.

Return Value

On success filelength returns a long value the file length in bytes. On error it returns -1 and the global variable errno is set to

EBADF Bad file number

Example
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
char buf[11] = "0123456789";
/* create a file containing 10 bytes */
handle = open("DUMMY.FIL", O_CREAT);
write(handle, buf, strlen(buf));
/* display the size of the file */
printf("file length in bytes: %ld\n", filelength(handle));
/* close the file */
close(handle);
return 0;
} 3
Portability

POSIX Win32 ANSI C ANSI C++


+

907
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.15.27 _fileno
Header File

stdio.h

Category

Input/output Routines

Prototype
int _fileno(FILE *stream);

Description

Gets the file handle.

_fileno is a macro that returns the file handle for the given stream. If stream has more than one handle _fileno returns the handle
assigned to the stream when it was first opened.

Return Value

_fileno returns the integer file handle associated with stream.

Example
#include <stdio.h>
int main(void)
{
FILE *stream;
int handle;
/* create a file */
stream = fopen("DUMMY.FIL", "w");
/* obtain the file handle associated with the stream */
handle = fileno(stream);
/* display the handle number */
printf("handle number: %d\n", handle);
/* close the file */
fclose(stream);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

3.1.5.15.28 getftime, setftime


Header File
3
io.h

Category

Input/output Routines

Prototype
int getftime(int handle, struct ftime *ftimep);
int setftime(int handle, struct ftime *ftimep);

908
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

Gets and sets the file date and time.

getftime retrieves the file time and date for the disk file associated with the open handle. The ftime structure pointed to by ftimep
is filled in with the file's time and date.

setftime sets the file date and time of the disk file associated with the open handle to the date and time in the ftime structure
pointed to by ftimep. The file must not be written to after the setftime call or the changed information will be lost. The file must be
open for writing; an EACCES error will occur if the file is open for read-only access.

setftime requires the file to be open for writing; an EACCES error will occur if the file is open for read-only access.

The ftime structure is defined as follows:


struct ftime {
unsigned ft_tsec: 5; /* two seconds */
unsigned ft_min: 6; /* minutes */
unsigned ft_hour: 5; /* hours */
unsigned ft_day: 5; /* days */
unsigned ft_month: 4; /* months */
unsigned ft_year: 7; /* year - 1980*/
};

Return Value

getftime and setftime return 0 on success.

In the event of an error return -1 is returned and the global variable errno is set to one of the following values:

EACCES Permission denied


EBADF Bad file number
EINVFNC Invalid function number

Example
#include <stdio.h>
#include <io.h>
int main(void)
{
FILE *stream;
std::ftime ft;
if ((stream = fopen("TEST.$$$",
"wt")) == NULL)
{
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
getftime(fileno(stream), &ft); 3
printf("File time: %u:%u:%u\n",
ft.ft_hour, ft.ft_min,
ft.ft_tsec * 2);
printf("File date: %u/%u/%u\n",
ft.ft_month, ft.ft_day,
ft.ft_year+1980);
fclose(stream);
return 0;
}

909
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.15.29 isatty
Header File

io.h

Category

Input/output Routines

Prototype
int isatty(int handle);

Description

Checks for device type.

isatty determines whether handle is associated with any one of the following character devices:

• a terminal
• a console
• a printer
• a serial port
Return Value
If the device is one of the four character devices listed above, isatty returns a nonzero integer. If it is not such a device, isatty
returns 0.
Example
#include <stdio.h>
#include <io.h>
int main(void)
{
int handle;
handle = fileno(stdout);
if (isatty(handle))
printf("Handle %d is a device type\n", handle);
else
printf("Handle %d isn't a device type\n", handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

3 3.1.5.15.30 lock
Header File

io.h

Category

Input/output Routines

Prototype

910
3.1 Référence C++ RAD Studio C Runtime Library Reference

int lock(int handle, long offset, long length);

Description

Sets file-sharing locks.

lock provides an interface to the operating system file-sharing mechanism.

A lock can be placed on arbitrary, nonoverlapping regions of any file. A program attempting to read or write into a locked region
will retry the operation three times. If all three retries fail, the call fails with an error.

Return Value

lock returns 0 on success. On error, lock returns -1 and sets the global variable errno to

EACCES Locking violation

Example
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <process.h>
#include <share.h>
#include <stdio.h>
int main(void)
{
int handle, status;
long length;
handle = _sopen("c:\\autoexec.bat",
O_RDONLY,SH_DENYNO,S_IREAD);
if (handle < 0)
{
printf("_sopen failed\n");
exit(1);
}
length = filelength(handle);
status = lock(handle,0L,length/2);
if (status == 0)
printf("lock succeeded\n");
else
printf("lock failed\n");
status = unlock(handle,0L,length/2);
if (status == 0)
printf("unlock succeeded\n");
else
printf("unlock failed\n");
close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ 3

3.1.5.15.31 locking
Header File

io.h, sys\locking.h

Category

911
C Runtime Library Reference RAD Studio 3.1 Référence C++

Input/output Routines

Prototype
int locking(int handle, int cmd, long length);

Description

Sets or resets file-sharing locks.

locking provides an interface to the operating system file-sharing mechanism. The file to be locked or unlocked is the open file
specified by handle. The region to be locked or unlocked starts at the current file position, and is length bytes long.

Locks can be placed on arbitrary, nonoverlapping regions of any file. A program attempting to read or write into a locked region
will retry the operation three times. If all three retries fail, the call fails with an error.

The cmd specifies the action to be taken (the values are defined in sys\locking.h):

LK_LOCK Lock the region. If the lock is unsuccessful, try once a second for 10 seconds before giving up.
LK_RLCK Same as LK_LOCK.
LK_NBLCK Lock the region. If the lock if unsuccessful, give up immediately.
LK_NBRLCK Same as LK_NBLCK.
LK_UNLCK Unlock the region, which must have been previously locked.

Return Value

On successful operations, locking returns 0. Otherwise, it returns -1, and the global variable errno is set to one of the following
values:

EACCES File already locked or unlocked


EBADF Bad file number
EDEADLOCK File cannot be locked after 10 retries (cmd is LK_LOCK or LK_RLCK)
EINVAL Invalid cmd, or SHARE.EXE not loaded

Example
#include <io.h>
#include <fcntl.h>
#include <process.h>
#include <share.h>
#include <stdio.h>
#include <sys\locking.h>
int main(void)
{
int handle, status;
long length;
handle = sopen("c:\\autoexec.bat", O_RDONLY,SH_DENYNO);
if (handle < 0) {
printf("sopen failed\n");
3 exit(1);
}
length = filelength(handle);
status = locking(handle,LK_LOCK,length/2);
if (status == 0)
printf("lock succeeded\n");
else
perror("lock failed");
status = locking(handle,LK_UNLCK,length/2);
if (status == 0)
printf("unlock succeeded\n");

912
3.1 Référence C++ RAD Studio C Runtime Library Reference

else
perror("unlock failed");
close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.32 lseek
Header File

io.h

Category

Input/output Routines

Prototype
long lseek(int handle, long offset, int fromwhere);

Description

Moves file pointer.

lseek sets the file pointer associated with handle to a new position offset bytes beyond the file location given by fromwhere.
fromwhere must be one of the following symbolic constants (defined in io.h):

SEEK_CUR Current file pointer position


SEEK_END End-of-file
SEEK_SET File beginning

Return Value

lseek returns the offset of the pointer’s new position measured in bytes from the file beginning. lseek returns -1L on error, and
the global variable errno is set to one of the following values:

EBADF Bad file handle


EINVAL Invalid argument
ESPIPE Illegal seek on device

On devices incapable of seeking (such as terminals and printers), the return value is undefined.

Example
#include <sys\stat.h>
3
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
char msg[] = "This is a test";
char ch;

913
C Runtime Library Reference RAD Studio 3.1 Référence C++

/* create a file */
handle = open("TEST.$$$", O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
/* write some data to the file */
write(handle, msg, strlen(msg));
/* seek to the beginning of the file */
lseek(handle, 0L, SEEK_SET);
/* reads chars from the file until we hit EOF */
do
{
read(handle, &ch, 1);
printf("%c", ch);
} while (!eof(handle));
close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

3.1.5.15.33 read
Header File

io.h

Category

Input/output Routines

Prototype
int read(int handle, void *buf, unsigned len);

Description

Reads from file.

read attempts to read len bytes from the file associated with handle into the buffer pointed to by buf.

For a file opened in text mode, read removes carriage returns and reports end-of-file when it reaches a Ctrl-Z.

The file handle handle is obtained from a creat, open, dup, or dup2 call.

On disk files, read begins reading at the current file pointer. When the reading is complete, it increments the file pointer by the
number of bytes read. On devices, the bytes are read directly from the device.

The maximum number of bytes that read can read is UINT_MAX -1, because UINT_MAX is the same as -1, the error return
indicator. UINT_MAX is defined in limits.h.

Return Value

3 On successful completion, read returns an integer indicating the number of bytes placed in the buffer. If the file was opened in
text mode, read does not count carriage returns or Ctrl-Z characters in the number of bytes read.

On end-of-file, read returns 0. On error, read returns -1 and sets the global variable errno to one of the following values:

EACCES Permission denied


EBADF Bad file number

Example

914
3.1 Référence C++ RAD Studio C Runtime Library Reference

#include <stdio.h>
#include <io.h>
#include <alloc.h>
#include <fcntl.h>
#include <process.h>
#include <sys\stat.h>
int main(void)
{
void *buf;
int handle, bytes;
buf = malloc(10);
/*
Looks for a file in the current directory named TEST.$$$ and attempts to read 10 bytes from
it. To use this example you should create the file TEST.$$$.
*/
if ((handle =
open("TEST.$$$", O_RDONLY | O_BINARY, S_IWRITE | S_IREAD)) == -1)
{
printf("Error Opening File\n");
exit(1);
}
if ((bytes = read(handle, buf, 10)) == -1) {
printf("Read Failed.\n");
exit(1);
}
else {
printf("Read: %d bytes read.\n", bytes);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

3.1.5.15.34 setmode
Header File

io.h

Category

Input/output Routines

Prototype
int setmode(int handle, int amode);

Description

Sets mode of an open file.


3
setmode sets the mode of the open file associated with handle to either binary or text. The argument amode must have a value
of either O_BINARY or O_TEXT, never both. (These symbolic constants are defined in fcntl.h.)

Return Value

setmode returns the previous translation mode if successful. On error it returns -1 and sets the global variable errno to

EINVAL Invalid argument

915
C Runtime Library Reference RAD Studio 3.1 Référence C++

Example
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
int main (int argc, char ** argv )
(
FILE *fp;
int newmode;
long where;
char buf[256];
fp = fopen( argv[1], "r+" );
if ( !fp )
{
printf( "Couldn't open %s\n", argv[1] );
return -1;
}
newmode = setmode( fileno( fp ), O_BINARY );
if ( newmode == -1 )
{
printf( "Couldn't set mode of %s\n", argv[1] );
return -2
}
fp->flags |= _F_BIN;
where = ftell( fp );
printf ("file position: %d\n", where );
fread( buf, 1, 1, fp );
where = ftell ( fp );
printf( "read %c, file position: %ld\n", *buf, where );
fclose ( fp );
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.35 tell
Header File

io.h

Category

Input/output Routines

Prototype
long tell(int handle);

Description
3
Gets the current position of a file pointer.

tell gets the current position of the file pointer associated with handle and expresses it as the number of bytes from the beginning
of the file.

Return Value

tell returns the current file pointer position. A return of -1 (long) indicates an error, and the global variable errno is set to

916
3.1 Référence C++ RAD Studio C Runtime Library Reference

EBADF Bad file number

Example
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
char msg[] = "Hello world";
if ((handle = open("TEST.$$$", O_CREAT | O_TEXT | O_APPEND)) == -1)
{
perror("Error:");
return 1;
}
write(handle, msg, strlen(msg));
printf("The file pointer is at byte %ld\n", tell(handle));
close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.36 umask
Header File

io.h, sys\stat.h

Category

Input/output Routines

Prototype
unsigned umask(unsigned mode);

Description

Sets file read/write permission mask.

The umask function sets the access permission mask used by open and creat. Bits that are set in mode will be cleared in the
access permission of files subsequently created by open and creat.

The mode can have one of the following values, defined in sys\stat.h:

S_IWRITE Permission to write


3
S_IREAD Permission to read
S_IREAD|S_IWRITE Permission to read and write

Return Value

The previous value of the mask. There is no error return.

Example

917
C Runtime Library Reference RAD Studio 3.1 Référence C++

#include <io.h>
#include <stdio.h>
#include <sys\stat.h>
#define FILENAME "TEST.$$$"
int main(void)
{
unsigned oldmask;
FILE *f;
struct stat statbuf;
/* Cause subsequent files to be created as read-only */
oldmask = umask(S_IWRITE);
printf("Old mask = 0x%x\n",oldmask);
/* Create a zero-length file */
if ((f = fopen(FILENAME,"w+")) == NULL)
{
perror("Unable to create output file");
return (1);
}
fclose(f);
/* Verify that the file is read-only */
if (stat(FILENAME,&statbuf) != 0)
{
perror("Unable to get information about output file");
return (1);
}
if (statbuf.st_mode & S_IWRITE)
printf("Error! %s is writable!\n",FILENAME);
else
printf("Success! %s is not writable.\n",FILENAME);
return (0);
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

3.1.5.15.37 unlock
Header File

io.h

Category

Input/output Routines

Prototype
int unlock(int handle, long offset, long length);

Description

3 Releases file-sharing locks.

unlock provides an interface to the operating system file-sharing mechanism. unlock removes a lock previously placed with a call
to lock. To avoid error, all locks must be removed before a file is closed. A program must release all locks before completing.

Return Value

On success, unlock returns 0

O error, it returns -1.

918
3.1 Référence C++ RAD Studio C Runtime Library Reference

Example
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <process.h>
#include <share.h>
#include <stdio.h>
int main(void)
{
int handle, status;
long length;
handle = _sopen("c:\\autoexec.bat",O_RDONLY,SH_DENYNO,S_IREAD);
if (handle < 0)
{
printf("_sopen failed\n");
exit(1);
}
length = filelength(handle);
status = lock(handle,0L,length/2);
if (status == 0)
printf("lock succeeded\n");
else
printf("lock failed\n");
status = unlock(handle,0L,length/2);
if (status == 0)
printf("unlock succeeded\n");
else
printf("unlock failed\n");
close(handle);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.15.38 vsscanf
Header File

io.h

Category

Memory and String Manipulation Routines

Prototype
int vsscanf(const char *buffer, const char *format, va_list arglist);

Description
3
Scans and formats input from a stream.

The v...scanf functions are known as alternate entry points for the ...scanf functions. They behave exactly like their ...scanf
counterparts, but they accept a pointer to a list of arguments instead of an argument list.

Remarque: For details on format specifiers, see Scanf Format Specifiers.

vsscanf scans a series of input fields, one character at a time, reading from a stream. Then each field is formatted according to a
format specifier passed to vsscanf in the format string pointed to by format. Finally, vsscanf stores the formatted input at an

919
C Runtime Library Reference RAD Studio 3.1 Référence C++

address passed to it as an argument following format. There must be the same number of format specifiers and addresses as
there are input fields.

vsscanf might stop scanning a particular field before it reaches the normal end-of-field (whitespace) character, or it might
terminate entirely, for a number of reasons. See scanf for a discussion of possible causes.

Return Value

vsscanf returns the number of input fields successfully scanned, converted, and stored; the return value does not include
scanned fields that were not stored. If no fields were stored, the return value is 0.

If vsscanf attempts to read at end-of-string, the return value is EOF.

Example
#include <stdio.h>
#include <stdarg.h>
char buffer[80] = "30 90.0 abc";
int vssf(char *fmt, ...)
{
va_list argptr;
int cnt;
fflush(stdin);
va_start(argptr, fmt);
cnt = vsscanf(buffer, fmt, argptr);
va_end(argptr);
return(cnt);
}
int main(void)
{
int inumber;
float fnumber;
char string[80];
vssf("%d %f %s", &inumber, &fnumber, string);
printf("%d %f %s\n", inumber, fnumber, string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + +

3.1.5.15.39 write
Header File

io.h

Category

Input/output Routines
3
Prototype
int write(int handle, void *buf, unsigned len);

Description

Writes to a file.

write writes a buffer of data to the file or device named by the given handle. handle is a file handle obtained from a creat, open,
dup, or dup2 call.

920
3.1 Référence C++ RAD Studio C Runtime Library Reference

This function attempts to write len bytes from the buffer pointed to by buf to the file associated with handle. Except when write is
used to write to a text file, the number of bytes written to the file will be no more than the number requested. The maximum
number of bytes that write can write is UINT_MAX -1, because UINT_MAX is the same as -1, which is the error return indicator
for write. On text files, when write sees a linefeed (LF) character, it outputs a CR/LF pair. UINT_MAX is defined in limits.h.

If the number of bytes actually written is less than that requested, the condition should be considered an error and probably
indicates a full disk. For disks or disk files, writing always proceeds from the current file pointer. For devices, bytes are sent
directly to the device. For files opened with the O_APPEND option, the file pointer is positioned to EOF by write before writing
the data.

Return Value

write returns the number of bytes written. A write to a text file does not count generated carriage returns. In case of error, write
returns -1 and sets the global variable errno to one of the following values:

EACCES Permission denied


EBADF Bad file number

Example
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys\stat.h>
#include <io.h>
#include <string.h>
int main(void)
{
int handle;
char string[40];
int length, res;
/*
Create a file named "TEST.$$$" in the current directory and write a string to it. If
"TEST.$$$" already exists, it will be overwritten.
*/
if ((handle = open("TEST.$$$", O_WRONLY | O_CREAT | O_TRUNC,
S_IREAD | S_IWRITE)) == -1)
{
printf("Error opening file.\n");
exit(1);
}
strcpy(string, "Hello, world!\n");
length = strlen(string);
if ((res = write(handle, string, length)) != length)
{
printf("Error writing to the file.\n");
exit(1);
}
printf("Wrote %d bytes to the file.\n", res);
close(handle);
return 0;
}
Portability
3

POSIX Win32 ANSI C ANSI C++


+ +

921
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.16 limits.h
The following functions, macros, and classes are provided in limits.h:

Rubriques
Nom Description
CHAR_xxx #defines ( see page 922) Header File
limits.h
Description
INT_xxx #defines ( see page 922) Header File
limits.h
Description
Maximum and minimum value for type int.
LONG_xxx #defines ( see page 923) Header File
limits.h
Description
Maximum and minimum value for type long.
SCHAR_xxx #defines ( see page 923) Header File
limits.h
Description
SHRT_xxx #defines ( see page 923) Header File
limits.h
Description
Uxxxx_MAX #defines ( see page 923) Header File
limits.h
Description

3.1.5.16.1 CHAR_xxx #defines


Header File

limits.h

Description

Name Meaning
CHAR_BIT Type char, number of bits
CHAR_MAX Type char, minimum value
CHAR_MIN Type char, maximum value

These values are independent of whether type char is defined as signed or unsigned by default.

3.1.5.16.2 INT_xxx #defines


3 Header File

limits.h

Description

Maximum and minimum value for type int.

Name Meaning
INT_MAX Type int, maximum value

922
3.1 Référence C++ RAD Studio C Runtime Library Reference

INT_MIN Type int, minimum value

3.1.5.16.3 LONG_xxx #defines


Header File

limits.h

Description

Maximum and minimum value for type long.

Name Meaning
LONG_MAX Type long, maximum value
LONG_MIN Type long, minimum value

3.1.5.16.4 SCHAR_xxx #defines


Header File

limits.h

Description

Name Meaning
SCHAR_MAX Type char, maximum value
SCHAR_MIN Type char, minimum value

3.1.5.16.5 SHRT_xxx #defines


Header File

limits.h

Description

Name Meaning
SHRT_MAX Type short, maximum value
SHRT_MIN Type short, minimum value

3.1.5.16.6 Uxxxx_MAX #defines 3


Header File

limits.h

Description

Name Maximum value for type xxx


UCHAR_MAX unsigned char

923
C Runtime Library Reference RAD Studio 3.1 Référence C++

USHRT_MAX unsigned short


UINT_MAX unsigned integer
ULONG_MAX unsigned long

3.1.5.17 locale.h
The following functions, macros, and classes are provided in locale.h:

Rubriques
Nom Description
localeconv ( see page 924) Header File
locale.h
Category
Miscellaneous Routines
Prototype
struct lconv *localeconv(void);
Description
Queries the locale for numeric format.
This function provides information about the monetary and other numeric formats
for the current locale. The information is stored in a struct lconv type. The
structure can only be modified by the setlocale. Subsequent calls to localeconv
will update the lconv structure.
The lconv structure is defined in locale.h. It contains the following fields:
setlocale, _wsetlocale ( see page 926) Header File
locale.h
Category
Miscellaneous Routines
Prototype
char *setlocale(int category, const char *locale);
wchar_t * _wsetlocale( int category, const wchar_t *locale);
Description
Use the setlocale to select or query a locale.
C++ Builder supports all locales supported in Win95/98/2000 operating systems.
See your system documentation for details.
The possible values for the category argument are as follows:

3.1.5.17.1 localeconv
Header File

locale.h

Category

Miscellaneous Routines

Prototype
3 struct lconv *localeconv(void);

Description

Queries the locale for numeric format.

This function provides information about the monetary and other numeric formats for the current locale. The information is stored
in a struct lconv type. The structure can only be modified by the setlocale. Subsequent calls to localeconv will update the lconv
structure.

924
3.1 Référence C++ RAD Studio C Runtime Library Reference

The lconv structure is defined in locale.h. It contains the following fields:

char Decimal point used in nonmonetary formats. This can never be an empty string.
char Separator used to group digits to the left of the decimal point. Not used with monetary quantities.
char Size of each group of digits. Not used with monetary quantities. See the value listing table below.
char International monetary symbol in the current locale. The symbol format is specified in the ISO 4217
Codes for the Representation of Currency and Funds.
char Local monetary symbol for the current locale.
char Decimal point used to format monetary quantities.
char Separator used to group digits to the left of the decimal point for monetary quantities.
char Size of each group of digits used in monetary quantities. See the value listing table below.
char String indicating nonnegative monetary quantities.
char String indicating negative monetary quantities.
char Number of digits after the decimal point that are to be displayed in an internationally formatted
monetary quantity.
char Number of digits after the decimal point that are to be displayed in a formatted monetary quantity.
char Set to 1 if currency_symbol precedes a nonnegative formatted monetary quantity. If currency_symbol
is after the quantity, it is set to 0.
char Set to 1 if currency_symbol is to be separated from the nonnegative formatted monetary quantity by a
space. Set to 0 if there is no space separation.
char Set to 1 if currency_symbol precedes a negative formatted monetary quantity. If currency_symbol is
after the quantity, set to 0.
char Set to 1 if currency_symbol is to be separated from the negative formatted monetary quantity by a
space. Set to 0 if there is no space separation.
char Indicate where to position the positive sign in a nonnegative formatted monetary quantity.
char Indicate where to position the positive sign in a negative formatted monetary quantity.

Any of the above strings (except decimal_point) that is empty “ “ is not supported in the current locale. The nonstring char
elements are nonnegative numbers. Any nonstring char element that is set to CHAR_MAX indicates that the element is not
supported in the current locale.

The grouping and mon_grouping elements are set and interpreted as follows:

CHAR_MAX No further grouping is to be performed.


0 The previous element is to be used repeatedly for the remainder of the digits.
any other integer Indicates how many digits make up the current group. The next element is read to determine the size
of the next group of digits before the current group.

The p_sign_posn and n_sign_posn elements are set and interpreted as follows:
3
0 Use parentheses to surround the quantity and currency_symbol.
1 Sign string precedes the quantity and currency_symbol.
2 Sign string succeeds the quantity and currency_symbol.
3 Sign string immediately precedes the quantity and currency_symbol.
4 Sign string immediately succeeds the quantity and currency_symbol.

925
C Runtime Library Reference RAD Studio 3.1 Référence C++

Return Value

Returns a pointer to the the filled-in structure of type struct lconv. The values in the structure will change whenever setlocale
modifies the LC_MONETARY or LC_NUMERIC categories.

Example
#include <locale.h>
#include <stdio.h>
int main(void)
{
struct lconv ll;
struct lconv *conv = &ll;
/* read the locality conversion structure */
conv = localeconv();
/* display the structure */
printf("Decimal Point : %s\n", conv-> decimal_point);
printf("Thousands Separator : %s\n", conv-> thousands_sep);
printf("Grouping : %s\n", conv-> grouping);
printf("International Currency symbol : %s\n", conv-> int_curr_symbol);
printf("$ thousands separator : %s\n", conv-> mon_thousands_sep);
printf("$ grouping : %s\n", conv-> mon_grouping);
printf("Positive sign : %s\n", conv-> positive_sign);
printf("Negative sign : %s\n", conv-> negative_sign);
printf("International fraction digits : %d\n", conv-> int_frac_digits);
printf("Fraction digits : %d\n", conv-> frac_digits);
printf("Positive $ symbol precedes : %d\n", conv-> p_cs_precedes);
printf("Positive sign space separation: %d\n", conv-> p_sep_by_space);
printf("Negative $ symbol precedes : %d\n", conv-> n_cs_precedes);
printf("Negative sign space separation: %d\n", conv-> n_sep_by_space);
printf("Positive sign position : %d\n", conv-> p_sign_posn);
printf("Negative sign position : %d\n", conv-> n_sign_posn);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.17.2 setlocale, _wsetlocale


Header File

locale.h

Category

Miscellaneous Routines

Prototype
char *setlocale(int category, const char *locale);
3
wchar_t * _wsetlocale( int category, const wchar_t *locale);

Description

Use the setlocale to select or query a locale.

C++ Builder supports all locales supported in Win95/98/2000 operating systems. See your system documentation for details.

The possible values for the category argument are as follows:

926
3.1 Référence C++ RAD Studio C Runtime Library Reference

LC_ALL Affects all the following categories


LC_COLLATE Affects strcoll and strxfrm
LC_CTYPE Affects single-byte character handling functions. The mbstowcs and mbtowc functions are not
affected.
LC_MONETARY Affects monetary formatting by the localeconv function
LC_NUMERIC Affects the decimal point of non-monetary data formatting. This includes the printf family of functions,
and the information returned by localeconv.
LC_TIME Affects strftime

The locale argument is a pointer to the name of the locale or named locale category. Passing a NULL pointer returns the current
locale in effect. Passing a pointer that points to a null string requests setlocale to look for environment variables to determine
which locale to set. The locale names are not case sensitive.

When setlocale is unable to honor a locale request, the preexisting locale in effect is unchanged and a null pointer is returned.

If the locale argument is a NULL pointer, the locale string for the category is returned. If category is LC_ALL, a complete locale
string is returned. The structure of the complete locale string consists of the names of all the categories in the current locale
concatenated and separated by semicolons. This string can be used as the locale parameter when calling setlocale with any of
the LC_xxx values. This will reinstate all the locale categories that are named in the complete locale string, and allows saving
and restoring of locale states. If the complete locale string is used with a single category, for example, LC_TIME, only that
category will be restored from the locale string.

If an empty string "" is used as the locale parameter an implementation-defined locale is used. This is the ANSI C specified
behavior.

To take advantage of dynamically loadable locales in your application, define _ _USELOCALES_ _ for each module. If _
_USELOCALES_ _ is not defined, all locale-sensitive functions and macros will work only with the default C locale.

If a NULL pointer is used as the argument for the locale parameter, setlocale returns a string that specifies the current locale in
effect. If the category parameter specifies a single category, such as LC_COLLATE, the string pointed to will be the name of that
category. If LC_ALL is used as the category parameter then the string pointed to will be a full locale string that will indicate the
name of each category in effect.
.
.
.
localenameptr = setlocale( LC_COLLATE, NULL );
if (localenameptr)
printf( "%s\n", localenameptr );
.
.
. 3
The output here will be one of the module names together with the specified code page. For example, the output could be
LC_COLLATE = English_United States.437.
.
.
.

927
C Runtime Library Reference RAD Studio 3.1 Référence C++

localenameptr = setlocale( LC_ALL, NULL );


if (localenameptr)
printf( "%s\n", localenameptr );
.
.
.

An example of the output here could be the following:


LC_COLLATE=English_United States.437;
LC_TIME=English_United States.437;
LC_CTYPE=English_United States.437;

Each category in this full string is delimited by a semicolon. This string can be copied and saved by an application and then used
again to restore the same locale categories at another time. Each delimited name corresponds to the locale category constants
defined in locale.h. Therefore, the first name is the name of the LC_COLLATE category, the second is the LC_CTYPE category,
and so on. Any other categories named in the locale.h header file are reserved for future implementation.

To set all default categories for the specified French locale:


setlocale( LC_ALL, "French_France.850" );

To find out which code page is currently being used:


localenameptr = setlocale( LC_ALL, NULL );

Return value

If selection is successful, setlocale returns a pointer to a string that is associated with the selected category (or possibly all
categories) for the new locale.

If UNICODE is defined, _wsetlocale returns a wchar_t string.

On failure, a NULL pointer is returned and the locale is unchanged. All other possible returns are discussed in the Remarks
section above.

Example
#include <locale.h>
#include <stdio.h>
int main(void)
{
char *old_locale;
/* The only locale supported in Borland C++ is "C" */
old_locale = setlocale(LC_ALL,"C");
printf("Old locale was %s\n",old_locale);
return 0;
}
Portability
3
POSIX Win32 ANSI C ANSI C++
setlocale + + + +
_wsetlocale +

928
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.18 malloc.h
The following functions, macros, and classes are provided in malloc.h:

Rubriques
Nom Description
alloca ( see page 929) Header File
malloc.h
Category
Memory Routines
Prototype
void *alloca(size_t size);
Description
Allocates temporary stack space.
alloca allocates size bytes on the stack; the allocated space is automatically
freed up when the calling function exits.
The use of alloca is not encouraged. In the try-block of a C++ program the alloca
function should never be used. If an exception is thrown, any values placed on
the stack by alloca will be corrupted.
Return Value
If enough stack space is available, alloca returns a pointer to the allocated stack
area. Otherwise, it returns NULL.
Example

3.1.5.18.1 alloca
Header File

malloc.h

Category

Memory Routines

Prototype
void *alloca(size_t size);

Description

Allocates temporary stack space.

alloca allocates size bytes on the stack; the allocated space is automatically freed up when the calling function exits.

The use of alloca is not encouraged. In the try-block of a C++ program the alloca function should never be used. If an exception
is thrown, any values placed on the stack by alloca will be corrupted.

Return Value

If enough stack space is available, alloca returns a pointer to the allocated stack area. Otherwise, it returns NULL.

Example 3
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
void test(int a)
{
char *newstack;
int len = a;
char dummy[1];
dummy[0] = 0; /* force good stack frame */

929
C Runtime Library Reference RAD Studio 3.1 Référence C++

printf("SP before calling alloca(0x%X) = 0x%X\n",len,_SP);


newstack = (char *) alloca(len);
printf("SP after calling alloca = 0x%X\n",_SP);
if (newstack)
printf("Alloca(0x%X) returned %p\n",len,newstack);
else
printf("Alloca(0x%X) failed\n",len);
}
void main()
{
test(256);
test(16384);
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.19 math.h
The following functions, macros, and classes are provided in math.h:

Rubriques
Nom Description
HUGE_VAL #defines ( see page 940) Header File
math.h
Description
Overflow value for math functions.
M_E, M_LOGxxx, M_LNxx #defines ( see page 941) Header File
math.h
Description
The constant values for logarithm functions.
M_SQRTxx #defines ( see page 941) Header File
math.h
Description
Constant values for square roots of 2.
PI constants ( see page 941) Header File
math.h
Description
Common constants of pi

930
3.1 Référence C++ RAD Studio C Runtime Library Reference

atof, _wtof ( see page 942) Header File


stdlib.h, math.h
Category
Conversion Routines, Math Routines
Prototype
double atof(const char *s);
double _wtof(const wchar_t *s);
Description
Converts a string to a floating-point number.

• atof converts a string pointed to by s to double; this


function recognizes the character representation of a
floating-point number, made up of the following:
• An optional string of tabs and spaces
• An optional sign
• A string of digits and an optional decimal point (the digits
can be on both sides of the decimal point)
• An optional e or E followed by an optional signed integer
The characters must match this generic... suite ( see page
942)
_atold, _wtold ( see page 942) Header File
math.h
Category
Conversion Routines, Math Routines
Prototype
long double _atold(const char *s);
long double _wtold(const wchar_t *s);
Description
Converts a string to a long double.
_wtold is the wide-character version. It converts a wide-character string to a long
double.
_atof is the floating-point version of _atold.
_atold converts a string pointed to by s to a long double; this functions
recognizes:
An optional string of tabs and spaces
An optional sign
A string of digits and an optional decimal point
An optional e or E followed by an optional signed integer
The first unrecognized character ends... suite ( see page 942)
_i64toa, _i64tow ( see page 943) Header File
math.h, stdlib.h
Category
Conversion Routines, Math Routines,
Prototype
char *_i64toa(__int64 value, char *string, int radix);
wchar_t *_i64tow(__int64 value, wchar_t *string, int radix);
Description
_i64toa converts an __int64 to a string. _i64tow is the unicode version. It
converts a __int64 to a wide-character string.
These functions convert value to a null-terminated string and store the result in
string. value is an __int64.
radix specifies the base to be used in converting value; it must be between 2 and
3
36, inclusive. If value is negative and radix is 10, the first character of string is the
minus sign... suite ( see page 943)

931
C Runtime Library Reference RAD Studio 3.1 Référence C++

_matherr, _matherrl ( see page 944) Header File


math.h
Category
Diagnostic Routines, Math Routines
Prototype
int _matherr(struct _exception *e);
int _matherrl(struct _exceptionl *e);
Description
User-modifiable math error handler.
_matherr is called when an error is generated by the math library.
_matherrl is the long double version; it is called when an error is generated by
the long double math functions.
_matherr and _matherrl each serve as a user hook (a function that can be
customized by the user) that you can replace by writing your own math
error-handling routine.
_matherr and _matherrl are useful for information on trapping domain and range
errors caused by the... suite ( see page 944)
abs ( see page 945) Header File
stdlib.h, math.h
Category
Math Routines, Inline Routines
Prototype
int abs(int x);
Description
Returns the absolute value of an integer.
abs returns the absolute value of the integer argument x. If abs is called when
stdlib.h has been included, it's treated as a macro that expands to inline code.
If you want to use the abs function instead of the macro, include
#undef abs
in your program, after the #include <stdlib.h>.
Return Value
The abs function returns an integer in the range of 0 to INT_MAX, with the
exception that an argument with the value INT_MIN is returned... suite ( see
page 945)
acos, acosl ( see page 946) Header File
math.h
Category
Math Routines
Prototype
double acos(double x);
long double acosl(long double x);
Description
Calculates the arc cosine.
acos returns the arc cosine of the input value.
acosl is the long double version; it takes a long double argument and returns a
long double result.
Arguments to acos and acosl must be in the range -1 to 1, or else acos and acosl
return NAN and set the global variable errno to:
EDOM Domain error
Return Value
acos and acosl of an argument between -1 and +1 return a value in the range 0
to pi. Error... suite ( see page 946)

932
3.1 Référence C++ RAD Studio C Runtime Library Reference

asin, asinl ( see page 947) Header File


math.h
Category
Math Routines
Prototype
double asin(double x);
long double asinl(long double x);
Description
Calculates the arc sine.
asin of a real argument returns the arc sine of the input value.
asinl is the long double version; it takes a long double argument and returns a
long double result.
Real arguments to asin and asinl must be in the range -1 to 1, or else asin and
asinl return NAN and set the global variable errno to
EDOM Domain error
Return Value
asin and asinl of a real argument return a value in the range -pi/2 to... suite (
see page 947)
atan, atanl ( see page 948) Header File
math.h
Category
Math Routines
Prototype
double atan(double x);
long double atanl(long double x);
Description
Calculates the arc tangent.
atan calculates the arc tangent of the input value.
atanl is the long double version; it takes a long double argument and returns a
long double result.
Return Value
atan and atanl of a real argument return a value in the range -pi/2 to pi/2. Error
handling for these functions can be modified through the functions _matherr and
_matherrl.
Example
atan2, atan2l ( see page 949) Header File
math.h
Category
Math Routines
Prototype
double atan2(double y, double x);
long double atan2l(long double y, long double x);
Description
Calculates the arc tangent of y/x.
atan2 returns the arc tangent of y/x; it produces correct results even when the
resulting angle is near pi/2 or -pi/2 (x near 0). If both x and y are set to 0, the
function sets the global variable errno to EDOM, indicating a domain error.
atan2l is the long double version; it takes long double arguments and returns a
long double result.
Return Value
atan2 and atan2l return a value in... suite ( see page 949)

933
C Runtime Library Reference RAD Studio 3.1 Référence C++

cabs, cabsl ( see page 949) Header File


math.h
Category
Math Routines
Prototype
double cabs(struct complex z);
long double cabsl(struct _complexl z);
Description
cabs calculates the absolute value of a complex number. cabs is a macro that
calculates the absolute value of z, a complex number. z is a structure with type
complex; the structure is defined in math.h as
struct complex {
double x, y;
};
where x is the real part, and y is the imaginary part.
Calling cabs is equivalent to calling sqrt with the real and imaginary components
of z, as shown here:
sqrt(z.x * z.x + z.y * z.y)
cabsl... suite ( see page 949)
ceil, ceill ( see page 951) Header File
math.h
Category
Math Routines
Prototype
double ceil(double x);
long double ceill(long double x);
Description
Rounds up.
ceil finds the smallest integer not less than x.
ceill is the long double version; it takes a long double argument and returns a
long double result.
Return Value
These functions return the integer found as a double (ceil) or a long double
(ceill).
Example
cos, cosl ( see page 952) Header File
math.h
Category
Math Routines, Inline Routines
Prototype
double cos(double x);
long double cosl(long double x);
Description
Calculates the cosine of a value.
cos computes the cosine of the input value. The angle is specified in radians.
cosl is the long double version; it takes a long double argument and returns a
long double result.
Return Value
cos of a real argument returns a value in the range -1 to 1. Error handling for
these functions can be modified through _matherr (or _matherrl).
Example

934
3.1 Référence C++ RAD Studio C Runtime Library Reference

cosh, coshl ( see page 952) Header File


math.h
Category
Math Routines
Prototype
double cosh(double x);
long double coshl(long double x);
Description
Calculates the hyperbolic cosine of a value.
cosh computes the hyperbolic cosine:
coshl is the long double version; it takes a long double argument and returns a
long double result.
Return Value
cosh returns the hyperbolic cosine of the argument.
When the correct value would create an overflow, these functions return the
value HUGE_VAL (cosh) or _LHUGE_VAL (coshl) with the appropriate sign, and
the global variable errno is set to ERANGE. Error handling for these functions
can be modified through the functions _matherr... suite ( see page 952)
exp, expl ( see page 953) Header File
math.h
Category
Math Routines
Prototype
double exp(double x);
long double expl(long double x);
Description
Calculates the exponential e to the x.
expl is the long double version; it takes a long double argument and returns a
long double result.
Return Value
exp returns e to the x.
Sometimes the arguments passed to these functions produce results that
overflow or are incalculable. When the correct value overflows, exp returns the
value HUGE_VAL and expl returns _LHUGE_VAL. Results of excessively large
magnitude cause the global variable errno to be set to
fabs, fabsl ( see page 954) Header File
math.h
Category
Math Routines
Prototype
double fabs(double x);
long double fabsl(long double x);
Description
Returns the absolute value of a floating-point number.
fabs calculates the absolute value of x, a double. fabsl is the long double
version; it takes a long double argument and returns a long double result.
Return Value
fabs and fabsl return the absolute value of x.
Example
floor, floorl ( see page 955) Header File
math.h
Category
Math Routines
Prototype
double floor(double x);
long double floorl(long double x);
3
Description
Rounds down.
floor finds the largest integer not greater than x.
floorl is the long double version; it takes a long double argument and returns a
long double result.
Return Value
floor returns the integer found as a double. floorl returns the integer found as a
long double.
Portability

935
C Runtime Library Reference RAD Studio 3.1 Référence C++

fmod, fmodl ( see page 955) Header File


math.h
Category
Math Routines
Prototype
double fmod(double x, double y);
long double fmodl(long double x, long double y);
Description
Calculates x modulo y, the remainder of x/y.
fmod calculates x modulo y (the remainder f, where x = ay + f for some integer a,
and 0 < f < y).
fmodl is the long double version; it takes long double arguments and returns a
long double result.
Return Value
fmod and fmodl return the remainder f where x = ay + f (as described above).
When y = 0, fmod and fmodl return 0.
Example
frexp, frexpl ( see page 956) Header File
math.h
Category
Math Routines
Prototype
double frexp(double x, int *exponent);
long double frexpl(long double x, int *exponent);
Description
Splits a number into mantissa and exponent.
frexp calculates the mantissa m (a double greater than or equal to 0.5 and less
than 1) and the integer value n such that x (the original double value) equals m *
2n. frexp stores n in the integer that exponent points to.
frexpl is the long double version; it takes a long double argument for x and
returns a long double result.
Return Value
frexp and frexpl return the mantissa m.... suite ( see page 956)
hypot, hypotl ( see page 957) Header File
math.h
Category
Math Routines
Prototype
double hypot(double x, double y);
long double hypotl(long double x, long double y);
Description
Calculates hypotenuse of a right triangle.
hypot calculates the value z where
z2 = x2 + y2 and z >= 0
This is equivalent to the length of the hypotenuse of a right triangle, if the lengths
of the two sides are x and y.
hypotl is the long double version; it takes long double arguments and returns a
long double result.
Return Value
On success, these functions return z, a double (hypot) or a long double)... suite
( see page 957)

936
3.1 Référence C++ RAD Studio C Runtime Library Reference

ldexp, ldexpl ( see page 958) Header File


math.h
Category
Math Routines
Prototype
double ldexp(double x, int exp);
long double ldexpl(long double x, int exp);
Description
Calculates x * 2^exp.
lexpl is the long double version; it takes a long double argument for x and
returns a long double result.
Return Value
On success, ldexp (or ldexpl) returns the value it calculated, x * 2^exp. Error
handling for these routines can be modified through the functions _matherr and
_matherrl.
Example
ldiv ( see page 959) Header File
math.h
Category
Math Routines
Prototype
ldiv_t ldiv(long int numer, long int denom);
Description
Divides two longs, returning quotient and remainder.
ldiv divides two longs and returns both the quotient and the remainder as an
ldiv_t type. numer and denom are the numerator and denominator, respectively.
The ldiv_t type is a structure of longs defined in stdlib.h as follows:
typedef struct {
long int quot; /* quotient */
long int rem; /* remainder */
} ldiv_t;
Return Value
ldiv returns a structure whose elements are quot (the quotient) and rem (the
remainder).
Example
log, logl ( see page 959) Header File
math.h
Category
Math Routines
Prototype
double log(double x);
long double logl(long double x);
Description
Calculates the natural logarithm of x.
log calculates the natural logarithm of x.
logl is the long double version; it takes a long double argument and returns a
long double result.
Return Value
On success, log and logl return the value calculated, ln(x).
errno
log10, log10l ( see page 960) Header File
math.h
Category
Math Routines
Prototype 3
double log10(double x);
long double log10l(long double x);
Description
log10 calculates the base ten logarithm of x.
log10l is the long double version; it takes a long double argument and returns a
long double result.
Return Value
On success, log10 (or log10l) returns the calculated value log base ten of x.
If the argument x passed to these functions is real and less than 0, the global
variable errno is set to

937
C Runtime Library Reference RAD Studio 3.1 Référence C++

modf, modfl ( see page 961) Header File


math.h
Category
Math Routines
Prototype
double modf(double x, double *ipart);
long double modfl(long double x, long double *ipart);
Description
Splits a double or long double into integer and fractional parts.
modf breaks the double x into two parts: the integer and the fraction. modf stores
the integer in ipart and returns the fraction.
modfl is the long double version; it takes long double arguments and returns a
long double result.
Return Value
modf and modfl return the fractional part of x.
Example
poly, polyl ( see page 962) Header File
math.h
Category
Math Routines
Prototype
double poly(double x, int degree, double coeffs[]);
long double polyl(long double x, int degree, long double
coeffs[]);
Description
Generates a polynomial from arguments.
poly generates a polynomial in x, of degree degree, with coefficients coeffs[0],
coeffs[1], ..., coeffs[degree]. For example, if n = 4, the generated polynomial is:
polyl is the long double version; it takes long double arguments and returns a
long double result.
Return Value
poly and polyl return the value of the polynomial as evaluated for the given x.
Example
pow, powl ( see page 963) Header File
math.h
Category
Math Routines
Prototype
double pow(double x, double y);
long double powl(long double x, long double y);
Description
Calculates x to the power of y.
powl is the long double version; it takes long double arguments and returns a
long double result.
Return Value
On success, pow and powl return the value calculated of x to the power of y.
Sometimes the arguments passed to these functions produce results that
overflow or are incalculable. When the correct value would overflow, the
functions return the value HUGE_VAL (pow) or _LHUGE_VAL (powl). Results of
excessively large magnitude can... suite ( see page 963)

938
3.1 Référence C++ RAD Studio C Runtime Library Reference

pow10, pow10l ( see page 964) Header File


math.h
Category
Math Routines
Prototype
double pow10(int p);
long double pow10l(int p);
Description
Calculates 10 to the power of p.
pow10l is the long double version; it takes long double arguments and returns
a long double result.
Return Value
On success, pow10 returns the value calculated, 10 to the power of p and
pow10l returns a long double result.
The result is actually calculated to long double accuracy. All arguments are
valid, although some can cause an underflow or overflow.
Example
sin, sinl ( see page 964) Header File
math.h
Category
Math Routines
Prototype
double sin(double x);
long double sinl(long double x);
Description
Calculates sine.
sin computes the sine of the input value. Angles are specified in radians.
sinl is the long double version; it takes a long double argument and returns a
long double result. Error handling for these functions can be modified through
the functions _matherr and _matherrl.
Return Value
sin and sinl return the sine of the input value.
Example
sinh, sinhl ( see page 965) Header File
math.h
Category
Math Routines, Inline Routines
Prototype
double sinh(double x);
long double sinhl(long double x);
Description
Calculates hyperbolic sine.
sinh computes the hyperbolic sine.
sinl is the long double version; it takes a long double argument and returns a
long double result. Error handling for sinh and sinhl can be modified through the
functions _matherr and _matherrl.
Return Value
sinh and sinhl return the hyperbolic sine of x.
When the correct value overflows, these functions return the value HUGE_VAL
(sinh) or _LHUGE_VAL (sinhl) of appropriate sign. Also, the global variable errno
is set to ERANGE.
Example

939
C Runtime Library Reference RAD Studio 3.1 Référence C++

sqrt, sqrtl ( see page 966) Header File


math.h
Category
Math Routines
Prototype
double sqrt(double x);
long double sqrtl(long double x);
Description
Calculates the positive square root.
sqrt calculates the positive square root of the argument x.
sqrtl is the long double version; it takes a long double argument and returns a
long double result. Error handling for these functions can be modified through
the functions _matherr and _matherrl.
Return Value
On success, sqrt and sqrtl return the value calculated, the square root of x. If x is
real and positive, the result is positive. If x is real and negative, the global
variable errno... suite ( see page 966)
tan, tanl ( see page 967) Header File
math.h
Category
Math Routines
Prototype
double tan(double x);
long double tanl(long double x);
Description
Calculates the tangent.
tan calculates the tangent. Angles are specified in radians.
tanl is the long double version; it takes a long double argument and returns a
long double result. Error handling for these routines can be modified through the
functions _matherr and _matherrl..
Return Value
tan and tanl return the tangent of x, sin(x)/cos(x).
Example
tanh, tanhl ( see page 967) Header File
math.h
Category
Math Routines
Prototype
double tanh(double x);
long double tanhl(long double x);
Description
Calculates the hyperbolic tangent.
tanh computes the hyperbolic tangent, sinh(x)/cosh(x).
tanhl is the long double version; it takes a long double argument and returns a
long double result. Error handling for these functions can be modified through
the functions _matherr and _matherrl.
Return Value
tanh and tanhl return the hyperbolic tangent of x.
Example

3.1.5.19.1 HUGE_VAL #defines


Header File
3
math.h

Description

Overflow value for math functions.

940
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.19.2 M_E, M_LOGxxx, M_LNxx #defines


Header File

math.h

Description

The constant values for logarithm functions.

Name Meaning
M_E The value of e
M_LOG2E The value of log(e)
M_LOG10E The value of log10(e)
M_LN2 The value of ln(2)
M_LN10 The value of ln(10)

3.1.5.19.3 M_SQRTxx #defines


Header File

math.h

Description

Constant values for square roots of 2.

Name Meaning
M_SQRT2 Square root of 2
M_SQRT_2 1/2 the square root of 2

3.1.5.19.4 PI constants
Header File

math.h

Description

Common constants of pi

Name Meaning
M_PI pi
M_PI_2 One-half pi
3
M_PI_4 One-fourth pi
M_1_PI One divided by pi
M_2_PI Two divided by pi
M_1_SQRTPI One divided by the square root of pi
M_2_SQRTPI Two divided by the square root of pi

941
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.19.5 atof, _wtof


Header File

stdlib.h, math.h

Category

Conversion Routines, Math Routines

Prototype
double atof(const char *s);
double _wtof(const wchar_t *s);

Description

Converts a string to a floating-point number.

• atof converts a string pointed to by s to double; this function recognizes the character representation of a floating-point
number, made up of the following:
• An optional string of tabs and spaces
• An optional sign
• A string of digits and an optional decimal point (the digits can be on both sides of the decimal point)
• An optional e or E followed by an optional signed integer
The characters must match this generic format:
[whitespace] [sign] [ddd] [.] [ddd] [e|E[sign]ddd]
atof also recognizes +INF and -INF for plus and minus infinity, and +NAN and -NAN for not-a-number.
In this function, the first unrecognized character ends the conversion.
The functions strtod and _strtold are similar to atof and provide better error detection, and hence are preferred in some
applications.
Return Value
Returns the converted value of the input string.
If there is an overflow, atof returns plus or minus HUGE_VAL (or _LHUGE_VAL), errno is set to ERANGE (Result out of range),
and _matherr (or _matherrl) is not called.

3.1.5.19.6 _atold, _wtold


Header File

math.h

Category
3 Conversion Routines, Math Routines

Prototype
long double _atold(const char *s);
long double _wtold(const wchar_t *s);

Description

Converts a string to a long double.

942
3.1 Référence C++ RAD Studio C Runtime Library Reference

_wtold is the wide-character version. It converts a wide-character string to a long double.

_atof is the floating-point version of _atold.

_atold converts a string pointed to by s to a long double; this functions recognizes:

An optional string of tabs and spaces

An optional sign

A string of digits and an optional decimal point

An optional e or E followed by an optional signed integer

The first unrecognized character ends the conversion. There are no provisions for overflow.

The functions strtod and _strtold are similar to atof and _atold; they provide better error detection, and hence are preferred in
some applications.

Return Value

Returns the converted value of the input string.

If there is an overflow, _atold returns plus or minus HUGE_VAL (or _LHUGE_VAL), errno is set to ERANGE (Result out of
range), and _matherr (or _matherrl) is not called.

Portability

POSIX Win32 ANSI C ANSI C++


_atold +
_wtold +

3.1.5.19.7 _i64toa, _i64tow


Header File

math.h, stdlib.h

Category

Conversion Routines, Math Routines,

Prototype
char *_i64toa(__int64 value, char *string, int radix);
wchar_t *_i64tow(__int64 value, wchar_t *string, int radix);

Description

_i64toa converts an __int64 to a string. _i64tow is the unicode version. It converts a __int64 to a wide-character string.

These functions convert value to a null-terminated string and store the result in string. value is an __int64.
3
radix specifies the base to be used in converting value; it must be between 2 and 36, inclusive. If value is negative and radix is
10, the first character of string is the minus sign (-).

Remarque: The space allocated for string must be large enough to hold the returned string, including the terminating null
character (\0). These functions can return up to 33 bytes.

Return Value

Returns a pointer to string.

943
C Runtime Library Reference RAD Studio 3.1 Référence C++

Portability

POSIX Win32 ANSI C ANSI C++


_i64toa +
_i64tow +

3.1.5.19.8 _matherr, _matherrl


Header File

math.h

Category

Diagnostic Routines, Math Routines

Prototype
int _matherr(struct _exception *e);
int _matherrl(struct _exceptionl *e);

Description

User-modifiable math error handler.

_matherr is called when an error is generated by the math library.

_matherrl is the long double version; it is called when an error is generated by the long double math functions.

_matherr and _matherrl each serve as a user hook (a function that can be customized by the user) that you can replace by
writing your own math error-handling routine.

_matherr and _matherrl are useful for information on trapping domain and range errors caused by the math functions. They do
not trap floating-point exceptions, such as division by zero. See signal for information on trapping such errors.

You can define your own _matherr or _matherrl routine to be a custom error handler (such as one that catches and resolves
certain types of errors); this customized function overrides the default version in the C library. The customized _matherr or
_matherrl should return 0 if it fails to resolve the error, or nonzero if the error is resolved. When _matherr or _matherrl return
nonzero, no error message is printed and the global variable errno is not changed.

Here are the _exception and _exceptionl structures (defined in math.h):


struct _exception {
int type;
char *name;
double arg1, arg2, retval;
};
3
struct _exceptionl {
int type;
char *name;
long double arg1, arg2, retval;
};

The members of the _exception and _exceptionl structures are shown in the following table:

944
3.1 Référence C++ RAD Studio C Runtime Library Reference

type The type of mathematical error that occurred; an enum type defined in the typedef _mexcep (see
definition after this list).
name A pointer to a null-terminated string holding the name of the math library function that resulted in an
error.
arg1, arg2 The arguments (passed to the function that name points to) caused the error; if only one argument
was passed to the function, it is stored in arg1.
retval The default return value for _matherr (or _matherrl); you can modify this value.

The typedef _mexcep, also defined in math.h, enumerates the following symbolic constants representing possible mathematical
errors:

DOMAIN Argument was not in domain of function, such as log(-1).


SING Argument would result in a singularity, such as pow(0, -2).
OVERFLOW Argument would produce a function result greater than DBL_MAX (or LDBL_MAX), such as
exp(1000).
UNDERFLOW Argument would produce a function result less than DBL_MIN (or LDBL_MIN), such as exp(-1000).
TLOSS Argument would produce function result with total loss of significant digits, such as sin(10e70).

The macros DBL_MAX, DBL_MIN, LDBL_MAX, and LDBL_MIN are defined in float.h

The source code to the default _matherr and _matherrl is on the C++Builder distribution disks.

The UNIX-style _matherr and _matherrl default behavior (printing a message and terminating) is not ANSI compatible. If you
want a UNIX-style version of these routines, use MATHERR.C and MATHERRL.C provided on the C++Builder distribution disks.

Example
#include <math.h>
#include <string.h>
#include <stdio.h>
int _matherr (struct _exception *a)
{
if (a->type == DOMAIN)
if (!strcmp(a->name,"sqrt")) {
a->retval = sqrt (-(a->arg1));
return 1;
}
return 0;
}
int main(void)
{
double x = -2.0, y;
y = sqrt(x);
printf("_Matherr corrected value: %lf\n",y);
return 0;
}

3.1.5.19.9 abs 3
Header File

stdlib.h, math.h

Category

Math Routines, Inline Routines

Prototype

945
C Runtime Library Reference RAD Studio 3.1 Référence C++

int abs(int x);

Description

Returns the absolute value of an integer.

abs returns the absolute value of the integer argument x. If abs is called when stdlib.h has been included, it's treated as a macro
that expands to inline code.

If you want to use the abs function instead of the macro, include

#undef abs

in your program, after the #include <stdlib.h>.

Return Value

The abs function returns an integer in the range of 0 to INT_MAX, with the exception that an argument with the value INT_MIN is
returned as INT_MIN. The values for INT_MAX and INT_MIN are defined in header file limit.h.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
int number = -1234;
printf("number: %d absolute value: %d\n", number, abs(number));
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.19.10 acos, acosl


Header File

math.h

Category

Math Routines

Prototype
double acos(double x);
long double acosl(long double x);

Description
3 Calculates the arc cosine.

acos returns the arc cosine of the input value.

acosl is the long double version; it takes a long double argument and returns a long double result.

Arguments to acos and acosl must be in the range -1 to 1, or else acos and acosl return NAN and set the global variable errno to:

EDOM Domain error

Return Value

946
3.1 Référence C++ RAD Studio C Runtime Library Reference

acos and acosl of an argument between -1 and +1 return a value in the range 0 to pi. Error handling for these routines can be
modified through the functions _matherr_matherr and _matherrl.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result;
double x = 0.5;
result = acos(x);
printf("The arc cosine of %lf is %lf\n", x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


acos + + + +
acosl + + +

3.1.5.19.11 asin, asinl


Header File

math.h

Category

Math Routines

Prototype
double asin(double x);
long double asinl(long double x);

Description

Calculates the arc sine.

asin of a real argument returns the arc sine of the input value.

asinl is the long double version; it takes a long double argument and returns a long double result.

Real arguments to asin and asinl must be in the range -1 to 1, or else asin and asinl return NAN and set the global variable errno
to

EDOM Domain error

Return Value

asin and asinl of a real argument return a value in the range -pi/2 to pi/2. Error handling for these functions may be modified 3
through the functions _matherr and _matherrl.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result;

947
C Runtime Library Reference RAD Studio 3.1 Référence C++

double x = 0.5;
result = asin(x);
printf("The arc sin of %lf is %lf\n", x, result);
return(0);
}
Portability

POSIX Win32 ANSI C ANSI C++


asin + + + +
asinl + + +

3.1.5.19.12 atan, atanl


Header File

math.h

Category

Math Routines

Prototype
double atan(double x);
long double atanl(long double x);

Description

Calculates the arc tangent.

atan calculates the arc tangent of the input value.

atanl is the long double version; it takes a long double argument and returns a long double result.

Return Value

atan and atanl of a real argument return a value in the range -pi/2 to pi/2. Error handling for these functions can be modified
through the functions _matherr and _matherrl.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result;
double x = 0.5;
result = atan(x);
printf("The arc tangent of %lf is %lf\n", x, result);
return(0);
}
3
Portability

POSIX Win32 ANSI C ANSI C++


atan + + + +
atanl + + +

948
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.19.13 atan2, atan2l


Header File

math.h

Category

Math Routines

Prototype
double atan2(double y, double x);
long double atan2l(long double y, long double x);

Description

Calculates the arc tangent of y/x.

atan2 returns the arc tangent of y/x; it produces correct results even when the resulting angle is near pi/2 or -pi/2 (x near 0). If
both x and y are set to 0, the function sets the global variable errno to EDOM, indicating a domain error.

atan2l is the long double version; it takes long double arguments and returns a long double result.

Return Value

atan2 and atan2l return a value in the range -pi to pi. Error handling for these functions can be modified through the functions
_matherr and _matherrl.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result;
double x = 90.0, y = 45.0;
result = atan2(y, x);
printf("The arc tangent ratio of %lf is %lf\n", (y / x), result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


atan2 + + + +
atan2l + + +

3.1.5.19.14 cabs, cabsl


Header File
3
math.h

Category

Math Routines

Prototype
double cabs(struct complex z);

949
C Runtime Library Reference RAD Studio 3.1 Référence C++

long double cabsl(struct _complexl z);

Description

cabs calculates the absolute value of a complex number. cabs is a macro that calculates the absolute value of z, a complex
number. z is a structure with type complex; the structure is defined in math.h as
struct complex {
double x, y;
};

where x is the real part, and y is the imaginary part.

Calling cabs is equivalent to calling sqrt with the real and imaginary components of z, as shown here:
sqrt(z.x * z.x + z.y * z.y)

cabsl is the long double version; it takes a structure with type _complexl as an argument, and returns a long double result. The
structure is defined in math.h as
struct _complexl {
long double x, y;
};

Return Value

cabs (or cabsl) returns the absolute value of z, a double. On overflow, cabs (or cabsl) returns HUGE_VAL (or _LHUGE_VAL)
and sets the global variable errno to

ERANGE Result out of range

Error handling for these functions can be modified through the functions _matherr and _matherrl.

Example
#include <stdio.h>
#include <math.h>
#ifdef __cplusplus
#include <complex.h>
#endif
#ifdef __cplusplus /* if C++, use class complex */
void print_abs(void)
{
complex<float> z(1.0, 2.0);
double absval;
absval = abs(z);
printf("The absolute value of %.2lfi %.2lfj is %.2lf",
real(z), imag(z), absval);
}
#else /* below function is for C (and not C++) */
void print_abs(void)
{
3 struct complex z;
double absval;
z.x = 2.0;
z.y = 1.0;
absval = cabs(z);
printf("The absolute value of %.2lfi %.2lfj is %.2lf",
z.x, z.y, absval);
}
#endif
int main(void)
{

950
3.1 Référence C++ RAD Studio C Runtime Library Reference

print_abs();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


cabs +
cabsl +

3.1.5.19.15 ceil, ceill


Header File

math.h

Category

Math Routines

Prototype
double ceil(double x);
long double ceill(long double x);

Description

Rounds up.

ceil finds the smallest integer not less than x.

ceill is the long double version; it takes a long double argument and returns a long double result.

Return Value

These functions return the integer found as a double (ceil) or a long double (ceill).

Example
#include <math.h>
#include <stdio.h>
int main(void)
{
double number = 123.54;
double down, up;
down = floor(number);
up = ceil(number);
printf("original number %5.2lf\n", number);
printf("number rounded down %5.2lf\n", down);
printf("number rounded up %5.2lf\n", up);
return 0;
}
3
Portability

POSIX Win32 ANSI C ANSI C++


ceil + + + +
ceill + + +

951
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.19.16 cos, cosl


Header File

math.h

Category

Math Routines, Inline Routines

Prototype
double cos(double x);
long double cosl(long double x);

Description

Calculates the cosine of a value.

cos computes the cosine of the input value. The angle is specified in radians.

cosl is the long double version; it takes a long double argument and returns a long double result.

Return Value

cos of a real argument returns a value in the range -1 to 1. Error handling for these functions can be modified through _matherr
(or _matherrl).

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result;
double x = 0.5;
result = cos(x);
printf("The cosine of %lf is %lf\n", x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


cos + + + +
cosl + + +

3.1.5.19.17 cosh, coshl


Header File
3
math.h

Category

Math Routines

Prototype
double cosh(double x);

952
3.1 Référence C++ RAD Studio C Runtime Library Reference

long double coshl(long double x);

Description

Calculates the hyperbolic cosine of a value.

cosh computes the hyperbolic cosine:

coshl is the long double version; it takes a long double argument and returns a long double result.

Return Value

cosh returns the hyperbolic cosine of the argument.

When the correct value would create an overflow, these functions return the value HUGE_VAL (cosh) or _LHUGE_VAL (coshl)
with the appropriate sign, and the global variable errno is set to ERANGE. Error handling for these functions can be modified
through the functions _matherr and _matherrl.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result;
double x = 0.5;
result = cosh(x);
printf("The hyperbolic cosine of %lf is %lf\n", x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


cosh + + + +
coshl + + +

3.1.5.19.18 exp, expl


Header File

math.h

Category

Math Routines

Prototype
double exp(double x);
long double expl(long double x);

Description 3
Calculates the exponential e to the x.

expl is the long double version; it takes a long double argument and returns a long double result.

Return Value

exp returns e to the x.

Sometimes the arguments passed to these functions produce results that overflow or are incalculable. When the correct value

953
C Runtime Library Reference RAD Studio 3.1 Référence C++

overflows, exp returns the value HUGE_VAL and expl returns _LHUGE_VAL. Results of excessively large magnitude cause the
global variable errno to be set to

ERANGE Result out of range

On underflow, these functions return 0.0, and the global variable errno is not changed. Error handling for these functions can be
modified through the functions _matherr and _matherrl.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result;
double x = 4.0;
result = exp(x);
printf("'e' raised to the power \
of %lf (e ^ %lf) = %lf\n",
x, x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


exp + + + +
expl + + +

3.1.5.19.19 fabs, fabsl


Header File

math.h

Category

Math Routines

Prototype
double fabs(double x);
long double fabsl(long double x);

Description

Returns the absolute value of a floating-point number.

fabs calculates the absolute value of x, a double. fabsl is the long double version; it takes a long double argument and returns
a long double result.
3
Return Value

fabs and fabsl return the absolute value of x.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{

954
3.1 Référence C++ RAD Studio C Runtime Library Reference

float number = -1234.0;

printf("number: %f absolute value: %f\n", number, fabs(number));


return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


fabs + + + +
fabsl + + +

3.1.5.19.20 floor, floorl


Header File

math.h

Category

Math Routines

Prototype
double floor(double x);
long double floorl(long double x);

Description

Rounds down.

floor finds the largest integer not greater than x.

floorl is the long double version; it takes a long double argument and returns a long double result.

Return Value

floor returns the integer found as a double. floorl returns the integer found as a long double.

Portability

POSIX Win32 ANSI C ANSI C++


floor + + + +
floorl + + +

3.1.5.19.21 fmod, fmodl


Header File
3
math.h

Category

Math Routines

Prototype
double fmod(double x, double y);

955
C Runtime Library Reference RAD Studio 3.1 Référence C++

long double fmodl(long double x, long double y);

Description

Calculates x modulo y, the remainder of x/y.

fmod calculates x modulo y (the remainder f, where x = ay + f for some integer a, and 0 < f < y).

fmodl is the long double version; it takes long double arguments and returns a long double result.

Return Value

fmod and fmodl return the remainder f where x = ay + f (as described above). When y = 0, fmod and fmodl return 0.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double x = 5.0, y = 2.0;
double result;
result = fmod(x,y);
printf("The remainder of (%lf / %lf) is %lf\n", x, y, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


fmod + + + +
fmodl + + +

3.1.5.19.22 frexp, frexpl


Header File

math.h

Category

Math Routines

Prototype
double frexp(double x, int *exponent);
long double frexpl(long double x, int *exponent);

Description

Splits a number into mantissa and exponent.

3 frexp calculates the mantissa m (a double greater than or equal to 0.5 and less than 1) and the integer value n such that x (the
original double value) equals m * 2n. frexp stores n in the integer that exponent points to.

frexpl is the long double version; it takes a long double argument for x and returns a long double result.

Return Value

frexp and frexpl return the mantissa m. Error handling for these routines can be modified through the functions _matherr and
_matherrl.

Example

956
3.1 Référence C++ RAD Studio C Runtime Library Reference

#include <math.h>
#include <stdio.h>
int main(void)
{
double mantissa, number;
int exponent;
number = 8.0;
mantissa = frexp(number, &exponent);
printf("The number %lf is ", number);
printf("%lf times two to the ", mantissa);
printf("power of %d\n", exponent);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


frexp + + + +
frexpl + + +

3.1.5.19.23 hypot, hypotl


Header File

math.h

Category

Math Routines

Prototype
double hypot(double x, double y);
long double hypotl(long double x, long double y);

Description

Calculates hypotenuse of a right triangle.

hypot calculates the value z where

z2 = x2 + y2 and z >= 0

This is equivalent to the length of the hypotenuse of a right triangle, if the lengths of the two sides are x and y.

hypotl is the long double version; it takes long double arguments and returns a long double result.

Return Value

On success, these functions return z, a double (hypot) or a long double) (hypotl). On error (such as an overflow), they set the
global variable errno to

ERANGE Result out of range


3

and return the value HUGE_VAL (hypot) or _LHUGE_VAL) (hypotl). Error handling for these routines can be modified through
the functions _matherr and _matherrl.

Example
#include <stdio.h>
#include <math.h>

957
C Runtime Library Reference RAD Studio 3.1 Référence C++

int main(void)
{
double result;
double x = 3.0;
double y = 4.0;
result = hypot(x, y);
printf("The hypotenuse is: %lf\n", result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


hypot + + +
hypotl + + +

3.1.5.19.24 ldexp, ldexpl


Header File

math.h

Category

Math Routines

Prototype
double ldexp(double x, int exp);
long double ldexpl(long double x, int exp);

Description

Calculates x * 2^exp.

lexpl is the long double version; it takes a long double argument for x and returns a long double result.

Return Value

On success, ldexp (or ldexpl) returns the value it calculated, x * 2^exp. Error handling for these routines can be modified through
the functions _matherr and _matherrl.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double value;
double x = 2;
/* ldexp raises 2 by a power of 3
then multiplies the result by 2 */
3 value = ldexp(x,3);
printf("The ldexp value is: %lf\n", value);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


ldexp + + + +

958
3.1 Référence C++ RAD Studio C Runtime Library Reference

ldexpl + + +

3.1.5.19.25 ldiv
Header File

math.h

Category

Math Routines

Prototype
ldiv_t ldiv(long int numer, long int denom);

Description

Divides two longs, returning quotient and remainder.

ldiv divides two longs and returns both the quotient and the remainder as an ldiv_t type. numer and denom are the numerator
and denominator, respectively.

The ldiv_t type is a structure of longs defined in stdlib.h as follows:


typedef struct {
long int quot; /* quotient */
long int rem; /* remainder */
} ldiv_t;

Return Value

ldiv returns a structure whose elements are quot (the quotient) and rem (the remainder).

Example
/* ldiv example */
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
ldiv_t lx;
lx = ldiv(100000L, 30000L);
printf("100000 div 30000 = %ld remainder %ld\n", lx.quot, lx.rem);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + + 3

3.1.5.19.26 log, logl


Header File

math.h

959
C Runtime Library Reference RAD Studio 3.1 Référence C++

Category

Math Routines

Prototype
double log(double x);
long double logl(long double x);

Description

Calculates the natural logarithm of x.

log calculates the natural logarithm of x.

logl is the long double version; it takes a long double argument and returns a long double result.

Return Value

On success, log and logl return the value calculated, ln(x).

errno

EDOM Domain error

If x is 0, the functions return the value negative HUGE_VAL (log) or negative _LHUGE_VAL (logl), and set errno to ERANGE.
Error handling for these routines can be modified through the functions _matherr and _matherrl.

Example
#include <math.h>
#include <stdio.h>
int main(void)
{
double result;
double x = 8.6872;
result = log(x);
printf("The natural log of %lf is %lf\n", x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


log + + + +
logl + + +

3.1.5.19.27 log10, log10l


Header File
3 math.h

Category

Math Routines

Prototype
double log10(double x);
long double log10l(long double x);

960
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

log10 calculates the base ten logarithm of x.

log10l is the long double version; it takes a long double argument and returns a long double result.

Return Value

On success, log10 (or log10l) returns the calculated value log base ten of x.

If the argument x passed to these functions is real and less than 0, the global variable errno is set to

EDOM Domain error

If x is 0, these functions return the value negative HUGE_VAL (log10) or _LHUGE_VAL (log10l). Error handling for these
routines can be modified through the functions _matherr and _matherrl.

Example
#include <math.h>
#include <stdio.h>
int main(void)
{
double result;
double x = 800.6872;
result = log10(x);
printf("The common log of %lf is %lf\n", x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


log10 + + + +
log10l + + +

3.1.5.19.28 modf, modfl


Header File

math.h

Category

Math Routines

Prototype
double modf(double x, double *ipart);
long double modfl(long double x, long double *ipart);

Description 3
Splits a double or long double into integer and fractional parts.

modf breaks the double x into two parts: the integer and the fraction. modf stores the integer in ipart and returns the fraction.

modfl is the long double version; it takes long double arguments and returns a long double result.

Return Value

modf and modfl return the fractional part of x.

961
C Runtime Library Reference RAD Studio 3.1 Référence C++

Example
#include <math.h>
#include <stdio.h>
int main(void)
{
double fraction, integer;
double number = 100000.567;
fraction = modf(number, &integer);
printf("The whole and fractional parts of %lf are %lf and %lf\n",
number, integer, fraction);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


modf + + + +
modfl + + +

3.1.5.19.29 poly, polyl


Header File

math.h

Category

Math Routines

Prototype
double poly(double x, int degree, double coeffs[]);
long double polyl(long double x, int degree, long double coeffs[]);

Description

Generates a polynomial from arguments.

poly generates a polynomial in x, of degree degree, with coefficients coeffs[0], coeffs[1], ..., coeffs[degree]. For example, if n = 4,
the generated polynomial is:

polyl is the long double version; it takes long double arguments and returns a long double result.

Return Value

poly and polyl return the value of the polynomial as evaluated for the given x.

Example
#include <stdio.h>
#include <math.h>
3 /* polynomial: x**3 - 2x**2 + 5x - 1 */
int main(void)
{
double array[] = { -1.0, 5.0, -2.0, 1.0
};
double result;
result = poly(2.0, 3, array);
printf("The polynomial: x**3 - 2.0x**2 + 5x - 1 at 2.0 is %lf\n", result);
return 0;
}

962
3.1 Référence C++ RAD Studio C Runtime Library Reference

Portability

POSIX Win32 ANSI C ANSI C++


poly +
polyl +

3.1.5.19.30 pow, powl


Header File

math.h

Category

Math Routines

Prototype
double pow(double x, double y);
long double powl(long double x, long double y);

Description

Calculates x to the power of y.

powl is the long double version; it takes long double arguments and returns a long double result.

Return Value

On success, pow and powl return the value calculated of x to the power of y.

Sometimes the arguments passed to these functions produce results that overflow or are incalculable. When the correct value
would overflow, the functions return the value HUGE_VAL (pow) or _LHUGE_VAL (powl). Results of excessively large
magnitude can cause the global variable errno to be set to

ERANGE Result out of range

If the argument x passed to pow or powl is real and less than 0, and y is not a whole number, or if x is 0 and y is less than 0, or
you call pow(0,0), the global variable errno is set to

EDOM Domain error

Error handling for these functions can be modified through the functions _matherr and _matherrl.

Example
#include <math.h>
#include <stdio.h>
int main(void)
{ 3
double x = 2.0, y = 3.0;
printf("%lf raised to %lf is %lf\n", x, y, pow(x, y));
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


pow + + + +

963
C Runtime Library Reference RAD Studio 3.1 Référence C++

powl + + +

3.1.5.19.31 pow10, pow10l


Header File

math.h

Category

Math Routines

Prototype
double pow10(int p);
long double pow10l(int p);

Description

Calculates 10 to the power of p.

pow10l is the long double version; it takes long double arguments and returns a long double result.

Return Value

On success, pow10 returns the value calculated, 10 to the power of p and pow10l returns a long double result.

The result is actually calculated to long double accuracy. All arguments are valid, although some can cause an underflow or
overflow.

Example
#include <math.h>
#include <stdio.h>
int main(void)
{
double p = 3.0;
printf("Ten raised to %lf is %lf\n", p, pow10(p));
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


pow10 +
pow10l +

3.1.5.19.32 sin, sinl


3
Header File

math.h

Category

Math Routines

Prototype

964
3.1 Référence C++ RAD Studio C Runtime Library Reference

double sin(double x);


long double sinl(long double x);

Description

Calculates sine.

sin computes the sine of the input value. Angles are specified in radians.

sinl is the long double version; it takes a long double argument and returns a long double result. Error handling for these
functions can be modified through the functions _matherr and _matherrl.

Return Value

sin and sinl return the sine of the input value.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result, x = 0.5;
result = sin(x);
printf("The sin of %lf is %lf\n", x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


sin + + + +
sinl + + +

3.1.5.19.33 sinh, sinhl


Header File

math.h

Category

Math Routines, Inline Routines

Prototype
double sinh(double x);
long double sinhl(long double x);

Description

Calculates hyperbolic sine. 3


sinh computes the hyperbolic sine.

sinl is the long double version; it takes a long double argument and returns a long double result. Error handling for sinh and
sinhl can be modified through the functions _matherr and _matherrl.

Return Value

sinh and sinhl return the hyperbolic sine of x.

965
C Runtime Library Reference RAD Studio 3.1 Référence C++

When the correct value overflows, these functions return the value HUGE_VAL (sinh) or _LHUGE_VAL (sinhl) of appropriate
sign. Also, the global variable errno is set to ERANGE.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result, x = 0.5;
result = sinh(x);
printf("The hyperbolic sin of %lf is %lf\n", x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


sinh + + + +
sinhl + + +

3.1.5.19.34 sqrt, sqrtl


Header File

math.h

Category

Math Routines

Prototype
double sqrt(double x);
long double sqrtl(long double x);

Description

Calculates the positive square root.

sqrt calculates the positive square root of the argument x.

sqrtl is the long double version; it takes a long double argument and returns a long double result. Error handling for these
functions can be modified through the functions _matherr and _matherrl.

Return Value

On success, sqrt and sqrtl return the value calculated, the square root of x. If x is real and positive, the result is positive. If x is
real and negative, the global variable errno is set to

EDOM Domain error


3
Example
#include <math.h>
#include <stdio.h>
int main(void)
{
double x = 4.0, result;
result = sqrt(x);
printf("The square root of %lf is %lf\n", x, result);

966
3.1 Référence C++ RAD Studio C Runtime Library Reference

return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


sqrt + + + +
sqrtl + + +

3.1.5.19.35 tan, tanl


Header File

math.h

Category

Math Routines

Prototype
double tan(double x);
long double tanl(long double x);

Description

Calculates the tangent.

tan calculates the tangent. Angles are specified in radians.

tanl is the long double version; it takes a long double argument and returns a long double result. Error handling for these
routines can be modified through the functions _matherr and _matherrl..

Return Value

tan and tanl return the tangent of x, sin(x)/cos(x).

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result, x;
x = 0.5;
result = tan(x);
printf("The tan of %lf is %lf\n", x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++ 3


tan + + + +
tanl + + +

3.1.5.19.36 tanh, tanhl


Header File

967
C Runtime Library Reference RAD Studio 3.1 Référence C++

math.h

Category

Math Routines

Prototype
double tanh(double x);
long double tanhl(long double x);

Description

Calculates the hyperbolic tangent.

tanh computes the hyperbolic tangent, sinh(x)/cosh(x).

tanhl is the long double version; it takes a long double argument and returns a long double result. Error handling for these
functions can be modified through the functions _matherr and _matherrl.

Return Value

tanh and tanhl return the hyperbolic tangent of x.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
double result, x;
x = 0.5;
result = tanh(x);
printf("The hyperbolic tangent of %lf is %lf\n", x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


tanh + + + +
tanhl + + +

3.1.5.20 mem.h
The following functions, macros, and classes are provided in mem.h:

968
3.1 Référence C++ RAD Studio C Runtime Library Reference

Rubriques
Nom Description
memccpy ( see page 971) Header File
mem.h, string.h
Category
Memory and String Manipulation Routines
Prototype
void *memccpy(void *dest, const void *src, int c, size_t n);
Description
Copies a block of n bytes.
memccpy is available on UNIX System V systems.
memccpy copies a block of n bytes from src to dest. The copying stops as soon
as either of the following occurs:

• The character c is first copied into dest.


• n bytes have been copied into dest.
Return Value
memccpy returns a pointer to the byte in dest immediately
following c, if c was copied; otherwise, memccpy returns
NULL.
Example
memchr, _wmemchr ( see page 972) Header File
mem.h, string.h
Category
Memory and String Manipulation Routines, Inline Routines, C++ Prototyped
Routines
Prototype
void *memchr(const void s, int c, size_t n);/ C only */
const void *memchr(const void *s, int c, size_t n);// C++
only
void *memchr(void *s, int c, size_t n);// C++ only
void *memchr(const void s, int c, size_t n);/ C and C++ */
void * _wmemchr(void s, int c, size_t n);/ unicode version
*/
Description
Searches n bytes for character c.
memchr is available on UNIX System V systems.
memchr searches the first n bytes of the block pointed to by s for... suite ( see
page 972)
memcmp ( see page 973) Header File
mem.h, string.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
int memcmp(const void *s1, const void *s2, size_t n);
Description
Compares two blocks for a length of exactly n bytes.
memcmp is available on UNIX System V systems.
memcmp compares the first n bytes of the blocks s1 and s2 as unsigned chars.
Return Value
Because it compares bytes as unsigned chars, memcmp returns a value that is
3
• < 0 if s1 is less than s2
• = 0 if s1 is the same as s2
• > 0 if s1 is greater than s2
For... suite ( see page 973)

969
C Runtime Library Reference RAD Studio 3.1 Référence C++

memcpy, _wmemcpy ( see page 974) Header File


mem.h, string.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
void *memcpy(void *dest, const void *src, size_t n);
void *_wmemcpy(void *dest, const void *src, size_t n);
Description
Copies a block of n bytes.
memcpy is available on UNIX System V systems.
memcpy copies a block of n bytes from src to dest. If src and dest overlap, the
behavior of memcpy is undefined.
Return Value
memcpy returns dest.
Example
memicmp ( see page 974) Header File
mem.h, string.h
Category
Memory and String Manipulation Routines
Prototype
int memicmp(const void *s1, const void *s2, size_t n);
Description
Compares n bytes of two character arrays, ignoring case.
memicmp is available on UNIX System V systems.
memicmp compares the first n bytes of the blocks s1 and s2, ignoring character
case (upper or lower).
Return Value
memicmp returns a value that is

• < 0 if s1 is less than s2


• = 0 if s1 is the same as s2
• > 0 if s1 is greater than s2
Example
memmove ( see page 975) Header File
mem.h, string.h
Category
Memory and String Manipulation Routines
Prototype
void *memmove(void *dest, const void *src, size_t n);
Description
Copies a block of n bytes.
memmove copies a block of n bytes from src to dest. Even when the source and
destination blocks overlap, bytes in the overlapping locations are copied correctly.
Return Value
memmove returns dest.
Example
memset, _wmemset ( see page 976) Header File
mem.h, string.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
void *memset(void *s, int c, size_t n);
3 void *_wmemset(void *s, int c, size_t n);
Description
Sets n bytes of a block of memory to byte c.
memset sets the first n bytes of the array s to the character c.
Return Value
memset returns s.
Example

970
3.1 Référence C++ RAD Studio C Runtime Library Reference

setmem ( see page 977) Header File


mem.h
Category
Memory and String Manipulation Routines
Prototype
void setmem(void *dest, unsigned length, char value);
Description
Assigns a value to a range of memory.
setmem sets a block of length bytes, pointed to by dest, to the byte value.
Return Value
None.
Example

3.1.5.20.1 memccpy
Header File

mem.h, string.h

Category

Memory and String Manipulation Routines

Prototype
void *memccpy(void *dest, const void *src, int c, size_t n);

Description

Copies a block of n bytes.

memccpy is available on UNIX System V systems.

memccpy copies a block of n bytes from src to dest. The copying stops as soon as either of the following occurs:

• The character c is first copied into dest.


• n bytes have been copied into dest.
Return Value
memccpy returns a pointer to the byte in dest immediately following c, if c was copied; otherwise, memccpy returns NULL.
Example
#include <string.h>
#include <stdio.h>
int main(void)
{
char *src = "This is the source string";
char dest[50];
char *ptr;
ptr = (char *) memccpy(dest, src, 'c', strlen(src));
if (ptr)
{
*ptr = '\0';
printf("The character was found: %s\n", dest); 3
}
else
printf("The character wasn't found\n");
return 0;
}
Portability

971
C Runtime Library Reference RAD Studio 3.1 Référence C++

POSIX Win32 ANSI C ANSI C++


+

3.1.5.20.2 memchr, _wmemchr


Header File

mem.h, string.h

Category

Memory and String Manipulation Routines, Inline Routines, C++ Prototyped Routines

Prototype
void *memchr(const void s, int c, size_t n);/ C only */
const void *memchr(const void *s, int c, size_t n);// C++ only
void *memchr(void *s, int c, size_t n);// C++ only
void *memchr(const void s, int c, size_t n);/ C and C++ */
void * _wmemchr(void s, int c, size_t n);/ unicode version */

Description

Searches n bytes for character c.

memchr is available on UNIX System V systems.

memchr searches the first n bytes of the block pointed to by s for character c.

Return Value

On success, memchr returns a pointer to the first occurrence of c in s; otherwise, it returns NULL.

Remarque: If you are using the intrinsic version of these functions, the case of n = 0 will return NULL.

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
char str[17];
char *ptr;
strcpy(str, "This is a string");
ptr = (char *) memchr(str, 'r', strlen(str));
if (ptr)
printf("The character 'r' is at position: %d\n", ptr - str);
else
printf("The character was not found\n");
3 return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


memchr + + + +
_wmemchr +

972
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.20.3 memcmp
Header File

mem.h, string.h

Category

Memory and String Manipulation Routines, Inline Routines

Prototype
int memcmp(const void *s1, const void *s2, size_t n);

Description

Compares two blocks for a length of exactly n bytes.

memcmp is available on UNIX System V systems.

memcmp compares the first n bytes of the blocks s1 and s2 as unsigned chars.

Return Value

Because it compares bytes as unsigned chars, memcmp returns a value that is

• < 0 if s1 is less than s2


• = 0 if s1 is the same as s2
• > 0 if s1 is greater than s2
For example,
memcmp(“\xFF”, “\x7F”, 1)
returns a value greater than 0.
Remarque: If you are using the intrinsic version of these functions, the case of n = 0 will return NULL.
Example
#include <stdio.h>
#include <string.h>
int main(void)
{
char *buf1 = "aaa";
char *buf2 = "bbb";
char *buf3 = "ccc";
int stat;
stat = memcmp(buf2, buf1, strlen(buf2));
if (stat > 0)
printf("buffer 2 is greater than buffer 1\n");
else
printf("buffer 2 is less than buffer 1\n");
stat = memcmp(buf2, buf3, strlen(buf2));
if (stat > 0)
printf("buffer 2 is greater than buffer 3\n"); 3
else
printf("buffer 2 is less than buffer 3\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

973
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.20.4 memcpy, _wmemcpy


Header File

mem.h, string.h

Category

Memory and String Manipulation Routines, Inline Routines

Prototype
void *memcpy(void *dest, const void *src, size_t n);
void *_wmemcpy(void *dest, const void *src, size_t n);

Description

Copies a block of n bytes.

memcpy is available on UNIX System V systems.

memcpy copies a block of n bytes from src to dest. If src and dest overlap, the behavior of memcpy is undefined.

Return Value

memcpy returns dest.

Example
#include <stdio.h>
#include <string.h>
int main(void)
{
char src[] = "******************************";
char dest[] = "abcdefghijlkmnopqrstuvwxyz0123456709";
char *ptr;
printf("destination before memcpy: %s\n", dest);
ptr = (char *) memcpy(dest, src, strlen(src));
if (ptr)
printf("destination after memcpy: %s\n", dest);
else
printf("memcpy failed\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


memcpy + + + +
_wmemcpy +

3
3.1.5.20.5 memicmp
Header File

mem.h, string.h

Category

Memory and String Manipulation Routines

974
3.1 Référence C++ RAD Studio C Runtime Library Reference

Prototype
int memicmp(const void *s1, const void *s2, size_t n);

Description

Compares n bytes of two character arrays, ignoring case.

memicmp is available on UNIX System V systems.

memicmp compares the first n bytes of the blocks s1 and s2, ignoring character case (upper or lower).

Return Value

memicmp returns a value that is

• < 0 if s1 is less than s2


• = 0 if s1 is the same as s2
• > 0 if s1 is greater than s2
Example
#include <stdio.h>
#include <string.h>
int main(void)
{
char *buf1 = "ABCDE123";
char *buf2 = "abcde456";
int stat;
stat = memicmp(buf1, buf2, 5);
printf("The strings to position 5 are ");
if (stat)
printf("not ");
printf("the same\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.20.6 memmove
Header File

mem.h, string.h

Category

Memory and String Manipulation Routines

Prototype
3
void *memmove(void *dest, const void *src, size_t n);

Description

Copies a block of n bytes.

memmove copies a block of n bytes from src to dest. Even when the source and destination blocks overlap, bytes in the
overlapping locations are copied correctly.

975
C Runtime Library Reference RAD Studio 3.1 Référence C++

Return Value

memmove returns dest.

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
char *dest = "abcdefghijklmnopqrstuvwxyz0123456789";
char *src = "******************************";
printf("destination prior to memmove: %s\n", dest);
memmove(dest, src, 26);
printf("destination after memmove: %s\n", dest);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


memmove + + + +
_fmemmove

3.1.5.20.7 memset, _wmemset


Header File

mem.h, string.h

Category

Memory and String Manipulation Routines, Inline Routines

Prototype
void *memset(void *s, int c, size_t n);
void *_wmemset(void *s, int c, size_t n);

Description

Sets n bytes of a block of memory to byte c.

memset sets the first n bytes of the array s to the character c.

Return Value

memset returns s.

Example
#include <string.h>
3 #include <stdio.h>
#include <mem.h>
int main(void)
{
char buffer[] = "Hello world\n";
printf("Buffer before memset: %s\n", buffer);
memset(buffer, '*', strlen(buffer) - 1);
printf("Buffer after memset: %s\n", buffer);
return 0;
}

976
3.1 Référence C++ RAD Studio C Runtime Library Reference

Portability

POSIX Win32 ANSI C ANSI C++


memset + + + +
_wmemset +

3.1.5.20.8 setmem
Header File

mem.h

Category

Memory and String Manipulation Routines

Prototype
void setmem(void *dest, unsigned length, char value);

Description

Assigns a value to a range of memory.

setmem sets a block of length bytes, pointed to by dest, to the byte value.

Return Value

None.

Example
#include <stdio.h>
#include <alloc.h>
#include <mem.h>
int main(void)
{
char *dest;
dest = (char *) calloc(21, sizeof(char));
setmem(dest, 20, 'c');
printf("%s\n", dest);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.21 new.h 3
The following functions, macros, and classes are provided in new.h:

977
C Runtime Library Reference RAD Studio 3.1 Référence C++

Rubriques
Nom Description
_new_handler ( see page 978) Header File
new.h
Syntax
typedef void (*pvf)();
pvf _new_handler;
Description
_new_handler contains a pointer to a function that takes no arguments and
returns void. If operator new() is unable to allocate the space required, it will call
the function pointed to by _new_handler; if that function returns it will try the
allocation again. By default, the function pointed to by _new_handler simply
terminates the application. The application can replace this handler, however,
with a function that can try to free up some space. This is done by assigning
directly to _new_handler or by calling the function set_new_handler, which
returns... suite ( see page 978)
set_new_handler function ( see page 979) Header File
new.h
Category
Memory Routines
Syntax
typedef void (new * new_handler)();
new_handler set_new_handler(new_handler my_handler);
Description
set_new_handler installs the function to be called when the global operator new
or operator new[]() cannot allocate the requested memory. By default the new
operators throw an bad_alloc exception if memory cannot be allocated. You can
change this default behavior by calling set_new_handler to set a new handler. To
retain the traditional version of new, which does not throw exceptions, you can
use set_new_handler(0).
If new cannot allocate the requested memory, it calls the handler that was set by
a previous call to set_new_handler.... suite ( see page 979)

3.1.5.21.1 _new_handler
Header File

new.h

Syntax
typedef void (*pvf)();
pvf _new_handler;

Description

_new_handler contains a pointer to a function that takes no arguments and returns void. If operator new() is unable to allocate
the space required, it will call the function pointed to by _new_handler; if that function returns it will try the allocation again. By
default, the function pointed to by _new_handler simply terminates the application. The application can replace this handler,
however, with a function that can try to free up some space. This is done by assigning directly to _new_handler or by calling the
function set_new_handler, which returns a pointer to the former handler.

3 As an alternative, you can set using the function set_new_handler, like this:
pvf set_new_handler(pvf p);

_new_handler is provided primarily for compatibility with C++ version 1.2. In most cases this functionality can be better provided
by overloading operator new().

Example

978
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.21.2 set_new_handler function


Header File

new.h

Category

Memory Routines

Syntax
typedef void (new * new_handler)();
new_handler set_new_handler(new_handler my_handler);

Description

set_new_handler installs the function to be called when the global operator new or operator new[]() cannot allocate the
requested memory. By default the new operators throw an bad_alloc exception if memory cannot be allocated. You can change
this default behavior by calling set_new_handler to set a new handler. To retain the traditional version of new, which does not
throw exceptions, you can use set_new_handler(0).

If new cannot allocate the requested memory, it calls the handler that was set by a previous call to set_new_handler. If there is
no handler installed by set_new_handler, new returns 0. my_handler should specify the actions to be taken when new cannot
satisfy a request for memory allocation. The new_handler type, defined in new.h, is a function that takes no arguments and
returns void. A new_handler can throw a bad_alloc exception.

• The user-defined my_handler should do one of the following:


• return after freeing memory
• throw an bad_alloc exception or an exception derived from bad_alloc
• call abort or exit functions
If my_handler returns, then new will again attempt to satisfy the request.
Ideally, my_handler would free up memory and return. new would then be able to satisfy the request and the program would
continue. However, if my_handler cannot provide memory for new, my_handler must throw an exception or terminate the
program. Otherwise, an infinite loop will be created.
Preferably, you should overload operator new() and operator new[]() to take appropriate actions for your applications.
Return Value
set_new_handler returns the old handler, if one has been registered.
The user-defined argument function, my_handler, should not return a value.
Example
#include <iostream>
#include <new.h>
#include <stdlib.h>
using std::cout;
using std::hex; 3
void mem_warn() {
std::cerr << "\nCan't allocate!";
exit(1);
}

void main(void) {
std::set_new_handler(mem_warn);
char *ptr = new char[100];
cout << "\nFirst allocation: ptr = " << hex << long(ptr);
ptr = new char[64000U];

979
C Runtime Library Reference RAD Studio 3.1 Référence C++

cout << "\nFinal allocation: ptr = " << hex << long(ptr);
std::set_new_handler(0); // Reset to default.
}

3.1.5.22 process.h
The following functions, macros, and classes are provided in process.h:

Rubriques
Nom Description
P_xxxx #defines ( see page 984) Header File
process.h
Description
Modes used by the spawn... functions.
_adopt_thread ( see page 984) Header File
process.h
Category
Process Control Routines
Prototype
_PTHREAD_ADOPTION_DATA _adopt_thread(void (_USERENTRY
*__start_address)(void *), void * __arglist, int free_flag
);
Description
“Adopts” a thread, created with the Windows API CreateThread function, to the
C++Builder RTL by hooking up the necessary internal data (exceptions, stack
info, and so forth). _adopt_thread thereby allows the RTL to handle exception
issues in that thread. The execution path of this thread is then transferred to
another function (the adoptive thread function). From the RTL's perspective,
during the execution of this adoptive thread function, the thread appears as if it
had been created by a call to... suite ( see page 984)
_beginthread ( see page 985) Header File
process.h
Category
Process Control Routines
Prototype
unsigned long _beginthread(void (_USERENTRY *__start)(void
*), unsigned __stksize, void *__arg);
Description
Starts execution of a new thread.
Remarque: The start_address must be declared to be _USERENTRY.
The _beginthread function creates and starts a new thread. The thread starts
execution at start_address.
The size of its stack in bytes is stack_size; the stack is allocated by the operating
system after the stack size is rounded up to the next multiple of 4096. The thread
is passed arglist as its only parameter; it can be NULL, but must be present. The
thread function should... suite ( see page 985)
_beginthreadNT ( see page 987) Header File
process.h
Category
Process Control Routines
Prototype
unsigned long _beginthreadNT(void (_USERENTRY
*start_address)(void *), unsigned stack_size, void
*arglist, void *security_attrib, unsigned long
3 create_flags, unsigned long *thread_id);
Description
Starts execution of a new thread under Windows NT.
Remarque: The start_address must be declared to be _USERENTRY.
All multithread Windows NT programs must use _beginthreadNT or the
_beginthread function instead of the operating system thread-creation API
function because these functions perform initialization required for correct
operation of the runtime library functions. The _beginthreadNT function provides
support for the operating system security. These functions are available only in
the multithread libraries.
The _beginthreadNT... suite ( see page 987)

980
3.1 Référence C++ RAD Studio C Runtime Library Reference

_beginthreadex ( see page 989) Header File


process.h
Category
Process Control Routines
Prototype
unsigned long _beginthreadex(void *__security_attr,
unsigned __stksize, unsigned (__stdcall *__start)(void *),
void *__arg, unsigned __create_flags, unsigned
*__thread_id);
Description
Creates a thread and allows specifying the other parameters of the OS API
CreateThread (such as security and thread creation flags). The _endthreadex
function will be called automatically when the thread function terminates. The
value returned from your thread function will be passed along to _endthreadex,
which in turn will pass it along to the ExitThread API. The return value can then
be retrieved using the GetExitCodeThread API.
Unlike _endthread, the _endthreadex function does not... suite ( see page
989)
_c_exit ( see page 990) Header File
process.h
Category
Process Control Routines
Prototype
void _c_exit(void);
Description
Performs _exit cleanup without terminating the program.
_c_exit performs the same cleanup as _exit, except that it does not terminate the
calling process.
Return Value
None.
Example
_cexit ( see page 991) Header File
process.h
Category
Process Control Routines
Prototype
void _cexit(void);
Description
Performs exit cleanup without terminating the program.
_cexit performs the same cleanup as exit, closing all files but without terminating
the calling process. The _cexit function calls any registered "exit functions"
(posted with atexit). Before _cexit returns, it flushes all input/output buffers and
closes all streams that were open.
Return Value
None.
Example
_endthread ( see page 992) Header File
process.h
Category
Process Control Routines
Prototype
void _endthread(void);
Description
Terminates execution of a thread.
The _endthread function terminates the currently executing thread by closing the
thread handle and calling the ExitThread API. The thread must have been started
by an earlier call to _beginthread or _beginthreadNT.. _endthread is called
3
automatically by the runtime library when your thread function terminates.
This function is available in the multithread libraries; it is not in the
single-threaded libraries.
Return Value
The function does not return a value.

981
C Runtime Library Reference RAD Studio 3.1 Référence C++

_endthreadex ( see page 993) Header File


process.h
Category
Process Control Routines
Prototype
void _endthreadex(unsigned thread_retval);
Description
Terminates execution of the current thread by calling the ExitThread API, but
without closing the handle. The thread must have been created by an earlier call
to _beginthreadex. The runtime library will call _endthreadex autotmatically,
when your thread function terminates. _endthreadex receives the return value of
your thread function in thread_retval, and will pass it along to the Win32
ExitThread API.
Remarque: Note: Performs the same operation as _endthread(), but does not
close the thread handle.
Return Value
None.
_expand ( see page 993) Header File
process.h
Category
Memory Routines
Prototype
void *_expand(void *block, size_t size);
Description
Grows or shrinks a heap block in place.
This function attempts to change the size of an allocated memory block without
moving the block's location in the heap. The data in the block are not changed,
up to the smaller of the old and new sizes of the block. The block must have
been allocated earlier with malloc, calloc, or realloc, and must not have been
freed.
Return Value
If _expand is able to resize the block without moving it, _expand returns a pointer
to the block,... suite ( see page 993)
_unadopt_thread ( see page 994) Header File
process.h
Category
Process Control Routines
Prototype
void _unadopt_thread(_PTHREAD_ADOPTION_DATA thd);
Description
Frees the RTL thread-specific data associated with a previous call to
_adopt_thread.
Return Value
None.
Portability
cwait ( see page 994) Header File
process.h
Category
Process Control Routines
Prototype
int cwait(int *statloc, int pid, int action);
Description
Waits for child process to terminate.
The cwait function waits for a child process to terminate. The process ID of the
child to wait for is pid. If statloc is not NULL, it points to the location where cwait
3 will store the termination status. The action specifies whether to wait for the
process alone, or for the process and all of its children.
If the child process terminated normally (by calling exit, or returning from main),
the termination status word is defined as follows:... suite ( see page 994)

982
3.1 Référence C++ RAD Studio C Runtime Library Reference

execl, execle, execlp, execlpe, execv, execve, execvp, execvpe, _wexecl, Header File
_wexecle, _wexeclp, _wexeclpe, _wexecv, _wexecve, _wexecvp, _wexecvpe ( process.h
see page 996)
Category
Process Control Routines
Prototype
int execl(char *path, char *arg0 *arg1, ..., *argn, NULL);
int _wexecl(wchar_t *path, wchar_t *arg0 *arg1, ..., *argn,
NULL);
int execle(char *path, char *arg0, *arg1, ..., *argn, NULL,
char **env);
int _wexecle(wchar_t *path, wchar_t *arg0, *arg1, ...,
*argn, NULL, wchar_t **env);
int execlp(char *path, char *arg0,*arg1, ..., *argn, NULL);
int _wexeclp(wchar_t *path, wchar_t *arg0,*arg1, ...,
*argn, NULL);
int execlpe(char *path, char *arg0, *arg1, ..., *argn,
NULL, char **env);
int _wexeclpe(wchar_t *path, wchar_t *arg0, *arg1, ...,
*argn, NULL, wchar_t **env);
int execv(char *path, char *argv[]);
int _wexecv(wchar_t *path, wchar_t *argv[]);
int execve(char *path, char... suite ( see page 996)
getpid ( see page 998) Header File
process.h
Category
Process Control Routines
Prototype
unsigned getpid(void)
Description
Gets the process ID of a program.
This function returns the current process ID--an integer that uniquely identifies
the process.
Return Value
getpid returns the current process' ID.
Example
spawnl, spawnle, spawnlp, spawnlpe, spawnv, spawnve, spawnvp, spawnvpe, Header File
_wspawnl, _wspawnle, _wspawnlp, _wspawnlpe, _wspawnv, _wspawnve, process.h
_wspawnvp, _wspawnvpe ( see page 998)
Category
Process Control Routines
Prototype
int spawnl(int mode, char *path, char *arg0, arg1, ...,
argn, NULL);
int _wspawnl(int mode, wchar_t *path, wchar_t *arg0, arg1,
..., argn, NULL);
int spawnle(int mode, char *path, char *arg0, arg1, ...,
argn, NULL, char *envp[]);
int _wspawnle(int mode, wchar_t *path, wchar_t *arg0, arg1,
..., argn, NULL, wchar_t *envp[]);
int spawnlp(int mode, char *path, char *arg0, arg1, ...,
argn, NULL);
int _wspawnlp(int mode, wchar_t *path, wchar_t *arg0, arg1,
..., argn, NULL);
int spawnlpe(int mode, char *path, char *arg0, arg1, ...,
argn, NULL, char *envp[]);
int _wspawnlpe(int mode, wchar_t *path, wchar_t *arg0,
arg1, ...,... suite ( see page 998)

983
C Runtime Library Reference RAD Studio 3.1 Référence C++

wait ( see page 1001) Header File


process.h
Category
Process Control Routines
Prototype
int wait(int *statloc);
Description
Waits for one or more child processes to terminate.
The wait function waits for one or more child processes to terminate. The child
processes must be those created by the calling program; wait cannot wait for
grandchildren (processes spawned by child processes). If statloc is not NULL, it
points to location where wait will store the termination status.
If the child process terminated normally (by calling exit, or returning from main),
the termination status word is defined as follows:

3.1.5.22.1 P_xxxx #defines


Header File

process.h

Description

Modes used by the spawn... functions.

Constant Meaning
P_WAIT Child runs separately, parent waits until exit
P_DETACH Child and parent run concurrently with child process in background mode
P_NOWAIT Child and parent run concurrently (Not implemented)
P_NOWAITO Child and parent run concurrently, but the child process is not saved
P_OVERLAY Child replaces parent so that parent no longer exists

3.1.5.22.2 _adopt_thread
Header File

process.h

Category

Process Control Routines

Prototype
_PTHREAD_ADOPTION_DATA _adopt_thread(void (_USERENTRY *__start_address)(void *), void *
__arglist, int free_flag );

Description
3 “Adopts” a thread, created with the Windows API CreateThread function, to the C++Builder RTL by hooking up the necessary
internal data (exceptions, stack info, and so forth). _adopt_thread thereby allows the RTL to handle exception issues in that
thread. The execution path of this thread is then transferred to another function (the adoptive thread function). From the RTL's
perspective, during the execution of this adoptive thread function, the thread appears as if it had been created by a call to
_beginthreadex and is allowed all the benefits, such as calling other RTL functions and throwing/catching exceptions.

To create a thread, a user normally calls _beginthread. This hooks up the internal data automatically. _adopt_thread is primarily
used in cases in which this internal data is not present. For example, this happens when a user is called from a thread that came

984
3.1 Référence C++ RAD Studio C Runtime Library Reference

from an outside source, such as ISAPI.

Using _adopt_thread thereby allows C++Builder compiled DLLs to be used from non-C++Builder EXEs. _adopt_thread works by:

• calling the user function (passing in the arglist param)


• unhooking the exception information
• returning a handle to the thread context
This process allows the same function to be used again (without reallocating all that data). At the end of this cycle, the
_unadopt_thread function can be called to finally free up the rest of this data.
The last parameter, free_flag, determines whether the thread data structures are freed upon function exit:
• If free_flag is zero, then when the adoptive function exits only its exception handler is un-hooked. The rest of the RTL specific
data that had been allocated during the thread's adoption, remains valid. If the same thread then calls _adopt_thread again,
the existing data is used, the exception handler is rehooked, and the specified adoptive thread function is called.
• If free_flag is set to non-zero, the thread data structures will be freed before _adopt_thread returns. In this case the returned
thread handle will be NULL since its associated date has already been freed.
Return Value
If the __free_flag parameter is false (zero), _adopt_thread returns a handle (thread context) that can later be used to free these
data structures by passing it to _unadopt_thread().
If the __free_flag parameter to _adopt_thread is non-zero, the thread data is freed before _adopt_thread returns, and the
returned handle is NULL.
If an error has occurred, errno is set to:
ENOMEM Not enough memory
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.22.3 _beginthread
Header File

process.h

Category

Process Control Routines

Prototype
unsigned long _beginthread(void (_USERENTRY *__start)(void *), unsigned __stksize, void
*__arg);

Description

Starts execution of a new thread. 3


Remarque: The start_address must be declared to be _USERENTRY.

The _beginthread function creates and starts a new thread. The thread starts execution at start_address.

The size of its stack in bytes is stack_size; the stack is allocated by the operating system after the stack size is rounded up to the
next multiple of 4096. The thread is passed arglist as its only parameter; it can be NULL, but must be present. The thread
function should terminate by simply returning; the _endthread. function will be called automatically. The _endthread function will
automatically close the handle, and set the return value of the thread to zero.

985
C Runtime Library Reference RAD Studio 3.1 Référence C++

Either this function or _beginthreadNT must be used instead of the operating system thread-creation API function because
_beginthread and _beginthreadNT perform initialization required for correct operation of the runtime library functions.

This function is available only in the multithread libraries.

Return Value

_beginthread returns the handle of the new thread. The return value is a standard Windows handle that can be used in operating
system API's such as SuspendThread and ResumeThread.

On error, the function returns -1, and the global variable errno is set to one of the following values:

EAGAIN Too many threads


EINVAL Invalid stack size (i.e. less than 16 bytes, or equal to zero)
ENOMEM Not enough memory

Also see the description of the Win32 API GetLastError, in the MSDN Library.

Example
/* Use the -tWM (32-bit multi-threaded target) command-line switch for this example */
#include <stdio.h>
#include <errno.h>
#include <stddef.h> /* _threadid variable */
#include <process.h> /* _beginthread, _endthread */
#include <time.h> /* time, _ctime */
void thread_code(void *threadno)
{
time_t t;
time(&t);
printf("Executing thread number %d, ID = %d, time = %s\n",
(int)threadno, _threadid, ctime(&t));

void start_thread(int i)
{
int thread_id;
#if defined(__WIN32__)
if ((thread_id = _beginthread(thread_code,4096,(void *)i)) == (unsigned long)-1)
#else
if ((thread_id = _beginthread(thread_code,4096,(void *)i)) == -1)
#endif
{
printf("Unable to create thread %d, errno = %d\n",i,errno);
return;
}
printf("Created thread %d, ID = %ld\n",i,thread_id);
}
int main(void)
{
int i;
for (i = 1; i < 20; i++)
3 start_thread(i);
printf("Hit ENTER to exit main thread.\n");
getchar();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

986
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.22.4 _beginthreadNT
Header File

process.h

Category

Process Control Routines

Prototype
unsigned long _beginthreadNT(void (_USERENTRY *start_address)(void *), unsigned stack_size,
void *arglist, void *security_attrib, unsigned long create_flags, unsigned long *thread_id);

Description

Starts execution of a new thread under Windows NT.

Remarque: The start_address must be declared to be _USERENTRY.

All multithread Windows NT programs must use _beginthreadNT or the _beginthread function instead of the operating system
thread-creation API function because these functions perform initialization required for correct operation of the runtime library
functions. The _beginthreadNT function provides support for the operating system security. These functions are available only in
the multithread libraries.

The _beginthreadNT function creates and starts a new thread. The thread starts execution at start_address. When your thread
terminates, the _endthread function will be called automatically. _endthread will close the thread handle, and call the ExitThread
API.

The size of its stack in bytes is stack_size; the stack is allocated by the operating system after the stack size is rounded up to the
next multiple of 4096. The thread arglist can be NULL, but must be present.

The _beginthreadNT function uses the security_attr pointer to access the SECURITY_ATTRIBUTES structure. The structure
contains the security attributes for the thread. If security_attr is NULL, the thread is created with default security attributes. The
thread handle is not inherited if security_attr is NULL.

_beginthreadNT reads the create_flags variable for flags that provide additional information about the thread creation. This
variable can be zero, specifying that the thread will run immediately upon creation. The variable can also be
CREATE_SUSPENDED; in which case, the thread will not run until the ResumeThread function is called. ResumeThread is
provided by the Win32 API.

_beginthreadNT initializes the thread_id variable with the thread identifier.

Return Value

On success, _beginthreadNT returns the handle of the new thread. The return value is a standard Windows handle that can be
used in operating system API's such as SuspendThread and ResumeThread.

On error, it returns -1, and the global variable errno is set to one of the following values:

EAGAIN Too many threads 3


EINVAL Invalid stack size (i.e. less than 16 bytes, or equal to zero)
ENOMEM Not enough memory

Also see the description of the Win32 API GetLastError, in the MSDN Library.

Example
/* Use the -tWM (32-bit multi-threaded target) command-line switch for this example */

987
C Runtime Library Reference RAD Studio 3.1 Référence C++

#pragma checkoption -tWM


#include <windows.h>
#include <process.h>
#include <stdio.h>
#define NTHREADS 25
static LONG runningThreads = 0;
static HANDLE doneEvent;
/* This function acts as the 'main' function for each new thread */
static void threadMain(void *arg)
{
printf("Thread %2d has an ID of %u\n", (int)arg, GetCurrentThreadId());
/* Use InterlockedDecrement() to modify the global runningThreads in a
* thread safe manner. When the count hits 0, signal the main thread if
* it created an event for us.
*/
if (InterlockedDecrement(&runningThreads) == 0 && doneEvent)
SetEvent(doneEvent);
}
int main(void)
{
HANDLE hThreads[NTHREADS];
int i;
DWORD threadId;
SECURITY_ATTRIBUTES sa = {
sizeof(SECURITY_ATTRIBUTES), /* structure size */
0, /* No security descriptor */
TRUE /* Thread handle is inheritable */
};
/* Create NTHREADS inheritable threads that are initially suspended and that will run
starting at threadMain()*/
for(i = 0; i < NTHREADS; i++) {
hThreads[i] = (HANDLE)_beginthreadNT(
threadMain, /* Thread starting address */
4096, /* Thread stack size */
(void *)i, /* Thread start argument */
&sa, /* Thread security */
CREATE_SUSPENDED, /* Create in suspended state */
&threadId); /* Thread ID */
if(hThreads[i] == INVALID_HANDLE_VALUE) {
MessageBox(0, "Thread Creation Failed", "Error", MB_OK);
return 1;
}
++runningThreads;
printf("Created thread %2d with an ID of %u\n", i, threadId);
}
printf("\nPress ENTER to thaw all threads\n\n");
getchar();
/* Create the event that will signal when all threads are done */
doneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

/* Resume the suspended threads */


for(i = 0; i < NTHREADS; i++)
ResumeThread(hThreads[i]);
/* Wait for all threads to finish execution, if we can */
if (doneEvent) {
WaitForSingleObject(doneEvent, INFINITE);
3 CloseHandle(doneEvent);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

988
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.22.5 _beginthreadex
Header File

process.h

Category

Process Control Routines

Prototype
unsigned long _beginthreadex(void *__security_attr, unsigned __stksize, unsigned (__stdcall
*__start)(void *), void *__arg, unsigned __create_flags, unsigned *__thread_id);

Description

Creates a thread and allows specifying the other parameters of the OS API CreateThread (such as security and thread creation
flags). The _endthreadex function will be called automatically when the thread function terminates. The value returned from your
thread function will be passed along to _endthreadex, which in turn will pass it along to the ExitThread API. The return value can
then be retrieved using the GetExitCodeThread API.

Unlike _endthread, the _endthreadex function does not close the thread handle, thereby allowing other threads to block on this
one without fear that the handle will be freed out from under the system.

Other than the order of parameters and the closing of the thread handle, _beginthreadex performs same operation as
_beginthreadNT.

Remarque: Note: The start address needs to be defined to return an unsigned, which is the thread exit code.

Return Value

_beginthreadex returns the handle of the new thread. The return value is a standard Windows handle that can be used in
operating system API's such as SuspendThread and ResumeThread.

If unsuccessful, 0 is returned, and errno is set as follows:

EAGAIN Too many threads


ENOMEM Not enough memory
EINVAL Bad stack value (i.e. less than 16 bytes or equal to zero)

Also see the description of the Win32 API GetLastError, in the MSDN Library.

Example
//* Use the -tWM (32-bit multi-threaded target) command-line switch for this example */
#pragma checkoption -tWM
#include <windows.h>
#include <process.h>
#include <stdio.h>
#define NTHREADS 25
/* This function acts as the 'main' function for each new thread */ 3
static unsigned __stdcall threadMain(void *arg)
{
printf("Thread %2d has an ID of %u\n", (int)arg, GetCurrentThreadId());
return 0;
}
int main(void)
{
HANDLE hThreads[NTHREADS];
int i;

989
C Runtime Library Reference RAD Studio 3.1 Référence C++

unsigned threadId;
SECURITY_ATTRIBUTES sa = {
sizeof(SECURITY_ATTRIBUTES), /* structure size */
0, /* No security descriptor */
TRUE /* Thread handle is inheritable */
};
/* Create NTHREADS inheritable threads that are initially suspended and that will run
starting at threadMain()*/
for(i = 0; i < NTHREADS; i++) {
hThreads[i] = (HANDLE)_beginthreadex(
&sa, /* Thread security */
4096, /* Thread stack size */
threadMain, /* Thread starting address */
(void *)i, /* Thread start argument */
CREATE_SUSPENDED, /* Create in suspended state */
&threadId); /* Thread ID */
if(hThreads[i] == INVALID_HANDLE_VALUE) {
MessageBox(0, "Thread Creation Failed", "Error", MB_OK);
return 1;
}
printf("Created thread %2d with an ID of %u\n", i, threadId);
}
printf("\nPress ENTER to thaw all threads\n\n");
getchar();

/* Resume the suspended threads */


for(i = 0; i < NTHREADS; i++)
ResumeThread(hThreads[i]);

/* Wait for the threads to run */


WaitForMultipleObjects(NTHREADS, hThreads, TRUE, INFINITE);
/* Close all of the thread handles */
for(i = 0; i < NTHREADS; i++)
CloseHandle(hThreads[i]);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.22.6 _c_exit
Header File

process.h

Category

Process Control Routines

Prototype
3
void _c_exit(void);

Description

Performs _exit cleanup without terminating the program.

_c_exit performs the same cleanup as _exit, except that it does not terminate the calling process.

Return Value

990
3.1 Référence C++ RAD Studio C Runtime Library Reference

None.

Example
#include <process.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
main()
{
int fd;
char c;

if ((fd = open("_c_exit.c",O_RDONLY)) < 0)


{
printf("Unable to open _c_exit.c for reading\n");
return 1;
}
if (read(fd,&c,1) != 1)
printf("Unable to read from open file handle %d before _c_exit\n",fd);
else
printf("Successfully read from open file handle %d before _c_exit\n",fd);
_c_exit();
if (read(fd,&c,1) != 1)
printf("Unable to read from open file handle %d after _c_exit\n",fd);
else
printf("Successfully read from open file handle %d after _c_exit\n",fd);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.22.7 _cexit
Header File

process.h

Category

Process Control Routines

Prototype
void _cexit(void);

Description

Performs exit cleanup without terminating the program.

_cexit performs the same cleanup as exit, closing all files but without terminating the calling process. The _cexit function calls 3
any registered "exit functions" (posted with atexit). Before _cexit returns, it flushes all input/output buffers and closes all streams
that were open.

Return Value

None.

Example
#include <windows.h>

991
C Runtime Library Reference RAD Studio 3.1 Référence C++

#include <process.h>
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
void exit_func(void)
{
printf("Exit function called\n\n");
printf("Close Window to return to program... It will beep if able to read from file");
}
int main(void)
{
int fd;
char c;
if ((fd = open("_cexit.c",O_RDONLY)) < 0)
{
printf("Unable to open _cexit.c for reading\n");
return 1;
}
atexit(exit_func);
if (read(fd,&c,1) != 1)
printf("Unable to read from open file handle %d before _cexit\n",fd);
else
printf("Successfully read from open file handle %d before _cexit\n",fd);
_cexit();
if (read(fd,&c,1) == 1)
MessageBeep(0);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.22.8 _endthread
Header File

process.h

Category

Process Control Routines

Prototype
void _endthread(void);

Description

Terminates execution of a thread.

3 The _endthread function terminates the currently executing thread by closing the thread handle and calling the ExitThread API.
The thread must have been started by an earlier call to _beginthread or _beginthreadNT.. _endthread is called automatically by
the runtime library when your thread function terminates.

This function is available in the multithread libraries; it is not in the single-threaded libraries.

Return Value

The function does not return a value.

992
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.22.9 _endthreadex
Header File

process.h

Category

Process Control Routines

Prototype
void _endthreadex(unsigned thread_retval);

Description

Terminates execution of the current thread by calling the ExitThread API, but without closing the handle. The thread must have
been created by an earlier call to _beginthreadex. The runtime library will call _endthreadex autotmatically, when your thread
function terminates. _endthreadex receives the return value of your thread function in thread_retval, and will pass it along to the
Win32 ExitThread API.

Remarque: Note: Performs the same operation as _endthread(), but does not close the thread handle.

Return Value

None.

3.1.5.22.10 _expand
Header File

process.h

Category

Memory Routines

Prototype
void *_expand(void *block, size_t size);

Description

Grows or shrinks a heap block in place.

This function attempts to change the size of an allocated memory block without moving the block's location in the heap. The data
in the block are not changed, up to the smaller of the old and new sizes of the block. The block must have been allocated earlier
with malloc, calloc, or realloc, and must not have been freed.

Return Value

If _expand is able to resize the block without moving it, _expand returns a pointer to the block, whose address is unchanged. If
_expand is unsuccessful, it returns a NULL pointer and does not modify or resize the block. 3
Example
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
void main(void)
{
char *bufchar, *newbuf;

993
C Runtime Library Reference RAD Studio 3.1 Référence C++

printf( "Allocate a 512 element buffer\n" );


if( (bufchar = (char *) calloc(512, sizeof( char ) )) == NULL)
exit( 1 );
printf( "Allocated %d bytes at %Fp\n",
_msize ( bufchar ), (void __far *)bufchar );
if ((newbuf = (char *) _expand (bufchar, 1024)) == NULL)
printf ("cannot expand");
else {
bufchar = newbuf;
printf (" Expanded block to %d bytes at %Fp\n",
_msize( bufchar ) , (void __far *)bufchar );
}
free( bufchar );
exit (0);
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.22.11 _unadopt_thread
Header File

process.h

Category

Process Control Routines

Prototype
void _unadopt_thread(_PTHREAD_ADOPTION_DATA thd);

Description

Frees the RTL thread-specific data associated with a previous call to _adopt_thread.

Return Value

None.

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.22.12 cwait
3 Header File

process.h

Category

Process Control Routines

Prototype
int cwait(int *statloc, int pid, int action);

994
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

Waits for child process to terminate.

The cwait function waits for a child process to terminate. The process ID of the child to wait for is pid. If statloc is not NULL, it
points to the location where cwait will store the termination status. The action specifies whether to wait for the process alone, or
for the process and all of its children.

If the child process terminated normally (by calling exit, or returning from main), the termination status word is defined as follows:

Bits 0-7 Zero


Bits 8-15 The least significant byte of the return code from the child process. This is the value that is passed to
exit, or is returned from main. If the child process simply exited from main without returning a value,
this value will be unpredictable.

If the child process terminated abnormally, the termination status word is defined as follows:

Bits 0-7Termination information about the child:

1 Critical error abort.


2 Execution fault, protection exception.
3 External termination signal.
Bits 8-15 Zero

Bits 8-15 Zero

If pid is 0, cwait waits for any child process to terminate. Otherwise, pid specifies the process ID of the process to wait for; this
value must have been obtained by an earlier call to an asynchronous spawn function.

The acceptable values for action are WAIT_CHILD, which waits for the specified child only, and WAIT_GRANDCHILD, which
waits for the specified child and all of its children. These two values are defined in process.h.

Return Value

When cwait returns after a normal child process termination, it returns the process ID of the child.

When cwait returns after an abnormal child termination, it returns -1 to the parent and sets errno to EINTR (the child process
terminated abnormally).

If cwait returns without a child process completion, it returns a -1 value and sets errno to one of the following values:

ECHILD No child exists or the pid value is bad


EINVAL A bad action value was specified

Portability

POSIX Win32 ANSI C ANSI C++ 3


+

995
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.22.13 execl, execle, execlp, execlpe, execv, execve, execvp, execvpe,


_wexecl, _wexecle, _wexeclp, _wexeclpe, _wexecv, _wexecve, _wexecvp,
_wexecvpe
Header File

process.h

Category

Process Control Routines

Prototype
int execl(char *path, char *arg0 *arg1, ..., *argn, NULL);
int _wexecl(wchar_t *path, wchar_t *arg0 *arg1, ..., *argn, NULL);
int execle(char *path, char *arg0, *arg1, ..., *argn, NULL, char **env);
int _wexecle(wchar_t *path, wchar_t *arg0, *arg1, ..., *argn, NULL, wchar_t **env);
int execlp(char *path, char *arg0,*arg1, ..., *argn, NULL);
int _wexeclp(wchar_t *path, wchar_t *arg0,*arg1, ..., *argn, NULL);
int execlpe(char *path, char *arg0, *arg1, ..., *argn, NULL, char **env);
int _wexeclpe(wchar_t *path, wchar_t *arg0, *arg1, ..., *argn, NULL, wchar_t **env);
int execv(char *path, char *argv[]);
int _wexecv(wchar_t *path, wchar_t *argv[]);
int execve(char *path, char *argv[], char **env);
int _wexecve(wchar_t *path, wchar_t *argv[], wchar_t **env);
int execvp(char *path, char *argv[]);
int _wexecvp(wchar_t *path, wchar_t *argv[]);
int execvpe(char *path, char *argv[], char **env);
int _wexecvpe(wchar_t *path, wchar_t *argv[], wchar_t **env);

Description

Loads and runs other programs.

The functions in the exec... family load and run (execute) other programs, known as child processes. When an exec... call
succeeds, the child process overlays the parent process. There must be sufficient memory available for loading and executing
the child process.

path is the file name of the called child process. The exec... functions search for path using the standard search algorithm:
3 • If no explicit extension is given, the functions search for the file as given. If the file is not found, they add .EXE and search
again. If not found, they add .COM and search again. If found, the command processor, COMSPEC (Windows) or
COMMAND.COM (DOS), is used to run the batch file.
• If an explicit extension or a period is given, the functions search for the file exactly as given.
The suffixes l, v, p, and e added to the exec... "family name" specify that the named function operates with certain capabilities.

996
3.1 Référence C++ RAD Studio C Runtime Library Reference

l specifies that the argument pointers (arg0, arg1, ..., argn) are passed as separate arguments.
Typically, the l suffix is used when you know in advance the number of arguments to be passed.
v specifies that the argument pointers (argv[0] ..., arg[n]) are passed as an array of pointers. Typically,
the v suffix is used when a variable number of arguments is to be passed.
p specifies that the function searches for the file in those directories specified by the PATH environment
variable (without the p suffix, the function searches only the current working directory). If the path
parameter does not contain an explicit directory, the function searches first the current directory, then
the directories set with the PATH environment variable.
e specifies that the argument env can be passed to the child process, letting you alter the environment
for the child process. Without the e suffix, child processes inherit the environment of the parent
process.

Each function in the exec... family must have one of the two argument-specifying suffixes (either l or v). The path search and
environment inheritance suffixes (p and e) are optional; for example:

• execl is an exec... function that takes separate arguments, searches only the root or current directory for the child, and passes
on the parent's environment to the child.
• execvpe is an exec... function that takes an array of argument pointers, incorporates PATH in its search for the child process,
and accepts the env argument for altering the child's environment.
The exec... functions must pass at least one argument to the child process (arg0 or argv[0]); this argument is, by convention, a
copy of path. (Using a different value for this 0th argument won't produce an error.)
path is available for the child process.
When the l suffix is used, arg0 usually points to path, and arg1, ..., argn point to character strings that form the new list of
arguments. A mandatory null following argn marks the end of the list.
When the e suffix is used, you pass a list of new environment settings through the argument env. This environment argument is
an array of character pointers. Each element points to a null-terminated character string of the form
envvar = value
where envvar is the name of an environment variable, and value is the string value to which envvar is set. The last element in
env is null. When env is null, the child inherits the parents' environment settings.
The combined length of arg0 + arg1 + ... + argn (or of argv[0] + argv[1] + ... + argn[n]), including space characters that separate
the arguments, must be less than 260 bytes. Null terminators are not counted.
When an exec... function call is made, any open files remain open in the child process.
Return Value
If successful, the exec... functions do not return. On error, the exec... functions return -1, and the global variable errno is set to
one of the following values:

EACCES Permission denied


EMFILE Too many open files
ENOENT Path or file name not found
ENOEXEC Exec format error
ENOMEM Not enough memory 3

Example
/* execl() example */
#include <stdio.h>
#include <process.h>

int main(int argc, char *argv[])


{

997
C Runtime Library Reference RAD Studio 3.1 Référence C++

int loop;
printf("%s running...\n\n", argv[0]);

if (argc == 1) { /* check for only one command-line parameter */


printf("%s calling itself again...\n", argv[0]);
execl(argv[0], argv[0], "ONE", "TWO", "THREE", NULL);
perror("EXEC:");
exit(1);
}
printf("%s called with arguments:\n", argv[0]);
for (loop = 1; loop <= argc; loop++)
puts(argv[loop]); /* Display all command-line parameters */
return 0;
}

3.1.5.22.14 getpid
Header File

process.h

Category

Process Control Routines

Prototype
unsigned getpid(void)

Description

Gets the process ID of a program.

This function returns the current process ID--an integer that uniquely identifies the process.

Return Value

getpid returns the current process' ID.

Example
#include <stdio.h>
#include <process.h>
int main()
{
printf("This program's process identification number (PID) "
"number is %X\n", getpid());
printf("Note: under DOS it is the PSP segment\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +
3

3.1.5.22.15 spawnl, spawnle, spawnlp, spawnlpe, spawnv, spawnve, spawnvp,


spawnvpe, _wspawnl, _wspawnle, _wspawnlp, _wspawnlpe, _wspawnv,
_wspawnve, _wspawnvp, _wspawnvpe
Header File

998
3.1 Référence C++ RAD Studio C Runtime Library Reference

process.h

Category

Process Control Routines

Prototype
int spawnl(int mode, char *path, char *arg0, arg1, ..., argn, NULL);
int _wspawnl(int mode, wchar_t *path, wchar_t *arg0, arg1, ..., argn, NULL);
int spawnle(int mode, char *path, char *arg0, arg1, ..., argn, NULL, char *envp[]);
int _wspawnle(int mode, wchar_t *path, wchar_t *arg0, arg1, ..., argn, NULL, wchar_t *envp[]);
int spawnlp(int mode, char *path, char *arg0, arg1, ..., argn, NULL);
int _wspawnlp(int mode, wchar_t *path, wchar_t *arg0, arg1, ..., argn, NULL);
int spawnlpe(int mode, char *path, char *arg0, arg1, ..., argn, NULL, char *envp[]);
int _wspawnlpe(int mode, wchar_t *path, wchar_t *arg0, arg1, ..., argn, NULL, wchar_t *envp[]);
int spawnv(int mode, char *path, char *argv[]);
int _wspawnv(int mode, wchar_t *path, wchar_t *argv[]);
int spawnve(int mode, char *path, char *argv[], char *envp[]);
int _wspawnve(int mode, wchar_t *path, wchar_t *argv[], wchar_t *envp[]);
int spawnvp(int mode, char *path, char *argv[]);
int _wspawnvp(int mode, wchar_t *path, wchar_t *argv[]);
int spawnvpe(int mode, char *path, char *argv[], char *envp[]);
int _wspawnvpe(int mode, wchar_t *path, wchar_t *argv[], wchar_t *envp[]);

Remarque: In spawnle, spawnlpe, spawnv, spawnve, spawnvp, and spawnvpe, the last string must be NULL.

Description

The functions in the spawn... family create and run (execute) other files, known as child processes. There must be sufficient
memory available for loading and executing a child process.

The value of mode determines what action the calling function (the parent process) takes after the spawn... call. The possible
values of mode are

P_WAIT Puts parent process on hold until child process completes execution.
P_NOWAIT Continues to run parent process while child process runs. The child process ID is returned, so that
the parent can wait for completion using cwait or wait.
P_NOWAITO Identical to P_NOWAIT except that the child process ID isn't saved by the operating system, so the
parent process can't wait for it using cwait or wait.
P_DETACH Identical to P_NOWAITO, except that the child process is executed in the background with no access
to the keyboard or the display. 3
P_OVERLAY Overlays child process in memory location formerly occupied by parent. Same as an exec... call.

path is the file name of the called child process. The spawn... function calls search for path using the standard operating system
search algorithm:

• If there is no extension or no period, they search for an exact file name. If the file is not found, they search for files first with
the extension EXE, then COM, and finally BAT.

999
C Runtime Library Reference RAD Studio 3.1 Référence C++

• If an extension is given, they search only for the exact file name.
• If only a period is given, they search only for the file name with no extension.
• If path does not contain an explicit directory, spawn... functions that have the p suffix search the current directory, then the
directories set with the operating system PATH environment variable.
The suffixes p, l, and v, and e added to the spawn... "family name" specify that the named function operates with certain
capabilities.

p The function searches for the file in those directories specified by the PATH environment
variable. Without the p suffix, the function searches only the current working directory.
l The argument pointers arg0, arg1, ..., argn are passed as separate arguments. Typically, the l suffix
is used when you know in advance the number of arguments to be passed.
v The argument pointers argv[0], ..., arg[n] are passed as an array of pointers. Typically, the v suffix is
used when a variable number of arguments is to be passed.
e The argument envp can be passed to the child process, letting you alter the environment for the child
process. Without the e suffix, child processes inherit the environment of the parent process.

Each function in the spawn... family must have one of the two argument-specifying suffixes (either l or v). The path search and
environment inheritance suffixes (p and e) are optional.

For example:

• spawnl takes separate arguments, searches only the current directory for the child, and passes on the parent's environment to
the child.
• spawnvpe takes an array of argument pointers, incorporates PATH in its search for the child process, and accepts the envp
argument for altering the child's environment.
The spawn... functions must pass at least one argument to the child process (arg0 or argv[0]). This argument is, by convention, a
copy of path. (Using a different value for this 0 argument won't produce an error.) If you want to pass an empty argument list
to the child process, then arg0 or argv[0] must be NULL.
When the l suffix is used, arg0 usually points to path, and arg1, ...., argn point to character strings that form the new list of
arguments. A mandatory null following argn marks the end of the list.
When the e suffix is used, you pass a list of new environment settings through the argument envp. This environment argument is
an array of character pointers. Each element points to a null-terminated character string of the form
envvar = value
where envvar is the name of an environment variable, and value is the string value to which envvar is set. The last element in
envp[] is null. When envp is null, the child inherits the parents' environment settings.
The combined length of arg0 + arg1 + ... + argn (or of argv[0] + argv[1] + ... + argv[n]), including space characters that separate
the arguments, must be less than 260 bytes for Windows (128 for DOS). Null-terminators are not counted.
When a spawn... function call is made, any open files remain open in the child process.
Return Value
When successful, the spawn... functions, where mode is P_WAIT, return the child process' exit status (0 for a normal
termination). If the child specifically calls exit with a nonzero argument, its exit status can be set to a nonzero value.
If mode is P_NOWAIT or P_NOWAITO, the spawn functions return the process ID of the child process. The ID obtained when
3 using P_NOWAIT can be passed to cwait.
On error, the spawn... functions return -1, and the global variable errno is set to one of the following values:

E2BIG Arg list too long


EINVAL Invalid argument
ENOENT Path or file name not found
ENOEXEC Exec format error

1000
3.1 Référence C++ RAD Studio C Runtime Library Reference

ENOMEM Not enough memory

Example
#include <process.h>
#include <stdio.h>
void spawnl_example(void)
{
int result;
result = spawnl(P_WAIT, "bcc32.exe", "bcc32.exe", NULL);
if (result == -1)
{
perror("Error from spawnl");
exit(1);
}
}
int main(void)
{
spawnl_example();
return 0;
}

3.1.5.22.16 wait
Header File

process.h

Category

Process Control Routines

Prototype
int wait(int *statloc);

Description

Waits for one or more child processes to terminate.

The wait function waits for one or more child processes to terminate. The child processes must be those created by the calling
program; wait cannot wait for grandchildren (processes spawned by child processes). If statloc is not NULL, it points to location
where wait will store the termination status.

If the child process terminated normally (by calling exit, or returning from main), the termination status word is defined as follows:

Bits 0-7 Zero.


Bits 8-15 The least significant byte of the return code from the child process. This is the value that is passed to
exit, or is returned from main. If the child process simply exited from main without returning a value,
this value will be unpredictable. If the child process terminated abnormally, the termination status
word is defined as follows:
Bits 0-7 Termination information about the child: 3

Bits 8-15 Zero.

Return Value

When wait returns after a normal child process termination it returns the process ID of the child.

1001
C Runtime Library Reference RAD Studio 3.1 Référence C++

When wait returns after an abnormal child termination it returns -1 to the parent and sets errno to EINTR.

If wait returns without a child process completion it returns a -1 value and sets errno to:

ECHILD No child process exists

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.23 setjmp.h
The following functions, macros, and classes are provided in setjmp.h:

Rubriques
Nom Description
longjmp ( see page 1003) Header File
setjmp.h
Category
Miscellaneous Routines
Prototype
void longjmp(jmp_buf jmpb, int retval);
Description
Performs nonlocal goto.
A call to longjmp restores the task state captured by the last call to setjmp with
the argument jmpb. It then returns in such a way that setjmp appears to have
returned with the value retval.
A Win32 task state includes:

• Register variables
• EBX, EDI, ESI
• Stack pointer (ESP)
• Frame pointer (EBP)
• No segment registers are saved
• Flags are not saved
A task state is complete enough that setjmp and longjmp can
be used to implement co-routines.
setjmp must be called before longjmp. The... suite ( see
page 1003)

1002
3.1 Référence C++ RAD Studio C Runtime Library Reference

setjmp ( see page 1004) Header File


setjmp.h
Category
Miscellaneous Routines
Prototype
int setjmp(jmp_buf jmpb);
Description
Sets up for nonlocal goto.
setjmp captures the complete task state in jmpb and returns 0.
A later call to longjmp with jmpb restores the captured task state and returns in
such a way that setjmp appears to have returned with the value val.
Under Win32, a task state includes:

• No segment registers are saved


• Register variables
• EBX, EDI, ESI
• Stack pointer (ESP)
• Frame pointer (EBP)
• Flags are not saved
A task state is complete enough that setjmp can be used to
implement co-routines.
setjmp must be called before... suite ( see page 1004)

3.1.5.23.1 longjmp
Header File

setjmp.h

Category

Miscellaneous Routines

Prototype
void longjmp(jmp_buf jmpb, int retval);

Description

Performs nonlocal goto.

A call to longjmp restores the task state captured by the last call to setjmp with the argument jmpb. It then returns in such a way
that setjmp appears to have returned with the value retval.

A Win32 task state includes:

• Register variables
• EBX, EDI, ESI
• Stack pointer (ESP) 3
• Frame pointer (EBP)
• No segment registers are saved
• Flags are not saved
A task state is complete enough that setjmp and longjmp can be used to implement co-routines.
setjmp must be called before longjmp. The routine that called setjmp and set up jmpb must still be active and cannot have
returned before the longjmp is called. If this happens, the results are unpredictable.

1003
C Runtime Library Reference RAD Studio 3.1 Référence C++

longjmp cannot pass the value 0; if 0 is passed in retval, longjmp will substitute 1.
Return Value
None.
Example
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
void subroutine(jmp_buf);
int main(void)
{

int value;
jmp_buf jumper;
value = setjmp(jumper);
if (value != 0)
{
printf("Longjmp with value %d\n", value);
exit(value);
}
printf("About to call subroutine ... \n");
subroutine(jumper);
return 0;
}
void subroutine(jmp_buf jumper)
{
longjmp(jumper,1);
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.23.2 setjmp
Header File

setjmp.h

Category

Miscellaneous Routines

Prototype
int setjmp(jmp_buf jmpb);

Description

Sets up for nonlocal goto.


3
setjmp captures the complete task state in jmpb and returns 0.

A later call to longjmp with jmpb restores the captured task state and returns in such a way that setjmp appears to have returned
with the value val.

Under Win32, a task state includes:

• No segment registers are saved


• Register variables

1004
3.1 Référence C++ RAD Studio C Runtime Library Reference

• EBX, EDI, ESI


• Stack pointer (ESP)
• Frame pointer (EBP)
• Flags are not saved
A task state is complete enough that setjmp can be used to implement co-routines.
setjmp must be called before longjmp. The routine that calls setjmp and sets up jmpb must still be active and cannot have
returned before the longjmp is called. If it has returned, the results are unpredictable.
setjmp is useful for dealing with errors and exceptions encountered in a low-level subroutine of a program.
Return Value
setjmp returns 0 when it is initially called. If the return is from a call to longjmp, setjmp returns a nonzero value (as in the
example).
Example
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
void subroutine(jmp_buf);
int main(void)
{

int value;
jmp_buf jumper;
value = setjmp(jumper);
if (value != 0)
{
printf("Longjmp with value %d\n", value);
exit(value);
}
printf("About to call subroutine ... \n");
subroutine(jumper);
return 0;
}
void subroutine(jmp_buf jumper)
{
longjmp(jumper,1);
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.24 share.h
The following functions, macros, and classes are provided in share.h:

Rubriques 3
Nom Description
SH_xxxx #defines ( see page 1006) Header File
share.h
Description
File-sharing mode for use with sopen.

1005
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.24.1 SH_xxxx #defines


Header File

share.h

Description

File-sharing mode for use with sopen.

SH_COMPAT Sets compatibility mode:


Allows other opens with SH_COMPAT. The call will fail if the file has already been opened in any
other shared mode.
SH_DENYNONE Permits read/write access
Allows other shared opens to the file, but not other SH_COMPAT opens
SH_DENYNO Permits read/write access (provided for compatibility)
SH_DENYRD Denies read access. Allows only writes from any other open to the file
SH_DENYRW Denies read/write access. Only the current handle may have access to the file
SH_DENYWR Denies write access. Allows only reads from any other open to the file
O_NOINHERIT The file is not passed to child programs

These file-sharing attributes are in addition to any locking performed on the files.

3.1.5.25 signal.h
The following functions, macros, and classes are provided in signal.h:

Rubriques
Nom Description
SIGxxxx #defines ( see page 1007) Header File
signal.h
Description
Signal types used by raise and signal.
SIG_xxx #defines ( see page 1007) Header File
signal.h
Description
Predefined functions for handling signals generated by raise or by external
events.
raise ( see page 1008) Header File
signal.h
Category
Process Control Routines
Prototype
3 int raise(int sig);
Description
Sends a software signal to the executing program.
raise sends a signal of type sig to the program. If the program has installed a
signal handler for the signal type specified by sig, that handler will be executed. If
no handler has been installed, the default action for that signal type will be taken.
The signal types currently defined in signal.h are noted here:

1006
3.1 Référence C++ RAD Studio C Runtime Library Reference

signal (C RTL) ( see page 1009) Header File


signal.h
Category
Process Control Routines
Prototype
void (_USERENTRY *signal(int sig, void (_USERENTRY
*func)(int sig[, int subcode])))(int);
Description
Specifies signal-handling actions.
signal determines how receipt of signal number sig will subsequently be treated.
You can install a user-specified handler routine (specified by the argument func)
or use one of the two predefined handlers, SIG_DFL and SIG_IGN, in signal.h.
The function func must be declared with the _USERENTRY calling convention.
A routine that catches a signal (such as a floating point) also clears the signal. To
continue to receive signals, a signal handler must be reinstalled by calling signal
again.... suite ( see page 1009)

3.1.5.25.1 SIGxxxx #defines


Header File

signal.h

Description

Signal types used by raise and signal.

Signal Note Meaning Default Action


SIGABRT (*) Abnormal termination = to calling _exit(3)
SIGFPE Bad floating-point operation = to calling _exit(1)
Arithmetic error caused by
division by 0, invalid operation, etc.
SIGILL Illegal operation = to calling _exit(1)
SIGINT Control-C interrupt = to calling _exit(3)
SIGSEGV Invalid access to storage = to calling _exit(1)
SIGTERM (*) Request for program termination = to calling _exit(1)

(*) Signal types marked with a (*) aren't generated by Borland C++ during normal operation. However, they can be generated
with raise.

3.1.5.25.2 SIG_xxx #defines


Header File

signal.h

Description 3
Predefined functions for handling signals generated by raise or by external events.

Name Meaning
SIG_DFL Terminate the program
SIG_IGN No action, ignore signal
SIG_ERR Return error code

1007
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.25.3 raise
Header File

signal.h

Category

Process Control Routines

Prototype
int raise(int sig);

Description

Sends a software signal to the executing program.

raise sends a signal of type sig to the program. If the program has installed a signal handler for the signal type specified by sig,
that handler will be executed. If no handler has been installed, the default action for that signal type will be taken.

The signal types currently defined in signal.h are noted here:

SIGABRT Abnormal termination


SIGFPE Bad floating-point operation
SIGILL Illegal instruction
SIGINT Ctrl-C interrupt
SIGSEGV Invalid access to storage
SIGTERM Request for program termination
SIGUSR1 User-defined signal
SIGUSR2 User-defined signal
SIGUSR3 User-defined signal
SIGBREAK Ctrl-Break interrupt

Remarque: SIGABRT isn’t generated by C++Builder during normal operation. It can, however, be generated by abort, raise, or
unhandled exceptions.

Return Value

On success, raise returns 0.

On error it returns nonzero.

Example
#include <signal.h>
int main(void)
3 {
int a, b;
a = 10;
b = 0;
if (b == 0)
/* preempt divide by zero error */
raise(SIGFPE);
a = a / b;
return 0;
}

1008
3.1 Référence C++ RAD Studio C Runtime Library Reference

Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.25.4 signal (C RTL)


Header File

signal.h

Category

Process Control Routines

Prototype
void (_USERENTRY *signal(int sig, void (_USERENTRY *func)(int sig[, int subcode])))(int);

Description

Specifies signal-handling actions.

signal determines how receipt of signal number sig will subsequently be treated. You can install a user-specified handler routine
(specified by the argument func) or use one of the two predefined handlers, SIG_DFL and SIG_IGN, in signal.h. The function
func must be declared with the _USERENTRY calling convention.

A routine that catches a signal (such as a floating point) also clears the signal. To continue to receive signals, a signal handler
must be reinstalled by calling signal again.

SIG_DFL Terminates the program


SIG_ERR Indicates an error return from signal
SIG_IGN Ignore this type signal

The following table shows signal types and their defaults:

SIGBREAK Keyboard must be in raw mode.


SIGABRT Abnormal termination. Default action is equivalent to calling _exit(3).
SIGFPE Arithmetic error caused by division by 0, invalid operation, and the like. Default action is equivalent to
calling _exit(1).
SIGILL Illegal operation. Default action is equivalent to calling _exit(1).
SIGINT Ctrl-C interrupt. Default action is equivalent to calling _exit(3).
SIGSEGV Illegal storage access. Default action is equivalent to calling _exit(1).
SIGTERM Request for program termination. Default action is equivalent to calling _exit(1).

3
User-defined signals can be generated only by calling raise. Default action is to ignore the signal.

signal.h defines a type called sig_atomic_t, the largest integer type the processor can load or store atomically in the presence of
asynchronous interrupts (this is a 32-bit integer -- a Borland C++ integer).

When a signal is generated by the raise function or by an external event, the following two things happen:

• If a user-specified handler has been installed for the signal, the action for that signal type is set to SIG_DFL.

1009
C Runtime Library Reference RAD Studio 3.1 Référence C++

• The user-specified function is called with the signal type as the parameter.
User-specified handler functions can terminate by a return or by a call to abort, _exit, exit, or longjmp. If your handler function is
expected to continue to receive and handle more signals, you must have the handler function call signal again.
Borland C++ implements an extension to ANSI C when the signal type is SIGFPE, SIGSEGV, or SIGILL. The user-specified
handler function is called with one or two extra parameters. If SIGFPE, SIGSEGV, or SIGILL has been raised as the result of
an explicit call to the raise function, the user-specified handler is called with one extra parameter, an integer specifying that
the handler is being explicitly invoked. The explicit activation values for SIGFPE, SIGSEGV and SIGILL are as follows
Remarque: Declarations of these types are defined in float.h.

SIGFPE FPE_EXPLICITGEN
SIGSEGV SEGV_EXPLICITGEN
SIGILL ILL_EXPLICITGEN

If SIGFPE is raised because of a floating-point exception, the user handler is called with one extra parameter that specifies the
FPE_xxx type of the signal. If SIGSEGV, SIGILL, or the integer-related variants of SIGFPE signals (FPE_INTOVFLOW or
FPE_INTDIV0) are raised as the result of a processor exception, the user handler is called with two extra parameters:

1.The SIGFPE, SIGSEGV, or SIGILL exception type (see float.h for all these types). This first parameter is the usual ANSI signal
type.

2.An integer pointer into the stack of the interrupt handler that called the user-specified handler. This pointer points to a list of the
processor registers saved when the exception occurred. The registers are in the same order as the parameters to an interrupt
function; that is, EBP, EDI, ESI, EDS, ES, EDX, ECX, EBX, EAX, EIP, CS, EFL. To have a register value changed when the
handler returns, change one of the locations in this list.

For example, to have a new SI value on return, do something like this:


*((int*)list_pointer + 2) = new_SI_value;

In this way, the handler can examine and make any adjustments to the registers that you want.

The following SIGFPE-type signals can occur (or be generated). They correspond to the exceptions that the 80x87 family is
capable of detecting, as well as the "INTEGER DIVIDE BY ZERO" and the "INTERRUPT ON OVERFLOW" on the main CPU.
(The declarations for these are in float.h.)

FPE_INTOVFLOW INTO executed with OF flag set


FPE_INTDIV0 Integer divide by zero
FPE_INVALID Invalid operation
FPE_ZERODIVIDE Division by zero
FPE_OVERFLOW Numeric overflow
FPE_UNDERFLOW Numeric underflow
FPE_INEXACT Precision

3 FPE_EXPLICITGEN User program executed raise(SIGFPE)


FPE_STACKFAULT Floating-point stack overflow or underflow
FPE_STACKFAULT Stack overflow

The FPE_INTOVFLOW and FPE_INTDIV0 signals are generated by integer operations, and the others are generated by
floating-point operations. Whether the floating-point exceptions are generated depends on the coprocessor control word, which
can be modified with _control87. Denormal exceptions are handled by Borland C++ and not passed to a signal handler.

The following SIGSEGV-type signals can occur:

1010
3.1 Référence C++ RAD Studio C Runtime Library Reference

SEGV_BOUND Bound constraint exception


SEGV_EXPLICITGEN raise(SIGSEGV) was executed

The following SIGILL-type signals can occur:

ILL_EXECUTION Illegal operation attempted


ILL_EXPLICITGEN raise(SIGILL) was executed

When the signal type is SIGFPE, SIGSEGV, or SIGILL, a return from a signal handler is generally not advisable if the state of the
floating point processor is corrupt, the results of an integer division are wrong, an operation that shouldn't have overflowed did, a
bound instruction failed, or an illegal operation was attempted. The only time a return is reasonable is when the handler alters
the registers so that a reasonable return context exists or the signal type indicates that the signal was generated explicitly (for
example, FPE_EXPLICITGEN, SEGV_EXPLICITGEN, or ILL_EXPLICITGEN). Generally in this case you would print an error
message and terminate the program using _exit, exit, or abort. If a return is executed under any other conditions, the program's
action will probably be unpredictable.

Remarque: Take special care when using the signal function in a multithread program. The SIGINT, SIGTERM, and SIGBREAK
signals can be used only by the main thread (thread one) in a non-Win32 application. When one of these signals occurs, the
currently executing thread is suspended, and control transfers to the signal handler (if any) set up by thread one. Other signals
can be handled by any thread.

Remarque: A signal handler should not use C++ runtime library functions, because a semaphore deadlock might occur. Instead,
the handler should simply set a flag or post a semaphore, and return immediately.

Return Value

On success, signal returns a pointer to the previous handler routine for the specified signal type.

On error, signal returns SIG_ERR, and the external variable errno is set to EINVAL.

Example
/* signal example */
/*
This example installs a signal handler routine for SIGFPE,
catches an integer overflow condition, makes an adjustment to AX
register, and returns. This example program MAY cause your computer
to crash, and will produce runtime errors depending on which memory
model is used.
*/
#pragma inline
#include <stdio.h>
#include <signal.h>
#ifdef __cplusplus
typedef void (*fptr)(int);
#else
typedef void (*fptr)();
#endif
void Catcher(int *reglist)
{ 3
signal(SIGFPE, (fptr)Catcher); // ******reinstall signal handler
printf("Caught it!\n"); *(reglist + 8) = 3; /* make return AX = 3 */
}
int main(void)
{
signal(SIGFPE, (fptr)Catcher); /* cast Catcher to appropriate type */
asm mov ax,07FFFH /* AX = 32767 */
asm inc ax /* cause overflow */
asm into /* activate handler */
/* The handler set AX to 3 on return. If that had not happened,

1011
C Runtime Library Reference RAD Studio 3.1 Référence C++

there would have been another exception when the next 'into'
executed after the 'dec' instruction. */
asm dec ax /* no overflow now */
asm into /* doesn't activate */
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.26 stdarg.h
The following functions, macros, and classes are provided in stdarg.h:

Rubriques
Nom Description
va_arg, va_end, va_start ( see page 1012) Header File
stdarg.h
Category
Variable Argument List Routines
Prototype
void va_start(va_list ap, lastfix);
type va_arg(va_list ap, type);
void va_end(va_list ap);
Description
Implement a variable argument list.
Some C functions, such as vfprintf and vprintf, take variable argument lists in
addition to taking a number of fixed (known) parameters. The va_arg, va_end,
and va_start macros provide a portable way to access these argument lists. They
are used for stepping through a list of arguments when the called function does
not know the number and types of the arguments being passed.
The header file stdarg.h declares one type (va_list) and... suite ( see page
1012)

3.1.5.26.1 va_arg, va_end, va_start


Header File

stdarg.h

Category

Variable Argument List Routines

Prototype
void va_start(va_list ap, lastfix);
type va_arg(va_list ap, type);
3
void va_end(va_list ap);

Description

Implement a variable argument list.

Some C functions, such as vfprintf and vprintf, take variable argument lists in addition to taking a number of fixed (known)
parameters. The va_arg, va_end, and va_start macros provide a portable way to access these argument lists. They are used for
stepping through a list of arguments when the called function does not know the number and types of the arguments being

1012
3.1 Référence C++ RAD Studio C Runtime Library Reference

passed.

The header file stdarg.h declares one type (va_list) and three macros (va_start, va_arg, and va_end).

• va_list: This array holds information needed by va_arg and va_end. When a called function takes a variable argument list, it
declares a variable ap of type va_list.
• va_start: This routine (implemented as a macro) sets ap to point to the first of the variable arguments being passed to the
function. va_start must be used before the first call to va_arg or va_end.
• va_start takes two parameters: ap and lastfix. (ap is explained under va_list in the preceding paragraph; lastfix is the name of
the last fixed parameter being passed to the called function.)
• va_arg: This routine (also implemented as a macro) expands to an expression that has the same type and value as the next
argument being passed (one of the variable arguments). The variable ap to va_arg should be the same ap that va_start
initialized.
Remarque: Because of default promotions, you cannot use char, unsigned char
, or float types with va_arg.
Remarque: The first time va_arg is used, it returns the first argument in the list. Each successive time va_arg is used, it
returns the next argument in the list. It does this by first dereferencing ap, and then incrementing ap to point to the following
item. va_arg uses the type to both perform the dereference and to locate the following item. Each successive time va_arg is
invoked, it modifies ap to point to the next argument in the list.
• va_end: This macro helps the called function perform a normal return. va_end might modify ap in such a way that it cannot be
used unless va_start is recalled. va_end should be called after va_arg has read all the arguments; failure to do so might
cause strange, undefined behavior in your program.
Return Value
va_start and va_end return no values; va_arg returns the current argument in the list (the one that ap is pointing to).
Example
#include <stdio.h>
#include <stdarg.h>
/* calculate sum of a 0 terminated list */
void sum(char *msg, ...)
{
int total = 0;
va_list ap;
int arg;
va_start(ap, msg);
while ((arg = va_arg(ap,int)) != 0) {
total += arg;
}
printf(msg, total);
va_end(ap);
}
int main(void) {
sum("The total of 1+2+3+4 is %d\n", 1,2,3,4,0);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++ 3


+ + + +

3.1.5.27 stddef.h
The following functions, macros, and classes are provided in stddef.h:

1013
C Runtime Library Reference RAD Studio 3.1 Référence C++

Rubriques
Nom Description
NULL #define ( see page 1014) Header File
stddef.h
Description
Null pointer constant that is compatible with any data object pointer. It is not
compatible with function pointers. When a pointer is equivalent to NULL it is
guaranteed not to point to any data object defined within the program.
_threadid ( see page 1014) Header File
stddef.h
Syntax
extern long _threadid;
Description
_threadid is a long integer that contains the ID of the currently executing thread.
It is implemented as a macro, and should be declared only by including stddef.h.
offsetof ( see page 1015) Header File
stddef.h
Category
Memory Routines
Prototype
size_t offsetof(struct_type, struct_member);
Description
Gets the byte offset to a structure member.
offsetof is available only as a macro. The argument struct_type is a struct type.
struct_member is any element of the struct that can be accessed through the
member selection operators or pointers.
If struct_member is a bit field, the result is undefined.
See also sizeof for more information on memory allocation and alignment of
structures.
Return Value
offsetof returns the number of bytes from the start of the structure to the start of
the named structure member.
Portability

3.1.5.27.1 NULL #define


Header File

stddef.h

Description

Null pointer constant that is compatible with any data object pointer. It is not compatible with function pointers. When a pointer is
equivalent to NULL it is guaranteed not to point to any data object defined within the program.

3.1.5.27.2 _threadid
Header File

stddef.h
3 Syntax
extern long _threadid;

Description

_threadid is a long integer that contains the ID of the currently executing thread. It is implemented as a macro, and should be
declared only by including stddef.h.

1014
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.27.3 offsetof
Header File

stddef.h

Category

Memory Routines

Prototype
size_t offsetof(struct_type, struct_member);

Description

Gets the byte offset to a structure member.

offsetof is available only as a macro. The argument struct_type is a struct type. struct_member is any element of the struct that
can be accessed through the member selection operators or pointers.

If struct_member is a bit field, the result is undefined.

See also sizeof for more information on memory allocation and alignment of structures.

Return Value

offsetof returns the number of bytes from the start of the structure to the start of the named structure member.

Portability

POSIX Win32 ANSI C ANSI C++


+ + +

3.1.5.28 stdio.h
The following functions, macros, and classes are provided in stdio.h:

Rubriques
Nom Description
BUFSIZ #define ( see page 1031) Header File
stdio.h
Description
Default buffer size used by setbuf function.
_F_xxxx #defines ( see page 1031) Header File
stdio.h
Description
File status flags of streams
OPEN_MAX #define ( see page 1032) Header File
stdio.h
3
Description
Number of files that can be open simultaneously.
L_ctermid #define ( see page 1032) Header File
stdio.h
Description
The length of a device id string.

1015
C Runtime Library Reference RAD Studio 3.1 Référence C++

L_tmpnam #define ( see page 1032) Header File


stdio.h
Description
Size of an array large enough to hold a temporary file name string.
TMP_MAX #define ( see page 1032) Header File
stdio.h
Description
Maximum number of unique file names.
_IOxxx #defines ( see page 1033) Header File
stdio.h
Description
Constants for defining buffering style to be used with a file.
_fsopen, _wfsopen ( see page 1033) Header File
stdio.h, share.h
Category
Input/output Routines
Prototype
FILE *_fsopen(const char *filename, const char *mode, int
shflag);
FILE *_wfsopen(const wchar_t *filename, const wchar_t
*mode, int shflag);
Description
Opens a stream with file sharing.
_fsopen opens the file named by filename and associates a stream with it.
_fsopen returns a pointer that is used to identify the stream in subsequent
operations.
The mode string used in calls to _fsopen is one of the following values:
_popen, _wpopen ( see page 1035) Header File
stdio.h
Category
Input/output Routines
Prototype
FILE *_popen (const char *command, const char *mode);
FILE *_wpopen (const wchar_t *command, const wchar_t *mode);
Description
Creates a command processor pipe.
The _popen function creates a pipe to the command processor. The command
processor is executed asynchronously, and is passed the command line in
command. The mode string specifies whether the pipe is connected to the
command processor’s standard input or output, and whether the pipe is to be
opened in binary or text mode.
The mode string can take one of the following values:
_vsnprintf;_vsnwprintf ( see page 1036) Header File
stdio.h
Category
Memory and String Manipulation Routines
Prototype
int _vsnprintf(char* buffer, size_t nsize, const char*
format, va_list param);
int _vsnwprintf(wchar_t* buffer, size_t nsize, const
wchar_t* format, va_list param);
Description
Sends formatted output to a string of a maximum length specified by nsize.
_vsnprintf and _vsnwprintf are Microsoft compatible with the _vsnprintf and
_vsnprintfw functions, respectively.
3 If the number of bytes to output is:

• < nsize, then all of the characters have been written,


including the terminating ‘\0’ character.
• == nsize, then nsize characters are written with no
terminating ‘\0’ character.
If nsize is 0, then the string will... suite ( see page 1036)

1016
3.1 Référence C++ RAD Studio C Runtime Library Reference

clearerr ( see page 1036) Header File


stdio.h
Category
Input/output Routines
Prototype
void clearerr(FILE *stream);
Description
Resets error indication.
clearerr resets the named stream's error and end-of-file indicators to 0. Once the
error indicator is set, stream operations continue to return error status until a call
is made to clearerr or rewind. The end-of-file indicator is reset with each input
operation.
Return Value
None.
Example
EOF #define ( see page 1037) Header File
stdio.h
Description
A constant indicating that end-of-file has been reached on a file.
fclose ( see page 1037) Header File
stdio.h
Category
Input/output Routines
Prototype
int fclose(FILE *stream);
Description
Closes a stream.
fclose closes the named stream. All buffers associated with the stream are
flushed before closing. System-allocated buffers are freed upon closing. Buffers
assigned with setbuf or setvbuf are not automatically freed. (But if setvbuf is
passed null for the buffer pointer it will free it upon close.)
Return Value
fclose returns 0 on success. It returns EOF if any errors were detected.
Portability
_fcloseall ( see page 1038) Header File
stdio.h
Category
Input/output Routines
Prototype
int _fcloseall(void);
Description
Closes open streams.
_fcloseall closes all open streams except
stdauxstdstreams
When _fcloseall flushes the associated buffers before closing a stream. The
buffers allocated by the system are released.
Remarque: stdprn and stdaux streams are not available in Win32.
Return Value
_fcloseall returns the total number of streams it closed. The _fcloseall function
returns EOF if any errors were detected.
Example
_fdopen, _wfdopen ( see page 1039) Header File
stdio.h
Category
Input/output Routines 3
Prototype
FILE *_fdopen(int handle, char *type);
FILE *_wfdopen(int handle, wchar_t *type);
Description
Associates a stream with a file handle.
_fdopen associates a stream with a file handle obtained from creat, dup, dup2, or
open.
The type of stream must match the mode of the open handle.
The type string used in a call to _fdopen is one of the following values:

1017
C Runtime Library Reference RAD Studio 3.1 Référence C++

feof ( see page 1040) Header File


stdio.h
Category
Input/output Routines
Prototype
int feof(FILE *stream);
Description
Detects end-of-file on a stream.
feof is a macro that tests the given stream for an end-of-file indicator. Once the
indicator is set read operations on the file return the indicator until rewind is
called or the file is closed. The end-of-file indicator is reset with each input
operation.
Return Value
feof returns nonzero if an end-of-file indicator was detected on the last input
operation on the named stream and 0 if end-of-file has not been reached.
Example
ferror ( see page 1041) Header File
stdio.h
Category
Input/output Routines
Prototype
int ferror(FILE *stream);
Description
Detects errors on stream.
ferror is a macro that tests the given stream for a read or write error. If the
stream's error indicator has been set it remains set until clearerr or rewind is
called or until the stream is closed.
Return Value
ferror returns nonzero if an error was detected on the named stream.
Example
fflush ( see page 1042) Header File
stdio.h
Category
Input/output Routines
Prototype
int fflush(FILE *stream);
Description
Flushes a stream.
If the given stream has buffered output fflush writes the output for stream to the
associated file.
The stream remains open after fflush has executed. fflush has no effect on an
unbuffered stream.
Return Value
fflush returns 0 on success. It returns EOF if any errors were detected.
Example
fgetc, fgetwc ( see page 1043) Header File
stdio.h
Category
Input/output Routines
Prototype
int fgetc(FILE *stream);
wint_t fgetwc(FILE *stream);
Description
Gets character from stream.
3 fgetc returns the next character on the named input stream.
Return Value
On success fgetc returns the character read after converting it to an int without
sign extension. On end-of-file or error it returns EOF.
Example

1018
3.1 Référence C++ RAD Studio C Runtime Library Reference

_fgetchar, _fgetwchar ( see page 1044) Header File


stdio.h
Category
Console I/O Routines
Prototype
int _fgetchar(void);
wint_t _fgetwchar(void);
Description
Reads a character from stdin.
_fgetchar returns the next character from stdin. It is defined as fgetc(stdin).
Remarque: For Win32 GUI applications, stdin must be redirected.
Return Value
On success _fgetchar returns the character read after converting it to an int
without sign extension. On end-of-file or error it returns EOF.
Example
fgetpos ( see page 1044) Header File
stdio.h
Category
Input/output Routines
Prototype
int fgetpos(FILE *stream, fpos_t *pos);
Description
Gets the current file pointer.
fgetpos stores the position of the file pointer associated with the given stream in
the location pointed to by pos. The exact value is unimportant; its value is
opaque except as a parameter to subsequent fsetpos calls.
Return Value
On success fgetpos returns 0. On failure it returns a nonzero value and sets the
global variable errno to
fgets, fgetws ( see page 1046) Header File
stdio.h
Category
Input/output Routines
Prototype
char *fgets(char *s, int n, FILE *stream);
wchar_t *fgetws(wchar_t *s, int n, FILE *stream); //
Unicode version
Description
Gets a string from a stream.
fgets reads characters from stream into the string s. The function stops reading
when it reads either n - 1 characters or a newline character whichever comes
first. fgets retains the newline character at the end of s. A null byte is appended
to s to mark the end of the string.
Return Value
On success fgets returns the string pointed to by s; it returns NULL on
end-of-file... suite ( see page 1046)
_flushall ( see page 1046) Header File
stdio.h
Category
Input/output Routines
Prototype
int _flushall(void);
Description
Flushes all streams.
_flushall clears all buffers associated with open input streams and writes all
buffers associated with open output streams to their respective files. Any read 3
operation following _flushall reads new data into the buffers from the input files.
Streams stay open after _flushall executes.
Return Value
_flushall returns an integer the number of open input and output streams.
Example

1019
C Runtime Library Reference RAD Studio 3.1 Référence C++

fopen, _wfopen ( see page 1047) Header File


stdio.h
Category
Input/output Routines
Prototype
FILE *fopen(const char *filename, const char *mode);
FILE *_wfopen(const wchar_t *filename, const wchar_t *mode);
Description
Opens a stream.
fopen opens the file named by filename and associates a stream with it. fopen
returns a pointer to be used to identify the stream in subsequent operations.
The mode string used in calls to fopen is one of the following values:
fprintf, fwprintf ( see page 1048) Header File
stdio.h
Category
Input/output Routines
Prototype
int fprintf(FILE *stream, const char *format[, argument,
...]);
int fwprintf(FILE *stream, const wchar_t *format[,
argument, ...]);
Description
Writes formatted output to a stream.
fprintf accepts a series of arguments applies to each a format specifier contained
in the format string pointed to by format and outputs the formatted data to a
stream. There must be the same number of format specifiers as arguments.
Remarque: For details on format specifiers, see printf Format Specifiers.
Return Value
fprintf returns the number of bytes output. In the event of error it returns EOF.
Example
fputc, fputwc ( see page 1049) Header File
stdio.h
Category
Input/output Routines
Prototype
int fputc(int c, FILE *stream);
wint_t fputwc(wint_t c, FILE *stream);
Description
Puts a character on a stream.
fputc outputs character c to the named stream.
Remarque: For Win32 GUI applications, stdin must be redirected.
Return Value
On success, fputc returns the character c. On error, it returns EOF.
Example
_fputchar, _fputwchar ( see page 1050) Header File
stdio.h
Category
Input/output Routines
Prototype
int _fputchar(int c);
wint_t _fputwchar(wint_t c);
Description
Outputs a character to stdout.
_fputchar outputs character c to stdout. _fputchar(c) is the same as fputc(cstdout).
3 Remarque: For Win32 GUI applications, stdout must be redirected.
Return Value
On success _fputchar returns the character c.
On error it returns EOF.
Example

1020
3.1 Référence C++ RAD Studio C Runtime Library Reference

fputs, fputws ( see page 1051) Header File


stdio.h
Category
Input/output Routines
Prototype
int fputs(const char *s, FILE *stream);
int fputws(const wchar_t *s, FILE *stream);
Description
Outputs a string on a stream.
fputs copies the null-terminated string s to the given output stream; it does not
append a newline character and the terminating null character is not copied.
Return Value
On success fputs returns a non-negative value.
On error it returns a value of EOF.
Example
fread ( see page 1051) Header File
stdio.h
Category
Input/output Routines
Prototype
size_t fread(void *ptr, size_t size, size_t n, FILE
*stream);
Description
Reads data from a stream.
fread reads n items of data each of length size bytes from the given input stream
into a block pointed to by ptr.
The total number of bytes read is (n * size).
Return Value
On success fread returns the number of items (not bytes) actually read.
On end-of-file or error it returns a short count (possibly 0).
Example
freopen, _wfreopen ( see page 1052) Header File
stdio.h
Category
Input/output Routines
Prototype
FILE *freopen(const char *filename, const char *mode, FILE
*stream);
FILE *_wfreopen(const wchar_t *filename, const wchar_t
*mode, FILE *stream);
Description
Associates a new file with an open stream.
freopen substitutes the named file in place of the open stream. It closes stream
regardless of whether the open succeeds. freopen is useful for changing the file
attached to stdin, stdout, or stderr.
The mode string used in calls to fopen is one of the following values:
fscanf, fwscanf ( see page 1053) Header File
stdio.h
Category
Input/output Routines
Prototype
int fscanf(FILE *stream, const char *format[, address,
...]);
int fwscanf(FILE *stream, const wchar_t *format[, address,
...]);
Description 3
Scans and formats input from a stream.
fscanf scans a series of input fields one character at a time reading from a
stream. Then each field is formatted according to a format specifier passed to
fscanf in the format string pointed to by format. Finally fscanf stores the formatted
input at an address passed to it as an argument following format. The number of
format specifiers and addresses must be the same as the number of... suite (
see page 1053)

1021
C Runtime Library Reference RAD Studio 3.1 Référence C++

fseek ( see page 1054) Header File


stdio.h
Category
Input/output Routines
Prototype
int fseek(FILE *stream, long offset, int whence);
Description
Repositions a file pointer on a stream.
fseek sets the file pointer associated with stream to a new position that is offset
bytes from the file location given by whence. For text mode streams offset should
be 0 or a value returned by ftell.
whence must be one of the values 0. 1, or 2 which represent three symbolic
constants (defined in stdio.h) as follows:
fseek discards any character pushed back using ungetc. fseek is used with
stream I/O; for file handle I/O use lseek.... suite ( see page 1054)
fsetpos ( see page 1056) Header File
stdio.h
Category
Input/output Routines
Prototype
int fsetpos(FILE *stream, const fpos_t *pos);
Description
Positions the file pointer of a stream.
fsetpos sets the file pointer associated with stream to a new position. The new
position is the value obtained by a previous call to fgetpos on that stream. It also
clears the end-of-file indicator on the file that stream points to and undoes any
effects of ungetc on that file. After a call to fsetpos the next operation on the file
can be input or output.
Return Value
On success fsetpos returns 0.
On failure it returns a nonzero... suite ( see page 1056)
ftell ( see page 1056) Header File
stdio.h
Category
Input/output Routines
Prototype
long int ftell(FILE *stream);
Description
Returns the current file pointer.
ftell returns the current file pointer for stream. The offset is measured in bytes
from the beginning of the file (if the file is binary). The value returned by ftell can
be used in a subsequent call to fseek.
Return Value
ftell returns the current file pointer position on success. It returns -1L on error and
sets the global variable errno to a positive value.
In the event of an error return the global variable errno is set to one of the
following... suite ( see page 1056)
fwrite ( see page 1057) Header File
stdio.h
Category
Input/output Routines
Prototype
size_t fwrite(const void *ptr, size_t size, size_t n, FILE
*stream);
Description
3 Writes to a stream.
fwrite appends n items of data each of length size bytes to the given output file.
The data written begins at ptr. The total number of bytes written is (n x size). ptr
in the declarations is a pointer to any object.
Return Value
On successful completion fwrite returns the number of items (not bytes) actually
written.
On error it returns a short count.
Example

1022
3.1 Référence C++ RAD Studio C Runtime Library Reference

getc, getwc ( see page 1058) Header File


stdio.h
Category
Input/output Routines
Prototype
int getc(FILE *stream);
wint_t getwc(FILE *stream);
Description
Gets character from stream.
getc returns the next character on the given input stream and increments the
stream's file pointer to point to the next character.
Remarque: For Win32 GUI applications, stdin must be redirected.
Return Value
On success, getc returns the character read, after converting it to an int without
sign extension.
On end-of-file or error, it returns EOF.
Example
getchar, getwchar ( see page 1059) Header File
stdio.h
Category
Console I/O Routines
Prototype
int getchar(void);
wint_t getwchar(void);
Description
Gets character from stdin.
getchar is a macro that returns the next character on the named input stream
stdin. It is defined to be getc(stdin).
Remarque: Do not use this function in Win32 GUI applications.
Return Value
On success, getchar returns the character read, after converting it to an int
without sign extension.
On end-of-file or error, it returns EOF.
Example
gets, _getws ( see page 1059) Header File
stdio.h
Category
Console I/O Routines
Prototype
char *gets(char *s);
wchar_t *_getws(wchar_t *s); // Unicode version
Description
Gets a string from stdin.
gets collects a string of characters terminated by a new line from the standard
input stream stdin and puts it into s. The new line is replaced by a null character
(\0) in s.
gets allows input strings to contain certain whitespace characters (spaces, tabs).
gets returns when it encounters a new line; everything up to the new line is
copied into s.
The gets function is not length-terminated. If the input string is sufficiently large,
data... suite ( see page 1059)

1023
C Runtime Library Reference RAD Studio 3.1 Référence C++

_getw ( see page 1060) Header File


stdio.h
Category
Input/output Routines
Prototype
int _getw(FILE *stream);
Description
Gets an integer from stream.
_getw returns the next integer in the named input stream. It assumes no special
alignment in the file.
_getw should not be used when the stream is opened in text mode.
Return Value
_getw returns the next integer on the input stream.
On end-of-file or error, _getw returns EOF.
Remarque: Because EOF is a legitimate value for _getw to return, feof or ferror
should be used to detect end-of-file or error.
Example
printf, wprintf ( see page 1061) Header File
stdio.h
Category
Console I/O Routines
Prototype
int printf(const char *format[, argument, ...]);
int wprintf(const wchar_t *format[, argument, ...]);
Description
Writes formatted output to stdout.
The printf function:

• Accepts a series of arguments


• Applies to each argument a format specifier contained in
the format string *format
• Outputs the formatted data (to the screen, a stream,
stdout, or a string)
There must be enough arguments for the format. If there are
not, the results will be unpredictable and likely disastrous.
Excess arguments (more than required by the format) are
merely ignored.
Remarque: For Win32 GUI applications, stdout must be
redirected.... suite ( see page 1061)
putc, putwc ( see page 1063) Header File
stdio.h
Category
Input/output Routines
Prototype
int putc(int c, FILE *stream);
wint_t putwc(wint_t c, FILE *stream);
Description
Outputs a character to a stream.
putc is a macro that outputs the character c to the stream given by stream.
Return Value
On success, putc returns the character printed, c.
3 On error, putc returns EOF.
Example

1024
3.1 Référence C++ RAD Studio C Runtime Library Reference

putchar, putwchar ( see page 1064) Header File


stdio.h
Category
Console I/O Routines
Prototype
int putchar(int c);
wint_t putwchar(wint_t c);
Description
putchar is a macro defined to be putc(c, stdout).
Remarque: For Win32 GUI applications, stdout must be redirected.
Return Value
On success, putchar returns the character c. On error, putchar returns EOF.
Example
puts, _putws ( see page 1065) Header File
stdio.h
Category
Console I/O Routines
Prototype
int puts(const char *s);
int _putws(const wchar_t *s);
Description
Outputs a string to stdout.
puts copies the null-terminated string s to the standard output stream stdout and
appends a newline character.
Remarque: For Win32 GUI applications, stdout must be redirected.
Return Value
On successful completion, puts returns a nonnegative value. Otherwise, it returns
a value of EOF.
Example
_putw ( see page 1065) Header File
stdio.h
Category
Input/output Routines
Prototype
int _putw(int w, FILE *stream);
Description
Writes an integer on a stream.
_putw outputs the integer w to the given stream. _putw neither expects nor
causes special alignment in the file.
Return Value
On success, _putw returns the integer w. On error, _putw returns EOF. Because
EOF is a legitimate integer, use ferror to detect errors with _putw.
Example
remove, _wremove ( see page 1067) Header File
stdio.h
Category
Input/output Routines
Prototype
int remove(const char *filename);
int _wremove(const wchar_t *filename);
Description
Removes a file.
remove deletes the file specified by filename. It is a macro that simply translates
its call to a call to unlink. If your file is open, be sure to close it before removing it.
The filename string can include a full path. 3
Return Value
On successful completion, remove returns 0. On error, it returns -1, and the
global variable errno is set to one of the following values:

1025
C Runtime Library Reference RAD Studio 3.1 Référence C++

rename, _wrename ( see page 1068) Header File


stdio.h
Category
Input/output Routines
Prototype
int rename(const char *oldname, const char *newname);
int _wrename(const wchar_t *oldname, const wchar_t
*newname);
Description
Renames a file.
rename changes the name of a file from oldname to newname. If a drive specifier
is given in newname, the specifier must be the same as that given in oldname.
Directories in oldname and newname need not be the same, so rename can be
used to move a file from one directory to another. Wildcards are not allowed.
This function will fail (EEXIST) if either file is currently open in any process.
Return Value
On... suite ( see page 1068)
rewind ( see page 1069) Header File
stdio.h
Category
Input/output Routines
Prototype
void rewind(FILE *stream);
Description
Repositions a file pointer to the beginning of a stream.
rewind(stream) is equivalent to fseek(stream, 0L, SEEK_SET), except that
rewind clears the end-of-file and error indicators, while fseek clears the end-of-file
indicator only.
After rewind, the next operation on an update file can be either input or output.
Return Value
None.
Example
_rmtmp ( see page 1069) Header File
stdio.h
Category
Input/output Routines
Prototype
int _rmtmp(void);
Description
Removes temporary files.
The _rmtmp function closes and deletes all open temporary file streams which
were previously created with tmpfile. The current directory must the same as
when the files were created, or the files will not be deleted.
Return Value
_rmtmp returns the total number of temporary files it closed and deleted.
Example

1026
3.1 Référence C++ RAD Studio C Runtime Library Reference

scanf, wscanf ( see page 1070) Header File


stdio.h
Category
Console I/O Routines
Prototype
int scanf(const char *format[, address, ...]);
int wscanf(const wchar_t *format[, address, ...]);
Description
Scans and formats input from the stdin stream.
Remarque: For Win32 GUI applications, stdin must be redirected.
The scanf function:

• scans a series of input fields one character at a time


• formats each field according to a corresponding format
specifier passed in the format string *format.
• vsscanf scans and formats input from a string, using an
argument list
There must be one format specifier and address for each
input field.
scanf might stop scanning a particular field before it... suite
( see page 1070)
setbuf ( see page 1072) Header File
stdio.h
Category
Input/output Routines
Prototype
void setbuf(FILE *stream, char *buf);
Description
Assigns buffering to a stream.
setbuf causes the buffer buf to be used for I/O buffering instead of an
automatically allocated buffer. It is used after stream has been opened.
If buf is null, I/O will be unbuffered; otherwise, it will be fully buffered. The buffer
must be BUFSIZ bytes long (specified in stdio.h).
stdin and stdout are unbuffered if they are not redirected; otherwise, they are fully
buffered. setbuf can be used to change the buffering style used.
Unbuffered means that characters written to a stream... suite ( see page 1072)
setvbuf ( see page 1073) Header File
stdio.h
Category
Input/output Routines
Prototype
int setvbuf(FILE *stream, char *buf, int type, size_t size);
Description
Assigns buffering to a stream.
setvbuf causes the buffer buf to be used for I/O buffering instead of an
automatically allocated buffer. It is used after the given stream is opened.
If buf is null, a buffer will be allocated using malloc; the buffer will use size as the
amount allocated. The buffer will be automatically freed on close. The size
parameter specifies the buffer size and must be greater than zero.
The parameter size is limited by the constant UINT_MAX as defined... suite (
see page 1073)

1027
C Runtime Library Reference RAD Studio 3.1 Référence C++

snprintf;snwprintf ( see page 1074) Header File


stdio.h
Category
Memory and String Manipulation Routines
Prototype
int snprintf(char* buffer, size_t nsize, const char* fmt,
...);
int snwprintf(wchar_t* buffer, size_t nsize, const wchar_t*
fmt, ...);
Description
Sends formatted output to a buffer of a maximum length specified by nsize.
If the number of bytes to output is:

• < nsize, then all of the characters have been written,


including the terminating ‘\0’ character.
• == nsize, then nsize characters are written, with no
terminating ‘\0’ character.
> nsize, then only nsize characters are written, with no
terminating ‘\0’ character.
If nsize is 0, then the string will not be... suite ( see page
1074)
sprintf, swprintf ( see page 1075) Header File
stdio.h
Category
Memory and String Manipulation Routines
Prototype
int sprintf(char *buffer, const char *format[, argument,
...]);
int swprintf(wchar_t *buffer, const wchar_t *format[,
argument, ...]);
Description
Writes formatted output to a string.
Remarque: For details on format specifiers, see printf.
sprintf accepts a series of arguments, applies to each a format specifier
contained in the format string pointed to by format, and outputs the formatted
data to a string.
sprintf applies the first format specifier to the first argument, the second to the
second, and so on. There must be the same number of format specifiers as
arguments.
Return... suite ( see page 1075)
sscanf, swscanf ( see page 1076) Header File
stdio.h
Category
Memory and String Manipulation Routines
Syntax
int sscanf(const char *buffer, const char *format[,
address, ...]);
int swscanf(const wchar_t *buffer, const wchar_t *format[,
address, ...]);
Description
Scans and formats input from a string.
Remarque: For details on format specifiers, see scanf.
sscanf scans a series of input fields, one character at a time, reading from a
string. Then each field is formatted according to a format specifier passed to
3 sscanf in the format string pointed to by format. Finally, sscanf stores the
formatted input at an address passed to it as an argument following format.
There must... suite ( see page 1076)
stderr, stdin, stdout ( see page 1077) Header File
stdio.h
Description
Predefined streams automatically opened when the program is started.

1028
3.1 Référence C++ RAD Studio C Runtime Library Reference

_tempnam, _wtempnam ( see page 1077) Header File


stdio.h
Category
Input/output Routines
Prototype
char *_tempnam(char *dir, char *prefix)
wchar_t *_wtempnam(wchar_t *dir, wchar_t *prefix)
Description
Creates a unique file name in specified directory.
The _tempnam function accepts single-byte or multibyte string arguments.
The _tempnam function creates a unique file name in arbitrary directories. The
unique file is not actually created; _tempnam only verifies that it does not
currently exist. It attempts to use the following directories, in the order shown,
when creating the file name:

• The directory specified by the TMP environment variable.


• The dir argument to _tempnam.
• The P_tmpdir definition in stdio.h. If you edit stdio.h...
suite ( see page 1077)
tmpfile ( see page 1078) Header File
stdio.h
Category
Input/output Routines
Prototype
FILE *tmpfile(void);
Description
Opens a “scratch” file in binary mode.
tmpfile creates a temporary binary file and opens it for update (w + b). If you do
not change the directory after creating the temporary file, the file is automatically
removed when it’s closed or when your program terminates.
Return Value
tmpfile returns a pointer to the stream of the temporary file created. If the file
can’t be created, tmpfile returns NULL.
Example
tmpnam, _wtmpnam ( see page 1079) Header File
stdio.h
Category
Input/output Routines
Prototype
char *tmpnam(char *s);
wchar_t *_wtmpnam(wchar_t *s);
Description
Creates a unique file name.
tmpnam creates a unique file name, which can safely be used as the name of a
temporary file. tmpnam generates a different string each time you call it, up to
TMP_MAX times. TMP_MAX is defined in stdio.h as 65,535.
The parameter to tmpnam, s, is either null or a pointer to an array of at least
L_tmpnam characters. L_tmpnam is defined in stdio.h. If s is NULL, tmpnam
leaves the generated temporary file name in an internal static object and
returns... suite ( see page 1079)
ungetc, ungetwc ( see page 1080) Header File
stdio.h
Category
Input/output Routines
Prototype
3
int ungetc(int c, FILE *stream);
wint_t ungetwc(wint_t c, FILE *stream);
Description
Pushes a character back into input stream.
Remarque: Do not use this function in Win32 GUI applications.
ungetc pushes the character c back onto the named input stream, which must be
open for reading. This character will be returned on the next call to getc or fread
for that stream. One character can be pushed back in all situations. A second call
to ungetc without a call to getc will force the previous character to be forgotten. A
call to fflush, fseek,... suite ( see page 1080)

1029
C Runtime Library Reference RAD Studio 3.1 Référence C++

vfprintf, vfwprintf ( see page 1081) Header File


stdio.h
Category
Input/output Routines
Prototype
int vfprintf(FILE *stream, const char *format, va_list
arglist);
int vfwprintf(FILE *stream, const wchar_t *format, va_list
arglist);
Description
Writes formatted output to a stream.
The v...printf functions are known as alternate entry points for the ...printf
functions. They behave exactly like their ...printf counterparts, but they accept a
pointer to a list of arguments instead of an argument list.
For details on format specifiers, see Printf Format Specifiers.
vfprintf accepts a pointer to a series of arguments, applies to each argument a
format specifier contained in the format string pointed to by format, and... suite
( see page 1081)
vfscanf ( see page 1082) Header File
stdio.h
Category
Input/output Routines
Prototype
int vfscanf(FILE *stream, const char *format,va_list
arglist);
Description
Scans and formats input from a stream.
The v...scanf functions are known as alternate entry points for the ...scanf
functions. They behave exactly like their ...scanf counterparts but they accept a
pointer to a list of arguments instead of an argument list.
For details on format specifiers, see Scanf Format Specifiers.
vfscanf scans a series of input fields one character at a time reading from a
stream. Then each field is formatted according to a format specifier passed to
vfscanf in the format string pointed... suite ( see page 1082)
vprintf, vwprintf ( see page 1083) Header File
stdio.h
Category
Console I/O Routines
Prototype
int vprintf(const char *format, va_list arglist);
int vwprintf(const wchar_t * format, va_list arglist);
Description
Writes formatted output to stdout.
Remarque: Do not use this function in Win32 GUI applications.
The v...printf functions are known as alternate entry points for the ...printf
functions. They behave exactly like their ...printf counterparts, but they accept a
pointer to a list of arguments instead of an argument list.
Remarque: For details on format specifiers, see Printf Format Specifiers.
vprintf accepts a pointer to a series of arguments, applies to each a format
specifier contained in the... suite ( see page 1083)
vscanf ( see page 1084) Header File
stdio.h
Category
Console I/O Routines
Prototype
int vscanf(const char *format, va_list arglist);
3 Description
Scans and formats input from stdin.
Remarque: Do not use this function in Win32 GUI applications.
The v...scanf functions are known as alternate entry points for the ...scanf
functions. They behave exactly like their ...scanf counterparts, but they accept a
pointer to a list of arguments instead of an argument list.
Remarque: For details on format specifiers, see Scanf Format Specifiers.
vscanf scans a series of input fields, one character at a time, reading from stdin.
Then each field is formatted according to a format... suite ( see page 1084)

1030
3.1 Référence C++ RAD Studio C Runtime Library Reference

vsnprintf;vsnwprintf ( see page 1085) Header File


stdio.h
Category
Memory and String Manipulation Routines
Prototype
int vsnprintf(char* buffer, size_t nsize, const char*
format, va_list param);
int vsnwprintf(wchar_t* buffer, size_t nsize, const
wchar_t* format, va_list param);
Description
Sends formatted output to a buffer of maximum length specified by nsize.
If the number of bytes to output is:

• < nsize, then all of the characters have been written,


including the terminating ‘\0’ character.
• == nsize, then nsize characters are written, with no
terminating ‘\0’ character.
> nsize, then only nsize characters are written, with no
terminating ‘\0’ character.
If nsize is 0, then the string will not... suite ( see page 1085)
vsprintf, vswprintf ( see page 1086) Header File
stdio.h
Category
Memory and String Manipulation Routines
Prototype
int vsprintf(char *buffer, const char *format, va_list
arglist);
int vswprintf(wchar_t *buffer, const wchar_t *format,
va_list arglist);
Description
Writes formatted output to a string.
The v...printf functions are known as alternate entry points for the ...printf
functions. They behave exactly like their ...printf counterparts, but they accept a
pointer to a list of arguments instead of an argument list.
vsprintf accepts a pointer to a series of arguments, applies to each a format
specifier contained in the format string pointed to by format, and outputs the
formatted data to a string.... suite ( see page 1086)

3.1.5.28.1 BUFSIZ #define


Header File

stdio.h

Description

Default buffer size used by setbuf function.

3.1.5.28.2 _F_xxxx #defines


Header File
3
stdio.h

Description

File status flags of streams

Name Meaning
_F_RDWR Read and write

1031
C Runtime Library Reference RAD Studio 3.1 Référence C++

_F_READ Read-only file


_F_WRIT Write-only file
_F_BUF Malloc'ed buffer data
_F_LBUF Line-buffered file
_F_ERR Error indicator
_F_EOF EOF indicator
_F_BIN Binary file indicator
_F_IN Data is incoming
_F_OUT Data is outgoing
_F_TERM File is a terminal

3.1.5.28.3 OPEN_MAX #define


Header File

stdio.h

Description

Number of files that can be open simultaneously.

Name Meaning
FOPEN_MAX Maximum files per process
SYS_OPEN Maximum files for system

3.1.5.28.4 L_ctermid #define


Header File

stdio.h

Description

The length of a device id string.

3.1.5.28.5 L_tmpnam #define


Header File

stdio.h
3 Description

Size of an array large enough to hold a temporary file name string.

3.1.5.28.6 TMP_MAX #define


Header File

stdio.h

1032
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

Maximum number of unique file names.

3.1.5.28.7 _IOxxx #defines


Header File

stdio.h

Description

Constants for defining buffering style to be used with a file.

Name Meaning
_IOFBF The file is fully buffered. When a buffer is empty, the next input operation will attempt to fill the entire
buffer.
On output, the buffer will be completely filled before any data is written to the file.
_IOLBF The file is line buffered. When a buffer is empty, the next input operation will still attempt to fill the
entire buffer.
On output, however, the buffer will be flushed whenever a newline character is written to the file.
_IONBF The file is unbuffered. The buf and size parameters of setbuf are ignored. Each input operation will
read directly from the file, and each output operation will immediately write the data to the file.

3.1.5.28.8 _fsopen, _wfsopen


Header File

stdio.h, share.h

Category

Input/output Routines

Prototype
FILE *_fsopen(const char *filename, const char *mode, int shflag);
FILE *_wfsopen(const wchar_t *filename, const wchar_t *mode, int shflag);

Description

Opens a stream with file sharing.

_fsopen opens the file named by filename and associates a stream with it. _fsopen returns a pointer that is used to identify the
stream in subsequent operations.

The mode string used in calls to _fsopen is one of the following values:
3
r Open for reading only.
w Create for writing. If a file by that name already exists, it will be overwritten.
a Append; open for writing at end of file. or create for writing if the file does not exist.
r+ Open an existing file for update (reading and writing).
w+ Create a new file for update (reading and writing). If a file by that name already exists, it will be
overwritten.

1033
C Runtime Library Reference RAD Studio 3.1 Référence C++

a+ Open for append; open (or create if the file does not exist) for update at the end of the file.

To specify that a given file is being opened or created in text mode append a t to the mode string (rt w+t and so on). Similarly to
specify binary mode append a b to the mode string (wb a+b and so on). _fsopen also allows the t or b to be inserted between the
letter and the + character in the mode string; for example rt+ is equivalent to r+t. If a t or b is not given in the mode string the
mode is governed by the global variable _fmode. If _fmode is set to O_BINARY files are opened in binary mode. If _fmode is set
to O_TEXT they are opened in text mode. These O_... constants are defined in fcntl.h.

When a file is opened for update, both input and output can be done on the resulting stream, however:

• output cannot be directly followed by input without an intervening fseek or rewind


• input cannot be directly followed by output without an intervening fseek, rewind, or an input that encounters end-of-file
shflag specifies the type of file-sharing allowed on the file filename. Symbolic constants for shflag are defined in share.h.

SH_COMPAT Sets compatibility mode


SH_DENYRW Denies read/write access
SH_DENYWR Denies write access
SH_DENYRD Denies read access
SH_DENYNONE Permits read/write access
SH_DENYNO Permits read/write access

Return Value

On successful completion _fsopen returns a pointer to the newly opened stream.

On error it returns NULL.

Example
#include <io.h>
#include <process.h>
#include <share.h>
#include <stdio.h>
int main(void)
{
FILE *f;
int status;
f = _fsopen("TESTFILE.DAT", "r", SH_DENYNO);
if (f == NULL)
{
printf("_fsopen failed\n");
exit(1);
}
status = access("TESTFILE.DAT", 6);
if (status == 0)
printf("read/write access allowed\n");
else
printf("read/write access not allowed\n");
3 fclose(f);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_fsopen +
_wfsopen NT only

1034
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.28.9 _popen, _wpopen


Header File

stdio.h

Category

Input/output Routines

Prototype
FILE *_popen (const char *command, const char *mode);
FILE *_wpopen (const wchar_t *command, const wchar_t *mode);

Description

Creates a command processor pipe.

The _popen function creates a pipe to the command processor. The command processor is executed asynchronously, and is
passed the command line in command. The mode string specifies whether the pipe is connected to the command processor’s
standard input or output, and whether the pipe is to be opened in binary or text mode.

The mode string can take one of the following values:

rt Read child command’s standard output (text).


rb Read child command’s standard output (binary).
wt Write to child command’s standard input (text).
wb Write to child command’s standard input (binary).

The terminating t or b is optional; if missing, the translation mode is determined by the external variable _fmode.

Use the _pclose function to close the pipe and obtain the return code of the command.

Return Value

On success, _popen returns a FILE pointer that can be used to read the standard output of the command, or to write to the
standard input of the command, depending on the mode string.

On error, it returns NULL.

Example
/* this program initiates a child process to run the dir command
and pipes the directory listing from the child to the parent.
*/
#include <stdio.h> // popen() pclose() feof() fgets() puts()
#include <string.h> // strlen()
int main( )
{
FILE* handle; // handle to one end of pipe 3
char message[256]; // buffer for text passed through pipe
int status; // function return value
// open a pipe to receive text from a process running "DIR"
handle = _popen("dir /b", "rt");
if (handle == NULL)
{
perror("_popen error");
}
// read and display input received from the child process
while (fgets(message, sizeof(message), handle))

1035
C Runtime Library Reference RAD Studio 3.1 Référence C++

{
fprintf(stdout, message);
}
// close the pipe and check the return status
status = _pclose(handle);
if (status == -1)
{
perror("_pclose error");
}
return(0);
}
Portability

POSIX Win32 ANSI C ANSI C++


_popen +
_wpopen NT only

3.1.5.28.10 _vsnprintf;_vsnwprintf
Header File

stdio.h

Category

Memory and String Manipulation Routines

Prototype
int _vsnprintf(char* buffer, size_t nsize, const char* format, va_list param);
int _vsnwprintf(wchar_t* buffer, size_t nsize, const wchar_t* format, va_list param);

Description

Sends formatted output to a string of a maximum length specified by nsize. _vsnprintf and _vsnwprintf are Microsoft compatible
with the _vsnprintf and _vsnprintfw functions, respectively.

If the number of bytes to output is:

• < nsize, then all of the characters have been written, including the terminating ‘\0’ character.
• == nsize, then nsize characters are written with no terminating ‘\0’ character.
If nsize is 0, then the string will not be written to (and may be NULL).
If nsize is too small, then return value is -1, and only nsize characters are written, with no terminating ‘\0’ character.
Return Value
Number of bytes output or –1 if nsize is too small.

3 3.1.5.28.11 clearerr
Header File

stdio.h

Category

Input/output Routines

1036
3.1 Référence C++ RAD Studio C Runtime Library Reference

Prototype
void clearerr(FILE *stream);

Description

Resets error indication.

clearerr resets the named stream's error and end-of-file indicators to 0. Once the error indicator is set, stream operations
continue to return error status until a call is made to clearerr or rewind. The end-of-file indicator is reset with each input operation.

Return Value

None.

Example
#include <stdio.h>
int main(void)
{
FILE *fp;
char ch;
/* open a file for writing */
fp = fopen("DUMMY.FIL", "w");
/* force an error condition by attempting to read */
ch = fgetc(fp);
printf("%c\n",ch);
if (ferror(fp))
{
/* display an error message */
printf("Error reading from DUMMY.FIL\n");
/* reset the error and EOF indicators */
clearerr(fp);
}
fclose(fp);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.12 EOF #define


Header File

stdio.h

Description

A constant indicating that end-of-file has been reached on a file.

3
3.1.5.28.13 fclose
Header File

stdio.h

Category

Input/output Routines

1037
C Runtime Library Reference RAD Studio 3.1 Référence C++

Prototype
int fclose(FILE *stream);

Description

Closes a stream.

fclose closes the named stream. All buffers associated with the stream are flushed before closing. System-allocated buffers are
freed upon closing. Buffers assigned with setbuf or setvbuf are not automatically freed. (But if setvbuf is passed null for the buffer
pointer it will free it upon close.)

Return Value

fclose returns 0 on success. It returns EOF if any errors were detected.

Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.14 _fcloseall
Header File

stdio.h

Category

Input/output Routines

Prototype
int _fcloseall(void);

Description

Closes open streams.

_fcloseall closes all open streams except

stdauxstdstreams

When _fcloseall flushes the associated buffers before closing a stream. The buffers allocated by the system are released.

Remarque: stdprn and stdaux streams are not available in Win32.

Return Value

_fcloseall returns the total number of streams it closed. The _fcloseall function returns EOF if any errors were detected.

Example

3 #include <stdio.h>
int main(void)
{
int streams_closed;
/* open two streams */
fopen("DUMMY.ONE", "w");
fopen("DUMMY.TWO", "w");
/* close the open streams */
streams_closed = fcloseall();
if (streams_closed == EOF)
/* issue an error message */

1038
3.1 Référence C++ RAD Studio C Runtime Library Reference

perror("Error");
else
/* print result of fcloseall() function */
printf("%d streams were closed.\n", streams_closed);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.28.15 _fdopen, _wfdopen


Header File

stdio.h

Category

Input/output Routines

Prototype
FILE *_fdopen(int handle, char *type);
FILE *_wfdopen(int handle, wchar_t *type);

Description

Associates a stream with a file handle.

_fdopen associates a stream with a file handle obtained from creat, dup, dup2, or open.

The type of stream must match the mode of the open handle.

The type string used in a call to _fdopen is one of the following values:

r Open for reading only. _fdopen returns NULL if the file cannot be opened.
w Create for writing. If the file already exists, its contents are overwritten.
a Append; open for writing at end-of-file or create for writing if the file does not exist.
r+ Open an existing file for update (reading and writing). _fdopen returns NULL if the file cannot be
opened.
w+ Create a new file for update. If the file already exists, its contents are overwritten.
a+ Open for append; open (or create if the file does not exist) for update at the end of the file.

To specify that a given file is being opened or created in text mode, append t to the value of the type string (for example, rt or
w+t).

Similarly, to specify binary mode, append b to the type string (for example, rb or w+b). 3
If t or b is not given in the type string, the mode is governed by the global variable _fmode.

If _fmode is set to O_BINARY, files will be opened in binary mode.

If _fmode is set to O_TEXT, files will be opened in text mode.

Note:The O_... constants are defined in fcntl.h.

When a file is opened for update, both input and output can be done on the resulting stream; however,

1039
C Runtime Library Reference RAD Studio 3.1 Référence C++

• output cannot be directly followed by input without an intervening fseek or rewind


• input cannot be directly followed by output without an intervening fseek, rewind, or an input that encounters end-of-file
Return Value
On successful completion _fdopen returns a pointer to the newly opened stream. In the event of error it returns NULL.
Example
#include <sys\stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main(void)
{
int handle;
FILE *stream;
/* open a file */
handle = open("DUMMY.FIL", O_CREAT,
S_IREAD | S_IWRITE);
/* now turn the handle into a stream */
stream = fdopen(handle, "w");
if (stream == NULL)
printf("fdopen failed\n");
else
{
fprintf(stream, "Hello world\n");
fclose(stream);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_fdopen + +
_wfdopen +

3.1.5.28.16 feof
Header File

stdio.h

Category

Input/output Routines

Prototype
int feof(FILE *stream);

Description
3
Detects end-of-file on a stream.

feof is a macro that tests the given stream for an end-of-file indicator. Once the indicator is set read operations on the file return
the indicator until rewind is called or the file is closed. The end-of-file indicator is reset with each input operation.

Return Value

feof returns nonzero if an end-of-file indicator was detected on the last input operation on the named stream and 0 if end-of-file
has not been reached.

1040
3.1 Référence C++ RAD Studio C Runtime Library Reference

Example
#include <stdio.h>
int main(void)
{
FILE *stream;
/* open a file for reading */
stream = fopen("DUMMY.FIL", "r");
/* read a character from the file */
fgetc(stream);
/* check for EOF */
if (feof(stream))
printf("We have reached end-of-file\n");
/* close the file */
fclose(stream);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.17 ferror
Header File

stdio.h

Category

Input/output Routines

Prototype
int ferror(FILE *stream);

Description

Detects errors on stream.

ferror is a macro that tests the given stream for a read or write error. If the stream's error indicator has been set it remains set
until clearerr or rewind is called or until the stream is closed.

Return Value

ferror returns nonzero if an error was detected on the named stream.

Example
#include <stdio.h>
int main(void)
{
FILE *stream; 3
/* open a file for writing */
stream = fopen("DUMMY.FIL", "w");
/* force an error condition by attempting to read */
(void) getc(stream);
if (ferror(stream)) /* test for an error on the stream */
{
/* display an error message */
printf("Error reading from DUMMY.FIL\n");
/* reset the error and EOF indicators */
clearerr(stream);

1041
C Runtime Library Reference RAD Studio 3.1 Référence C++

}
fclose(stream);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.18 fflush
Header File

stdio.h

Category

Input/output Routines

Prototype
int fflush(FILE *stream);

Description

Flushes a stream.

If the given stream has buffered output fflush writes the output for stream to the associated file.

The stream remains open after fflush has executed. fflush has no effect on an unbuffered stream.

Return Value

fflush returns 0 on success. It returns EOF if any errors were detected.

Example
#include <string.h>
#include <stdio.h>
#include <io.h>
void flush(FILE *stream);
int main(void)
{
FILE *stream;
char msg[] = "This is a test";
/* create a file */
stream = fopen("DUMMY.FIL", "w");
/* write some data to the file */
fwrite(msg, strlen(msg), 1, stream);
printf("Press ENTER to flush DUMMY.FIL:");
getchar();
/* flush the data to DUMMY.FIL without closing it */
flush(stream);
3 printf("\nFile was flushed, Press ENTER to quit:");
getchar();
return 0;
}
void flush(FILE *stream)
{
int duphandle;
/* flush the stream's internal buffer */
fflush(stream);
/* make a duplicate file handle */

1042
3.1 Référence C++ RAD Studio C Runtime Library Reference

duphandle = dup(fileno(stream));
/* close the duplicate handle to flush the DOS buffer */
close(duphandle);
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.19 fgetc, fgetwc


Header File

stdio.h

Category

Input/output Routines

Prototype
int fgetc(FILE *stream);
wint_t fgetwc(FILE *stream);

Description

Gets character from stream.

fgetc returns the next character on the named input stream.

Return Value

On success fgetc returns the character read after converting it to an int without sign extension. On end-of-file or error it returns
EOF.

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
FILE *stream;
char string[] = "This is a test";
char ch;
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* write a string into the file */
fwrite(string, strlen(string), 1, stream);
/* seek to the beginning of the file */
fseek(stream, 0, SEEK_SET);
do
{ 3
/* read a char from the file */
ch = fgetc(stream);
/* display the character */
putchar(ch);
} while (ch != EOF);
fclose(stream);
return 0;
}
Portability

1043
C Runtime Library Reference RAD Studio 3.1 Référence C++

POSIX Win32 ANSI C ANSI C++


fgetc + + + +
fgetwc + + +

3.1.5.28.20 _fgetchar, _fgetwchar


Header File

stdio.h

Category

Console I/O Routines

Prototype
int _fgetchar(void);
wint_t _fgetwchar(void);

Description

Reads a character from stdin.

_fgetchar returns the next character from stdin. It is defined as fgetc(stdin).

Remarque: For Win32 GUI applications, stdin must be redirected.

Return Value

On success _fgetchar returns the character read after converting it to an int without sign extension. On end-of-file or error it
returns EOF.

Example
#include <stdio.h>
int main(void)
{
char ch;
/* prompt the user for input */
printf("Enter a character followed by <Enter>: ");
/* read the character from stdin */
ch = fgetchar();
/* display what was read */
printf("The character read is: '%c'\n", ch);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


3 _fgetchar +
_fgetwchar +

3.1.5.28.21 fgetpos
Header File

stdio.h

1044
3.1 Référence C++ RAD Studio C Runtime Library Reference

Category

Input/output Routines

Prototype
int fgetpos(FILE *stream, fpos_t *pos);

Description

Gets the current file pointer.

fgetpos stores the position of the file pointer associated with the given stream in the location pointed to by pos. The exact value
is unimportant; its value is opaque except as a parameter to subsequent fsetpos calls.

Return Value

On success fgetpos returns 0. On failure it returns a nonzero value and sets the global variable errno to

EBADF Bad file number


EINVAL Invalid number

Example
#include <stdlib.h>
#include <stdio.h>
void showpos(FILE *stream);
int main(void)
{
FILE *stream;
fpos_t filepos;
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* save the file pointer position */
fgetpos(stream, &filepos);
/* write some data to the file */
fprintf(stream, "This is a test");
/* show the current file position */
showpos(stream);
/* set a new file position, display it */
if (fsetpos(stream, &filepos) == 0)
showpos(stream);
else
{
fprintf(stderr, "Error setting file pointer.\n");
exit(1);
}
/* close the file */
fclose(stream);
return 0;
}
void showpos(FILE *stream)
{
fpos_t pos;
/* display the current file pointer
position of a stream */ 3
fgetpos(stream, &pos);
printf("File position: %ld\n", pos);
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

1045
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.28.22 fgets, fgetws


Header File

stdio.h

Category

Input/output Routines

Prototype
char *fgets(char *s, int n, FILE *stream);
wchar_t *fgetws(wchar_t *s, int n, FILE *stream); // Unicode version

Description

Gets a string from a stream.

fgets reads characters from stream into the string s. The function stops reading when it reads either n - 1 characters or a newline
character whichever comes first. fgets retains the newline character at the end of s. A null byte is appended to s to mark the end
of the string.

Return Value

On success fgets returns the string pointed to by s; it returns NULL on end-of-file or error.

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
FILE *stream;
char string[] = "This is a test";
char msg[20];
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* write a string into the file */
fwrite(string, strlen(string), 1, stream);
/* seek to the start of the file */
fseek(stream, 0, SEEK_SET);
/* read a string from the file */
fgets(msg, strlen(string)+1, stream);
/* display the string */
printf("%s", msg);
fclose(stream);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


3 fgets + + + +
fgetws + + +

3.1.5.28.23 _flushall
Header File

1046
3.1 Référence C++ RAD Studio C Runtime Library Reference

stdio.h

Category

Input/output Routines

Prototype
int _flushall(void);

Description

Flushes all streams.

_flushall clears all buffers associated with open input streams and writes all buffers associated with open output streams to their
respective files. Any read operation following _flushall reads new data into the buffers from the input files. Streams stay open
after _flushall executes.

Return Value

_flushall returns an integer the number of open input and output streams.

Example
#include <stdio.h>
int main(void)
{
FILE *stream;
/* create a file */
stream = fopen("DUMMY.FIL", "w");
/* flush all open streams */
printf("%d streams were flushed.\n", flushall());
/* close the file */
fclose(stream);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.28.24 fopen, _wfopen


Header File

stdio.h

Category

Input/output Routines

Prototype
3
FILE *fopen(const char *filename, const char *mode);
FILE *_wfopen(const wchar_t *filename, const wchar_t *mode);

Description

Opens a stream.

fopen opens the file named by filename and associates a stream with it. fopen returns a pointer to be used to identify the stream
in subsequent operations.

1047
C Runtime Library Reference RAD Studio 3.1 Référence C++

The mode string used in calls to fopen is one of the following values:

r Open for reading only.


w Create for writing. If a file by that name already exists, it will be overwritten.
a Append; open for writing at end-of-file or create for writing if the file does not exist.
r+ Open an existing file for update (reading and writing).
w+ Create a new file for update (reading and writing). If a file by that name already exists, it will be
overwritten.
a+ Open for append; open (or create if the file does not exist) for update at the end of the file.

To specify that a given file is being opened or created in text mode append a t to the mode string (rt w+t and so on). Similarly to
specify binary mode append a b to the mode string (wb a+b and so on). fopen also allows the t or b to be inserted between the
letter and the + character in the mode string; for example rt+ is equivalent to r+t.

If a t or b is not given in the mode string the mode is governed by the global variable _fmode. If _fmode is set to O_B/INARY files
are opened in binary mode. If _fmode is set to O_TEXT they are opened in text mode. These O_... constants are defined in
fcntl.h.

When a file is opened for update, both input and output can be done on the resulting stream; however,

• output cannot be directly followed by input without an intervening fseek or rewind


• input cannot be directly followed by output without an intervening fseek, rewind, or an input that encounters end-of-file
Return Value
On successful completion fopen returns a pointer to the newly opened stream. In the event of error it returns NULL.
Portability

POSIX Win32 ANSI C ANSI C++


fopen + + + +
_wfopen NT only

3.1.5.28.25 fprintf, fwprintf


Header File

stdio.h

Category

Input/output Routines

Prototype
int fprintf(FILE *stream, const char *format[, argument, ...]);

3 int fwprintf(FILE *stream, const wchar_t *format[, argument, ...]);

Description

Writes formatted output to a stream.

fprintf accepts a series of arguments applies to each a format specifier contained in the format string pointed to by format and
outputs the formatted data to a stream. There must be the same number of format specifiers as arguments.

Remarque: For details on format specifiers, see printf Format Specifiers.

1048
3.1 Référence C++ RAD Studio C Runtime Library Reference

Return Value

fprintf returns the number of bytes output. In the event of error it returns EOF.

Example
#include <stdio.h>
int main(void)
{
FILE *stream;
int i = 100;
char c = 'C';
float f = 1.234;
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* write some data to the file */
fprintf(stream, "%d %c %f", i, c, f);
/* close the file */
fclose(stream);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


fprintf + + + +
fwprintf + + +

3.1.5.28.26 fputc, fputwc


Header File

stdio.h

Category

Input/output Routines

Prototype
int fputc(int c, FILE *stream);
wint_t fputwc(wint_t c, FILE *stream);

Description

Puts a character on a stream.

fputc outputs character c to the named stream.

Remarque: For Win32 GUI applications, stdin must be redirected.

Return Value
3
On success, fputc returns the character c. On error, it returns EOF.

Example
#include <stdio.h>
int main(void)
{
char msg[] = "Hello world";
int i = 0;
while (msg[i])

1049
C Runtime Library Reference RAD Studio 3.1 Référence C++

{
fputc(msg[i], stdout);
i++;
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


fputc + + + +
fputwc + + +

3.1.5.28.27 _fputchar, _fputwchar


Header File

stdio.h

Category

Input/output Routines

Prototype
int _fputchar(int c);
wint_t _fputwchar(wint_t c);

Description

Outputs a character to stdout.

_fputchar outputs character c to stdout. _fputchar(c) is the same as fputc(cstdout).

Remarque: For Win32 GUI applications, stdout must be redirected.

Return Value

On success _fputchar returns the character c.

On error it returns EOF.

Example
#include <stdio.h>
int main(void)
{
char msg[] = "This is a test";
int i = 0;
while (msg[i])
{
fputchar(msg[i]);
3 i++;
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_fputchar +

1050
3.1 Référence C++ RAD Studio C Runtime Library Reference

_fputwchar +

3.1.5.28.28 fputs, fputws


Header File

stdio.h

Category

Input/output Routines

Prototype
int fputs(const char *s, FILE *stream);
int fputws(const wchar_t *s, FILE *stream);

Description

Outputs a string on a stream.

fputs copies the null-terminated string s to the given output stream; it does not append a newline character and the terminating
null character is not copied.

Return Value

On success fputs returns a non-negative value.

On error it returns a value of EOF.

Example
#include <stdio.h>
int main(void)
{
/* write a string to standard output */
fputs("Hello world\n", stdout);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


fputs + + + +
fputws + + +

3.1.5.28.29 fread
Header File 3
stdio.h

Category

Input/output Routines

Prototype
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);

1051
C Runtime Library Reference RAD Studio 3.1 Référence C++

Description

Reads data from a stream.

fread reads n items of data each of length size bytes from the given input stream into a block pointed to by ptr.

The total number of bytes read is (n * size).

Return Value

On success fread returns the number of items (not bytes) actually read.

On end-of-file or error it returns a short count (possibly 0).

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
FILE *stream;
char msg[] = "this is a test";
char buf[20];
if ((stream = fopen("DUMMY.FIL", "w+"))
== NULL)
{
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
/* write some data to the file */
fwrite(msg, strlen(msg)+1, 1, stream);
/* seek to the beginning of the file */
fseek(stream, SEEK_SET, 0);
/* read the data and display it */
fread(buf, strlen(msg)+1, 1, stream);
printf("%s\n", buf);
fclose(stream);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.30 freopen, _wfreopen


Header File

stdio.h

Category

3 Input/output Routines

Prototype
FILE *freopen(const char *filename, const char *mode, FILE *stream);
FILE *_wfreopen(const wchar_t *filename, const wchar_t *mode, FILE *stream);

Description

Associates a new file with an open stream.

1052
3.1 Référence C++ RAD Studio C Runtime Library Reference

freopen substitutes the named file in place of the open stream. It closes stream regardless of whether the open succeeds.
freopen is useful for changing the file attached to stdin, stdout, or stderr.

The mode string used in calls to fopen is one of the following values:

r Open for reading only.


w Create for writing. .
a Append; open for writing at end-of-file or create for writing if the file does not exist.
r+ Open an existing file for update (reading and writing).
w+ Create a new file for update (reading and writing).
a+ Open for append; open (or create if the file does not exist) for update at the end of the file.

To specify that a given file is being opened or created in text mode append a t to the mode string (rt w+t and so on); similarly to
specify binary mode append a b to the mode string (wb a+b and so on).

If a t or b is not given in the mode string the mode is governed by the global variable _fmode. If _fmode is set to O_BINARY files
are opened in binary mode. If _fmode is set to O_TEXT they are opened in text mode. These O_... constants are defined in
fcntl.h.

When a file is opened for update, both input and output can be done on the resulting stream; however,

• output cannot be directly followed by input without an intervening fseek or rewind


• input cannot be directly followed by output without an intervening fseek, rewind, or an input that encounters end-of-file
Return Value
On successful completion freopen returns the argument stream.
On error it returns NULL.
Example
#include <stdio.h>
int main(void)
{
/* redirect standard output to a file */
if (freopen("OUTPUT.FIL", "w", stdout)
== NULL)
fprintf(stderr, "error redirecting stdout\n");
/* this output will go to a file */
printf("This will go into a file.");
/* close the standard output stream */
fclose(stdout);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


freopen + + + +
_wfreopen NT only 3

3.1.5.28.31 fscanf, fwscanf


Header File

stdio.h

1053
C Runtime Library Reference RAD Studio 3.1 Référence C++

Category

Input/output Routines

Prototype
int fscanf(FILE *stream, const char *format[, address, ...]);
int fwscanf(FILE *stream, const wchar_t *format[, address, ...]);

Description

Scans and formats input from a stream.

fscanf scans a series of input fields one character at a time reading from a stream. Then each field is formatted according to a
format specifier passed to fscanf in the format string pointed to by format. Finally fscanf stores the formatted input at an address
passed to it as an argument following format. The number of format specifiers and addresses must be the same as the number
of input fields.

Remarque: For details on format specifiers, see scanf Format Specifiers.

fscanf can stop scanning a particular field before it reaches the normal end-of-field character (whitespace) or it can terminate
entirely for a number of reasons. See scanf for a discussion of possible causes.

Return Value

fscanf returns the number of input fields successfully scanned, converted and stored. The return value does not include scanned
fields that were not stored.

If fscanf attempts to read at end-of-file, the return value is EOF. If no fields were stored, the return value is 0.

Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int i;
printf("Input an integer: ");
/* read an integer from the
standard input stream */
if (fscanf(stdin, "%d", &i))
printf("The integer read was: %i\n", i);
else
{
fprintf(stderr, "Error reading an integer from stdin.\n");
exit(1);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +
3

3.1.5.28.32 fseek
Header File

stdio.h

Category

1054
3.1 Référence C++ RAD Studio C Runtime Library Reference

Input/output Routines

Prototype
int fseek(FILE *stream, long offset, int whence);

Description

Repositions a file pointer on a stream.

fseek sets the file pointer associated with stream to a new position that is offset bytes from the file location given by whence. For
text mode streams offset should be 0 or a value returned by ftell.

whence must be one of the values 0. 1, or 2 which represent three symbolic constants (defined in stdio.h) as follows:

fseek discards any character pushed back using ungetc. fseek is used with stream I/O; for file handle I/O use lseek.

After fseek the next operation on an update file can be either input or output.

Return Value

fseek returns 0 if the pointer is successfully moved and nonzero on failure.

fseek might return a 0 indicating that the pointer has been moved successfully when in fact it has not been. This is because
DOS, which actually resets the pointer, does not verify the setting. fseek returns an error code only on an unopened file or device.

In the event of an error return the global variable errno is set to one of the following values:

EBADF Bad file pointer


EINVAL Invalid argument
ESPIPE Illegal seek on device

Example
#include <stdio.h>
long filesize(FILE *stream);
int main(void)
{
FILE *stream;
stream = fopen("MYFILE.TXT", "w+");
fprintf(stream, "This is a test");
printf("Filesize of MYFILE.TXT is %ld bytes\n", filesize(stream));
fclose(stream);
return 0;
}
long filesize(FILE *stream)
{
long curpos, length;
curpos = ftell(stream);
fseek(stream, 0L, SEEK_END);
length = ftell(stream);
fseek(stream, curpos, SEEK_SET);
return length;
}
3
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

1055
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.28.33 fsetpos
Header File

stdio.h

Category

Input/output Routines

Prototype
int fsetpos(FILE *stream, const fpos_t *pos);

Description

Positions the file pointer of a stream.

fsetpos sets the file pointer associated with stream to a new position. The new position is the value obtained by a previous call to
fgetpos on that stream. It also clears the end-of-file indicator on the file that stream points to and undoes any effects of ungetc on
that file. After a call to fsetpos the next operation on the file can be input or output.

Return Value

On success fsetpos returns 0.

On failure it returns a nonzero value and also sets the global variable errno to a nonzero value.

Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.34 ftell
Header File

stdio.h

Category

Input/output Routines

Prototype
long int ftell(FILE *stream);

Description

Returns the current file pointer.

3 ftell returns the current file pointer for stream. The offset is measured in bytes from the beginning of the file (if the file is binary).
The value returned by ftell can be used in a subsequent call to fseek.

Return Value

ftell returns the current file pointer position on success. It returns -1L on error and sets the global variable errno to a positive
value.

In the event of an error return the global variable errno is set to one of the following values:

1056
3.1 Référence C++ RAD Studio C Runtime Library Reference

EBADF Bad file pointer


ESPIPE Illegal seek on device

Example
#include <stdio.h>
int main(void)
{
FILE *stream;
stream = fopen("MYFILE.TXT", "w+");
fprintf(stream, "This is a test");
printf("The file pointer is at byte %ld\n", ftell(stream));
fclose(stream);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.35 fwrite
Header File

stdio.h

Category

Input/output Routines

Prototype
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);

Description

Writes to a stream.

fwrite appends n items of data each of length size bytes to the given output file. The data written begins at ptr. The total number
of bytes written is (n x size). ptr in the declarations is a pointer to any object.

Return Value

On successful completion fwrite returns the number of items (not bytes) actually written.

On error it returns a short count.

Example
#include <stdio.h>
struct mystruct 3
{
int i;
char ch;
};
int main(void)
{
FILE *stream;
struct mystruct s;
if ((stream = fopen("TEST.$$$", "wb")) == NULL) /* open file TEST.$$$ */
{

1057
C Runtime Library Reference RAD Studio 3.1 Référence C++

fprintf(stderr, "Cannot open output file.\n");


return 1;
}
s.i = 0;
s.ch = 'A';
fwrite(&s, sizeof(s), 1, stream); /* write struct s to file */
fclose(stream); /* close file */
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.36 getc, getwc


Header File

stdio.h

Category

Input/output Routines

Prototype
int getc(FILE *stream);
wint_t getwc(FILE *stream);

Description

Gets character from stream.

getc returns the next character on the given input stream and increments the stream's file pointer to point to the next character.

Remarque: For Win32 GUI applications, stdin must be redirected.

Return Value

On success, getc returns the character read, after converting it to an int without sign extension.

On end-of-file or error, it returns EOF.

Example
#include <stdio.h>
int main(void)
{
char ch;
printf("Input a character:");
/* read a character from the
standard input stream */
3 ch = getc(stdin);
printf("The character input was: '%c'\n", ch);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


getc + + + +

1058
3.1 Référence C++ RAD Studio C Runtime Library Reference

getwc + + +

3.1.5.28.37 getchar, getwchar


Header File

stdio.h

Category

Console I/O Routines

Prototype
int getchar(void);
wint_t getwchar(void);

Description

Gets character from stdin.

getchar is a macro that returns the next character on the named input stream stdin. It is defined to be getc(stdin).

Remarque: Do not use this function in Win32 GUI applications.

Return Value

On success, getchar returns the character read, after converting it to an int without sign extension.

On end-of-file or error, it returns EOF.

Example
#include <stdio.h>
int main(void)
{
int c;
/*
Note that getchar reads from stdin and is line buffered; this means it will not return until
you press ENTER.
*/
while ((c = getchar()) != '\n')
printf("%c", c);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


getchar + + + +
getwchar + + +
3

3.1.5.28.38 gets, _getws


Header File

stdio.h

Category

1059
C Runtime Library Reference RAD Studio 3.1 Référence C++

Console I/O Routines

Prototype
char *gets(char *s);
wchar_t *_getws(wchar_t *s); // Unicode version

Description

Gets a string from stdin.

gets collects a string of characters terminated by a new line from the standard input stream stdin and puts it into s. The new line
is replaced by a null character (\0) in s.

gets allows input strings to contain certain whitespace characters (spaces, tabs). gets returns when it encounters a new line;
everything up to the new line is copied into s.

The gets function is not length-terminated. If the input string is sufficiently large, data can be overwritten and corrupted. The fgets
function provides better control of input strings.

Remarque: For Win32 GUI applications, stdin must be redirected.

Return Value

On success, gets returns the string argument s.

On end-of-file or error, it returns NULL

Example
#include <stdio.h>
int main(void)
{
char string[80];
printf("Input a string:");
gets(string);
printf("The string input was: %s\n", string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


gets + + + +
_getws +

3.1.5.28.39 _getw
Header File

stdio.h
3
Category

Input/output Routines

Prototype
int _getw(FILE *stream);

Description

1060
3.1 Référence C++ RAD Studio C Runtime Library Reference

Gets an integer from stream.

_getw returns the next integer in the named input stream. It assumes no special alignment in the file.

_getw should not be used when the stream is opened in text mode.

Return Value

_getw returns the next integer on the input stream.

On end-of-file or error, _getw returns EOF.

Remarque: Because EOF is a legitimate value for _getw to return, feof or ferror should be used to detect end-of-file or error.

Example
#include <stdio.h>
#include <stdlib.h>
#define FNAME "test.$$$"
int main(void)
{
FILE *fp;
int word;
/* place the word in a file */
fp = fopen(FNAME, "wb");
if (fp == NULL)
{
printf("Error opening file %s\n", FNAME);
exit(1);
}
word = 94;
putw(word,fp);
if (ferror(fp))
printf("Error writing to file\n");
else
printf("Successful write\n");
fclose(fp);
/* reopen the file */
fp = fopen(FNAME, "rb");
if (fp == NULL)
{
printf("Error opening file %s\n", FNAME);
exit(1);
}
/* extract the word */
word = getw(fp);
if (ferror(fp))
printf("Error reading file\n");
else
printf("Successful read: word = %d\n", word);
/* clean up */
fclose(fp);
unlink(FNAME);
return 0;
}
Portability
3
POSIX Win32 ANSI C ANSI C++
+

3.1.5.28.40 printf, wprintf


Header File

1061
C Runtime Library Reference RAD Studio 3.1 Référence C++

stdio.h

Category

Console I/O Routines

Prototype
int printf(const char *format[, argument, ...]);
int wprintf(const wchar_t *format[, argument, ...]);

Description

Writes formatted output to stdout.

The printf function:

• Accepts a series of arguments


• Applies to each argument a format specifier contained in the format string *format
• Outputs the formatted data (to the screen, a stream, stdout, or a string)
There must be enough arguments for the format. If there are not, the results will be unpredictable and likely disastrous. Excess
arguments (more than required by the format) are merely ignored.
Remarque: For Win32 GUI applications, stdout must be redirected.
Return Value
On success, printf returns the number of bytes output.
On error, printf returns EOF.
More About printf
Example
#include <stdio.h>
#include <string.h>
#define I 555
#define R 5.5
int main(void)
{
int i,j,k,l;
char buf[7];
char *prefix = buf;
char tp[20];
printf("prefix 6d 6o 8x 10.2e "
"10.2f\n");
strcpy(prefix,"%");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
for (k = 0; k < 2; k++)
for (l = 0; l < 2; l++)
{
if (i==0) strcat(prefix,"-");
3 if (j==0) strcat(prefix,"+");
if (k==0) strcat(prefix,"#");
if (l==0) strcat(prefix,"0");
printf("%5s |",prefix);
strcpy(tp,prefix);
strcat(tp,"6d |");
printf(tp,I);
strcpy(tp,"");
strcpy(tp,prefix);
strcat(tp,"6o |");
printf(tp,I);

1062
3.1 Référence C++ RAD Studio C Runtime Library Reference

strcpy(tp,"");
strcpy(tp,prefix);
strcat(tp,"8x |");
printf(tp,I);
strcpy(tp,"");
strcpy(tp,prefix);
strcat(tp,"10.2e |");
printf(tp,R);
strcpy(tp,prefix);
strcat(tp,"10.2f |");
printf(tp,R);
printf(" \n");
strcpy(prefix,"%");
}
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


printf + + + +
_wprintf +

3.1.5.28.41 putc, putwc


Header File

stdio.h

Category

Input/output Routines

Prototype
int putc(int c, FILE *stream);
wint_t putwc(wint_t c, FILE *stream);

Description

Outputs a character to a stream.

putc is a macro that outputs the character c to the stream given by stream.

Return Value

On success, putc returns the character printed, c.

On error, putc returns EOF.

Example
3
#include <stdio.h>
int main(void)
{
char msg[] = "Hello world\n";
int i = 0;
while (msg[i])
putc(msg[i++], stdout);
return 0;
}

1063
C Runtime Library Reference RAD Studio 3.1 Référence C++

Portability

POSIX Win32 ANSI C ANSI C++


putc + + + +
putwc + + +

3.1.5.28.42 putchar, putwchar


Header File

stdio.h

Category

Console I/O Routines

Prototype
int putchar(int c);
wint_t putwchar(wint_t c);

Description

putchar is a macro defined to be putc(c, stdout).

Remarque: For Win32 GUI applications, stdout must be redirected.

Return Value

On success, putchar returns the character c. On error, putchar returns EOF.

Example
#include <stdio.h>
/* define some box-drawing characters */
#define LEFT_TOP 0xDA
#define RIGHT_TOP 0xBF
#define HORIZ 0xC4
#define VERT 0xB3
#define LEFT_BOT 0xC0
#define RIGHT_BOT 0xD9
int main(void)
{
char i, j;
/* draw the top of the box */
putchar(LEFT_TOP);
for (i=0; i<10; i++)
putchar(HORIZ);
putchar(RIGHT_TOP);
putchar('\n');
/* draw the middle */
for (i=0; i<4; i++)
3 {
putchar(VERT);
for (j=0; j<10; j++)
putchar(' ');
putchar(VERT);
putchar('\n');
}
/* draw the bottom */
putchar(LEFT_BOT);
for (i=0; i<10; i++)

1064
3.1 Référence C++ RAD Studio C Runtime Library Reference

putchar(HORIZ);
putchar(RIGHT_BOT);
putchar('\n');
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


putchar + + + +
putwchar + + +

3.1.5.28.43 puts, _putws


Header File

stdio.h

Category

Console I/O Routines

Prototype
int puts(const char *s);
int _putws(const wchar_t *s);

Description

Outputs a string to stdout.

puts copies the null-terminated string s to the standard output stream stdout and appends a newline character.

Remarque: For Win32 GUI applications, stdout must be redirected.

Return Value

On successful completion, puts returns a nonnegative value. Otherwise, it returns a value of EOF.

Example
#include <stdio.h>
int main(void)
{
char string[] = "This is an example output string\n";
puts(string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


puts + + + +
3
_putws +

3.1.5.28.44 _putw
Header File

1065
C Runtime Library Reference RAD Studio 3.1 Référence C++

stdio.h

Category

Input/output Routines

Prototype
int _putw(int w, FILE *stream);

Description

Writes an integer on a stream.

_putw outputs the integer w to the given stream. _putw neither expects nor causes special alignment in the file.

Return Value

On success, _putw returns the integer w. On error, _putw returns EOF. Because EOF is a legitimate integer, use ferror to detect
errors with _putw.

Example
#include <stdio.h>
#include <stdlib.h>
#define FNAME "test.$$$"
int main(void)
{
FILE *fp;
int word;
/* place the word in a file */
fp = fopen(FNAME, "wb");
if (fp == NULL)
{
printf("Error opening file %s\n", FNAME);
exit(1);
}
word = 94;
putw(word,fp);
if (ferror(fp))
printf("Error writing to file\n");
else
printf("Successful write\n");
fclose(fp);
/* reopen the file */
fp = fopen(FNAME, "rb");
if (fp == NULL)
{
printf("Error opening file %s\n", FNAME);
exit(1);
}
/* extract the word */
word = getw(fp);
if (ferror(fp))
printf("Error reading file\n");
else
3 printf("Successful read: word = %d\n", word);
/* clean up */
fclose(fp);
unlink(FNAME);
return 0;
}
Portability

1066
3.1 Référence C++ RAD Studio C Runtime Library Reference

POSIX Win32 ANSI C ANSI C++


+

3.1.5.28.45 remove, _wremove


Header File

stdio.h

Category

Input/output Routines

Prototype
int remove(const char *filename);
int _wremove(const wchar_t *filename);

Description

Removes a file.

remove deletes the file specified by filename. It is a macro that simply translates its call to a call to unlink. If your file is open, be
sure to close it before removing it.

The filename string can include a full path.

Return Value

On successful completion, remove returns 0. On error, it returns -1, and the global variable errno is set to one of the following
values:

EACCES Permission denied


ENOENT No such file or directory

Example
#include <stdio.h>
int main(void)
{
char file[80];
/* prompt for file name to delete */
printf("File to delete: ");
gets(file);
/* delete the file */
if (remove(file) == 0)
printf("Removed %s.\n",file);
else
perror("remove");
return 0; 3
}
Portability

POSIX Win32 ANSI C ANSI C++


remove + + + +
_wremove NT only

1067
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.28.46 rename, _wrename


Header File

stdio.h

Category

Input/output Routines

Prototype
int rename(const char *oldname, const char *newname);
int _wrename(const wchar_t *oldname, const wchar_t *newname);

Description

Renames a file.

rename changes the name of a file from oldname to newname. If a drive specifier is given in newname, the specifier must be the
same as that given in oldname.

Directories in oldname and newname need not be the same, so rename can be used to move a file from one directory to
another. Wildcards are not allowed.

This function will fail (EEXIST) if either file is currently open in any process.

Return Value

On success, rename returns 0.

On error (if the file cannot be renamed), it returns -1 and the global variable errno is set to one of the following values:

EEXIST Permission denied: file already exists.


ENOENT No such file or directory
ENOTSAM Not same device

Example
#include <stdio.h>
int main(void)
{
char oldname[80], newname[80];
/* prompt for file to rename and new name */
printf("File to rename: ");
gets(oldname);
printf("New name: ");
gets(newname);
/* Rename the file */
if (rename(oldname, newname) == 0)
printf("Renamed %s to %s.\n", oldname, newname);
3 else
perror("rename");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


rename + + + +

1068
3.1 Référence C++ RAD Studio C Runtime Library Reference

_wrename NT only

3.1.5.28.47 rewind
Header File

stdio.h

Category

Input/output Routines

Prototype
void rewind(FILE *stream);

Description

Repositions a file pointer to the beginning of a stream.

rewind(stream) is equivalent to fseek(stream, 0L, SEEK_SET), except that rewind clears the end-of-file and error indicators,
while fseek clears the end-of-file indicator only.

After rewind, the next operation on an update file can be either input or output.

Return Value

None.

Example
#include <stdio.h>
#include <dir.h>
int main(void)
{
FILE *fp;
char *fname = "TXXXXXX", *newname, first;
newname = mktemp(fname);
fp = fopen(newname,"w+");
fprintf(fp,"abcdefghijklmnopqrstuvwxyz");
rewind(fp);
fscanf(fp,"%c",&first);
printf("The first character is: %c\n",first);
fclose(fp);
remove(newname);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +
3

3.1.5.28.48 _rmtmp
Header File

stdio.h

Category

1069
C Runtime Library Reference RAD Studio 3.1 Référence C++

Input/output Routines

Prototype
int _rmtmp(void);

Description

Removes temporary files.

The _rmtmp function closes and deletes all open temporary file streams which were previously created with tmpfile. The current
directory must the same as when the files were created, or the files will not be deleted.

Return Value

_rmtmp returns the total number of temporary files it closed and deleted.

Example
#include <stdio.h>
#include <process.h>

void main()
{
FILE *stream;
int i;

/* Create temporary files */


for (i = 1; i <= 10; i++)
{
if ((stream = tmpfile()) == NULL)
perror("Could not open temporary file\n");
else
printf("Temporary file %d created\n", i);
}
/* Remove temporary files */
if (stream != NULL)
printf("%d temporary files deleted\n", rmtmp());
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.28.49 scanf, wscanf


Header File

stdio.h

Category

3 Console I/O Routines

Prototype
int scanf(const char *format[, address, ...]);
int wscanf(const wchar_t *format[, address, ...]);

Description

Scans and formats input from the stdin stream.

1070
3.1 Référence C++ RAD Studio C Runtime Library Reference

Remarque: For Win32 GUI applications, stdin must be redirected.

The scanf function:

• scans a series of input fields one character at a time


• formats each field according to a corresponding format specifier passed in the format string *format.
• vsscanf scans and formats input from a string, using an argument list
There must be one format specifier and address for each input field.
scanf might stop scanning a particular field before it reaches the normal end-of-field (whitespace) character, or it might terminate
entirely. For details about why this might happen, see When ...scanf Stops Scanning.
Remarque: scanf often leads to unexpected results if you diverge from an expected pattern. You must provide information
that tells scanf how to synchronize at the end of a line.
The combination of gets or fgets followed by sscanf is safe and easy, and therefore recommended over scanf.
Return Value
On success, scanf returns the number of input fields successfully scanned, converted, and stored. The return value does not
include scanned fields that were not stored.
On error:
• if no fields were stored, scanf returns 0.
• if scanf attempts to read at end-of-file or at end-of-string, it returns EOF.
More About scanf
Example
#include <stdio.h>
int main(void)
{
char label[20];
char name[20];
int entries = 0;
int loop, age;
double salary;
struct Entry_struct
{
char name[20];
int age;
float salary;
} entry[20];
/* Input a label as a string of characters restricting to 20 characters */
printf("\n\nPlease enter a label for the chart: ");
scanf("%20s", label);
fflush(stdin); /* flush the input stream in case of bad input */
/* Input number of entries as an integer */
printf("How many entries will there be? (less than 20) ");
scanf("%d", &entries);
fflush(stdin); /* flush the input stream in case of bad input */
/* input a name restricting input to only letters upper or lower case */
for (loop=0;loop<entries;++loop)
{
printf("Entry %d\n", loop); 3
printf(" Name : ");
scanf("%[A-Za-z]", entry[loop].name);
fflush(stdin); /* flush the input stream in case of bad input */
/* input an age as an integer */
printf(" Age : ");
scanf("%d", &entry[loop].age);
fflush(stdin); /* flush the input stream in case of bad input */
/* input a salary as a float */
printf(" Salary : ");

1071
C Runtime Library Reference RAD Studio 3.1 Référence C++

scanf("%f", &entry[loop].salary);
fflush(stdin); /* flush the input stream in case of bad input */
}
/* Input a name, age and salary as a string, integer, and double */
printf("\nPlease enter your name, age and salary\n");
scanf("%20s %d %lf", name, &age, &salary);
/* Print out the data that was input */
printf("\n\nTable %s\n",label);
printf("Compiled by %s age %d $%15.2lf\n", name, age, salary);
printf("-----------------------------------------------------\n");
for (loop=0;loop<entries;++loop)
printf("%4d | %-20s | %5d | %15.2lf\n",
loop + 1,
entry[loop].name,
entry[loop].age,
entry[loop].salary);
printf("-----------------------------------------------------\n");
return 0;
}

3.1.5.28.50 setbuf
Header File

stdio.h

Category

Input/output Routines

Prototype
void setbuf(FILE *stream, char *buf);

Description

Assigns buffering to a stream.

setbuf causes the buffer buf to be used for I/O buffering instead of an automatically allocated buffer. It is used after stream has
been opened.

If buf is null, I/O will be unbuffered; otherwise, it will be fully buffered. The buffer must be BUFSIZ bytes long (specified in stdio.h).

stdin and stdout are unbuffered if they are not redirected; otherwise, they are fully buffered. setbuf can be used to change the
buffering style used.

Unbuffered means that characters written to a stream are immediately output to the file or device, while buffered means that the
characters are accumulated and written as a block.

setbuf produces unpredictable results unless it is called immediately after opening stream or after a call to fseek. Calling setbuf
after stream has been unbuffered is legal and will not cause problems.

A common cause for error is to allocate the buffer as an automatic (local) variable and then fail to close the file before returning
from the function where the buffer was declared.
3
Return Value

None.

Example
#include <stdio.h>
/* BUFSIZ is defined in stdio.h */
char outbuf[BUFSIZ];
int main(void)

1072
3.1 Référence C++ RAD Studio C Runtime Library Reference

{
/* attach a buffer to the standard output stream */
setbuf(stdout, outbuf);
/* put some characters into the buffer */
puts("This is a test of buffered output.\n\n");
puts("This output will go into outbuf\n");
puts("and won't appear until the buffer\n");
puts("fills up or we flush the stream.\n");
/* flush the output buffer */
fflush(stdout);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.51 setvbuf
Header File

stdio.h

Category

Input/output Routines

Prototype
int setvbuf(FILE *stream, char *buf, int type, size_t size);

Description

Assigns buffering to a stream.

setvbuf causes the buffer buf to be used for I/O buffering instead of an automatically allocated buffer. It is used after the given
stream is opened.

If buf is null, a buffer will be allocated using malloc; the buffer will use size as the amount allocated. The buffer will be
automatically freed on close. The size parameter specifies the buffer size and must be greater than zero.

The parameter size is limited by the constant UINT_MAX as defined in limits.h.

stdin and stdout are unbuffered if they are not redirected; otherwise, they are fully buffered. Unbuffered means that characters
written to a stream are immediately output to the file or device, while buffered means that the characters are accumulated and
written as a block.

• The type parameter is one of the following:

_IOFBF fully buffered file. When a buffer is empty, the next input operation will attempt to fill the entire buffer.
On output, the buffer will be completely filled before any data is written to the file.
3
_IOLBF line buffered file. When a buffer is empty, the next input operation will still attempt to fill the entire
buffer. On output, however, the buffer will be flushed whenever a newline character is written to the
file.
_IONBF unbuffered file. The buf and size parameters are ignored. Each input operation will read directly from
the file, and each output operation will immediately write the data to the file.

A common cause for error is to allocate the buffer as an automatic (local) variable and then fail to close the file before returning

1073
C Runtime Library Reference RAD Studio 3.1 Référence C++

from the function where the buffer was declared.

Return Value

On success, setvbuf returns 0.

On error (if an invalid value is given for type or size, or if there is not enough space to allocate a buffer), it returns nonzero.

Example
#include <stdio.h>
int main(void)
{
FILE *input, *output;
char bufr[512];
input = fopen("file.in", "r+b");
output = fopen("file.out", "w");
/* set up input stream for minimal disk access,
using our own character buffer */
if (setvbuf(input, bufr, _IOFBF, 512) != 0)
printf("failed to set up buffer for input file\n");
else
printf("buffer set up for input file\n");
/* set up output stream for line buffering using space that
will be obtained through an indirect call to malloc */
if (setvbuf(output, NULL, _IOLBF, 132) != 0)
printf("failed to set up buffer for output file\n");
else
printf("buffer set up for output file\n");
/* perform file I/O here */
/* close files */
fclose(input);
fclose(output);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.52 snprintf;snwprintf
Header File

stdio.h

Category

Memory and String Manipulation Routines

Prototype

3 int snprintf(char* buffer, size_t nsize, const char* fmt, ...);


int snwprintf(wchar_t* buffer, size_t nsize, const wchar_t* fmt, ...);

Description

Sends formatted output to a buffer of a maximum length specified by nsize.

If the number of bytes to output is:

• < nsize, then all of the characters have been written, including the terminating ‘\0’ character.

1074
3.1 Référence C++ RAD Studio C Runtime Library Reference

• == nsize, then nsize characters are written, with no terminating ‘\0’ character.
> nsize, then only nsize characters are written, with no terminating ‘\0’ character.
If nsize is 0, then the string will not be written to (and may be NULL).
Return Value
Number of bytes output, or, if nsize is 0, the number of bytes needed, not including the terminating ‘\0’ character.

3.1.5.28.53 sprintf, swprintf


Header File

stdio.h

Category

Memory and String Manipulation Routines

Prototype
int sprintf(char *buffer, const char *format[, argument, ...]);
int swprintf(wchar_t *buffer, const wchar_t *format[, argument, ...]);

Description

Writes formatted output to a string.

Remarque: For details on format specifiers, see printf.

sprintf accepts a series of arguments, applies to each a format specifier contained in the format string pointed to by format, and
outputs the formatted data to a string.

sprintf applies the first format specifier to the first argument, the second to the second, and so on. There must be the same
number of format specifiers as arguments.

Return Value

On success, sprintf returns the number of bytes output. The return value does not include the terminating null byte in the count.

On error, sprintf returns EOF.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
char buffer[80];
sprintf(buffer, "An approximation of Pi is %f\n", M_PI);
puts(buffer);
return 0;
}
Portability 3
POSIX Win32 ANSI C ANSI C++
sprintf + + + +
swprintf + + +

1075
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.28.54 sscanf, swscanf


Header File

stdio.h

Category

Memory and String Manipulation Routines

Syntax
int sscanf(const char *buffer, const char *format[, address, ...]);
int swscanf(const wchar_t *buffer, const wchar_t *format[, address, ...]);

Description

Scans and formats input from a string.

Remarque: For details on format specifiers, see scanf.

sscanf scans a series of input fields, one character at a time, reading from a string. Then each field is formatted according to a
format specifier passed to sscanf in the format string pointed to by format. Finally, sscanf stores the formatted input at an
address passed to it as an argument following format. There must be the same number of format specifiers and addresses as
there are input fields.

sscanf might stop scanning a particular field before it reaches the normal end-of-field (whitespace) character, or it might
terminate entirely, for a number of reasons. See scanf for a discussion of possible causes.

Return Value

On success, sscanf returns the number of input fields successfully scanned, converted, and stored; the return value does not
include scanned fields that were not stored.

If sscanf attempts to read at end-of-string, it returns EOF.

On error (If no fields were stored), it returns 0.

Example
#include <stdio.h>
#include <stdlib.h>
char *names[4] = {"Peter", "Mike", "Shea", "Jerry"};
#define NUMITEMS 4
int main(void)
{
int loop;
char temp[4][80];
char name[20];
int age;
long salary;
/* create name, age and salary data */
for (loop=0; loop < NUMITEMS; ++loop)
3 sprintf(temp[loop], "%s %d %ld", names[loop], random(10) + 20, random(5000) + 27500L);
/* print title bar */
printf("%4s | %-20s | %5s | %15s\n", "#", "Name", "Age", "Salary");
printf(" --------------------------------------------------\n");
/* input a name, age and salary data */
for (loop=0; loop < NUMITEMS; ++loop)
{
sscanf(temp[loop],"%s %d %ld", &name, &age, &salary);
printf("%4d | %-20s | %5d | %15ld\n", loop + 1, name, age, salary);
}

1076
3.1 Référence C++ RAD Studio C Runtime Library Reference

return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


sscanf + + + +
swscanf + + +

3.1.5.28.55 stderr, stdin, stdout


Header File

stdio.h

Description

Predefined streams automatically opened when the program is started.

Name Meaning
stdin Standard input device
stdout Standard output device
stderr Standard error output device

3.1.5.28.56 _tempnam, _wtempnam


Header File

stdio.h

Category

Input/output Routines

Prototype
char *_tempnam(char *dir, char *prefix)
wchar_t *_wtempnam(wchar_t *dir, wchar_t *prefix)

Description

Creates a unique file name in specified directory.

The _tempnam function accepts single-byte or multibyte string arguments.

The _tempnam function creates a unique file name in arbitrary directories. The unique file is not actually created; _tempnam only
verifies that it does not currently exist. It attempts to use the following directories, in the order shown, when creating the file name:
3
• The directory specified by the TMP environment variable.
• The dir argument to _tempnam.
• The P_tmpdir definition in stdio.h. If you edit stdio.h and change this definition, _tempnam will not use the new definition.
• The current working directory.
If any of these directories is NULL, or undefined, or does not exist, it is skipped.
The prefix argument specifies the first part of the file name; it cannot be longer than 5 characters, and cannot contain a period (.).

1077
C Runtime Library Reference RAD Studio 3.1 Référence C++

A unique file name is created by concatenating the directory name, the prefix, and 6 unique characters. Space for the
resulting file name is allocated with malloc; when this file name is no longer needed, the caller should call free to free it.
If you do create a temporary file using the name constructed by _tempnam, it is your responsibility to delete the file name (for
example, with a call to remove). It is not deleted automatically. (tmpfile does delete the file name.)
Return Value
If _tempnam is successful, it returns a pointer to the unique temporary file name, which the caller can pass to free when it is no
longer needed. Otherwise, if _tempnam cannot create a unique file name, it returns NULL.
Example
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
FILE *stream;
int i;
char *name;
for (i = 1; i <= 10; i++) {
if ((name = tempnam("\\tmp","wow")) == NULL)
perror("tempnam couldn't create name");
else {
printf("Creating %s\n",name);
if ((stream = fopen(name,"wb")) == NULL)
perror("Could not open temporary file\n");
else
fclose(stream);
}
free(name);
}
printf("Warning: temp files not deleted.\n");
}
Portability

POSIX Win32 ANSI C ANSI C++


_tempnam +
_wtempnam +

3.1.5.28.57 tmpfile
Header File

stdio.h

Category

Input/output Routines

Prototype

3 FILE *tmpfile(void);

Description

Opens a “scratch” file in binary mode.

tmpfile creates a temporary binary file and opens it for update (w + b). If you do not change the directory after creating the
temporary file, the file is automatically removed when it’s closed or when your program terminates.

Return Value

1078
3.1 Référence C++ RAD Studio C Runtime Library Reference

tmpfile returns a pointer to the stream of the temporary file created. If the file can’t be created, tmpfile returns NULL.

Example
#include <stdio.h>
#include <process.h>
int main(void)
{
FILE *tempfp;
tempfp = tmpfile();
if (tempfp)
printf("Temporary file created\n");
else
{
printf("Unable to create temporary file\n");
exit(1);
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.28.58 tmpnam, _wtmpnam


Header File

stdio.h

Category

Input/output Routines

Prototype
char *tmpnam(char *s);
wchar_t *_wtmpnam(wchar_t *s);

Description

Creates a unique file name.

tmpnam creates a unique file name, which can safely be used as the name of a temporary file. tmpnam generates a different
string each time you call it, up to TMP_MAX times. TMP_MAX is defined in stdio.h as 65,535.

The parameter to tmpnam, s, is either null or a pointer to an array of at least L_tmpnam characters. L_tmpnam is defined in
stdio.h. If s is NULL, tmpnam leaves the generated temporary file name in an internal static object and returns a pointer to that
object. If s is not NULL, tmpnam overwrites the internal static object and places its result in the pointed-to array, which must be
at least L_tmpnam characters long, and returns s.

If you do create such a temporary file with tmpnam, it is your responsibility to delete the file name (for example, with a call to
3
remove). It is not deleted automatically. (tmpfile does delete the file name.)

Return Value

If s is null, tmpnam returns a pointer to an internal static object. Otherwise, tmpnam returns s.

Example
#include <stdio.h>

1079
C Runtime Library Reference RAD Studio 3.1 Référence C++

int main(void)
{
char name[13];
tmpnam(name);
printf("Temporary name: %s\n", name);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


tmpnam + + + +
_wtmpnam +

3.1.5.28.59 ungetc, ungetwc


Header File

stdio.h

Category

Input/output Routines

Prototype
int ungetc(int c, FILE *stream);
wint_t ungetwc(wint_t c, FILE *stream);

Description

Pushes a character back into input stream.

Remarque: Do not use this function in Win32 GUI applications.

ungetc pushes the character c back onto the named input stream, which must be open for reading. This character will be
returned on the next call to getc or fread for that stream. One character can be pushed back in all situations. A second call to
ungetc without a call to getc will force the previous character to be forgotten. A call to fflush, fseek, fsetpos, or rewind erases all
memory of any pushed-back characters.

Return Value

On success, ungetc returns the character pushed back.

On error, it returns EOF.

Example
#include <stdio.h>
#include <ctype.h>
int main( void )
3 {
int i=0;
char ch;
puts("Input an integer followed by a char:");
/* read chars until non digit or EOF */
while((ch = getchar()) != EOF && isdigit(ch))
i = 10 * i + ch - 48; /* convert ASCII into int value */
/* if non digit char was read, push it back into input buffer */
if (ch != EOF)
ungetc(ch, stdin);
printf("i = %d, next char in buffer = %c\n", i, getchar());

1080
3.1 Référence C++ RAD Studio C Runtime Library Reference

return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


ungetc + + + +
ungetwc + + +

3.1.5.28.60 vfprintf, vfwprintf


Header File

stdio.h

Category

Input/output Routines

Prototype
int vfprintf(FILE *stream, const char *format, va_list arglist);
int vfwprintf(FILE *stream, const wchar_t *format, va_list arglist);

Description

Writes formatted output to a stream.

The v...printf functions are known as alternate entry points for the ...printf functions. They behave exactly like their ...printf
counterparts, but they accept a pointer to a list of arguments instead of an argument list.

For details on format specifiers, see Printf Format Specifiers.

vfprintf accepts a pointer to a series of arguments, applies to each argument a format specifier contained in the format string
pointed to by format, and outputs the formatted data to a stream. There must be the same number of format specifiers as
arguments.

Return Value

On success, vfprintf returns the number of bytes output.

On error, it returns EOF.

Example
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
FILE *fp;
int vfpf(char *fmt, ...)
{
va_list argptr; 3
int cnt;
va_start(argptr, fmt);
cnt = vfprintf(fp, fmt, argptr);
va_end(argptr);
return(cnt);
}
int main(void)
{
int inumber = 30;
float fnumber = 90.0;

1081
C Runtime Library Reference RAD Studio 3.1 Référence C++

char string[4] = "abc";


fp = tmpfile();
if (fp == NULL)
{
perror("tmpfile() call");
exit(1);
}
vfpf("%d %f %s", inumber, fnumber, string);
rewind(fp);
fscanf(fp,"%d %f %s", &inumber, &fnumber, string);
printf("%d %f %s\n", inumber, fnumber, string);
fclose(fp);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


vfprintf + + + +
vfwprintf + + +

3.1.5.28.61 vfscanf
Header File

stdio.h

Category

Input/output Routines

Prototype
int vfscanf(FILE *stream, const char *format,va_list arglist);

Description

Scans and formats input from a stream.

The v...scanf functions are known as alternate entry points for the ...scanf functions. They behave exactly like their ...scanf
counterparts but they accept a pointer to a list of arguments instead of an argument list.

For details on format specifiers, see Scanf Format Specifiers.

vfscanf scans a series of input fields one character at a time reading from a stream. Then each field is formatted according to a
format specifier passed to vfscanf in the format string pointed to by format. Finally vfscanf stores the formatted input at an
address passed to it as an argument following format. There must be the same number of format specifiers and addresses as
there are input fields. vfscanf might stop scanning a particular field before it reaches the normal end-of-field (whitespace)
character or it might terminate entirely for a number of reasons. See scanf for a discussion of possible causes.

Return Value
3
vfscanf returns the number of input fields successfully scanned converted and stored; the return value does not include scanned
fields that were not stored. If no fields were stored the return value is 0.

If vfscanf attempts to read at end-of-file the return value is EOF.

Example
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

1082
3.1 Référence C++ RAD Studio C Runtime Library Reference

FILE *fp;
int vfsf(char *fmt, ...)
{
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vfscanf(fp, fmt, argptr);
va_end(argptr);
return(cnt);
}
int main(void)
{
int inumber = 30;
float fnumber = 90.0;
char string[4] = "abc";
fp = tmpfile();
if (fp == NULL)
{
perror("tmpfile() call");
exit(1);
}
fprintf(fp,"%d %f %s\n",inumber,fnumber,string);
rewind(fp);
vfsf("%d %f %s",&inumber,&fnumber,string);
printf("%d %f %s\n",inumber,fnumber,string);
fclose(fp);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + +

3.1.5.28.62 vprintf, vwprintf


Header File

stdio.h

Category

Console I/O Routines

Prototype
int vprintf(const char *format, va_list arglist);
int vwprintf(const wchar_t * format, va_list arglist);

Description

Writes formatted output to stdout.


3
Remarque: Do not use this function in Win32 GUI applications.

The v...printf functions are known as alternate entry points for the ...printf functions. They behave exactly like their ...printf
counterparts, but they accept a pointer to a list of arguments instead of an argument list.

Remarque: For details on format specifiers, see Printf Format Specifiers.

vprintf accepts a pointer to a series of arguments, applies to each a format specifier contained in the format string pointed to by
format, and outputs the formatted data to stdout. There must be the same number of format specifiers as arguments.

1083
C Runtime Library Reference RAD Studio 3.1 Référence C++

Return Value

vprint returns the number of bytes output. In the event of error, vprint returns EOF.

Example
#include <stdio.h>
#include <stdarg.h>
int vpf(char *fmt, ...)
{
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vprintf(fmt, argptr);
va_end(argptr);
return(cnt);
}
int main(void)
{
int inumber = 30;
float fnumber = 90.0;
char *string = "abc";
vpf("%d %f %s\n",inumber,fnumber,string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


vprintf + + + +
vwprintf + + +

3.1.5.28.63 vscanf
Header File

stdio.h

Category

Console I/O Routines

Prototype
int vscanf(const char *format, va_list arglist);

Description

Scans and formats input from stdin.

Remarque: Do not use this function in Win32 GUI applications.

The v...scanf functions are known as alternate entry points for the ...scanf functions. They behave exactly like their ...scanf
3 counterparts, but they accept a pointer to a list of arguments instead of an argument list.

Remarque: For details on format specifiers, see Scanf Format Specifiers.

vscanf scans a series of input fields, one character at a time, reading from stdin. Then each field is formatted according to a
format specifier passed to vscanf in the format string pointed to by format. Finally, vscanf stores the formatted input at an
address passed to it as an argument following format. There must be the same number of format specifiers and addresses as
there are input fields.

1084
3.1 Référence C++ RAD Studio C Runtime Library Reference

vscanf might stop scanning a particular field before it reaches the normal end-of-field (whitespace) character, or it might
terminate entirely, for a number of reasons. See scanf for a discussion of possible causes.

Return Value

vscanf returns the number of input fields successfully scanned, converted, and stored; the return value does not include scanned
fields that were not stored. If no fields were stored, the return value is 0.

If vscanf attempts to read at end-of-file, the return value is EOF.

Example
#include <stdio.h>
#include <stdarg.h>
int vscnf(char *fmt, ...)
{
va_list argptr;
int cnt;
printf("Enter an integer, a float, and a string (e.g. i,f,s,)\n");
va_start(argptr, fmt);
cnt = vscanf(fmt, argptr);
va_end(argptr);
return(cnt);
}
int main(void)
{
int inumber;
float fnumber;
char string[80];
vscnf("%d, %f, %s", &inumber, &fnumber, string);
printf("%d %f %s\n", inumber, fnumber, string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + +

3.1.5.28.64 vsnprintf;vsnwprintf
Header File

stdio.h

Category

Memory and String Manipulation Routines

Prototype
int vsnprintf(char* buffer, size_t nsize, const char* format, va_list param);
int vsnwprintf(wchar_t* buffer, size_t nsize, const wchar_t* format, va_list param); 3
Description

Sends formatted output to a buffer of maximum length specified by nsize.

If the number of bytes to output is:

• < nsize, then all of the characters have been written, including the terminating ‘\0’ character.
• == nsize, then nsize characters are written, with no terminating ‘\0’ character.

1085
C Runtime Library Reference RAD Studio 3.1 Référence C++

> nsize, then only nsize characters are written, with no terminating ‘\0’ character.
If nsize is 0, then the string will not be written to (and may be NULL).
Return Value
Number of bytes output, or, if nsize is 0, the number of bytes needed, not including the terminating ‘\0’ character.

3.1.5.28.65 vsprintf, vswprintf


Header File

stdio.h

Category

Memory and String Manipulation Routines

Prototype
int vsprintf(char *buffer, const char *format, va_list arglist);
int vswprintf(wchar_t *buffer, const wchar_t *format, va_list arglist);

Description

Writes formatted output to a string.

The v...printf functions are known as alternate entry points for the ...printf functions. They behave exactly like their ...printf
counterparts, but they accept a pointer to a list of arguments instead of an argument list.

vsprintf accepts a pointer to a series of arguments, applies to each a format specifier contained in the format string pointed to by
format, and outputs the formatted data to a string. There must be the same number of format specifiers as arguments.

Return Value

vsprintf returns the number of bytes output. In the event of error, vsprintf returns EOF.

Example
#include <stdio.h>
#include <conio.h>
#include <stdarg.h>
char buffer[80];
int vspf(char *fmt, ...)
{
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsprintf(buffer, fmt, argptr);
va_end(argptr);
return(cnt);
}
int main(void)
{
int inumber = 30;
3 float fnumber = 90.0;
char string[4] = "abc";
vspf("%d %f %s", inumber, fnumber, string);
printf("%s\n", buffer);
return 0;
}
Portability

1086
3.1 Référence C++ RAD Studio C Runtime Library Reference

POSIX Win32 ANSI C ANSI C++


vsprintf + + + +
vswprintf + + +

3.1.5.29 stdlib.h
The following functions, macros, and classes are provided in stdlib.h:

Rubriques
Nom Description
EXIT_xxxx #defines ( see page 1101) Header File
stdlib.h
Description
Constants defining exit conditions for calls to the exit function.
RAND_MAX #define ( see page 1101) Header File
stdlib.h
Syntax
Description
Maximum value returned by rand function.
_argc ( see page 1102) Header File
stdlib.h
Syntax
extern int _argc;
Description
_argc has the same value as argc (passed to main) when the program starts.
This variable holds the number of arguments passed to the program. The value
includes the name of the program itself, so _argc and argc are always at least 1.
_argv, _wargv ( see page 1102) Header File
stdlib.h
Syntax
extern char **_argv;
extern wchar_t ** _wargv
Description
_argv points to an array containing the original command-line arguments (the
elements of argv[]) passed to main when the program starts.
_wargv is the Unicode version of _argv.
Portability
_atoi64, _wtoi64 ( see page 1102) Header File
stdlib.h
Category
Conversion Routines, Math Routines
Prototype
__int64 _atoi64(const char *s);
__int64 _wtoi64(const wchar_t *s);
Description
Converts a string to an __int64.
The syntax of the string must be:
__int64 ::= [isspace]* [sign] digit [digit]*
Only decimal integers are acceptable. 3
_wtoi64 is the wide-character version. It converts a wide-character string to an
__int64.
In this function, the first unrecognized character ends the conversion. There are
no provisions for overflow in atoi (results are undefined). There is no defined
method to return an error indication to the caller. The result is undefined if the
input string... suite ( see page 1102)

1087
C Runtime Library Reference RAD Studio 3.1 Référence C++

_crotl, _crotr ( see page 1103) Header File


stdlib.h
Category
Math Routines
Prototype
unsigned char _crotl(unsigned char val, int count);
unsigned char _crotr(unsigned char val, int count);
Description
Rotates an unsigned char left or right.
_crotl rotates the given val to the left count bits. _crotr rotates the given val to the
right count bits.
The argument val is an unsigned char, or its equivalent in decimal or
hexadecimal form.
Return Value

• The functions return the rotated byte:


• _crotl returns the value of val left-rotated count bits.
• _crotr returns the value of val right-rotated count bits.
Portability
_exit ( see page 1104) Header File
stdlib.h
Category
Process Control Routines
Prototype
void _exit(int status);
Description
Terminates program.
_exit terminates execution without closing any files, flushing any output, or calling
any exit functions.
The calling process uses status as the exit status of the process. Typically a
value of 0 is used to indicate a normal exit, and a nonzero value indicates some
error.
Return Value
None.
Example
_fullpath, _wfullpath ( see page 1104) Header File
stdlib.h
Category
Directory Control Routines
Prototype
char * _fullpath(char *buffer, const char *path, int
buflen);
wchar_t * _wfullpath(wchar_t *buffer, const wchar_t *path,
int buflen);
Description
Converts a path name from relative to absolute.
_fullpath converts the relative path name in path to an absolute path name that is
stored in the array of characters pointed to by buffer. The maximum number of
characters that can be stored at buffer is buflen. The function returns NULL if the
buffer isn't big enough to store the absolute path name or if the path contains an
invalid drive letter.
If buffer... suite ( see page 1104)
_lrand ( see page 1105) Header File
3 stdlib.h
Category
Math Routines
Prototype
long _lrand(void);
Description
_lrand is the long random number generator function. _rand uses a multiplicative
congruential random number generator with period 2^64 to return successive
pseudo-random numbers in the range from 0 to 2^31 - 1.
The generator is reinitialized by calling srand with an argument value of 1. It can
be set to a new starting point by calling srand with a given seed number.

1088
3.1 Référence C++ RAD Studio C Runtime Library Reference

_lrotl, _lrotr ( see page 1106) Header File


stdlib.h
Category
Math Routines
Prototype
unsigned long _lrotl(unsigned long val, int count);
unsigned long _lrotr(unsigned long val, int count);
Description
Rotates an unsigned long integer value to the left or right.
_Irotlrotates the given val to the left count bits. _lrotr rotates the given val to the
right count bits.
Return Value
The functions return the rotated integer:

• _lrotl returns the value of val left-rotated count bits.


• _lrotr returns the value of val right-rotated count bits.
Example
_makepath, _wmakepath ( see page 1107) Header File
stdlib.h
Category
Directory Control Routines
Prototype
void _makepath(char *path, const char *drive, const char
*dir, const char *name, const char *ext);
void _wmakepath(wchar_t *path, const wchar_t *drive, const
wchar_t *dir, const wchar_t *name, const wchar_t *ext);
Description
Builds a path from component parts.
_makepath makes a path name from its components. The new path name is
X:\DIR\SUBDIR\NAME.EXT
where
_rotl, _rotr ( see page 1108) Header File
stdlib.h
Category
Math Routines
Prototype
unsigned short _rotl(unsigned short value, int count);
unsigned short _rotr(unsigned short value, int count);
Description
Bit-rotates an unsigned short integer value to the left or right.
_rotl rotates the given value to the left count bits.
_rotr rotates the given value to the right count bits.
Return Value
_rotl, and _rotr return the rotated integer:

• _rotl returns the value of value left-rotated count bits.


• _rotr returns the value of value right-rotated count bits.
Example

1089
C Runtime Library Reference RAD Studio 3.1 Référence C++

_searchenv, _wsearchenv ( see page 1109) Header File


stdlib.h
Category
Miscellaneous Routines
Prototype
char *_searchenv(const char *file, const char *varname,
char *buf);
char *_wsearchenv(const wchar_t *file, const wchar_t
*varname, wchar_t *buf);
Description
Looks for a file, using an environment variable as the search path.
_searchenv attempts to locate file, searching along the path specified by the
operating system environment variable varname. Typical environment variables
that contain paths are PATH, LIB, and INCLUDE.
_searchenv searches for the file in the current directory of the current drive first. If
the file is not found there, the environment variable varname is fetched, and each
directory in the path it... suite ( see page 1109)
_searchstr, _wsearchstr ( see page 1110) Header File
stdlib.h
Category
Miscellaneous Routines
Prototype
void _searchstr(const char *file, const char *ipath, char
*buf);
void _wsearchstr(const wchar_t *file, const wchar_t
*ipath,wchar_t *pathname);
Description
Searches a list of directories for a file.
_searchstr attempts to locate file, searching along the path specified by the string
ipath.
_searchstr searches for the file in the current directory of the current drive first. If
the file is not found there, each directory in ipath is searched in turn until the file
is found, or the path is exhausted. The directories in ipath must be separated by
semicolons.
When the file is located,... suite ( see page 1110)
_splitpath, _wsplitpath ( see page 1111) Header File
stdlib.h
Category
Directory Control Routines
Prototype
void _splitpath(const char *path, char *drive, char *dir,
char *name, char *ext);
void _wsplitpath(const wchar_t *path, wchar_t *drive,
wchar_t *dir, wchar_t *name, wchar_t *ext);
Description
Splits a full path name into its components.
_splitpath takes a file's full path name (path) as a string in the form
X:\DIR\SUBDIR\NAME.EXT
and splits path into its four components. It then stores those components in the
strings pointed to by drive, dir, name, and ext. (All five components must be
passed, but any of them can be a null, which means the corresponding
component will be... suite ( see page 1111)

1090
3.1 Référence C++ RAD Studio C Runtime Library Reference

_ui64toa, _ui64tow ( see page 1113) Header File


stdlib.h
Category
Conversion Routines, Math Routines
Prototype
char *_ui64toa(unsigned __int64 value, char *string, int
radix);
wchar_t *_ui64tow(unsigned __int64 value, wchar_t *string,
int radix);
Description
_ui64toa converts an unsigned __int64 to a string.
_ui64tow is the unicode version. _ui64tow converts an unsigned __int64 to a
wide-character string.
These functions convert value to a null-terminated string and store the result in
string. value is an __int64.
radix specifies the base to be used in converting value; it must be between 2 and
36, inclusive. If value is negative and radix is 10, the first character of string is...
suite ( see page 1113)
abort ( see page 1113) Header File
stdlib.h
Category
Process Control Routines
Prototype
void abort(void);
Description
Abnormally terminates a program.
abort causes an abnormal program termination by calling raise(SIGABRT). If
there is no signal handler for SIGABRT, then abort writes a termination message
(Abnormal program termination) on stderr, then aborts the program by a call to
_exit with exit code 3.
Return Value
abort returns the exit code 3 to the parent process or to the operating system
command processor.
Example
atexit ( see page 1114) Header File
stdlib.h
Category
Process Control Routines
Prototype
int atexit(void (_USERENTRY * func)(void));
Description
Registers termination function.
atexit registers the function pointed to by func as an exit function. Upon normal
termination of the program, exit calls func just before returning to the operating
system. fcmp must be used with the _USERENTRY calling convention.
Each call to atexit registers another exit function. Up to 32 functions can be
registered. They are executed on a last-in, first-out basis (that is, the last function
registered is the first to be executed).
Return Value
atexit returns 0 on success and nonzero on failure... suite ( see page 1114)

1091
C Runtime Library Reference RAD Studio 3.1 Référence C++

atoi, _wtoi ( see page 1115) Header File


stdlib.h
Category
Conversion Routines, Math Routines
Prototype
int atoi(const char *s);
int _wtoi(const wchar_t *s);
Description
Converts a string to an integer.

• atoi converts a string pointed to by s to int; atoi


recognizes (in the following order)
• An optional string of tabs and spaces
• An optional sign
• A string of digits
The characters must match this generic format:
[ws] [sn] [ddd]
In this function, the first unrecognized character ends the
conversion. There are no provisions for overflow in atoi
(results are undefined).
Return Value
atoi returns the converted value of the input string. If the...
suite ( see page 1115)
atol, _wtol ( see page 1116) Header File
stdlib.h
Category
Conversion Routines, Math Routines
Prototype
long atol(const char *s);
long _wtol(const wchar_t *s);
Description
Converts a string to a long.

• atol converts the string pointed to by s to long. atol


recognizes (in the following order)
• An optional string of tabs and spaces
• An optional sign
• A string of digits
The characters must match this generic format:
[ws] [sn] [ddd]
In this function, the first unrecognized character ends the
conversion. There are no provisions for overflow in atol
(results are undefined).
Return Value
3
atol returns the converted value of the input string. If the...
suite ( see page 1116)

1092
3.1 Référence C++ RAD Studio C Runtime Library Reference

bsearch ( see page 1117) Header File


stdlib.h
Category
Memory and String Manipulation Routines
Prototype
void *bsearch(const void *key, const void *base, size_t
nelem, size_t width, int (_USERENTRY *fcmp)(const void *,
const void *));
Description
Binary search of an array.
bsearch searches a table (array) of nelem elements in memory, and returns the
address of the first entry in the table that matches the search key. The array must
be in order. If no match is found, bsearch returns 0.
Remarque: Because this is a binary search, the first matching entry is not
necessarily the first entry in the table.
The type size_t is defined... suite ( see page 1117)
div ( see page 1118) Header File
stdlib.h
Category
Math Routines
Prototype
div_t div(int numer, int denom);
Description
Divides two integers, returning quotient and remainder.
div divides two integers and returns both the quotient and the remainder as a
div_t type. numer and denom are the numerator and denominator, respectively.
The div_t type is a structure of integers defined (with typedef) in stdlib.h as
follows:
typedef struct {
int quot; /* quotient */
int rem; /* remainder */
} div_t;
Return Value
div returns a structure whose elements are quot (the quotient) and rem (the
remainder).
Example
ecvt ( see page 1119) Header File
stdlib.h
Category
Conversion Routines, Math Routines
Prototype
char *ecvt(double value, int ndig, int *dec, int *sign);
Description
Converts a floating-point number to a string.
ecvt converts value to a null-terminated string of ndig digits, starting with the
leftmost significant digit, and returns a pointer to the string. The position of the
decimal point relative to the beginning of the string is stored indirectly through
dec (a negative value for dec means that the decimal lies to the left of the
returned digits). There is no decimal point in the string itself. If the sign of value
is... suite ( see page 1119)
_environ, _wenviron ( see page 1120) Header File
stdlib.h
Syntax
extern char ** _environ;
extern wchar_t ** _wenviron
Description
_environ is an array of pointers to strings; it is used to access and alter the 3
operating system environment variables. Each string is of the form:
envvar = varvalue
where envvar is the name of an environment variable (such as PATH), and
varvalue is the string value to which envvar is set (such as
C:\Utils;C:\MyPrograms). The string varvalue can be empty.
When a program begins execution, the operating system environment settings
are passed directly to the program. Note that env, the third argument to main, is
equal... suite ( see page 1120)

1093
C Runtime Library Reference RAD Studio 3.1 Référence C++

exit ( see page 1120) Header File


stdlib.h
Category
Process Control Routines
Prototype
void exit(int status);
Description
Terminates program.
exit terminates the calling process. Before termination, all files are closed,
buffered output (waiting to be output) is written, and any registered "exit
functions" (posted with atexit) are called.
status is provided for the calling process as the exit status of the process.
Typically a value of 0 is used to indicate a normal exit, and a nonzero value
indicates some error. It can be, but is not required, to be set with one of the
following:
fcvt ( see page 1121) Header File
stdlib.h
Category
Conversion Routines, Math Routines
Prototype
char *fcvt(double value, int ndig, int *dec, int *sign);
Description
Converts a floating-point number to a string.
fcvt converts value to a null-terminated string digit starting with the leftmost
significant digit with ndig digits to the right of the decimal point. fcvt then returns a
pointer to the string. The position of the decimal point relative to the beginning of
the string is stored indirectly through dec (a negative value for dec means to the
left of the returned digits). There is no decimal point in the string itself. If... suite
( see page 1121)
gcvt ( see page 1122) Header File
stdlib.h
Category
Conversion Routines, Math Routines
Prototype
char *gcvt(double value, int ndec, char *buf);
Description
Converts floating-point number to a string.
gcvt converts value to a null-terminated ASCII string and stores the string in buf.
It produces ndec significant digits in FORTRAN F format, if possible; otherwise, it
returns the value in the printf E format (ready for printing). It might suppress
trailing zeros.
Return Value
gcvt returns the address of the string pointed to by buf.
Example
getenv, _wgetenv ( see page 1123) Header File
stdlib.h
Category
Process Control Routines
Prototype
char *getenv(const char *name);
wchar_t *_wgetenv(const wchar_t *name);
Description
Find or delete an environment variable from the system environment.
The environment consists of a series of entries that are of the form
name=string\0.
getenv returns the value of a specified variable. name can be either uppercase or
3 lowercase. name must not include the equal sign (=). If the specified environment
variable does not exist, getenv returns a NULL pointer.
To delete the variable from the environment, use getenv("name=").
Remarque: Environment entries must not be changed directly. If you want to...
suite ( see page 1123)

1094
3.1 Référence C++ RAD Studio C Runtime Library Reference

itoa, _itow ( see page 1124) Header File


stdlib.h
Category
Conversion Routines, Math Routines
Prototype
char *itoa(int value, char *string, int radix);
wchar_t *_itow(int value, wchar_t *string, int radix);
Description
Converts an integer to a string.
itoa converts value to a null-terminated string and stores the result in string. With
itoa, value is an integer. _itow is the unicode version of the function. It converts
an integer to a wide-character string.
radix specifies the base to be used in converting value; it must be between 2 and
36, inclusive. If value is negative and radix is 10, the first character of string is the
minus... suite ( see page 1124)
labs ( see page 1125) Header File
stdlib.h
Category
Math Routines
Prototype
long labs(long int x);
Description
Gives long absolute value.
labs computes the absolute value of the parameter x.
Return Value
labs returns the absolute value of x.
Example
lfind ( see page 1125) Header File
stdlib.h
Category
Memory and String Manipulation Routines
Prototype
void *lfind(const void *key, const void *base, size_t *num,
size_t width, int (_USERENTRY *fcmp)(const void *, const
void *));
Description
Performs a linear search.
lfind makes a linear search for the value of key in an array of sequential records.
It uses a user-defined comparison routine fcmp. The fcmp function must be used
with the _USERENTRY calling convention.
The array is described as having *num records that are width bytes wide, and
begins at the memory location pointed to by base.
Return Value
lfind returns the address of the first... suite ( see page 1125)
lsearch ( see page 1126) Header File
stdlib.h
Category
Memory and String Manipulation Routines
Prototype
void *lsearch(const void *key, void *base, size_t *num,
size_t width, int (_USERENTRY *fcmp)(const void *, const
void *));
Description
Performs a linear search.
lsearch searches a table for information. Because this is a linear search, the table
entries do not need to be sorted before a call to lsearch. If the item that key
points to is not in the table, lsearch appends that item to the table.
3
• base points to the base (0th element) of the search table.
• num points to an integer containing the number of entries
in... suite ( see page 1126)

1095
C Runtime Library Reference RAD Studio 3.1 Référence C++

ltoa, _ltoa, _ltow ( see page 1128) Header File


stdlib.h
Category
Conversion Routines, Math Routines
Prototype
char * ltoa(long value, char * string, int radix);
char *_ltoa(long value, char *string, int radix);
wchar_t *_ltow(long value, wchar_t *string, int radix);
Description
Converts a long to a string. _ltow is the unicode version. It converts a long to a
wide-charater string.
Converts value to a null-terminated string and stores the result in string. value is
a long.
radix specifies the base to be used in converting value; it must be between 2 and
36, inclusive. If value is negative and radix is 10, the first character of... suite (
see page 1128)
max ( see page 1129) Header File
stdlib.h
Category
C++ Prototyped Routines
Prototype
(type) max(a, b);
template <class T> T max( T t1, T t2 ); // C++ only
Description
Returns the larger of two values.
The C macro and the C++ template function compare two values and return the
larger of the two. Both arguments and the routine declaration must be of the
same type.
Return Value
max returns the larger of two values.
Portability
mblen ( see page 1129) Header File
stdlib.h
Category
Memory and String Manipulation Routines
Prototype
int mblen(const char *s, size_t n);
Description
Determines the length of a multibyte character.
If s is not null, mblen determines the number of bytes in the multibyte character
pointed to by s. The maximum number of bytes examined is specified by n.
The behavior of mblen is affected by the setting of LC_CTYPE category of the
current locale.
Return Value
If s is null, mblen returns a nonzero value if multibyte characters have
state-dependent encodings. Otherwise, mblen returns 0.
If s is not null, mblen returns 0 if s... suite ( see page 1129)
mbstowcs ( see page 1130) Header File
stdlib.h
Category
Conversion Routines, Memory and String Manipulation Routines
Prototype
size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n);
Description
Converts a multibyte string to a wchar_t array.
3 The function converts the multibyte string s into the array pointed to by pwcs. No
more than n values are stored in the array. If an invalid multibyte sequence is
encountered, mbstowcs returns (size_t) -1.
The pwcs array will not be terminated with a zero value if mbstowcs returns n.
Return Value
If an invalid multibyte sequence is encountered, mbstowcs returns (size_t) -1.
Otherwise, the function returns the number of array... suite ( see page 1130)

1096
3.1 Référence C++ RAD Studio C Runtime Library Reference

mbtowc ( see page 1131) Header File


stdlib.h
Category
Conversion Routines, Memory and String Manipulation Routines
Prototype
int mbtowc(wchar_t *pwc, const char *s, size_t n);
Description
Converts a multibyte character to wchar_t code.
If s is not null, mbtowc determines the number of bytes that comprise the
multibyte character pointed to by s. Next, mbtowc determines the value of the
type wchar_t that corresponds to that multibyte character. If there is a successful
match between wchar_t and the multibyte character, and pwc is not null, the
wchar_t value is stored in the array pointed to by pwc. At most n characters are
examined.
Return Value... suite ( see page 1131)
min ( see page 1132) Header File
stdlib.h
Category
C++ Prototyped Routines
Prototype
(type) min(a, b); /* macro version */
template <class T> T min( T t1, T t2 );// C++ only
Description
Returns the smaller of two values.
The C macro and the C++ template function compare two values and return the
smaller of the two. Both arguments and the routine declaration must be of the
same type.
Return Value
min returns the smaller of two values.
putenv, _wputenv ( see page 1132) Header File
stdlib.h
Category
Process Control Routines
Prototype
int putenv(const char *name);
int _wputenv(const wchar_t *name);
Description
Adds string to current environment.
putenv accepts the string name and adds it to the environment of the current
process. For example,
putenv(“PATH=C:\\BC”);
putenv can also be used to modify an existing name. name can be either
uppercase or lowercase. name must not include the equal sign (=). You can set a
variable to an empty value by specifying an empty string on the right side of the
‘=’ sign.
putenv can be used only to modify the current program’s _environment.... suite
( see page 1132)

1097
C Runtime Library Reference RAD Studio 3.1 Référence C++

qsort ( see page 1133) Header File


stdlib.h
Category
Memory and String Manipulation Routines
Prototype
void qsort(void *base, size_t nelem, size_t width, int
(_USERENTRY *fcmp)(const void *, const void *));
Description
Sorts using the quicksort algorithm.
qsort is an implementation of the “median of three” variant of the quicksort
algorithm. qsort sorts the entries in a table by repeatedly calling the user-defined
comparison function pointed to by fcmp.

• base points to the base (0th element) of the table to be


sorted.
• nelem is the number of entries in the table.
• width is the size of each entry in the table, in bytes.
fcmp, the comparison... suite ( see page 1133)
rand ( see page 1134) Header File
stdlib.h
Category
Math Routines
Prototype
int rand(void);
Description
Random number generator.
rand uses a multiplicative congruential random number generator with period 2 to
the 32nd power to return successive pseudo-random numbers in the range from
0 to RAND_MAX. The symbolic constant RAND_MAX is defined in stdlib.h.
Return Value
rand returns the generated pseudo-random number.
Example
random ( see page 1135) Header File
stdlib.h
Category
Math Routines
Prototype
int random(int num);
Description
Random number generator.
random returns a random number between 0 and (num-1). random(num) is a
macro defined in stdlib.h. Both num and the random number returned are
integers.
Return Value
random returns a number between 0 and (num-1).
Example
randomize ( see page 1136) Header File
stdlib.h, time.h
Category
Math Routines
Prototype
void randomize(void);
3 Description
Initializes random number generator.
randomize initializes the random number generator with a random value.
Return Value
None.
Example

1098
3.1 Référence C++ RAD Studio C Runtime Library Reference

srand ( see page 1137) Header File


stdlib.h
Category
Math Routines
Prototype
void srand(unsigned seed);
Description
Initializes random number generator.
The random number generator is reinitialized by calling srand with an argument
value of 1. It can be set to a new starting point by calling srand with a given seed
number.
Return Value
None.
Example
strlen, _mbslen, wcslen, _mbstrlen ( see page 1137) Header File
string.h, mbstring.h, stdlib.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
size_t strlen(const char *s);
size_t wcslen(const wchar_t *s);
size_t _mbslen(const unsigned char *s);
size_t _mbstrlen(const char *s)
Description
Calculates the length of a string.
strlen calculates the length of s.
_mbslen and _mbstrlen test the string argument to determine the number of
multibyte characters they contain.
_mbstrlen is affected by the LC_CTYPE category setting as determined by the
setlocale function. The function tests to determine whether the string argument is
a valid multibyte string.
_mbslen is affected by the code page that is in use. This... suite ( see page
1137)
strtod, _strtold, wcstod, _wcstold ( see page 1138) Header File
stdlib.h
Category
Conversion Routines, Math Routines
Prototype
double strtod(const char *s, char **endptr);
double wcstod(const wchar_t *s, wchar_t **endptr);
long double _strtold(const char *s, char **endptr);
long double _wcstold(const wchar_t *s, wchar_t **endptr);
Description
Convert a string to a double or long double value.
strtod converts a character string, s, to a double value. s is a sequence of
characters that can be interpreted as a double value; the characters must match
this generic format:
[ws] [sn] [ddd] [.] [ddd] [fmt[sn]ddd]
where:
strtol, wcstol ( see page 1140) Header File
stdlib.h
Category
Conversion Routines, Math Routines
Prototype
long strtol(const char *s, char **endptr, int radix);
long wcstol(const wchar_t *s, wchar_t **endptr, int radix); 3
Description
Converts a string to a long value.
strtol converts a character string, s, to a long integer value. s is a sequence of
characters that can be interpreted as a long value; the characters must match
this generic format:
[ws] [sn] [0] [x] [ddd]
where:

1099
C Runtime Library Reference RAD Studio 3.1 Référence C++

strtoul, wcstoul ( see page 1141) Header File


stdlib.h
Category
Conversion Routines, Math Routines
Prototype
unsigned long strtoul(const char *s, char **endptr, int
radix);
unsigned long wcstoul(const wchar_t *s, wchar_t **endptr,
int radix);
Description
Converts a string to an unsigned long in the given radix.
strtoul operates the same as strtol, except that it converts a string str to an
unsigned long value (where strtol converts to a long). Refer to the entry for
strtol for more information.
Return Value
strtoul returns the converted value, an unsigned long, or 0 on error.
Example
swab ( see page 1142) Header File
stdlib.h
Category
Memory and String Manipulation Routines
Prototype
void swab(char *from, char *to, int nbytes);
Description
Swaps bytes.
swab copies nbytes bytes from the from string to the to string. Adjacent even-
and odd-byte positions are swapped. This is useful for moving data from one
machine to another machine with a different byte order. nbytes should be even.
Return Value
None.
Example
system, _wsystem ( see page 1142) Header File
stdlib.h
Category
Process Control Routines
Prototype
int system(const char *command);
int _wsystem(const wchar_t *command);
Description
Issues an operating system command.
system invokes the operating system command processor to execute an
operating system command, batch file, or other program named by the string
command, from inside an executing C program.
To be located and executed, the program must be in the current directory or in
one of the directories listed in the PATH string in the environment.
The COMSPEC environment variable is used to find the command processor
program, so it need not be in the current directory.
Return... suite ( see page 1142)
ultoa, _ultow ( see page 1143) Header File
stdlib.h
Category
Conversion Routines, Math Routines
Prototype
char *ultoa(unsigned long value, char *string, int radix);
wchar_t *_ultow(unsigned long value, wchar_t *string, int
3 radix);
Description
Converts an unsigned long to a string.
ultoa converts value to a null-terminated string and stores the result in string.
value is an unsigned long.
radix specifies the base to be used in converting value; it must be between 2 and
36, inclusive. ultoa performs no overflow checking, and if value is negative and
radix equals 10, it does not set the minus sign.
Remarque: The space allocated for string must be... suite ( see page 1143)

1100
3.1 Référence C++ RAD Studio C Runtime Library Reference

wcstombs ( see page 1144) Header File


stdlib.h
Category
Conversion Routines, Memory and String Manipulation Routines
Prototype
size_t wcstombs(char *s, const wchar_t *pwcs, size_t n);
Description
Converts a wchar_t array into a multibyte string.
wcstombs converts the type wchar_t elements contained in pwcs into a multibyte
character string s. The process terminates if either a null character or an invalid
multibyte character is encountered.
No more than n bytes are modified. If n number of bytes are processed before a
null character is reached, the array s is not null terminated.
The behavior of wcstombs is affected by the setting of LC_CTYPE category of
the... suite ( see page 1144)
wctomb ( see page 1145) Header File
stdlib.h
Category
Conversion Routines, Memory and String Manipulation Routines
Prototype
int wctomb(char *s, wchar_t wc);
Description
Converts wchar_t code to a multibyte character.
If s is not null, wctomb determines the number of bytes needed to represent the
multibyte character corresponding to wc (including any change in shift state). The
multibyte character is stored in s. At most MB_CUR_MAX characters are stored.
If the value of wc is zero, wctomb is left in the initial state.
The behavior of wctomb is affected by the setting of LC_CTYPE category of the
current locale.
Return Value
If s is a... suite ( see page 1145)

3.1.5.29.1 EXIT_xxxx #defines


Header File

stdlib.h

Description

Constants defining exit conditions for calls to the exit function.

Name Meaning
EXIT_SUCCESS Normal program termination
EXIT_FAILURE Abnormal program termination

3.1.5.29.2 RAND_MAX #define


Header File

stdlib.h 3
Syntax

Description

Maximum value returned by rand function.

1101
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.29.3 _argc
Header File

stdlib.h

Syntax
extern int _argc;

Description

_argc has the same value as argc (passed to main) when the program starts. This variable holds the number of arguments
passed to the program. The value includes the name of the program itself, so _argc and argc are always at least 1.

3.1.5.29.4 _argv, _wargv


Header File

stdlib.h

Syntax
extern char **_argv;
extern wchar_t ** _wargv

Description

_argv points to an array containing the original command-line arguments (the elements of argv[]) passed to main when the
program starts.

_wargv is the Unicode version of _argv.

Portability

POSIX Win32 ANSI C ANSI C++


_argv +
_wargv NT only

3.1.5.29.5 _atoi64, _wtoi64


Header File

stdlib.h

Category

Conversion Routines, Math Routines


3
Prototype
__int64 _atoi64(const char *s);
__int64 _wtoi64(const wchar_t *s);

Description

Converts a string to an __int64.

1102
3.1 Référence C++ RAD Studio C Runtime Library Reference

The syntax of the string must be:


__int64 ::= [isspace]* [sign] digit [digit]*

Only decimal integers are acceptable.

_wtoi64 is the wide-character version. It converts a wide-character string to an __int64.

In this function, the first unrecognized character ends the conversion. There are no provisions for overflow in atoi (results are
undefined). There is no defined method to return an error indication to the caller. The result is undefined if the input string is
invalid.

Return Value

Returns the converted value of the input string. If the string cannot be converted to a __int64, the return value is 0.

Portability

POSIX Win32 ANSI C ANSI C++


_atoi64 +
_wtoi64 +

3.1.5.29.6 _crotl, _crotr


Header File

stdlib.h

Category

Math Routines

Prototype
unsigned char _crotl(unsigned char val, int count);
unsigned char _crotr(unsigned char val, int count);

Description

Rotates an unsigned char left or right.

_crotl rotates the given val to the left count bits. _crotr rotates the given val to the right count bits.

The argument val is an unsigned char, or its equivalent in decimal or hexadecimal form.

Return Value

• The functions return the rotated byte:


• _crotl returns the value of val left-rotated count bits.
• _crotr returns the value of val right-rotated count bits.
3
Portability

POSIX Win32 ANSI C ANSI C++


+

1103
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.29.7 _exit
Header File

stdlib.h

Category

Process Control Routines

Prototype
void _exit(int status);

Description

Terminates program.

_exit terminates execution without closing any files, flushing any output, or calling any exit functions.

The calling process uses status as the exit status of the process. Typically a value of 0 is used to indicate a normal exit, and a
nonzero value indicates some error.

Return Value

None.

Example
#include <stdlib.h>
#include <stdio.h>
void done(void);
int main(void)
{
atexit(done);
_exit(0);
return 0;
}
void done()
{
printf("hello\n");
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

3.1.5.29.8 _fullpath, _wfullpath


Header File
3 stdlib.h

Category

Directory Control Routines

Prototype
char * _fullpath(char *buffer, const char *path, int buflen);
wchar_t * _wfullpath(wchar_t *buffer, const wchar_t *path, int buflen);

1104
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

Converts a path name from relative to absolute.

_fullpath converts the relative path name in path to an absolute path name that is stored in the array of characters pointed to by
buffer. The maximum number of characters that can be stored at buffer is buflen. The function returns NULL if the buffer isn't big
enough to store the absolute path name or if the path contains an invalid drive letter.

If buffer is NULL, _fullpath allocates a buffer of up to _MAX_PATH characters. This buffer should be freed using free when it is
no longer needed. _MAX_PATH is defined in stdlib.h.

Return Value

If successful the _fullpath function returns a pointer to the buffer containing the absolute path name.

On error, this function returns NULL.

Example
#include <stdio.h>
#include <stdlib.h>
char buf[_MAX_PATH];
void main(int argc, char *argv[])
{
for ( ; argc; argv++, argc--)
{
if (_fullpath(buf, argv[0], _MAX_PATH) == NULL)
printf("Unable to obtain full path of %s\n",argv[0]);
else
printf("Full path of %s is %s\n",argv[0],buf);
}
}
Portability

POSIX Win32 ANSI C ANSI C++


_fullpath +
_wfullpath NT only

3.1.5.29.9 _lrand
Header File

stdlib.h

Category

Math Routines

Prototype
long _lrand(void);
3
Description

_lrand is the long random number generator function. _rand uses a multiplicative congruential random number generator with
period 2^64 to return successive pseudo-random numbers in the range from 0 to 2^31 - 1.

The generator is reinitialized by calling srand with an argument value of 1. It can be set to a new starting point by calling srand
with a given seed number.

1105
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.29.10 _lrotl, _lrotr


Header File

stdlib.h

Category

Math Routines

Prototype
unsigned long _lrotl(unsigned long val, int count);
unsigned long _lrotr(unsigned long val, int count);

Description

Rotates an unsigned long integer value to the left or right.

_Irotlrotates the given val to the left count bits. _lrotr rotates the given val to the right count bits.

Return Value

The functions return the rotated integer:

• _lrotl returns the value of val left-rotated count bits.


• _lrotr returns the value of val right-rotated count bits.
Example
#include <stdlib.h>
#include <stdio.h>
/* function prototypes */
int lrotl_example(void);
int lrotr_example(void);
/* lrotl example */
int lrotl_example(void)
{
unsigned long result;
unsigned long value = 100;
result = _lrotl(value,1);
printf("The value %lu rotated left one bit is: %lu\n", value, result);
return 0;
}
/* lrotr example */
int lrotr_example(void)
{
unsigned long result;
unsigned long value = 100;
result = _lrotr(value,1);
printf("The value %lu rotated right one bit is: %lu\n", value, result);
return 0;
}
int main(void)
3 {
lrotl_example();
lrotr_example();
return 0;
}
Portability

1106
3.1 Référence C++ RAD Studio C Runtime Library Reference

POSIX Win32 ANSI C ANSI C++


+

3.1.5.29.11 _makepath, _wmakepath


Header File

stdlib.h

Category

Directory Control Routines

Prototype
void _makepath(char *path, const char *drive, const char *dir, const char *name, const char
*ext);
void _wmakepath(wchar_t *path, const wchar_t *drive, const wchar_t *dir, const wchar_t *name,
const wchar_t *ext);

Description

Builds a path from component parts.

_makepath makes a path name from its components. The new path name is
X:\DIR\SUBDIR\NAME.EXT

where

drive = X:
dir = \DIR\SUBDIR\
name = NAME
ext = .EXT
If drive is empty or NULL, no drive is inserted in the path name. If it is missing a trailing colon (:), a colon is
inserted in the path name.
If dir is empty or NULL, no directory is inserted in the path name. If it is missing a trailing slash (\ or /), a
backslash is inserted in the path name.
If name is empty or NULL, no file name is inserted in the path name.
If ext is empty or NULL, no extension is inserted in the path name. If it is missing a leading period (.), a
period is inserted in the path name.
_makepath assumes there is enough space in path for the constructed path name. The maximum
constructed length is _MAX_PATH. _MAX_PATH is defined in stdlib.h.
_makepath and _splitpath are invertible; if you split a given path with _splitpath, then merge the resultant
components with _makepath, you end up with path. 3

If drive is empty or NULL, no drive is inserted in the path name. If it is missing a trailing colon (:), a colon is inserted in the path
name.

If dir is empty or NULL, no directory is inserted in the path name. If it is missing a trailing slash (\ or /), a backslash is inserted in
the path name.

If name is empty or NULL, no file name is inserted in the path name.

1107
C Runtime Library Reference RAD Studio 3.1 Référence C++

If ext is empty or NULL, no extension is inserted in the path name. If it is missing a leading period (.), a period is inserted in the
path name.

_makepath assumes there is enough space in path for the constructed path name. The maximum constructed length is
_MAX_PATH. _MAX_PATH is defined in stdlib.h.

_makepath and _splitpath are invertible; if you split a given path with _splitpath, then merge the resultant components with
_makepath, you end up with path.

Return Value

Example
#include <dir.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s[_MAX_PATH];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char file[_MAX_FNAME];
char ext[_MAX_EXT];
getcwd(s,_MAX_PATH); /* get current working directory */
if (s[strlen(s)-1] != '\\')
strcat(s,"\\"); /* append a trailing \ character */
_splitpath(s,drive,dir,file,ext); /* split the string to separate
elems */
strcpy(file,"DATA");
strcpy(ext,".TXT");
_makepath(s,drive,dir,file,ext); /* merge everything into one string */
puts(s); /* display resulting string */
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_makepath +
_wmakepath +

3.1.5.29.12 _rotl, _rotr


Header File

stdlib.h

Category

Math Routines
3 Prototype
unsigned short _rotl(unsigned short value, int count);
unsigned short _rotr(unsigned short value, int count);

Description

Bit-rotates an unsigned short integer value to the left or right.

_rotl rotates the given value to the left count bits.

1108
3.1 Référence C++ RAD Studio C Runtime Library Reference

_rotr rotates the given value to the right count bits.

Return Value

_rotl, and _rotr return the rotated integer:

• _rotl returns the value of value left-rotated count bits.


• _rotr returns the value of value right-rotated count bits.
Example
#include <stdlib.h>
#include <stdio.h>
/* rotl example */
int rotl_example(void)
{
unsigned value, result;
value = 32767;
result = _rotl(value, 1);
printf("The value %u rotated left one bit is: %u\n", value, result);
return 0;
}
/* rotr example */
int rotr_example(void)
{
unsigned value, result;
value = 32767;
result = _rotr(value, 1);
printf("The value %u rotated right one bit is: %u\n", value, result);
return 0;
}
int main(void)
{
rotl_example();
rotr_example();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_rotl +
_rotr

3.1.5.29.13 _searchenv, _wsearchenv


Header File

stdlib.h

Category

Miscellaneous Routines 3
Prototype
char *_searchenv(const char *file, const char *varname, char *buf);
char *_wsearchenv(const wchar_t *file, const wchar_t *varname, wchar_t *buf);

Description

Looks for a file, using an environment variable as the search path.

1109
C Runtime Library Reference RAD Studio 3.1 Référence C++

_searchenv attempts to locate file, searching along the path specified by the operating system environment variable varname.
Typical environment variables that contain paths are PATH, LIB, and INCLUDE.

_searchenv searches for the file in the current directory of the current drive first. If the file is not found there, the environment
variable varname is fetched, and each directory in the path it specifies is searched in turn until the file is found, or the path is
exhausted.

When the file is located, the full path name is stored in the buffer pointed to by buf. This string can be used in a call to access the
file (for example, with fopen or exec...). The buffer is assumed to be large enough to store any possible file name. If the file
cannot be successfully located, an empty string (consisting of only a null character) will be stored at buf.

Return Value

None.

Example
#include <stdio.h>
#include <stdlib.h>

char buf[_MAX_PATH];

int main(void)
{
/* ILINK32 will be found in your installation directory */
_searchenv("ILINK32.EXE","PATH",buf);
if (buf[0] == '\0')
printf("ILINK32.EXE not found\n");
else
printf("ILINK32.EXE found in %s\n", buf);

/* looks for nonexistent file */


_searchenv("NOTEXIST.FIL","PATH",buf);
if (buf[0] == '\0')
printf("NOTEXIST.FIL not found\n");
else
printf("NOTEXIST.FIL found in %s\n", buf);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_searchenv +
_wsearchenv NT only

3.1.5.29.14 _searchstr, _wsearchstr


Header File

stdlib.h
3
Category

Miscellaneous Routines

Prototype
void _searchstr(const char *file, const char *ipath, char *buf);
void _wsearchstr(const wchar_t *file, const wchar_t *ipath,wchar_t *pathname);

1110
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

Searches a list of directories for a file.

_searchstr attempts to locate file, searching along the path specified by the string ipath.

_searchstr searches for the file in the current directory of the current drive first. If the file is not found there, each directory in
ipath is searched in turn until the file is found, or the path is exhausted. The directories in ipath must be separated by semicolons.

When the file is located, the full path name is stored in the buffer pointed by by buf. This string can be used in a call to access
the file (for example, with fopen or exec...). The buffer is assumed to be large enough to store any possible file name. The
constant _MAX_PATH defined in stdlib.h, is the size of the largest file name. If the file cannot be successfully located, an empty
string (consisting of only a null character) will be stored at buf.

Return Value

None.

Example
#include <stdio.h>
#include <stdlib.h>
char buf[_MAX_PATH];
int main(void)
{
/* look for ILINK32.EXE */
_searchstr("ILINK32.EXE", "PATH", buf);
if (buf[0] == '\0')
printf ("ILINK32.EXE not found\n");
else
printf ("ILINK32.EXE found in %s\n", buf);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_searchstr +
_wsearchstr NT only

3.1.5.29.15 _splitpath, _wsplitpath


Header File

stdlib.h

Category

Directory Control Routines

Prototype
void _splitpath(const char *path, char *drive, char *dir, char *name, char *ext); 3
void _wsplitpath(const wchar_t *path, wchar_t *drive, wchar_t *dir, wchar_t *name, wchar_t
*ext);

Description

Splits a full path name into its components.

_splitpath takes a file's full path name (path) as a string in the form

1111
C Runtime Library Reference RAD Studio 3.1 Référence C++

X:\DIR\SUBDIR\NAME.EXT

and splits path into its four components. It then stores those components in the strings pointed to by drive, dir, name, and ext.
(All five components must be passed, but any of them can be a null, which means the corresponding component will be parsed
but not stored.) The maximum sizes for these strings are given by the constants _MAX_DRIVE, _MAX_DIR, _MAX_PATH,
_MAX_FNAME, and _MAX_EXT (defined in stdlib.h), and each size includes space for the null-terminator. These constants are
defined in stdlib.h.

_MAX_PATH path
_MAX_DRIVE drive; includes colon (:)
_MAX_DIR dir; includes leading and trailing backslashes (\)
_MAX_FNAME name
_MAX_EXT ext; includes leading dot (.)

_splitpath assumes that there is enough space to store each non-null component.

When _splitpath splits path, it treats the punctuation as follows:

• drive includes the colon (C:, A:, and so on).


• dir includes the leading and trailing backslashes (\BC\include\, \source\, and so on).
• name includes the file name.
• ext includes the dot preceding the extension (.C, .EXE, and so on).
_makepath and _splitpath are invertible; if you split a given path with _splitpath, then merge the resultant components with
_makepath, you end up with path.
Return Value
None.
Example
#include <dir.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char s[_MAX_PATH];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char file[_MAX_FNAME];
char ext[_MAX_EXT];
/* get current working directory */
getcwd(s,_MAX_PATH);
if (s[strlen(s)-1] != '\\')
/* append a trailing \ character */
strcat(s,"\\");
/* split the string to separate elems */
_splitpath(s,drive,dir,file,ext);
3 strcpy(file,"DATA");
strcpy(ext,".TXT");
/* merge everything into one string */
_makepath(s,drive,dir,file,ext);
/* display resulting string */
puts(s);
return 0;
}
Portability

1112
3.1 Référence C++ RAD Studio C Runtime Library Reference

POSIX Win32 ANSI C ANSI C++


_splitpath +
_wsplitpath +

3.1.5.29.16 _ui64toa, _ui64tow


Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
char *_ui64toa(unsigned __int64 value, char *string, int radix);
wchar_t *_ui64tow(unsigned __int64 value, wchar_t *string, int radix);

Description

_ui64toa converts an unsigned __int64 to a string.

_ui64tow is the unicode version. _ui64tow converts an unsigned __int64 to a wide-character string.

These functions convert value to a null-terminated string and store the result in string. value is an __int64.

radix specifies the base to be used in converting value; it must be between 2 and 36, inclusive. If value is negative and radix is
10, the first character of string is the minus sign (-).

Remarque: The space allocated for string must be large enough to hold the returned string, including the terminating null
character (\0). Can return up to 33 bytes.

Return Value

Returns a pointer to string.

Portability

POSIX Win32 ANSI C ANSI C++


_ui64toa
_ui64tow +

3.1.5.29.17 abort
Header File
3
stdlib.h

Category

Process Control Routines

Prototype
void abort(void);

1113
C Runtime Library Reference RAD Studio 3.1 Référence C++

Description

Abnormally terminates a program.

abort causes an abnormal program termination by calling raise(SIGABRT). If there is no signal handler for SIGABRT, then abort
writes a termination message (Abnormal program termination) on stderr, then aborts the program by a call to _exit with exit code
3.

Return Value

abort returns the exit code 3 to the parent process or to the operating system command processor.

Example
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
printf("Calling abort()\n");
abort();
return 0; /* This is never reached */
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.18 atexit
Header File

stdlib.h

Category

Process Control Routines

Prototype
int atexit(void (_USERENTRY * func)(void));

Description

Registers termination function.

atexit registers the function pointed to by func as an exit function. Upon normal termination of the program, exit calls func just
before returning to the operating system. fcmp must be used with the _USERENTRY calling convention.

Each call to atexit registers another exit function. Up to 32 functions can be registered. They are executed on a last-in, first-out
basis (that is, the last function registered is the first to be executed).

Return Value
3
atexit returns 0 on success and nonzero on failure (no space left to register the function).

Example
#include <stdio.h>
#include <stdlib.h>
void exit_fn1(void)
{
printf("Exit function #1 called\n");

1114
3.1 Référence C++ RAD Studio C Runtime Library Reference

}
void exit_fn2(void)
{
printf("Exit function #2 called\n");
}
int main(void)
{
/* post exit function #1 */
atexit(exit_fn1);
/* post exit function #2 */
atexit(exit_fn2);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.19 atoi, _wtoi


Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
int atoi(const char *s);
int _wtoi(const wchar_t *s);

Description

Converts a string to an integer.

• atoi converts a string pointed to by s to int; atoi recognizes (in the following order)
• An optional string of tabs and spaces
• An optional sign
• A string of digits
The characters must match this generic format:
[ws] [sn] [ddd]
In this function, the first unrecognized character ends the conversion. There are no provisions for overflow in atoi (results are
undefined).
Return Value
atoi returns the converted value of the input string. If the string cannot be converted to a number of the corresponding type (int), 3
atoi returns 0.
Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int n;
char *str = "12345.67";

1115
C Runtime Library Reference RAD Studio 3.1 Référence C++

n = atoi(str);
printf("string = %s integer = %d\n", str, n);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


atoi + + + +
_wtoi +

3.1.5.29.20 atol, _wtol


Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
long atol(const char *s);
long _wtol(const wchar_t *s);

Description

Converts a string to a long.

• atol converts the string pointed to by s to long. atol recognizes (in the following order)
• An optional string of tabs and spaces
• An optional sign
• A string of digits
The characters must match this generic format:
[ws] [sn] [ddd]
In this function, the first unrecognized character ends the conversion. There are no provisions for overflow in atol (results are
undefined).
Return Value
atol returns the converted value of the input string. If the string cannot be converted to a number of the corresponding type (b),
atol returns 0.
Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
3 {
long l;
char *lstr = "98765432";
l = atol(lstr);
printf("string = %s integer = %ld\n", lstr, l);
return(0);
}
Portability

1116
3.1 Référence C++ RAD Studio C Runtime Library Reference

POSIX Win32 ANSI C ANSI C++


atol + + + +
_wtol +

3.1.5.29.21 bsearch
Header File

stdlib.h

Category

Memory and String Manipulation Routines

Prototype
void *bsearch(const void *key, const void *base, size_t nelem, size_t width, int (_USERENTRY
*fcmp)(const void *, const void *));

Description

Binary search of an array.

bsearch searches a table (array) of nelem elements in memory, and returns the address of the first entry in the table that
matches the search key. The array must be in order. If no match is found, bsearch returns 0.

Remarque: Because this is a binary search, the first matching entry is not necessarily the first entry in the table.

The type size_t is defined in stddef.h header file.

• nelem gives the number of elements in the table.


• width specifies the number of bytes in each table entry.
The comparison routine fcmp must be used with the _USERENTRY calling convention.
fcmp is called with two arguments: elem1 and elem2. Each argument points to an item to be compared. The comparison function
compares each of the pointed-to items (*elem1 and *elem2), and returns an integer based on the results of the comparison.
• For bsearch, the fcmp return value is
• < 0 if *elem1 < *elem2
• == 0 if *elem1 == *elem2
• > 0 if *elem1 > *elem2
Return Value
bsearch returns the address of the first entry in the table that matches the search key. If no match is found, bsearch returns 0.
Example
#include <stdlib.h>
#include <stdio.h>
typedef int (*fptr)(const void*, const void*);
3
#define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
int numarray[] = {123, 145, 512, 627, 800, 933};
int numeric (const int *p1, const int *p2)
{
return(*p1 - *p2);
}
#pragma argsused
int lookup(int key)
{

1117
C Runtime Library Reference RAD Studio 3.1 Référence C++

int *itemptr;
/* The cast of (int(*)(const void *,const void*))
is needed to avoid a type mismatch error at
compile time */
itemptr = (int *) bsearch (&key, numarray, NELEMS(numarray),
sizeof(int), (fptr)numeric);
return (itemptr != NULL);
}
int main(void)
{
if (lookup(512))
printf("512 is in the table.\n");
else
printf("512 isn't in the table.\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.22 div
Header File

stdlib.h

Category

Math Routines

Prototype
div_t div(int numer, int denom);

Description

Divides two integers, returning quotient and remainder.

div divides two integers and returns both the quotient and the remainder as a div_t type. numer and denom are the numerator
and denominator, respectively. The div_t type is a structure of integers defined (with typedef) in stdlib.h as follows:
typedef struct {
int quot; /* quotient */
int rem; /* remainder */
} div_t;

Return Value

div returns a structure whose elements are quot (the quotient) and rem (the remainder).
3
Example
/* div example */
#include <stdlib.h>
#include <stdio.h>
div_t x;
int main(void)
{
x = div(10,3);
printf("10 div 3 = %d remainder %d\n",

1118
3.1 Référence C++ RAD Studio C Runtime Library Reference

x.quot, x.rem);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.23 ecvt
Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
char *ecvt(double value, int ndig, int *dec, int *sign);

Description

Converts a floating-point number to a string.

ecvt converts value to a null-terminated string of ndig digits, starting with the leftmost significant digit, and returns a pointer to the
string. The position of the decimal point relative to the beginning of the string is stored indirectly through dec (a negative value for
dec means that the decimal lies to the left of the returned digits). There is no decimal point in the string itself. If the sign of value
is negative, the word pointed to by sign is nonzero; otherwise, it's 0. The low-order digit is rounded.

Return Value

The return value of ecvt points to static data for the string of digits whose content is overwritten by each call to ecvt and fcvt.

Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *string;
double value;
int dec, sign;
int ndig = 10;
value = 9.876;
string = ecvt(value, ndig, &dec, &sign);
printf("string = %s dec = %d sign = %d\n", string, dec, sign);
value = -123.45;
ndig= 15;
string = ecvt(value,ndig,&dec,&sign);
printf("string = %s dec = %d sign = %d\n", string, dec, sign);
value = 0.6789e5; /* scientific notation */ 3
ndig = 5;
string = ecvt(value,ndig,&dec,&sign);
printf("string = %s dec = %d sign = %d\n", string, dec, sign);
return 0;
}
Portability

1119
C Runtime Library Reference RAD Studio 3.1 Référence C++

POSIX Win32 ANSI C ANSI C++


+

3.1.5.29.24 _environ, _wenviron


Header File

stdlib.h

Syntax
extern char ** _environ;
extern wchar_t ** _wenviron

Description

_environ is an array of pointers to strings; it is used to access and alter the operating system environment variables. Each string
is of the form:
envvar = varvalue

where envvar is the name of an environment variable (such as PATH), and varvalue is the string value to which envvar is set
(such as C:\Utils;C:\MyPrograms). The string varvalue can be empty.

When a program begins execution, the operating system environment settings are passed directly to the program. Note that env,
the third argument to main, is equal to the initial setting of _environ.

The _environ array can be accessed by getenv; however, the putenv function is the only routine that should be used to add,
change or delete the _environ array entries. This is because modification can resize and relocate the process environment array,
but _environ is automatically adjusted so that it always points to the array.

Portability

POSIX Win32 ANSI C ANSI C++


_environ +
_wenviron NT only

3.1.5.29.25 exit
Header File

stdlib.h

Category

Process Control Routines


3
Prototype
void exit(int status);

Description

Terminates program.

exit terminates the calling process. Before termination, all files are closed, buffered output (waiting to be output) is written, and

1120
3.1 Référence C++ RAD Studio C Runtime Library Reference

any registered "exit functions" (posted with atexit) are called.

status is provided for the calling process as the exit status of the process. Typically a value of 0 is used to indicate a normal exit,
and a nonzero value indicates some error. It can be, but is not required, to be set with one of the following:

EXIT_FAILURE Abnormal program termination; signal to operating system that program has terminated with an error
EXIT_SUCCESS Normal program termination

Return Value

None.

Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int status;
printf("Enter either 1 or 2\n");
status = getchar();
exit(status - '0');
/* Note: this line is never reached */
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.26 fcvt
Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
char *fcvt(double value, int ndig, int *dec, int *sign);

Description

Converts a floating-point number to a string.

fcvt converts value to a null-terminated string digit starting with the leftmost significant digit with ndig digits to the right of the
decimal point. fcvt then returns a pointer to the string. The position of the decimal point relative to the beginning of the string is
stored indirectly through dec (a negative value for dec means to the left of the returned digits). There is no decimal point in the 3
string itself. If the sign of value is negative the word pointed to by sign is nonzero; otherwise it is 0.

The correct digit has been rounded for the number of digits to the right of the decimal point specified by ndig.

Return Value

The return value of fcvt points to static data whose content is overwritten by each call to fcvt and ecvt.

Example

1121
C Runtime Library Reference RAD Studio 3.1 Référence C++

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *str;
double num;
int dec, sign, ndig = 5;
/* a regular number */
num = 9.876;
str = fcvt(num, ndig, &dec, &sign);
printf("string = %10s decimal place = %d sign = %d\n", str, dec, sign);
/* a negative number */
num = -123.45;
str = fcvt(num, ndig, &dec, &sign);
printf("string = %10s decimal place = %d sign = %d\n", str, dec, sign);
/* scientific notation */
num = 0.678e5;
str = fcvt(num, ndig, &dec, &sign);
printf("string = %10s decimal place= %d sign = %d\n", str, dec, sign);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.29.27 gcvt
Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
char *gcvt(double value, int ndec, char *buf);

Description

Converts floating-point number to a string.

gcvt converts value to a null-terminated ASCII string and stores the string in buf. It produces ndec significant digits in FORTRAN
F format, if possible; otherwise, it returns the value in the printf E format (ready for printing). It might suppress trailing zeros.

Return Value

gcvt returns the address of the string pointed to by buf.

Example
3
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char str[25];
double num;
int sig = 5; /* significant digits */
/* a regular number */
num = 9.876;
gcvt(num, sig, str);

1122
3.1 Référence C++ RAD Studio C Runtime Library Reference

printf("string = %s\n", str);


/* a negative number */
num = -123.4567;
gcvt(num, sig, str);
printf("string = %s\n", str);
/* scientific notation */
num = 0.678e5;
gcvt(num, sig, str);
printf("string = %s\n", str);
return(0);
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.29.28 getenv, _wgetenv


Header File

stdlib.h

Category

Process Control Routines

Prototype
char *getenv(const char *name);
wchar_t *_wgetenv(const wchar_t *name);

Description

Find or delete an environment variable from the system environment.

The environment consists of a series of entries that are of the form name=string\0.

getenv returns the value of a specified variable. name can be either uppercase or lowercase. name must not include the equal
sign (=). If the specified environment variable does not exist, getenv returns a NULL pointer.

To delete the variable from the environment, use getenv("name=").

Remarque: Environment entries must not be changed directly. If you want to change an environment value, you must use
putenv.

Return Value

On success, getenv returns the value associated with name.

If the specified name is not defined in the environment, getenv returns a NULL pointer.

Example 3
#include <stdio.h>
#include <stdlib.h>
#include <alloc.h>
#include <string.h>
int main(void)
{
char *path, *ptr;
int i = 0;
/* get the current path environment */

1123
C Runtime Library Reference RAD Studio 3.1 Référence C++

ptr = getenv("PATH");
/* set up new path */
path = (char *) malloc(strlen(ptr)+15);
strcpy(path,"PATH=");
strcat(path,ptr);
strcat(path,";c:\\temp");
/* replace the current path and display current environment */
putenv(path);
while (_environ[i])
printf("%s\n",_environ[i++]);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


getenv + + + +
_wgetenv +

3.1.5.29.29 itoa, _itow


Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
char *itoa(int value, char *string, int radix);
wchar_t *_itow(int value, wchar_t *string, int radix);

Description

Converts an integer to a string.

itoa converts value to a null-terminated string and stores the result in string. With itoa, value is an integer. _itow is the unicode
version of the function. It converts an integer to a wide-character string.

radix specifies the base to be used in converting value; it must be between 2 and 36, inclusive. If value is negative and radix is
10, the first character of string is the minus sign (-).

Remarque: The space allocated for string must be large enough to hold the returned string, including the terminating null
character (\0). itoa can return up to 33 bytes.

Return Value

itoa returns a pointer to string.

3 Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int number = 12345;
char string[25];
itoa(number, string, 10);
printf("integer = %d string = %s\n", number, string);
return 0;

1124
3.1 Référence C++ RAD Studio C Runtime Library Reference

}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.29.30 labs
Header File

stdlib.h

Category

Math Routines

Prototype
long labs(long int x);

Description

Gives long absolute value.

labs computes the absolute value of the parameter x.

Return Value

labs returns the absolute value of x.

Example
#include <stdio.h>
#include <math.h>
int main(void)
{
long result;
long x = -12345678L;
result= labs(x);
printf("number: %ld abs value: %ld\n", x, result);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.31 lfind
Header File
3
stdlib.h

Category

Memory and String Manipulation Routines

Prototype
void *lfind(const void *key, const void *base, size_t *num, size_t width, int (_USERENTRY

1125
C Runtime Library Reference RAD Studio 3.1 Référence C++

*fcmp)(const void *, const void *));

Description

Performs a linear search.

lfind makes a linear search for the value of key in an array of sequential records. It uses a user-defined comparison routine fcmp.
The fcmp function must be used with the _USERENTRY calling convention.

The array is described as having *num records that are width bytes wide, and begins at the memory location pointed to by base.

Return Value

lfind returns the address of the first entry in the table that matches the search key. If no match is found, lfind returns NULL. The
comparison routine must return 0 if *elem1 == *elem2, and nonzero otherwise (elem1 and elem2 are its two parameters).

Example
#include <stdio.h>
#include <stdlib.h>
int compare(int *x, int *y)
{
return( *x - *y );
}
int main(void)
{
int array[5] = {35, 87, 46, 99, 12};
size_t nelem = 5;
int key;
int *result;
key = 99;
result = (int *) lfind(&key, array, &nelem,
sizeof(int), (int(*)(const void *,const void *))compare);
if (result)
printf("Number %d found\n",key);
else
printf("Number %d not found\n",key);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.29.32 lsearch
Header File

stdlib.h

Category
3 Memory and String Manipulation Routines

Prototype
void *lsearch(const void *key, void *base, size_t *num, size_t width, int (_USERENTRY
*fcmp)(const void *, const void *));

Description

Performs a linear search.

1126
3.1 Référence C++ RAD Studio C Runtime Library Reference

lsearch searches a table for information. Because this is a linear search, the table entries do not need to be sorted before a call
to lsearch. If the item that key points to is not in the table, lsearch appends that item to the table.

• base points to the base (0th element) of the search table.


• num points to an integer containing the number of entries in the table.
• width contains the number of bytes in each entry.
• key points to the item to be searched for (the search key).
The function fcmp must be used with the _USERENTRY calling convention.
The argument fcmp points to a user-written comparison routine, that compares two items and returns a value based on the
comparison.
To search the table, lsearch makes repeated calls to the routine whose address is passed in fcmp.
On each call to the comparison routine, lsearch passes two arguments:

key a pointer to the item being searched for


elem pointer to the element of base being compared.

fcmp is free to interpret the search key and the table entries in any way.

Return Value

lsearch returns the address of the first entry in the table that matches the search key.

If the search key is not identical to *elem, fcmp returns a nonzero integer. If the search key is identical to *elem, fcmp returns 0.

Example
#include <stdlib.h>
#include <stdio.h>
#include <string.h> /* for strcmp declaration */
/* initialize number of colors */
char *colors[10] = { "Red", "Blue", "Green" };
int ncolors = 3;
int colorscmp(char **arg1, char **arg2)
{
return(strcmp(*arg1, *arg2));
}
int addelem(char **key)
{
int oldn = ncolors;
lsearch(key, colors, (size_t *)&ncolors, sizeof(char *),
(int(*)(const void *,const void *))colorscmp);
return(ncolors == oldn);
}
int main(void)
{
int i;
char *key = "Purple";
if (addelem(&key))
printf("%s already in colors table\n", key);
else
{ 3
printf("%s added to colors table\n", key);
}
printf("The colors:\n");
for (i = 0; i < ncolors; i++)
printf("%s\n", colors[i]);
return 0;
}
Portability

1127
C Runtime Library Reference RAD Studio 3.1 Référence C++

POSIX Win32 ANSI C ANSI C++


+

3.1.5.29.33 ltoa, _ltoa, _ltow


Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
char * ltoa(long value, char * string, int radix);
char *_ltoa(long value, char *string, int radix);
wchar_t *_ltow(long value, wchar_t *string, int radix);

Description

Converts a long to a string. _ltow is the unicode version. It converts a long to a wide-charater string.

Converts value to a null-terminated string and stores the result in string. value is a long.

radix specifies the base to be used in converting value; it must be between 2 and 36, inclusive. If value is negative and radix is
10, the first character of string is the minus sign (-).

Remarque: The space allocated for string must be large enough to hold the returned string, including the terminating null
character (\0). Can return up to 33 bytes.

Return Value

Returns a pointer to string.

Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char string[25];
long value = 123456789L;
ltoa(value,string,10);
printf("number = %ld string = %s\n", value, string);
return 0;
}
Portability

3 POSIX Win32 ANSI C ANSI C++


ltoa +
_ltoa +
_ltow +

1128
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.29.34 max
Header File

stdlib.h

Category

C++ Prototyped Routines

Prototype
(type) max(a, b);
template <class T> T max( T t1, T t2 ); // C++ only

Description

Returns the larger of two values.

The C macro and the C++ template function compare two values and return the larger of the two. Both arguments and the
routine declaration must be of the same type.

Return Value

max returns the larger of two values.

Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.29.35 mblen
Header File

stdlib.h

Category

Memory and String Manipulation Routines

Prototype
int mblen(const char *s, size_t n);

Description

Determines the length of a multibyte character.

If s is not null, mblen determines the number of bytes in the multibyte character pointed to by s. The maximum number of bytes
examined is specified by n. 3
The behavior of mblen is affected by the setting of LC_CTYPE category of the current locale.

Return Value

If s is null, mblen returns a nonzero value if multibyte characters have state-dependent encodings. Otherwise, mblen returns 0.

If s is not null, mblen returns 0 if s points to the null character, and -1 if the next n bytes do not comprise a valid multibyte
character; the number of bytes that comprise a valid multibyte character.

1129
C Runtime Library Reference RAD Studio 3.1 Référence C++

Example
#include <stdlib.h>
#include <stdio.h>
void main (void)
{
int i ;
char *mulbc = (char *)malloc( sizeof( char) );
wchar_t widec = L'a';
printf (" convert a wide character to multibyte character:\n" );
i = wctomb (mulbc, widec);
printf( "\tCharacters converted: %u\n", i);
printf( "\tMultibyte character: %x\n\n", mulbc);
printf( " Find length--in byte-- of multibyte character:\n");
i = mblen( mulbc, MB_CUR_MAX);
printf("\tLength--in bytes--if multiple character: %u\n",i);
printf("\tWide character: %x\n\n", mulbc);
printf( " Attempt to find length of a Wide character Null:\n");
widec = L'\0';
wctomb(mulbc, widec);
i = mblen( mulbc, MB_CUR_MAX);
printf("\tLength--in bytes--if multiple character: %u\n",i);
printf("\tWide character: %x\n\n", mulbc);
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.36 mbstowcs
Header File

stdlib.h

Category

Conversion Routines, Memory and String Manipulation Routines

Prototype
size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n);

Description

Converts a multibyte string to a wchar_t array.

The function converts the multibyte string s into the array pointed to by pwcs. No more than n values are stored in the array. If an
invalid multibyte sequence is encountered, mbstowcs returns (size_t) -1.

The pwcs array will not be terminated with a zero value if mbstowcs returns n.

3 Return Value

If an invalid multibyte sequence is encountered, mbstowcs returns (size_t) -1. Otherwise, the function returns the number of
array elements modified, not including the terminating code, if any.

Example
#include <stdio.h>
#include <stdlib.h>
void main(void)
{

1130
3.1 Référence C++ RAD Studio C Runtime Library Reference

int x;
char *mbst = (char *)malloc(MB_CUR_MAX);
wchar_t *pwst = L"Hi";
wchar_t *pwc = (wchar_t *)malloc(sizeof( wchar_t));
printf ("Convert to multibyte string:\n");
x = wcstombs (mbst, pwst, MB_CUR_MAX);
printf ("\tCharacters converted %u\n",x);
printf ("\tHEx value of first");
printf (" multibyte character: %#.4x\n\n", mbst);
printf ("Convert back to wide character string:\n");
x = mbstowcs(pwc, mbst, MB_CUR_MAX);
printf( "\tCharacters converted: %u\n",x);
printf( "\tHex value of first");
printf( "wide character: %#.4x\n\n", pwc);
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.37 mbtowc
Header File

stdlib.h

Category

Conversion Routines, Memory and String Manipulation Routines

Prototype
int mbtowc(wchar_t *pwc, const char *s, size_t n);

Description

Converts a multibyte character to wchar_t code.

If s is not null, mbtowc determines the number of bytes that comprise the multibyte character pointed to by s. Next, mbtowc
determines the value of the type wchar_t that corresponds to that multibyte character. If there is a successful match between
wchar_t and the multibyte character, and pwc is not null, the wchar_t value is stored in the array pointed to by pwc. At most n
characters are examined.

Return Value

When s points to an invalid multibyte character, -1 is returned. When s points to the null character, 0 is returned. Otherwise,
mbtowc returns the number of bytes that comprise the converted multibyte character.

The return value never exceeds MB_CUR_MAX or the value of n.

Example
3
#include <stdlib.h>
#include<stdio.h>
void main(void)
{
int x;
char *mbchar = (char *)calloc(1, sizeof( char));
wchar_t wchar = L'a';
wchar_t *pwcnull = NULL;
wchar_t *pwchar = (wchar_t *)calloc(1, sizeof( wchar_t ));
printf ("Convert a wide character to multibyte character:\n");

1131
C Runtime Library Reference RAD Studio 3.1 Référence C++

x = wctomb( mbchar, wchar);


printf( "\tCharacters converted: %u\n", x);
printf( "\tMultibyte character: %x\n\n", mbchar);
printf ("Convert multibyte character back to a wide character:\n");
x = mbtowc( pwchar, mbchar, MB_CUR_MAX );
printf( "\tBytes converted: %u\n", x);
printf( "\tWide character: %x\n\n", pwchar);
printf ("Atempt to convert when target is NULL\n" );
printf (" returns the length of the multibyte character:\n" );
x = mbtowc (pwcnull, mbchar, MB_CUR_MAX );
printf ( "\tlength of multibyte character:%u\n\n", x );
printf ("Attempt to convert a NULL pointer to a" );
printf (" wide character:\n" );
mbchar = NULL;
x = mbtowc (pwchar, mbchar, MB_CUR_MAX);
printf( "\tBytes converted: %u\n", x );
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.38 min
Header File

stdlib.h

Category

C++ Prototyped Routines

Prototype
(type) min(a, b); /* macro version */
template <class T> T min( T t1, T t2 );// C++ only

Description

Returns the smaller of two values.

The C macro and the C++ template function compare two values and return the smaller of the two. Both arguments and the
routine declaration must be of the same type.

Return Value

min returns the smaller of two values.

3.1.5.29.39 putenv, _wputenv


3 Header File

stdlib.h

Category

Process Control Routines

Prototype
int putenv(const char *name);

1132
3.1 Référence C++ RAD Studio C Runtime Library Reference

int _wputenv(const wchar_t *name);

Description

Adds string to current environment.

putenv accepts the string name and adds it to the environment of the current process. For example,
putenv(“PATH=C:\\BC”);

putenv can also be used to modify an existing name. name can be either uppercase or lowercase. name must not include the
equal sign (=). You can set a variable to an empty value by specifying an empty string on the right side of the ‘=’ sign.

putenv can be used only to modify the current program’s _environment. Once the program ends, the old _environment is
restored. The _environment of the current process is passed to child processes, including any changes made by putenv.

Note that the string given to putenv must be static or global. Unpredictable results will occur if a local or dynamic string given to
putenv is used after the string memory is released.

Return Value

On success, putenv returns 0; on failure, -1.

Example
#include <stdio.h>
#include <stdlib.h>
#include <alloc.h>
#include <string.h>
int main(void)
{
char *path, *ptr;
int i = 0;
/* get the current path environment */
ptr = getenv("PATH");
/* set up new path */
path = (char *) malloc(strlen(ptr)+15);
strcpy(path,"PATH=");
strcat(path,ptr);
strcat(path,";c:\\temp");
/* replace the current path and display current environment */
putenv(path);
while (_environ[i])
printf("%s\n",_environ[i++]);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


putenv +
_wputenv NT only

3
3.1.5.29.40 qsort
Header File

stdlib.h

Category

Memory and String Manipulation Routines

1133
C Runtime Library Reference RAD Studio 3.1 Référence C++

Prototype
void qsort(void *base, size_t nelem, size_t width, int (_USERENTRY *fcmp)(const void *, const
void *));

Description

Sorts using the quicksort algorithm.

qsort is an implementation of the “median of three” variant of the quicksort algorithm. qsort sorts the entries in a table by
repeatedly calling the user-defined comparison function pointed to by fcmp.

• base points to the base (0th element) of the table to be sorted.


• nelem is the number of entries in the table.
• width is the size of each entry in the table, in bytes.
fcmp, the comparison function, must be used with the _USERENTRY calling convention.
• fcmp accepts two arguments, elem1 and elem2, each a pointer to an entry in the table. The comparison function compares
each of the pointed-to items (*elem1 and *elem2), and returns an integer based on the result of the comparison.
• *elem1 < *elem2 fcmp returns an integer < 0
• *elem1 == *elem2 fcmp returns 0
• *elem1 > *elem2 fcmp returns an integer > 0
In the comparison, the less-than symbol (<) means the left element should appear before the right element in the final, sorted
sequence. Similarly, the greater-than (>) symbol means the left element should appear after the right element in the final,
sorted sequence.
Return Value
None.
Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int sort_function( const void *a, const void *b);
char list[5][4] = { "cat", "car", "cab", "cap", "can" };
int main(void)
{
int x;
qsort((void *)list, 5, sizeof(list[0]), sort_function);
for (x = 0; x < 5; x++)
printf("%s\n", list[x]);
return 0;
}
int sort_function( const void *a, const void *b)
{
return( strcmp((char *)a,(char *)b) );
}
Portability

3 POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.41 rand
Header File

stdlib.h

1134
3.1 Référence C++ RAD Studio C Runtime Library Reference

Category

Math Routines

Prototype
int rand(void);

Description

Random number generator.

rand uses a multiplicative congruential random number generator with period 2 to the 32nd power to return successive
pseudo-random numbers in the range from 0 to RAND_MAX. The symbolic constant RAND_MAX is defined in stdlib.h.

Return Value

rand returns the generated pseudo-random number.

Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int i;
randomize();
printf("Ten random numbers from 0 to 99\n\n");
for(i=0; i<10; i++)
printf("%d\n", rand() % 100);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.42 random
Header File

stdlib.h

Category

Math Routines

Prototype
int random(int num);

Description

Random number generator. 3


random returns a random number between 0 and (num-1). random(num) is a macro defined in stdlib.h. Both num and the
random number returned are integers.

Return Value

random returns a number between 0 and (num-1).

Example

1135
C Runtime Library Reference RAD Studio 3.1 Référence C++

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
/* prints a random number in the range 0 to 99 */
int main(void)
{
randomize();
printf("Random number in the 0-99 range: %d\n", random (100));
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.29.43 randomize
Header File

stdlib.h, time.h

Category

Math Routines

Prototype
void randomize(void);

Description

Initializes random number generator.

randomize initializes the random number generator with a random value.

Return Value

None.

Example
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
int i;
randomize();
printf("Ten random numbers from 0 to 99\n\n");
for(i=0; i<10; i++)
printf("%d\n", rand() % 100);
return 0;
}
3
Portability

POSIX Win32 ANSI C ANSI C++


+

1136
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.29.44 srand
Header File

stdlib.h

Category

Math Routines

Prototype
void srand(unsigned seed);

Description

Initializes random number generator.

The random number generator is reinitialized by calling srand with an argument value of 1. It can be set to a new starting point
by calling srand with a given seed number.

Return Value

None.

Example
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
int i;
time_t t;
srand((unsigned) time(&t));
printf("Ten random numbers from 0 to 99\n\n");
for(i=0; i<10; i++)
printf("%d\n", rand() % 100);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.45 strlen, _mbslen, wcslen, _mbstrlen


Header File

string.h, mbstring.h, stdlib.h

Category
3
Memory and String Manipulation Routines, Inline Routines

Prototype
size_t strlen(const char *s);
size_t wcslen(const wchar_t *s);
size_t _mbslen(const unsigned char *s);

1137
C Runtime Library Reference RAD Studio 3.1 Référence C++

size_t _mbstrlen(const char *s)

Description

Calculates the length of a string.

strlen calculates the length of s.

_mbslen and _mbstrlen test the string argument to determine the number of multibyte characters they contain.

_mbstrlen is affected by the LC_CTYPE category setting as determined by the setlocale function. The function tests to determine
whether the string argument is a valid multibyte string.

_mbslen is affected by the code page that is in use. This function doesn’t test for multibyte validity.

Return Value

strlen returns the number of characters in s, not counting the null-terminating character.

Example
#include <stdio.h>
#include <string.h>
int main(void)
{
char *string = "CodeGear";
printf("%d\n", strlen(string));
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strlen + + + +
_mbslen +
wcslen + + +
_mbstrlen +

3.1.5.29.46 strtod, _strtold, wcstod, _wcstold


Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
double strtod(const char *s, char **endptr);
3 double wcstod(const wchar_t *s, wchar_t **endptr);
long double _strtold(const char *s, char **endptr);
long double _wcstold(const wchar_t *s, wchar_t **endptr);

Description

Convert a string to a double or long double value.

strtod converts a character string, s, to a double value. s is a sequence of characters that can be interpreted as a double value;

1138
3.1 Référence C++ RAD Studio C Runtime Library Reference

the characters must match this generic format:


[ws] [sn] [ddd] [.] [ddd] [fmt[sn]ddd]

where:

[ws] = optional whitespace


[sn] = optional sign (+ or -)
[ddd] = optional digits
[fmt] = optional e or E
[.] = optional decimal point

strtod also recognizes +INF and -INF for plus and minus infinity, and +NAN and -NAN for not-a-number.

For example, here are some character strings that strtod can convert to double:
+ 1231.1981 e-1
502.85E2
+ 2010.952

strtod stops reading the string at the first character that cannot be interpreted as an appropriate part of a double value.

If endptr is not null, strtod sets *endptr to point to the character that stopped the scan (*endptr = &stopper). endptr is useful for
error detection.

_strtold is the long double version; it converts a string to a long double value.

Return Value

These functions return the value of s as a double (strtod) or a long double (_strtold). In case of overflow, they return plus or
minus HUGE_VAL (strtod) or _LHUGE_VAL (_strtold).

Example
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char input[80], *endptr;
double value;
printf("Enter a floating point number:");
gets(input);
value = strtod(input, &endptr);
printf("The string is %s the number is %lf\n", input, value);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strtod + + + + 3
_strtold +
wcstod + + +
_wcstold +

1139
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.29.47 strtol, wcstol


Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
long strtol(const char *s, char **endptr, int radix);
long wcstol(const wchar_t *s, wchar_t **endptr, int radix);

Description

Converts a string to a long value.

strtol converts a character string, s, to a long integer value. s is a sequence of characters that can be interpreted as a long
value; the characters must match this generic format:
[ws] [sn] [0] [x] [ddd]

where:

[ws] = optional whitespace


[sn] = optional sign (+ or -)
[0] = optional zero (0)
[x] = optional x or X
[ddd] = optional digits

strtol stops reading the string at the first character it doesn't recognize.

If radix is between 2 and 36, the long integer is expressed in base radix. If radix is 0, the first few characters of s determine the
base of the value being converted.

If radix is 1, it is considered to be an invalid value. If radix is less than 0 or greater than 36, it is considered to be an invalid value.

Any invalid value for radix causes the result to be 0 and sets the next character pointer *endptr to the starting string pointer.

If the value in s is meant to be interpreted as octal, any character other than 0 to 7 will be unrecognized.

If the value in s is meant to be interpreted as decimal, any character other than 0 to 9 will be unrecognized.

If the value in s is meant to be interpreted as a number in any other base, then only the numerals and letters used to represent
numbers in that base will be recognized. (For example, if radix equals 5, only 0 to 4 will be recognized; if radix equals 20, only 0
to 9 and A to J will be recognized.)

If endptr is not null, strtol sets *endptr to point to the character that stopped the scan (*endptr = &stopper).
3
Return Value

strtol returns the value of the converted string, or 0 on error.

Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{

1140
3.1 Référence C++ RAD Studio C Runtime Library Reference

char *string = "87654321", *endptr;


long lnumber;
/* strtol converts string to long integer */
lnumber = strtol(string, &endptr, 10);
printf("string = %s long = %ld\n", string, lnumber);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strtol + + + +
wcstol + + +

3.1.5.29.48 strtoul, wcstoul


Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
unsigned long strtoul(const char *s, char **endptr, int radix);
unsigned long wcstoul(const wchar_t *s, wchar_t **endptr, int radix);

Description

Converts a string to an unsigned long in the given radix.

strtoul operates the same as strtol, except that it converts a string str to an unsigned long value (where strtol converts to a
long). Refer to the entry for strtol for more information.

Return Value

strtoul returns the converted value, an unsigned long, or 0 on error.

Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
char *string = "87654321", *endptr;
unsigned long lnumber;
lnumber = strtoul(string, &endptr, 10);
printf("string = %s long = %lu\n",
string, lnumber);
return 0;
} 3
Portability

POSIX Win32 ANSI C ANSI C++


strtoul + + + +
wcstoul + + +

1141
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.29.49 swab
Header File

stdlib.h

Category

Memory and String Manipulation Routines

Prototype
void swab(char *from, char *to, int nbytes);

Description

Swaps bytes.

swab copies nbytes bytes from the from string to the to string. Adjacent even- and odd-byte positions are swapped. This is useful
for moving data from one machine to another machine with a different byte order. nbytes should be even.

Return Value

None.

Example
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char source[15] = "rFna koBlrna d";
char target[15];
int main(void)
{
swab(source, target, strlen(source));
printf("This is target: %s\n", target);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ +

3.1.5.29.50 system, _wsystem


Header File

stdlib.h

Category
3 Process Control Routines

Prototype
int system(const char *command);
int _wsystem(const wchar_t *command);

Description

Issues an operating system command.

1142
3.1 Référence C++ RAD Studio C Runtime Library Reference

system invokes the operating system command processor to execute an operating system command, batch file, or other
program named by the string command, from inside an executing C program.

To be located and executed, the program must be in the current directory or in one of the directories listed in the PATH string in
the environment.

The COMSPEC environment variable is used to find the command processor program, so it need not be in the current directory.

Return Value

If command is a NULL pointer, system returns nonzero if a command processor is available.

If command is not a NULL pointer, system returns 0 if the command processor was successfully started.

If an error occurred, a -1 is returned and errno is set to one of the following:

ENOENT Path or file function not found


ENOEXEC Exec format error
ENOMEM Not enough memory

Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
printf("About to spawn a command-line program.\n");
system("dir");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


system + +
_wsystem NT only

3.1.5.29.51 ultoa, _ultow


Header File

stdlib.h

Category

Conversion Routines, Math Routines

Prototype
char *ultoa(unsigned long value, char *string, int radix);
3
wchar_t *_ultow(unsigned long value, wchar_t *string, int radix);

Description

Converts an unsigned long to a string.

ultoa converts value to a null-terminated string and stores the result in string. value is an unsigned long.

radix specifies the base to be used in converting value; it must be between 2 and 36, inclusive. ultoa performs no overflow
checking, and if value is negative and radix equals 10, it does not set the minus sign.

1143
C Runtime Library Reference RAD Studio 3.1 Référence C++

Remarque: The space allocated for string must be large enough to hold the returned string, including the terminating null
character (\0). ultoa can return up to 33 bytes.

Return Value

ultoa returns string.

Example
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
unsigned long lnumber = 3123456789L;
char string[25];
ultoa(lnumber,string,10);
printf("string = %s unsigned long = %lu\n",string,lnumber);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


ultoa +
_ultow +

3.1.5.29.52 wcstombs
Header File

stdlib.h

Category

Conversion Routines, Memory and String Manipulation Routines

Prototype
size_t wcstombs(char *s, const wchar_t *pwcs, size_t n);

Description

Converts a wchar_t array into a multibyte string.

wcstombs converts the type wchar_t elements contained in pwcs into a multibyte character string s. The process terminates if
either a null character or an invalid multibyte character is encountered.

No more than n bytes are modified. If n number of bytes are processed before a null character is reached, the array s is not null
terminated.

The behavior of wcstombs is affected by the setting of LC_CTYPE category of the current locale.
3 Return Value

If an invalid multibyte character is encountered, wcstombs returns (size_t) -1. Otherwise, the function returns the number of
bytes modified, not including the terminating code, if any.

Example
#include <stdio.h>
#include <stdlib.h>
void main(void)
{

1144
3.1 Référence C++ RAD Studio C Runtime Library Reference

int x;
char *pbuf = (char*)malloc( MB_CUR_MAX);
wchar_t *pwcsEOL = L'\0';
char *pwchi= L"Hi there!";

printf (" Convert entire wchar string into a multibyte string:\n");


x = wcstombs( pbuf, pwchi,MB_CUR_MAX);
printf ("Character converted: %u\n", x);
printf ("Multibyte string character: %1s\n\n",pbuf);
printf (" Convert when target is NULL\n");
x = wcstombs( pbuf, pwcsEOL, MB_CUR_MAX);
printf ("Character converted: %u\n",x);
printf ("Multibyte string: %1s\n\n",pbuf);

}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.29.53 wctomb
Header File

stdlib.h

Category

Conversion Routines, Memory and String Manipulation Routines

Prototype
int wctomb(char *s, wchar_t wc);

Description

Converts wchar_t code to a multibyte character.

If s is not null, wctomb determines the number of bytes needed to represent the multibyte character corresponding to wc
(including any change in shift state). The multibyte character is stored in s. At most MB_CUR_MAX characters are stored. If the
value of wc is zero, wctomb is left in the initial state.

The behavior of wctomb is affected by the setting of LC_CTYPE category of the current locale.

Return Value

If s is a NULL pointer, wctomb returns a nonzero value if multibyte character encodings do have state-dependent encodings, and
a zero value if they do not.

If s is not a NULL pointer, wctomb returns -1 if the wc value does not represent a valid multibyte character. Otherwise, wctomb
returns the number of bytes that are contained in the multibyte character corresponding to wc. In no case will the return value be
greater than the value of MB_CUR_MAX macro. 3
Example
#include <stdio.h>
#include <stdlib.h>
void main(void)
{
int x;
wchar_t wc = L'a';
char *pmbNULL = NULL;

1145
C Runtime Library Reference RAD Studio 3.1 Référence C++

char *pmb = (char *)malloc(sizeof( char ));


printf (" Convert a wchar_t array into a multibyte string:\n");
x = wctomb( pmb, wc);
printf ("Character converted: %u\n", x);
printf ("Multibyte string: %1s\n\n",pmb);
printf (" Convert when target is NULL\n");
x = wctomb( pmbNULL, wc);
printf ("Character converted: %u\n",x);
printf ("Multibyte stri ng: %1s\n\n",pmbNULL);

}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.30 string.h
The following functions, macros, and classes are provided in string.h:

Rubriques
Nom Description
_ismbblead, _ismbbtrail ( see page 1159) Header File
mbstring.h
Category
Classification Routines
Prototype
int _ismbblead(unsigned int c);
int _ismbbtrail(unsigned int c);
Description
_ismbblead and _ismbbtrail are used to test whether the argument c is the first or
the second byte of a multibyte character.
_ismbblead and _ismbbtrail are affected by the code page in use. You can set
the code page by using the _setlocale function.
Return Value
If c is in the lead byte of a multibyte character, _ismbblead returns true.
If c is in the trail byte of a multibyte character, _ismbbtrail returns a nonzero value.
_ismbclegal ( see page 1160) Header File
mbstring.h
Category
Classification Routines
Prototype
int _ismbclegal(unsigned int c);
Description
_ismbclegal tests whether each byte of the c argument is in the code page that is
currently in use.
Return Value
_ismbclegal returns a nonzero value if the argument c is a valid multibyte
character on the current code page. Otherwise, the function returns zero.

1146
3.1 Référence C++ RAD Studio C Runtime Library Reference

_ismbslead, _ismbstrail ( see page 1160) Header File


mbstring.h
Category
Classification Routines
Prototype
int _ismbslead(const unsigned char *s1, const unsigned char
*s2);
int _ismbstrail(const unsigned char *s1, const unsigned
char *s2);
Description
The _ismbslead and _ismbstrail functions test the s1 argument to determine
whether the s2 argument is a pointer to the lead byte or the trail byte. The test is
case-sensitive.
Return Value
The _ismbslead and _ismbstrail routines return -1 if s2 points to a lead byte or a
trail byte, respectively. If the test is false, the routines return zero.
_mbbtype ( see page 1160) Header File
mbstring.h
Category
Classification Routines
Prototype
int _mbbtype(unsigned char ch, int mode);
Description
The _mbbtype function inspects the multibyte argument, character ch, to
determine whether it is a single-byte character, or whether ch is the leadbyte or
trailing byte in a multibyte character. The _mbbtype function can determine
whether ch is an invalid character.
Return Value
The value that _mbbtype returns is one of the following manifest constants,
defined in mbctype.h. The return value depends on the value of ch and the test
which you want performed on ch.
_mbccpy ( see page 1161) Header File
mbstring.h
Category
Memory and String Manipulation Routines
Prototype
void _mbccpy(unsigned char *dest, unsigned char *src);
Description
The _mbccpy function copies a multibyte character from src to dest. The
_mbccpy function makes an implicit call to _ismbblead so that the src pointer
references a lead byte. If src doesn’t reference a lead byte, no copy is performed.
Return Value
None.
_mbsbtype ( see page 1161) Header File
mbstring.h
Category
Classification Routines
Prototype
int _mbsbtype(const unsigned char *str, size_t nbyte);
Description
The nbyte argument specifies the number of bytes from the start of the
zero-based string.
The _mbsbtype function inspects the argument str to determine whether the byte
at the position specified by nbyte is a single-byte character, or whether it is the
leadbyte or trailing byte in a multibyte character. The _mbsbtype function can
determine whether the byte pointed at is an invalid character or a NULL byte.
Any invalid bytes in str before nbyte are ignored. 3
Return Value
The value that _mbsbtype returns is... suite ( see page 1161)

1147
C Runtime Library Reference RAD Studio 3.1 Référence C++

_mbsnbcmp ( see page 1162) Header File


mbstring.h
Category
Memory and String Manipulation Routines
Prototype
int _mbsnbcmp(const unsigned char *s1, const unsigned char
s2, size_t maxlen);
Description
_mbsnbcmp makes an case-sensitive comparison of s1 and s2 for no more than
maxlen bytes. It starts with the first byte in each string and continues with
subsequent bytes until the corresponding bytes differ or until it has examined
maxlen bytes.
_mbsnbcmp is case sensitive.
_mbsnbcmp is not affected by locale.
_mbsnbcmp compares bytes based on the current multibyte code page.
Return Value

• _mbsnbcmp returns an integer value based on the result


of comparing s1 (or part of... suite ( see page 1162)
_mbsnbcnt, _mbsnccnt, _strncnt, _wcsncnt ( see page 1162) Header File
mbstring.h
Category
Memory and String Manipulation Routines
Prototype
size_t _mbsnbcnt(const unsigned char * str, size_t nmbc);
size_t _mbsnccnt(const unsigned char * str, size_t nbyte);
Description
If _MBCS is defined:
_mbsnbcnt is mapped to the portable macro _tcsnbcnt
_mbsnccnt is mapped to the portable macro _tcsnccnt If _UNICODE is defined:
both _mbsnbcnt and _mbsnccnt are mapped to the _wcsncnt macro
If neither _MBCS nor _UNICODE are defined.
_tcsnbcnt and _tcsnccnt are mapped to the _strncnt macro _strncnt is the
single-byte version of these functions. _wcsncnt is the wide-character version of
these functions.
_strncnt and _wcsncnt are available only for... suite ( see page 1162)
_mbsnbcoll, _mbsnbicoll ( see page 1163) Header File
mbstring.h
Category
Memory and String Manipulation Routines
Prototype
int _mbsnbcoll(const unsigned char *s1, const unsigned char
*s2, maxlen);
int _mbsnbicoll(const unsigned char *s1, const unsigned
char *s2, maxlen);
Description
_mbsnbicoll is the case-insensitive version of _mbsnbcoll.
These functions collate the strings specified by arguments s1 and s2. The
collation order is determined by lexicographic order as specified by the current
multibyte code page. At most, maxlen number of bytes are collated.
Remarque: Note:
The lexicographic order is not always the same as the order of characters in the
character set.If the last byte in s1 or s2 is... suite ( see page 1163)

1148
3.1 Référence C++ RAD Studio C Runtime Library Reference

_mbsnbcpy ( see page 1164) Header File


mbstring.h
Category
Memory and String Manipulation Routines
Prototype
unsigned char *_mbsnbcpy(unsigned char *dest, unsigned char
*src, size_t maxlen);
Description
The _mbsnbcpy function copies at most maxlen number of characters from the
src buffer to the dest buffer. The dest buffer is null terminated after the copy.
It is the user’s responsibility to be sure that dest is large enough to allow the
copy. An improper buffer size can result in memory corruption.
Return Value
The function returns dest.
_mbsnbicmp ( see page 1164) Header File
mbstring.h
Category
Memory and String Manipulation Routines
Prototype
int _mbsnbicmp(const unsigned char *s1, const unsigned char
s2, size_t maxlen);
Description
_mbsnbicmp ignores case while making a comparison of s1 and s2 for no more
than maxlen bytes. It starts with the first byte in each string and continues with
subsequent bytes until the corresponding bytes differ or until it has examined
maxlen bytes.
_mbsnbicmp is not case sensitive.
_mbsnbicmp is not affected by locale.
_mbsnbicmp compares bytes based on the current multibyte code page.
Return Value

• _mbsnbicmp returns an integer value based on the result


of comparing s1... suite ( see page 1164)
_mbsnbset ( see page 1165) Header File
mbstring.h
Category
Memory and String Manipulation Routines
Prototype
unsigned char *_mbsnbset(unsigned char str, unsigned int
ch, size_t maxlen);
Description
_mbsnbset sets at most maxlen number of bytes in the string str to the character
ch. The argument ch can be a single or multibyte character.
The function quits if the terminating null character is found before maxlen is
reached. If ch is a multibyte character that cannot be accomodated at the end of
str, the last character in str is set to a blank character.
Return Value
strset returns str.
_mbsninc, _strninc, _wcsninc ( see page 1165) Header File
mbstring.h
Category
Memory and String Manipulation Routines
Prototype
unsigned char *_mbsninc(const unsigned char *str, size_t
num);
Description 3
The functions increment the character array str by num number of characters.
These functions should be accessed through the portable macro, _tcsninc,
defined in tchar.h.
Return value
The functions return a pointer to the resized character string specified by the
argument str.

1149
C Runtime Library Reference RAD Studio 3.1 Référence C++

_mbsspnp, _strspnp, _wcsspnp ( see page 1165) Header File


mbstring.h
Category
Memory and String Manipulation Routines
Prototype
unsigned char *_mbsspnp(const unsigned char *s1, const
unsigned char *s2);
Description
Each of these functions search for the first character in s1 that is not contained in
s2.
Use the portable macro, _tcsspnp, defined in tchar.h, to access these functions.
Return Value
The functions return a pointer to the first character in s1 that is not found in the
character set for s2.
If every character from s1 is found in s2, each of the functions return NULL.
_strdec, mbsdec, _wcsdec ( see page 1166) Header File
mbstring.h, tchar.h
Category
Memory and String Manipulation Routines
Prototype
unsigned char *_mbsdec(const unsigned char *s, const
unsigned char *p);
inline char *_strdec(const char * s1, const char * s2) {
return (char *)(s1,(s2-1));
// From tchar.h
#define _tcsdec _strdec
#define _tcsdec _wcsdec
Description
_mbsdec returns a pointer p indicating the character in string s back to 1 byte
backward. If there are no more characters before string p (it is the same position
as s), _mbsdec returns a null pointer.
_strdec is the single-byte version of this function.
_wcsdec is the wide-character version of this function.
Return Value... suite ( see page 1166)
_strerror ( see page 1166) Header File
string.h, stdio.h
Category
Memory and String Manipulation Routines
Prototype
char *_strerror(const char *s);
Description
Builds a customized error message.
_strerror lets you generate customized error messages; it returns a pointer to a
null-terminated string containing an error message.

• If s is null, the return value points to the most recent error


message.
• If s is not null, the return value contains s (your
customized error message), a colon, a space, the
most-recently generated system error message, and a
new line. s should be 94 characters or less.
Return Value
_strerror returns a pointer to a constructed error string....
3 suite ( see page 1166)

1150
3.1 Référence C++ RAD Studio C Runtime Library Reference

_strinc, mbsinc, _wcsinc ( see page 1167) Header File


mbstring.h, tchar.h
Category
Memory and String Manipulation Routines
Prototype
unsigned char *_mbsinc(const unsigned char *p);
// From tchar.h
#define _tcsinc _strinc
#define _tcsinc _wcsinc
inline char * strinc(const char * s) { return (char
*)(s+1); }
Description
_mbsinc increments a string pointer by one byte.
_strdec is the single-byte version of this function.
_wcsdec is the wide-character version of this function.
Return Value
Returns a pointer that is forwarded by 1 byte.
_strnextc,_mbsnextc,_wcsnextc ( see page 1168) Header File
tchar.h, mbstring.h
Category
Memory and String Manipulation Routines
Prototype
unsigned int _strnextc(const char *str);
unsigned int _mbsnextc (const unsigned char *str);
Description
These routines should be accessed by using the portable _tcsnextc function. The
functions inspect the current character in str. The pointer to str is not advanced.
Return Value
The functions return the integer value of the character pointed to by str.
Example
stpcpy, _wstpcpy, _stpcpy ( see page 1168) Header File
string.h
Category
Memory and String Manipulation Routines
Prototype
char *stpcpy(char *dest, const char *src);
wchar * _wcspcpy(wchar *dest, const wchar *src);
Description
Copies one string into another.
_stpcpy copies the string src to dest, stopping after the terminating null character
of src has been reached.
Return Value
stpcpy returns a pointer to the terminating null character of dest.
If UNICODE is defined, _wcspcpy returns a pointer to the terminating null
character of the wchar_t dest string.
Example
strcat, _mbscat, wcscat ( see page 1169) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
char *strcat(char *dest, const char *src);
wchar_t *wcscat(wchar_t *dest, const wchar_t *src);
unsigned char *_mbscat(unsigned char *dest, const unsigned
char *src);
Description
3
Appends one string to another.
strcat appends a copy of src to the end of dest. The length of the resulting string
is strlen(dest) + strlen(src).
Return Value
strcat returns a pointer to the concatenated strings.
Example

1151
C Runtime Library Reference RAD Studio 3.1 Référence C++

strchr, _mbschr, wcschr ( see page 1170) Header File


string.h
Category
Memory and String Manipulation Routines, Inline Routines, C++ Prototyped
Routines
Prototype
char *strchr(const char *s, int c);/* C only */
const char *strchr(const char *s, int c);// C++ only
char *strchr( char *s, int c);// C++ only
wchar_t *wcschr(const wchar_t *s, int c);
unsigned char * _mbschr(const unsigned char *s, unsigned
int c);
Description
Scans a string for the first occurrence of a given character.
strchr scans a string in the forward direction, looking for a specific character.
strchr finds the first occurrence of the character c in the string s. The
null-terminator is considered to... suite ( see page 1170)
strcmp, _mbscmp, wcscmp ( see page 1171) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
int strcmp(const char *s1, const char *s2);
int wcscmp(const wchar_t *s1, const wchar_t *s2);
int _mbscmp(const unsigned char *s1, const unsigned char
*s2);
Description
Compares one string to another.
strcmp performs an unsigned comparison of s1 to s2, starting with the first
character in each string and continuing with subsequent characters until the
corresponding characters differ or until the end of the strings is reached.
Return Value
strcmpi ( see page 1172) Header File
string.h, wchar.h
Category
Memory and String Manipulation Routines
Prototype
int strcmpi(const char *s1, const char *s2);
int _wcscmpi(const wchar_t *s1, const wchar_t *s2);
Description
Compares one string to another, without case sensitivity.
strcmpi performs an unsigned comparison of s1 to s2, without case sensitivity
(same as stricmp--implemented as a macro).
It returns a value (< 0, 0, or > 0) based on the result of comparing s1 (or part of it)
to s2 (or part of it).
The routine strcmpi is the same as stricmp. strcmpi is implemented through a
macro in string.h and translates calls from strcmpi... suite ( see page 1172)
strcoll,_stricoll, _mbscoll, _mbsicoll, wcscoll, _wcsicoll ( see page 1173) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines
Prototype
int strcoll(const char *s1, const char *s2);
int wcscoll(const wchar_t *s1, const wchar_t *s2);
int _stricoll(const char *s1, const char *s2);
int _wcsicoll(const wchar_t *s1, wconst_t char *s2);
3 int _mbscoll(const unsigned char *s1, const unsigned char
*s2);
int _mbsicoll(const unsigned char *s1, const unsigned char
*s2);
Description
Compares two strings.
strcoll compares the string pointed to by s1 to the string pointed to by s2,
according to the current locale's LC_COLLATE category.
_stricoll performs like strcoll but is not case sensitive.
Remarque: Note
_stricoll does not compare string according... suite ( see page 1173)

1152
3.1 Référence C++ RAD Studio C Runtime Library Reference

strcpy ( see page 1174) Header File


string.h, wchar.h, mbstring.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
char *strcpy(char *dest, const char *src);
wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
unsigned char *_mbscpy(unsigned char *dest, const unsigned
char *src);
Description
Copies one string into another.
Copies string src to dest, stopping after the terminating null character has been
moved.
Return Value
strcpy returns dest.
Example
strcspn, _mbscspn, wcscspn ( see page 1175) Header File
string.h, wchar.h, mbstring.h
Category
Memory and String Manipulation Routines
Prototype
size_t strcspn(const char *s1, const char *s2);
size_t wcscspn(const wchar_t *s1, const wchar_t *s2);
size_t _mbscspn(const unsigned char *s1, const unsigned
char *s2);
Description
Scans a string for the initial segment not containing any subset of a given set of
characters.
The strcspn functions search s1 until any one of the characters contained in s2 is
found. The number of characters which were read in s1 is the return value. The
string termination character is not counted. Neither string is altered during the
search.
Return Value
strcspn returns... suite ( see page 1175)
strdup, _mbsdup, _wcsdup ( see page 1176) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines
Prototype
char *strdup(const char *s);
wchar_t *_wcsdup(const wchar_t *s);
unsigned char *_mbsdup(const wchar_t *s);
Description
Copies a string into a newly created location.
strdup makes a duplicate of string s, obtaining space with a call to malloc. The
allocated space is (strlen(s) + 1) bytes long. The user is responsible for freeing
the space allocated by strdup when it is no longer needed.
Return Value
strdup returns a pointer to the storage location containing the duplicated string, or
returns null if space could not be allocated.
Example
strerror ( see page 1176) Header File
string.h
Category
Memory and String Manipulation Routines
Prototype 3
char *strerror(int errnum);
Description
Returns a pointer to an error message string.
strerror takes an int parameter errnum, an error number, and returns a pointer to
an error message string associated with errnum.
Return Value
strerror returns a pointer to a constructed error string. The error message string is
constructed in a static buffer that is overwritten with each call to strerror.
Example

1153
C Runtime Library Reference RAD Studio 3.1 Référence C++

stricmp, _mbsicmp, _wcsicmp ( see page 1177) Header File


string.h, mbstring.h
Category
Memory and String Manipulation Routines
Prototype
int stricmp(const char *s1, const char *s2);
int _wcsicmp(const wchar_t *s1, const wchar_t *s2);
int _mbsicmp(const unsigned char *s1, const unsigned char
*s2);
Description
Compares one string to another, without case sensitivity.
stricmp performs an unsigned comparison of s1 to s2, starting with the first
character in each string and continuing with subsequent characters until the
corresponding characters differ or until the end of the strings is reached. The
comparison is not case sensitive.
It returns a value (< 0, 0, or > 0) based on the result of... suite ( see page 1177)
strlwr, _mbslwr, _wcslwr ( see page 1178) Header File
string.h, mbstring.h
Category
Conversion Routines, Memory and String Manipulation Routines
Prototype
char *strlwr(char *s);
wchar_t *_wcslwr(wchar_t *s);
unsigned char *_mbslwr(unsigned char *s);
Description
Converts uppercase letters in a string to lowercase.
strlwr converts uppercase letters in string s to lowercase according to the current
locale's LC_CTYPE category. For the C locale, the conversion is from uppercase
letters (A to Z) to lowercase letters (a to z). No other characters are changed.
Return Value
strlwr returns a pointer to the string s.
Example
strncat ( see page 1179) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
char *strncat(char *dest, const char *src, size_t maxlen);
wchar_t *wcsncat(wchar_t *dest, const wchar_t *src, size_t
maxlen);
unsigned char *_mbsncat(unsigned char *dest, const unsigned
char *src, size_t maxlen);
unsigned char *_mbsnbcat(unsigned char *__dest, const
unsigned char *__src, _SIZE_T __maxlen);
Description
Appends a portion of one string to another.
strncat copies at most maxlen characters of src to the end of dest and then
appends a null character. The maximum length of the resulting string is
strlen(dest) + maxlen.
For _mbsnbcat, if the second byte of 2-bytes character is... suite ( see page
1179)

1154
3.1 Référence C++ RAD Studio C Runtime Library Reference

strncmp, _mbsncmp, wcsncmp ( see page 1180) Header File


string.h, mbstring.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
int strncmp(const char *s1, const char *s2, size_t maxlen);
int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t
maxlen);
int _mbsncmp(const unsigned char *s1, const unsigned char
*s2, size_t maxlen);
#define _mbccmp(__s1, __s2) _mbsncmp((__s1),(__s2),1)
Description
Compares a portion of one string to a portion of another.
strncmp makes the same unsigned comparison as strcmp, but looks at no more
than maxlen characters. It starts with the first character in each string and
continues with subsequent characters until the corresponding characters differ or
until it has examined maxlen characters.... suite ( see page 1180)
strncmpi, wcsncmpi ( see page 1181) Header File
string.h
Category
Memory and String Manipulation Routines
Prototype
int strncmpi(const char *s1, const char *s2, size_t n);
int wcsncmpi(const wchar_t *s1, const wchar_t *s2, size_t
n);
Description
Compares a portion of one string to a portion of another, without case sensitivity.
strncmpi performs a signed comparison of s1 to s2, for a maximum length of n
bytes, starting with the first character in each string and continuing with
subsequent characters until the corresponding characters differ or until n
characters have been examined. The comparison is not case sensitive. (strncmpi
is the same as strnicmp--implemented as a macro). It... suite ( see page 1181)
strncoll, strnicoll, _mbsncoll, _mbsnicoll, _wcsncoll, _wcsnicoll ( see page 1182) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines
Prototype
int _strncoll(const char *s1, const char *s2, size_t n);
int _wcsncoll(const wchar_t *s1, const wchar_t *s2, size_t
n);
int _strnicoll(const char *s1, const char *s2, size_t n);
int _wcsnicoll(const wchar_t *s1, const wchar_t *s2, size_t
n);
int _mbsncoll(const unsigned char *s1, const unsigned char
*s2, size_t n);
int _mbsnicoll(const unsigned char *s1, const unsigned char
*s2, size_t n);
Description
_strncoll compares n number of elements from the string pointed to by s1 to the
string pointed to by s2, according to the current locale's LC_COLLATE category.
_strnicoll performs like... suite ( see page 1182)

1155
C Runtime Library Reference RAD Studio 3.1 Référence C++

strncpy, _mbsncpy, wcsncpy ( see page 1182) Header File


string.h, mbstring.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
char *strncpy(char *dest, const char *src, size_t maxlen);
wchar_t *wcsncpy(wchar_t *dest, const wchar_t *src, size_t
maxlen);
unsigned char *_mbsncpy(unsigned char *dest, const unsigned
char *src, size_t maxlen);
Description
Copies a given number of bytes from one string into another, truncating or
padding as necessary.
strncpy copies up to maxlen characters from src into dest, truncating or
null-padding dest. The target string, dest, might not be null-terminated if the
length of src is maxlen or more.
Return Value
strncpy returns dest.
Example
strnicmp, _mbsnicmp, _wcsnicmp ( see page 1183) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines
Prototype
int strnicmp(const char *s1, const char *s2, size_t maxlen);
int _wcsnicmp(const wchar_t *s1, const wchar_t *s2, size_t
maxlen);
int _mbsnicmp(const unsigned char *s1, const unsigned char
*s2, size_t maxlen);
Description
Compares a portion of one string to a portion of another, without case sensitivity.
strnicmp performs a signed comparison of s1 to s2, for a maximum length of
maxlen bytes, starting with the first character in each string and continuing with
subsequent characters until the corresponding characters differ or until the end of
the strings is reached. The comparison... suite ( see page 1183)
strnset, _mbsnset, _wcsnset ( see page 1184) Header File
string.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
char *strnset(char *s, int ch, size_t n);
wchar_t *_wcsnset(wchar_t *s, wchar_t ch, size_t n);
unsigned char *_mbsnset(unsigned char *s, unsigned int ch,
size_t n);
Description
Sets a specified number of characters in a string to a given character.
strnset copies the character ch into the first n bytes of the string s. If n > strlen(s),
then strlen(s) replaces n. It stops when n characters have been set, or when a
null character is found.
Return Value
Each of these functions return s.
Example

1156
3.1 Référence C++ RAD Studio C Runtime Library Reference

strpbrk, _mbspbrk, wcspbrk ( see page 1185) Header File


string.h, mbstring.h
Category
C++ Prototyped Routines, Memory and String Manipulation Routines
Prototype
char *strpbrk(const char *s1, const char *s2); /* C only */
const char *strpbrk(const char *s1, const char *s2); // C++
only
char *strpbrk(char *s1, const char *s2); // C++ only
wchar_t * wcspbrk(const wchar_t *s1, const wchar_t *s2);
unsigned char *_mbspbrk(const unsigned char *s1, const
unsigned char *s2);
Description
Scans a string for the first occurrence of any character from a given set.
strpbrk scans a string, s1, for the first occurrence of any character appearing in
s2.
Return Value
strpbrk returns a pointer to... suite ( see page 1185)
strrchr, _mbsrchr, wcsrchr ( see page 1186) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines, Inline Routines, C++ Prototyped
Routines
Prototype
char *strrchr(const char *s, int c); /* C only */
const char *strrchr(const char *s, int c); // C++ only
char *strrchr(char *s, int c); // C++ only
wchar_t *wcsrchr(const wchar_t *s, wchar_t c);
unsigned char * _mbsrchr(const unsigned char *s, unsigned
int c);
Description
Scans a string for the last occurrence of a given character.
strrchr scans a string in the reverse direction, looking for a specific character.
strrchr finds the last occurrence of the character c in the string s. The
null-terminator... suite ( see page 1186)
strrev, _mbsrev, _wcsrev ( see page 1187) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines
Prototype
char *strrev(char *s);
wchar_t *_wcsrev(wchar_t *s);
unsigned char *_mbsrev(unsigned char *s);
Description
Reverses a string.
strrev changes all characters in a string to reverse order, except the terminating
null character. (For example, it would change string\0 to gnirts\0.)
Return Value
strrev returns a pointer to the reversed string.
Example
strset, _mbsset, _wcsset ( see page 1188) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines, Inline Routines
Prototype
char *strset(char *s, int ch); 3
wchar_t *_wcsset(wchar_t *s, wchar_t ch);
unsigned char *_mbsset(unsigned char *s, unsigned int ch);
Description
Sets all characters in a string to a given character.
strset sets all characters in the string s to the character ch. It quits when the
terminating null character is found.
Return Value
strset returns s.
Example

1157
C Runtime Library Reference RAD Studio 3.1 Référence C++

strspn, _mbsspn, wcsspn ( see page 1188) Header File


string.h, mbstring.h
Category
Memory and String Manipulation Routines
Prototype
size_t strspn(const char *s1, const char *s2);
size_t wcsspn(const wchar_t *s1, const wchar_t *s2);
size_t _mbsspn(const unsigned char *s1, const unsigned char
*s2);
Description
Scans a string for the first segment that is a subset of a given set of characters.
strspn finds the initial segment of string s1 that consists entirely of characters
from string s2.
Return Value
strspn returns the length of the initial segment of s1 that consists entirely of
characters from s2.
Example
strstr, _mbsstr, wcsstr ( see page 1189) Header File
string.h
Category
C++ Prototyped Routines, Memory and String Manipulation Routines
Prototype
char *strstr(const char *s1, const char *s2); /* C only */
const char *strstr(const char *s1, const char *s2); // C++
only
char *strstr(char *s1, const char *s2); // C++ only
wchar_t * wcsstr(const wchar_t *s1, const wchar_t *s2);
unsigned char * _mbsstr(const unsigned char *s1, const
unsigned char *s2);
Description
Scans a string for the occurrence of a given substring.
strstr scans s1 for the first occurrence of the substring s2.
Return Value
strstr returns a pointer to the element in s1, where s2 begins (points... suite (
see page 1189)
strtok, _mbstok, wcstok ( see page 1190) Header File
string.h, mbstring.h
Category
Memory and String Manipulation Routines
Prototype
char *strtok(char *s1, const char *s2);
wchar_t *wcstok(wchar_t *s1, const wchar_t *s2);
unsigned char *_mbstok(unsigned char *s1, const unsigned
char *s2);
Description
Searches one string for tokens, which are separated by delimiters defined in a
second string.
strtok considers the string s1 to consist of a sequence of zero or more text
tokens, separated by spans of one or more characters from the separator string
s2.
The first call to strtok returns a pointer to the first character of the first token in s1
and writes a null character... suite ( see page 1190)

1158
3.1 Référence C++ RAD Studio C Runtime Library Reference

strupr, _mbsupr, _wcsupr ( see page 1191) Header File


string.h, mbstring.h
Category
Conversion Routines, Memory and String Manipulation Routines
Prototype
char *strupr(char *s);
wchar_t *_wcsupr(wchar_t *s);
unsigned char *_mbsupr(unsigned char *s);
Description
Converts lowercase letters in a string to uppercase.
strupr converts lowercase letters in string s to uppercase according to the current
locale's LC_CTYPE category. For the default C locale, the conversion is from
lowercase letters (a to z) to uppercase letters (A to Z). No other characters are
changed.
Return Value
strupr returns s.
Example
strxfrm, wcsxfrm ( see page 1192) Header File
string.h
Category
Memory and String Manipulation Routines
Prototype
size_t strxfrm(char *target, const char *source, size_t n);
size_t wcsxfrm(wchar_t *target, const wchar_t *source,
size_t n);
Description
Transforms a portion of a string to a specified collation.
strxfrm transforms the string pointed to by source into the string target for no
more than n characters. The transformation is such that if the strcmp function is
applied to the resulting strings, its return corresponds with the return values of
the strcoll function.
No more than n characters, including the terminating null character, are copied to
target.
strxfrm transforms a character string... suite ( see page 1192)

3.1.5.30.1 _ismbblead, _ismbbtrail


Header File

mbstring.h

Category

Classification Routines

Prototype
int _ismbblead(unsigned int c);
int _ismbbtrail(unsigned int c);

Description

_ismbblead and _ismbbtrail are used to test whether the argument c is the first or the second byte of a multibyte character.

_ismbblead and _ismbbtrail are affected by the code page in use. You can set the code page by using the _setlocale function. 3
Return Value

If c is in the lead byte of a multibyte character, _ismbblead returns true.

If c is in the trail byte of a multibyte character, _ismbbtrail returns a nonzero value.

1159
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.30.2 _ismbclegal
Header File

mbstring.h

Category

Classification Routines

Prototype
int _ismbclegal(unsigned int c);

Description

_ismbclegal tests whether each byte of the c argument is in the code page that is currently in use.

Return Value

_ismbclegal returns a nonzero value if the argument c is a valid multibyte character on the current code page. Otherwise, the
function returns zero.

3.1.5.30.3 _ismbslead, _ismbstrail


Header File

mbstring.h

Category

Classification Routines

Prototype
int _ismbslead(const unsigned char *s1, const unsigned char *s2);
int _ismbstrail(const unsigned char *s1, const unsigned char *s2);

Description

The _ismbslead and _ismbstrail functions test the s1 argument to determine whether the s2 argument is a pointer to the lead
byte or the trail byte. The test is case-sensitive.

Return Value

The _ismbslead and _ismbstrail routines return -1 if s2 points to a lead byte or a trail byte, respectively. If the test is false, the
routines return zero.

3.1.5.30.4 _mbbtype
3 Header File

mbstring.h

Category

Classification Routines

Prototype
int _mbbtype(unsigned char ch, int mode);

1160
3.1 Référence C++ RAD Studio C Runtime Library Reference

Description

The _mbbtype function inspects the multibyte argument, character ch, to determine whether it is a single-byte character, or
whether ch is the leadbyte or trailing byte in a multibyte character. The _mbbtype function can determine whether ch is an invalid
character.

Return Value

The value that _mbbtype returns is one of the following manifest constants, defined in mbctype.h. The return value depends on
the value of ch and the test which you want performed on ch.

3.1.5.30.5 _mbccpy
Header File

mbstring.h

Category

Memory and String Manipulation Routines

Prototype
void _mbccpy(unsigned char *dest, unsigned char *src);

Description

The _mbccpy function copies a multibyte character from src to dest. The _mbccpy function makes an implicit call to _ismbblead
so that the src pointer references a lead byte. If src doesn’t reference a lead byte, no copy is performed.

Return Value

None.

3.1.5.30.6 _mbsbtype
Header File

mbstring.h

Category

Classification Routines

Prototype
int _mbsbtype(const unsigned char *str, size_t nbyte);

Description

The nbyte argument specifies the number of bytes from the start of the zero-based string.

The _mbsbtype function inspects the argument str to determine whether the byte at the position specified by nbyte is a 3
single-byte character, or whether it is the leadbyte or trailing byte in a multibyte character. The _mbsbtype function can
determine whether the byte pointed at is an invalid character or a NULL byte.

Any invalid bytes in str before nbyte are ignored.

Return Value

The value that _mbsbtype returns is one of the following manifest constants, defined in mbctype.h.

1161
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.30.7 _mbsnbcmp
Header File

mbstring.h

Category

Memory and String Manipulation Routines

Prototype
int _mbsnbcmp(const unsigned char *s1, const unsigned char s2, size_t maxlen);

Description

_mbsnbcmp makes an case-sensitive comparison of s1 and s2 for no more than maxlen bytes. It starts with the first byte in each
string and continues with subsequent bytes until the corresponding bytes differ or until it has examined maxlen bytes.

_mbsnbcmp is case sensitive.

_mbsnbcmp is not affected by locale.

_mbsnbcmp compares bytes based on the current multibyte code page.

Return Value

• _mbsnbcmp returns an integer value based on the result of comparing s1 (or part of it) to s2 (or part of it):
• < 0 if s1 is less than s2
• == 0 if s1 is the same as s2
• > 0 if s1 is greater than s2

3.1.5.30.8 _mbsnbcnt, _mbsnccnt, _strncnt, _wcsncnt


Header File

mbstring.h

Category

Memory and String Manipulation Routines

Prototype
size_t _mbsnbcnt(const unsigned char * str, size_t nmbc);
size_t _mbsnccnt(const unsigned char * str, size_t nbyte);

Description

If _MBCS is defined:
3 _mbsnbcnt is mapped to the portable macro _tcsnbcnt

_mbsnccnt is mapped to the portable macro _tcsnccnt If _UNICODE is defined:

both _mbsnbcnt and _mbsnccnt are mapped to the _wcsncnt macro

If neither _MBCS nor _UNICODE are defined.

_tcsnbcnt and _tcsnccnt are mapped to the _strncnt macro _strncnt is the single-byte version of these functions. _wcsncnt is the
wide-character version of these functions.

1162
3.1 Référence C++ RAD Studio C Runtime Library Reference

_strncnt and _wcsncnt are available only for generic-text mappings. They should not be used directly.

_mbsnbcnt examines the first nmbc multibyte characters of the str argument. The function returns the number of bytes found in
the those characters.

_mbsnccnt examines the first nmbc bytes of the str argument. The function returns the number of characters found in those
bytes. If NULL is encountered in the second byte of a multibyte character, the whole character is considered NULL and will not
be included in the return value.

Each of the functions ends its examination of the str argument if NULL is reached before the specified number of characters or
bytes is examined.

If str has fewer than the specified number of characters or bytes, the function return the number of characters or bytes found in
str.

Return Value

_mbsnbcnt returns the number of bytes found.

_mbsnccnt returns the number of characters found.

If nmbc or nbyte are less than zero, the functions return 0.

3.1.5.30.9 _mbsnbcoll, _mbsnbicoll


Header File

mbstring.h

Category

Memory and String Manipulation Routines

Prototype
int _mbsnbcoll(const unsigned char *s1, const unsigned char *s2, maxlen);
int _mbsnbicoll(const unsigned char *s1, const unsigned char *s2, maxlen);

Description

_mbsnbicoll is the case-insensitive version of _mbsnbcoll.

These functions collate the strings specified by arguments s1 and s2. The collation order is determined by lexicographic order as
specified by the current multibyte code page. At most, maxlen number of bytes are collated.

Remarque: Note:

The lexicographic order is not always the same as the order of characters in the character set.If the last byte in s1 or s2 is a
leadbyte, it is not compared.

Return Value

• Each of these functions return an integer value based on the result of comparing s1 (or part of it) to s2 (or part of it): 3
• < 0 if s1 is less than s2
• == 0 if s1 is the same as s2
• > 0 if s1 is greater than s2
On error, each of these functions returns _NLSCMPERROR.

1163
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.30.10 _mbsnbcpy
Header File

mbstring.h

Category

Memory and String Manipulation Routines

Prototype
unsigned char *_mbsnbcpy(unsigned char *dest, unsigned char *src, size_t maxlen);

Description

The _mbsnbcpy function copies at most maxlen number of characters from the src buffer to the dest buffer. The dest buffer is
null terminated after the copy.

It is the user’s responsibility to be sure that dest is large enough to allow the copy. An improper buffer size can result in memory
corruption.

Return Value

The function returns dest.

3.1.5.30.11 _mbsnbicmp
Header File

mbstring.h

Category

Memory and String Manipulation Routines

Prototype
int _mbsnbicmp(const unsigned char *s1, const unsigned char s2, size_t maxlen);

Description

_mbsnbicmp ignores case while making a comparison of s1 and s2 for no more than maxlen bytes. It starts with the first byte in
each string and continues with subsequent bytes until the corresponding bytes differ or until it has examined maxlen bytes.

_mbsnbicmp is not case sensitive.

_mbsnbicmp is not affected by locale.

_mbsnbicmp compares bytes based on the current multibyte code page.

Return Value
3 • _mbsnbicmp returns an integer value based on the result of comparing s1 (or part of it) to s2 (or part of it):
• < 0 if s1 is less than s2
• == 0 if s1 is the same as s2
• > 0 if s1 is greater than s2

1164
3.1 Référence C++ RAD Studio C Runtime Library Reference

3.1.5.30.12 _mbsnbset
Header File

mbstring.h

Category

Memory and String Manipulation Routines

Prototype
unsigned char *_mbsnbset(unsigned char str, unsigned int ch, size_t maxlen);

Description

_mbsnbset sets at most maxlen number of bytes in the string str to the character ch. The argument ch can be a single or
multibyte character.

The function quits if the terminating null character is found before maxlen is reached. If ch is a multibyte character that cannot be
accomodated at the end of str, the last character in str is set to a blank character.

Return Value

strset returns str.

3.1.5.30.13 _mbsninc, _strninc, _wcsninc


Header File

mbstring.h

Category

Memory and String Manipulation Routines

Prototype
unsigned char *_mbsninc(const unsigned char *str, size_t num);

Description

The functions increment the character array str by num number of characters.

These functions should be accessed through the portable macro, _tcsninc, defined in tchar.h.

Return value

The functions return a pointer to the resized character string specified by the argument str.

3.1.5.30.14 _mbsspnp, _strspnp, _wcsspnp


3
Header File

mbstring.h

Category

Memory and String Manipulation Routines

Prototype

1165
C Runtime Library Reference RAD Studio 3.1 Référence C++

unsigned char *_mbsspnp(const unsigned char *s1, const unsigned char *s2);

Description

Each of these functions search for the first character in s1 that is not contained in s2.

Use the portable macro, _tcsspnp, defined in tchar.h, to access these functions.

Return Value

The functions return a pointer to the first character in s1 that is not found in the character set for s2.

If every character from s1 is found in s2, each of the functions return NULL.

3.1.5.30.15 _strdec, mbsdec, _wcsdec


Header File

mbstring.h, tchar.h

Category

Memory and String Manipulation Routines

Prototype
unsigned char *_mbsdec(const unsigned char *s, const unsigned char *p);
inline char *_strdec(const char * s1, const char * s2) { return (char *)(s1,(s2-1));
// From tchar.h
#define _tcsdec _strdec
#define _tcsdec _wcsdec

Description

_mbsdec returns a pointer p indicating the character in string s back to 1 byte backward. If there are no more characters before
string p (it is the same position as s), _mbsdec returns a null pointer.

_strdec is the single-byte version of this function.

_wcsdec is the wide-character version of this function.

Return Value

Returns a pointer back to 1 byte, or null pointer if there is no character before p.

3.1.5.30.16 _strerror
Header File

string.h, stdio.h
3
Category

Memory and String Manipulation Routines

Prototype
char *_strerror(const char *s);

Description

1166
3.1 Référence C++ RAD Studio C Runtime Library Reference

Builds a customized error message.

_strerror lets you generate customized error messages; it returns a pointer to a null-terminated string containing an error
message.

• If s is null, the return value points to the most recent error message.
• If s is not null, the return value contains s (your customized error message), a colon, a space, the most-recently generated
system error message, and a new line. s should be 94 characters or less.
Return Value
_strerror returns a pointer to a constructed error string. The error message string is constructed in a static buffer that is
overwritten with each call to _strerror.
Example
#include <stdio.h>
#include <errno.h>
int main(void)
{
char *buffer;
buffer = strerror(errno);
printf("Error: %s\n", buffer);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.30.17 _strinc, mbsinc, _wcsinc


Header File

mbstring.h, tchar.h

Category

Memory and String Manipulation Routines

Prototype
unsigned char *_mbsinc(const unsigned char *p);
// From tchar.h
#define _tcsinc _strinc
#define _tcsinc _wcsinc
inline char * strinc(const char * s) { return (char *)(s+1); }

Description
3
_mbsinc increments a string pointer by one byte.

_strdec is the single-byte version of this function.

_wcsdec is the wide-character version of this function.

Return Value

Returns a pointer that is forwarded by 1 byte.

1167
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.30.18 _strnextc,_mbsnextc,_wcsnextc
Header File

tchar.h, mbstring.h

Category

Memory and String Manipulation Routines

Prototype
unsigned int _strnextc(const char *str);
unsigned int _mbsnextc (const unsigned char *str);

Description

These routines should be accessed by using the portable _tcsnextc function. The functions inspect the current character in str.
The pointer to str is not advanced.

Return Value

The functions return the integer value of the character pointed to by str.

Example
#include <tchar.h>
#include <stdio.h>
int main()
{
unsigned int retval = 0;
const unsigned char *string = "ABC";
retval = _strnextc(string);
printf("The starting character:%c", retval);
retval = _strnextc(++string);
printf("\nThe next character:%c", retval);
return 0;
}
/***
The starting character:A
The next character:B
***/

3.1.5.30.19 stpcpy, _wstpcpy, _stpcpy


Header File

string.h

Category

Memory and String Manipulation Routines


3 Prototype
char *stpcpy(char *dest, const char *src);
wchar * _wcspcpy(wchar *dest, const wchar *src);

Description

Copies one string into another.

_stpcpy copies the string src to dest, stopping after the terminating null character of src has been reached.

1168
3.1 Référence C++ RAD Studio C Runtime Library Reference

Return Value

stpcpy returns a pointer to the terminating null character of dest.

If UNICODE is defined, _wcspcpy returns a pointer to the terminating null character of the wchar_t dest string.

Example
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[10];
char *str1 = "abcdefghi";
stpcpy(string, str1);
printf("%s\n", string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_stpcpy +
_wcspcpy +

3.1.5.30.20 strcat, _mbscat, wcscat


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines, Inline Routines

Prototype
char *strcat(char *dest, const char *src);
wchar_t *wcscat(wchar_t *dest, const wchar_t *src);
unsigned char *_mbscat(unsigned char *dest, const unsigned char *src);

Description

Appends one string to another.

strcat appends a copy of src to the end of dest. The length of the resulting string is strlen(dest) + strlen(src).

Return Value

strcat returns a pointer to the concatenated strings.

Example 3
#include <string.h>
#include <stdio.h>
int main(void)
{
char destination[25];
char *blank = " ", *c = "C++", *CodeGear = "CodeGear";
strcpy(destination, CodeGear);
strcat(destination, blank);
strcat(destination, c);

1169
C Runtime Library Reference RAD Studio 3.1 Référence C++

printf("%s\n", destination);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strcat + + + +
_mbscat +
wcscat + + +

3.1.5.30.21 strchr, _mbschr, wcschr


Header File

string.h

Category

Memory and String Manipulation Routines, Inline Routines, C++ Prototyped Routines

Prototype
char *strchr(const char *s, int c);/* C only */
const char *strchr(const char *s, int c);// C++ only
char *strchr( char *s, int c);// C++ only
wchar_t *wcschr(const wchar_t *s, int c);
unsigned char * _mbschr(const unsigned char *s, unsigned int c);

Description

Scans a string for the first occurrence of a given character.

strchr scans a string in the forward direction, looking for a specific character. strchr finds the first occurrence of the character c in
the string s. The null-terminator is considered to be part of the string.

For example:
strchr(strs,0)

returns a pointer to the terminating null character of the string strs.

Return Value

strchr returns a pointer to the first occurrence of the character c in s; if c does not occur in s, strchr returns null.

Example
#include <string.h>
3 #include <stdio.h>
int main(void)
{
char string[15];
char *ptr, c = 'r';
strcpy(string, "This is a string");
ptr = strchr(string, c);
if (ptr)
printf("The character %c is at position: %d\n", c, ptr-string);
else
printf("The character was not found\n");

1170
3.1 Référence C++ RAD Studio C Runtime Library Reference

return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strchr + + + +
_mbschr +
wcschr + + +

3.1.5.30.22 strcmp, _mbscmp, wcscmp


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines, Inline Routines

Prototype
int strcmp(const char *s1, const char *s2);
int wcscmp(const wchar_t *s1, const wchar_t *s2);
int _mbscmp(const unsigned char *s1, const unsigned char *s2);

Description

Compares one string to another.

strcmp performs an unsigned comparison of s1 to s2, starting with the first character in each string and continuing with
subsequent characters until the corresponding characters differ or until the end of the strings is reached.

Return Value

less than s2 <0


the same as s2 == 0
greater than s2 >0

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
char *buf1 = "aaa", *buf2 = "bbb", *buf3 = "ccc";
int ptr;
ptr = strcmp(buf2, buf1);
if (ptr > 0) 3
printf("buffer 2 is greater than buffer 1\n");
else
printf("buffer 2 is less than buffer 1\n");
ptr = strcmp(buf2, buf3);
if (ptr > 0)
printf("buffer 2 is greater than buffer 3\n");
else
printf("buffer 2 is less than buffer 3\n");
return 0;
}

1171
C Runtime Library Reference RAD Studio 3.1 Référence C++

Portability

POSIX Win32 ANSI C ANSI C++


strcmp + + + +
_mbscmp +
wcscmp + + +

3.1.5.30.23 strcmpi
Header File

string.h, wchar.h

Category

Memory and String Manipulation Routines

Prototype
int strcmpi(const char *s1, const char *s2);
int _wcscmpi(const wchar_t *s1, const wchar_t *s2);

Description

Compares one string to another, without case sensitivity.

strcmpi performs an unsigned comparison of s1 to s2, without case sensitivity (same as stricmp--implemented as a macro).

It returns a value (< 0, 0, or > 0) based on the result of comparing s1 (or part of it) to s2 (or part of it).

The routine strcmpi is the same as stricmp. strcmpi is implemented through a macro in string.h and translates calls from strcmpi
to stricmp. Therefore, in order to use strcmpi, you must include the header file string.h for the macro to be available. This macro
is provided for compatibility with other C compilers.

Return Value

less than s2 <0


the same as s2 == 0
greater than s2 >0

Example
/* strncmpi example */
#include <string.h>
#include <stdio.h>
int main(void)
{
char *buf1 = "BBB", *buf2 = "bbb";
3 int ptr;
ptr = strcmpi(buf2, buf1);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1\n");
if (ptr < 0)
printf("buffer 2 is less than buffer 1\n");
if (ptr == 0)
printf("buffer 2 equals buffer 1\n");
return 0;
}

1172
3.1 Référence C++ RAD Studio C Runtime Library Reference

Portability

POSIX Win32 ANSI C ANSI C++


strcmpi +
_wcscmpi +

3.1.5.30.24 strcoll,_stricoll, _mbscoll, _mbsicoll, wcscoll, _wcsicoll


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines

Prototype
int strcoll(const char *s1, const char *s2);
int wcscoll(const wchar_t *s1, const wchar_t *s2);
int _stricoll(const char *s1, const char *s2);
int _wcsicoll(const wchar_t *s1, wconst_t char *s2);
int _mbscoll(const unsigned char *s1, const unsigned char *s2);
int _mbsicoll(const unsigned char *s1, const unsigned char *s2);

Description

Compares two strings.

strcoll compares the string pointed to by s1 to the string pointed to by s2, according to the current locale's LC_COLLATE
category.

_stricoll performs like strcoll but is not case sensitive.

Remarque: Note

_stricoll does not compare string according to the current locale's LC_COLLATE category. _stricoll gives you a stricmp. The
required collation is obtained by calling _lstricoll, or just plain stricoll (which maps to _lstricoll).

The real collation (_lstricoll) returns -1, 0 or 1, whereas _stricoll does a codepoint comparison, and returns < 0, 0 or > 0.

Return Value

less than s2 <0


the same as s2 == 0
greater than s2 >0
3
Example
#include <stdio.h>
#include <string.h>
int main(void)
{
char *two = "International";
char *one = "Borland";
int check;

1173
C Runtime Library Reference RAD Studio 3.1 Référence C++

check = strcoll(one, two);


if (check == 0)
printf("The strings are equal\n");
if (check < 0)
printf("%s comes before %s\n", one, two);
if (check > 0)
printf("%s comes before %s\n", two, one);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strcoll + + + +
_stricoll +
_mbscoll +
_mbsicoll +
wcscoll + + +
_wcsicoll +

3.1.5.30.25 strcpy
Header File

string.h, wchar.h, mbstring.h

Category

Memory and String Manipulation Routines, Inline Routines

Prototype
char *strcpy(char *dest, const char *src);
wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
unsigned char *_mbscpy(unsigned char *dest, const unsigned char *src);

Description

Copies one string into another.

Copies string src to dest, stopping after the terminating null character has been moved.

Return Value

strcpy returns dest.

Example
#include <stdio.h>
3 #include <string.h>
int main(void)
{
char string[10];
char *str1 = "abcdefghi";
strcpy(string, str1);
printf("%s\n", string);
return 0;
}

1174
3.1 Référence C++ RAD Studio C Runtime Library Reference

Portability

POSIX Win32 ANSI C ANSI C++


strcpy + + + +
_mbscpy +
wcscpy + + +

3.1.5.30.26 strcspn, _mbscspn, wcscspn


Header File

string.h, wchar.h, mbstring.h

Category

Memory and String Manipulation Routines

Prototype
size_t strcspn(const char *s1, const char *s2);
size_t wcscspn(const wchar_t *s1, const wchar_t *s2);
size_t _mbscspn(const unsigned char *s1, const unsigned char *s2);

Description

Scans a string for the initial segment not containing any subset of a given set of characters.

The strcspn functions search s1 until any one of the characters contained in s2 is found. The number of characters which were
read in s1 is the return value. The string termination character is not counted. Neither string is altered during the search.

Return Value

strcspn returns the length of the initial segment of string s1 that consists entirely of characters not from string s2.

Example
#include <stdio.h>
#include <string.h>
#include <alloc.h>
int main(void)
{
char *string1 = "1234567890";
char *string2 = "747DC8";
int length;
length = strcspn(string1, string2);
printf("Character where strings intersect is at position %d\n",
length);
return 0;
}
Portability 3
POSIX Win32 ANSI C ANSI C++
strcspn + + + +
_mbscspn +
wcscspn + + +

1175
C Runtime Library Reference RAD Studio 3.1 Référence C++

3.1.5.30.27 strdup, _mbsdup, _wcsdup


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines

Prototype
char *strdup(const char *s);
wchar_t *_wcsdup(const wchar_t *s);
unsigned char *_mbsdup(const wchar_t *s);

Description

Copies a string into a newly created location.

strdup makes a duplicate of string s, obtaining space with a call to malloc. The allocated space is (strlen(s) + 1) bytes long. The
user is responsible for freeing the space allocated by strdup when it is no longer needed.

Return Value

strdup returns a pointer to the storage location containing the duplicated string, or returns null if space could not be allocated.

Example
#include <stdio.h>
#include <string.h>
#include <alloc.h>
int main(void)
{
char *dup_str, *string = "abcde";
dup_str = strdup(string);
printf("%s\n", dup_str);
free(dup_str);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strdup +
_mbsdup +
_wcsdup +

3 3.1.5.30.28 strerror
Header File

string.h

Category

Memory and String Manipulation Routines

Prototype

1176
3.1 Référence C++ RAD Studio C Runtime Library Reference

char *strerror(int errnum);

Description

Returns a pointer to an error message string.

strerror takes an int parameter errnum, an error number, and returns a pointer to an error message string associated with
errnum.

Return Value

strerror returns a pointer to a constructed error string. The error message string is constructed in a static buffer that is overwritten
with each call to strerror.

Example
#include <stdio.h>
#include <errno.h>
int main(void)
{
char *buffer;
buffer = strerror(errno);
printf("Error: %s\n", buffer);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.30.29 stricmp, _mbsicmp, _wcsicmp


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines

Prototype
int stricmp(const char *s1, const char *s2);
int _wcsicmp(const wchar_t *s1, const wchar_t *s2);
int _mbsicmp(const unsigned char *s1, const unsigned char *s2);

Description

Compares one string to another, without case sensitivity.

stricmp performs an unsigned comparison of s1 to s2, starting with the first character in each string and continuing with
3
subsequent characters until the corresponding characters differ or until the end of the strings is reached. The comparison is not
case sensitive.

It returns a value (< 0, 0, or > 0) based on the result of comparing s1 (or part of it) to s2 (or part of it).

The routines stricmp and strcmpi are the same; strcmpi is implemented through a macro in string.h that translates calls from
strcmpi to stricmp. Therefore, in order to use stricmp, you must include the header file string.h for the macro to be available.

Return Value

1177
C Runtime Library Reference RAD Studio 3.1 Référence C++

less than s2 <0


the same as s2 == 0
greater than s2 >0

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
char *buf1 = "BBB", *buf2 = "bbb";
int ptr;
ptr = stricmp(buf2, buf1);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1\n");
if (ptr < 0)
printf("buffer 2 is less than buffer 1\n");
if (ptr == 0)
printf("buffer 2 equals buffer 1\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


stricmp + + +
_mbsicmp +
_wcsicmp +

3.1.5.30.30 strlwr, _mbslwr, _wcslwr


Header File

string.h, mbstring.h

Category

Conversion Routines, Memory and String Manipulation Routines

Prototype
char *strlwr(char *s);
wchar_t *_wcslwr(wchar_t *s);
unsigned char *_mbslwr(unsigned char *s);

Description

3 Converts uppercase letters in a string to lowercase.

strlwr converts uppercase letters in string s to lowercase according to the current locale's LC_CTYPE category. For the C locale,
the conversion is from uppercase letters (A to Z) to lowercase letters (a to z). No other characters are changed.

Return Value

strlwr returns a pointer to the string s.

Example

1178
3.1 Référence C++ RAD Studio C Runtime Library Reference

#include <stdio.h>
#include <string.h>
int main(void)
{
char *string = "CodeGear";
printf("string prior to strlwr: %s\n", string);
strlwr(string);
printf("string after strlwr: %s\n", string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strlwr +
_mbslwr +
_wcslwr +

3.1.5.30.31 strncat
Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines, Inline Routines

Prototype
char *strncat(char *dest, const char *src, size_t maxlen);
wchar_t *wcsncat(wchar_t *dest, const wchar_t *src, size_t maxlen);
unsigned char *_mbsncat(unsigned char *dest, const unsigned char *src, size_t maxlen);
unsigned char *_mbsnbcat(unsigned char *__dest, const unsigned char *__src, _SIZE_T __maxlen);

Description

Appends a portion of one string to another.

strncat copies at most maxlen characters of src to the end of dest and then appends a null character. The maximum length of the
resulting string is strlen(dest) + maxlen.

For _mbsnbcat, if the second byte of 2-bytes character is null, the first byte of this character is regarded as null.

These four functions behave identically and differ only with respect to the type of arguments and return types.

Return Value

strncat returns dest.

Example
3
#include <string.h>
#include <stdio.h>
int main(void)
{
char destination[25];
char *source = " States";
strcpy(destination, "United");
strncat(destination, source, 7);

1179
C Runtime Library Reference RAD Studio 3.1 Référence C++

printf("%s\n", destination);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strncat + + + +
_mbsncat +
_mbsnbcat +
_wcsncat +

3.1.5.30.32 strncmp, _mbsncmp, wcsncmp


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines, Inline Routines

Prototype
int strncmp(const char *s1, const char *s2, size_t maxlen);
int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t maxlen);
int _mbsncmp(const unsigned char *s1, const unsigned char *s2, size_t maxlen);
#define _mbccmp(__s1, __s2) _mbsncmp((__s1),(__s2),1)

Description

Compares a portion of one string to a portion of another.

strncmp makes the same unsigned comparison as strcmp, but looks at no more than maxlen characters. It starts with the first
character in each string and continues with subsequent characters until the corresponding characters differ or until it has
examined maxlen characters.

Return Value

• strncmp returns an int value based on the result of comparing s1 (or part of it) to s2 (or part of it):
• < 0 if s1 is less than s2
• == 0 if s1 is the same as s2
• > 0 if s1 is greater than s2
Example
#include <string.h>
3 #include <stdio.h>
int main(void)
{
char *buf1 = "aaabbb", *buf2 = "bbbccc", *buf3 = "ccc";
int ptr;
ptr = strncmp(buf2,buf1,3);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1\n");
else
printf("buffer 2 is less than buffer 1\n");

1180
3.1 Référence C++ RAD Studio C Runtime Library Reference

ptr = strncmp(buf2,buf3,3);
if (ptr > 0)
printf("buffer 2 is greater than buffer 3\n");
else
printf("buffer 2 is less than buffer 3\n");
return(0);
}
Portability

POSIX Win32 ANSI C ANSI C++


strncmp + + + +
_mbsncmp +
_mbccmp +
wcsncmp + + +

3.1.5.30.33 strncmpi, wcsncmpi


Header File

string.h

Category

Memory and String Manipulation Routines

Prototype
int strncmpi(const char *s1, const char *s2, size_t n);
int wcsncmpi(const wchar_t *s1, const wchar_t *s2, size_t n);

Description

Compares a portion of one string to a portion of another, without case sensitivity.

strncmpi performs a signed comparison of s1 to s2, for a maximum length of n bytes, starting with the first character in each
string and continuing with subsequent characters until the corresponding characters differ or until n characters have been
examined. The comparison is not case sensitive. (strncmpi is the same as strnicmp--implemented as a macro). It returns a value
(< 0, 0, or > 0) based on the result of comparing s1 (or part of it) to s2 (or part of it).

The routines strnicmp and strncmpi are the same; strncmpi is implemented through a macro in string.h that translates calls from
strncmpi to strnicmp. Therefore, in order to use strncmpi, you must include the header file string.h for the macro to be available.
This macro is provided for compatibility with other C compilers.

Return Value

less than s2 <0


the same as s2 == 0
3
greater than s2 >0

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
char *buf1 = "BBBccc", *buf2 = "bbbccc";

1181
C Runtime Library Reference RAD Studio 3.1 Référence C++

int ptr;
ptr = strncmpi(buf2,buf1,3);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1\n");
if (ptr < 0)
printf("buffer 2 is less than buffer 1\n");
if (ptr == 0)
printf("buffer 2 equals buffer 1\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strncmpi +
wcsncmpi +

3.1.5.30.34 strncoll, strnicoll, _mbsncoll, _mbsnicoll, _wcsncoll, _wcsnicoll


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines

Prototype
int _strncoll(const char *s1, const char *s2, size_t n);
int _wcsncoll(const wchar_t *s1, const wchar_t *s2, size_t n);
int _strnicoll(const char *s1, const char *s2, size_t n);
int _wcsnicoll(const wchar_t *s1, const wchar_t *s2, size_t n);
int _mbsncoll(const unsigned char *s1, const unsigned char *s2, size_t n);
int _mbsnicoll(const unsigned char *s1, const unsigned char *s2, size_t n);

Description

_strncoll compares n number of elements from the string pointed to by s1 to the string pointed to by s2, according to the current
locale's LC_COLLATE category.

_strnicoll performs like _strncoll but is not case sensitive.

Return Value

less than s2 <0


the same as s2 == 0
3 greater than s2 >0

3.1.5.30.35 strncpy, _mbsncpy, wcsncpy


Header File

string.h, mbstring.h

1182
3.1 Référence C++ RAD Studio C Runtime Library Reference

Category

Memory and String Manipulation Routines, Inline Routines

Prototype
char *strncpy(char *dest, const char *src, size_t maxlen);
wchar_t *wcsncpy(wchar_t *dest, const wchar_t *src, size_t maxlen);
unsigned char *_mbsncpy(unsigned char *dest, const unsigned char *src, size_t maxlen);

Description

Copies a given number of bytes from one string into another, truncating or padding as necessary.

strncpy copies up to maxlen characters from src into dest, truncating or null-padding dest. The target string, dest, might not be
null-terminated if the length of src is maxlen or more.

Return Value

strncpy returns dest.

Example
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[10];
char *str1 = "abcdefghi";
strncpy(string, str1, 3);
string[3] = '\0';
printf("%s\n", string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strncpy + + + +
_mbsncpy +
wcsncpy + + +

3.1.5.30.36 strnicmp, _mbsnicmp, _wcsnicmp


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines 3


Prototype
int strnicmp(const char *s1, const char *s2, size_t maxlen);
int _wcsnicmp(const wchar_t *s1, const wchar_t *s2, size_t maxlen);
int _mbsnicmp(const unsigned char *s1, const unsigned char *s2, size_t maxlen);

Description

1183
C Runtime Library Reference RAD Studio 3.1 Référence C++

Compares a portion of one string to a portion of another, without case sensitivity.

strnicmp performs a signed comparison of s1 to s2, for a maximum length of maxlen bytes, starting with the first character in
each string and continuing with subsequent characters until the corresponding characters differ or until the end of the strings is
reached. The comparison is not case sensitive.

It returns a value (< 0, 0, or > 0) based on the result of comparing s1 (or part of it) to s2 (or part of it).

Return Value

less than s2 <0


the same as s2 == 0
greater than s2 >0

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
char *buf1 = "BBBccc", *buf2 = "bbbccc";
int ptr;
ptr = strnicmp(buf2, buf1, 3);
if (ptr > 0)
printf("buffer 2 is greater than buffer 1\n");
if (ptr < 0)
printf("buffer 2 is less than buffer 1\n");
if (ptr == 0)
printf("buffer 2 equals buffer 1\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strnicmp +
_mbsnicmp +
_wcsnicmp +

3.1.5.30.37 strnset, _mbsnset, _wcsnset


Header File

string.h

Category

Memory and String Manipulation Routines, Inline Routines


3 Prototype
char *strnset(char *s, int ch, size_t n);
wchar_t *_wcsnset(wchar_t *s, wchar_t ch, size_t n);
unsigned char *_mbsnset(unsigned char *s, unsigned int ch, size_t n);

Description

Sets a specified number of characters in a string to a given character.

1184
3.1 Référence C++ RAD Studio C Runtime Library Reference

strnset copies the character ch into the first n bytes of the string s. If n > strlen(s), then strlen(s) replaces n. It stops when n
characters have been set, or when a null character is found.

Return Value

Each of these functions return s.

Example
#include <stdio.h>
#include <string.h>
int main(void)
{
char *string = "abcdefghijklmnopqrstuvwxyz";
char letter = 'x';
printf("string before strnset: %s\n", string);
strnset(string, letter, 13);
printf("string after strnset: %s\n", string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strnset +
_mbsnset +
_wcsnset +

3.1.5.30.38 strpbrk, _mbspbrk, wcspbrk


Header File

string.h, mbstring.h

Category

C++ Prototyped Routines, Memory and String Manipulation Routines

Prototype
char *strpbrk(const char *s1, const char *s2); /* C only */
const char *strpbrk(const char *s1, const char *s2); // C++ only
char *strpbrk(char *s1, const char *s2); // C++ only
wchar_t * wcspbrk(const wchar_t *s1, const wchar_t *s2);
unsigned char *_mbspbrk(const unsigned char *s1, const unsigned char *s2);

Description

Scans a string for the first occurrence of any character from a given set.
3
strpbrk scans a string, s1, for the first occurrence of any character appearing in s2.

Return Value

strpbrk returns a pointer to the first occurrence of any of the characters in s2. If none of the s2 characters occur in s1, strpbrk
returns null.

Example

1185
C Runtime Library Reference RAD Studio 3.1 Référence C++

#include <stdio.h>
#include <string.h>
int main(void)
{
char *string1 = "abcdefghijklmnopqrstuvwxyz";
char *string2 = "onm";
char *ptr;
ptr = strpbrk(string1, string2);
if (ptr)
printf("strpbrk found first character: %c\n", *ptr);
else
printf("strpbrk didn't find character in set\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strpbrk + + + +
_mbspbrk +
wcspbrk + + +

3.1.5.30.39 strrchr, _mbsrchr, wcsrchr


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines, Inline Routines, C++ Prototyped Routines

Prototype
char *strrchr(const char *s, int c); /* C only */
const char *strrchr(const char *s, int c); // C++ only
char *strrchr(char *s, int c); // C++ only
wchar_t *wcsrchr(const wchar_t *s, wchar_t c);
unsigned char * _mbsrchr(const unsigned char *s, unsigned int c);

Description

Scans a string for the last occurrence of a given character.

strrchr scans a string in the reverse direction, looking for a specific character. strrchr finds the last occurrence of the character c
in the string s. The null-terminator is considered to be part of the string.

Return Value
3 strrchr returns a pointer to the last occurrence of the character c. If c does not occur in s, strrchr returns null.

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
char string[15];
char *ptr, c = 'r';

1186
3.1 Référence C++ RAD Studio C Runtime Library Reference

strcpy(string, "This is a string");


ptr = strrchr(string, c);
if (ptr)
printf("The character %c is at position: %d\n", c, ptr-string);
else
printf("The character was not found\n");
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strrchr + + + +
_mbsrchr +
wcsrchr + + +

3.1.5.30.40 strrev, _mbsrev, _wcsrev


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines

Prototype
char *strrev(char *s);
wchar_t *_wcsrev(wchar_t *s);
unsigned char *_mbsrev(unsigned char *s);

Description

Reverses a string.

strrev changes all characters in a string to reverse order, except the terminating null character. (For example, it would change
string\0 to gnirts\0.)

Return Value

strrev returns a pointer to the reversed string.

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
char *forward = "string";
printf("Before strrev(): %s\n", forward); 3
strrev(forward);
printf("After strrev(): %s\n", forward);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strrev +

1187
C Runtime Library Reference RAD Studio 3.1 Référence C++

_mbsrev +
_wcsrev +

3.1.5.30.41 strset, _mbsset, _wcsset


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines, Inline Routines

Prototype
char *strset(char *s, int ch);
wchar_t *_wcsset(wchar_t *s, wchar_t ch);
unsigned char *_mbsset(unsigned char *s, unsigned int ch);

Description

Sets all characters in a string to a given character.

strset sets all characters in the string s to the character ch. It quits when the terminating null character is found.

Return Value

strset returns s.

Example
#include <stdio.h>
#include <string.h>
int main(void)
{
char string[10] = "123456789";
char symbol = 'c';
printf("Before strset(): %s\n", string);
strset(string, symbol);
printf("After strset(): %s\n", string);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strset +
_mbsset +
_wcsset +
3

3.1.5.30.42 strspn, _mbsspn, wcsspn


Header File

string.h, mbstring.h

Category

1188
3.1 Référence C++ RAD Studio C Runtime Library Reference

Memory and String Manipulation Routines

Prototype
size_t strspn(const char *s1, const char *s2);
size_t wcsspn(const wchar_t *s1, const wchar_t *s2);
size_t _mbsspn(const unsigned char *s1, const unsigned char *s2);

Description

Scans a string for the first segment that is a subset of a given set of characters.

strspn finds the initial segment of string s1 that consists entirely of characters from string s2.

Return Value

strspn returns the length of the initial segment of s1 that consists entirely of characters from s2.

Example
#include <stdio.h>
#include <string.h>
#include <alloc.h>
int main(void)
{
char *string1 = "1234567890";
char *string2 = "123DC8";
int length;
length = strspn(string1, string2);
printf("Character where strings differ is at position %d\n", length);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strspn + + + +
_mbsspn +
wcsspn + + +

3.1.5.30.43 strstr, _mbsstr, wcsstr


Header File

string.h

Category

C++ Prototyped Routines, Memory and String Manipulation Routines

Prototype
3
char *strstr(const char *s1, const char *s2); /* C only */
const char *strstr(const char *s1, const char *s2); // C++ only
char *strstr(char *s1, const char *s2); // C++ only
wchar_t * wcsstr(const wchar_t *s1, const wchar_t *s2);
unsigned char * _mbsstr(const unsigned char *s1, const unsigned char *s2);

1189
C Runtime Library Reference RAD Studio 3.1 Référence C++

Description

Scans a string for the occurrence of a given substring.

strstr scans s1 for the first occurrence of the substring s2.

Return Value

strstr returns a pointer to the element in s1, where s2 begins (points to s2 in s1). If s2 does not occur in s1, strstr returns null.

Example
#include <stdio.h>
#include <string.h>
int main(void)
{
char *str1 = "CodeGear", *str2 = "nation", *ptr;
ptr = strstr(str1, str2);
printf("The substring is: %s\n", ptr);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strstr + + + +
_mbsstr +
wcsstr + + +

3.1.5.30.44 strtok, _mbstok, wcstok


Header File

string.h, mbstring.h

Category

Memory and String Manipulation Routines

Prototype
char *strtok(char *s1, const char *s2);
wchar_t *wcstok(wchar_t *s1, const wchar_t *s2);
unsigned char *_mbstok(unsigned char *s1, const unsigned char *s2);

Description

Searches one string for tokens, which are separated by delimiters defined in a second string.

strtok considers the string s1 to consist of a sequence of zero or more text tokens, separated by spans of one or more characters
3 from the separator string s2.

The first call to strtok returns a pointer to the first character of the first token in s1 and writes a null character into s1 immediately
following the returned token. Subsequent calls with null for the first argument will work through the string s1 in this way, until no
tokens remain.

The separator string, s2, can be different from call to call.

Remarque: Calls to strtok cannot be nested with a function call that also uses strtok. Doing so will causes an endless loop.

Return Value

1190
3.1 Référence C++ RAD Studio C Runtime Library Reference

strtok returns a pointer to the token found in s1. A NULL pointer is returned when there are no more tokens.

Example
#include <string.h>
#include <stdio.h>
int main(void)
{
char input[16] = "abc,d";
char *p;
/* strtok places a NULL terminator
in front of the token, if found */
p = strtok(input, ",");
if (p) printf("%s\n", p);
/* A second call to strtok using a NULL
as the first parameter returns a pointer
to the character following the token */
p = strtok(NULL, ",");
if (p) printf("%s\n", p);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strtok + + + +
_mbstok +
wcstok + + +

3.1.5.30.45 strupr, _mbsupr, _wcsupr


Header File

string.h, mbstring.h

Category

Conversion Routines, Memory and String Manipulation Routines

Prototype
char *strupr(char *s);
wchar_t *_wcsupr(wchar_t *s);
unsigned char *_mbsupr(unsigned char *s);

Description

Converts lowercase letters in a string to uppercase.

strupr converts lowercase letters in string s to uppercase according to the current locale's LC_CTYPE category. For the default C
locale, the conversion is from lowercase letters (a to z) to uppercase letters (A to Z). No other characters are changed. 3
Return Value

strupr returns s.

Example
#include <stdio.h>
#include <string.h>
int main(void)

1191
C Runtime Library Reference RAD Studio 3.1 Référence C++

{
char *string = "abcdefghijklmnopqrstuvwxyz", *ptr;
/* converts string to upper case characters */
ptr = strupr(string);
printf("%s\n", ptr);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strupr +
_mbsupr +
_wcsupr +

3.1.5.30.46 strxfrm, wcsxfrm


Header File

string.h

Category

Memory and String Manipulation Routines

Prototype
size_t strxfrm(char *target, const char *source, size_t n);
size_t wcsxfrm(wchar_t *target, const wchar_t *source, size_t n);

Description

Transforms a portion of a string to a specified collation.

strxfrm transforms the string pointed to by source into the string target for no more than n characters. The transformation is such
that if the strcmp function is applied to the resulting strings, its return corresponds with the return values of the strcoll function.

No more than n characters, including the terminating null character, are copied to target.

strxfrm transforms a character string into a special string according to the current locale's LC_COLLATE category. The special
string that is built can be compared with another of the same type, byte for byte, to achieve a locale-correct collation result.
These special strings, which can be thought of as keys or tokenized strings, are not compatible across the different locales.

The tokens in the tokenized strings are built from the collation weights used by strcoll from the active locale's collation tables.

Processing stops only after all levels have been processed for the character string or the length of the tokenized string is equal to
the maxlen parameter.

All redundant tokens are removed from each level's set of tokens.

3 The tokenized string buffer must be large enough to contain the resulting tokenized string. The length of this buffer depends on
the size of the character string, the number of collation levels, the rules for each level and whether there are any special
characters in the character string. Certain special characters can cause extra character processing of the string resulting in more
space requirements. For example, the French character "oe" will take double the space for itself because in some locales, it
expands to collation weights for each level. Substrings that have substitutions will also cause extra space requirements.

There is no safe formula to determine the required string buffer size, but at least (levels * string length) are required.

Return Value

1192
3.1 Référence C++ RAD Studio C Runtime Library Reference

Number of characters copied not including the terminating null character. If the value returned is greater than or equal to n, the
content of target is indeterminate.

Example
#include <stdio.h>
#include <string.h>
#include <alloc.h>
int main(void)
{
char *target;
char *source = "Frank Borland";
int length;
/* allocate space for the target string */
target = (char *) calloc(80, sizeof(char));
/* copy the source over to the target and get the length */
length = strxfrm(target, source, 80);
/* print out the results */
printf("%s has the length %d\n", target, length);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strxfrm + + + +
wcsxfrm + + +

3.1.5.31 sys\stat.h
The following functions, macros, and classes are provided in sys\stat.h:

Rubriques
Nom Description
S_Ixxxx #defines ( see page 1194) Header File
sys\stat.h
Description
Definitions used for file status and directory functions.

1193
C Runtime Library Reference RAD Studio 3.1 Référence C++

_stati64, _tstati64, stati64, _wstati64 ( see page 1195) Header File


sys\stat.h, tchar.h
Category
Directory Control Routines
Prototype
int stati64(const char *pathname, struct stati64 *buff);
int _stati64(const char *__path, struct stati64 *__statbuf);
int _wstati64(const wchar_t *pathname, struct stati64
*buff);
// From tchar.h
#define _tstati64 _stati64
Description
Gather statistics about the file named by *pathP and place them in the buffer
*bufP.
The statistics fields are set thus:
st_devset to -1 if S_IFCHR, else set to drive holding the file.
st_ino0
st_modeUnix-style bit-set for file access rights
st_nlink1
st_uid0
st_gid0
st_rdevsame as st_dev
st_sizefile size (0 if S_IFDIR or S_IFCHR)
st_atimetime file last changed (seconds since 1970)
st_mtimesame as st_atime... suite ( see page 1195)
fstat, stat, _wstat ( see page 1196) Header File
sys\stat.h
Category
Input/output Routines
Prototype
int fstat(int handle, struct stat *statbuf);
int stat(const char *path, struct stat *statbuf);
int _wstat(const wchar_t *path, struct stat *statbuf);
Description
Gets open file information.
fstat stores information in the stat structure about the file or directory associated
with handle.
stat stores information about a given file or directory in the stat structure. The
name of the file is path.
statbuf points to the stat structure (defined in sys\stat.h). That structure contains
the following fields:

3.1.5.31.1 S_Ixxxx #defines


Header File

sys\stat.h

Description

Definitions used for file status and directory functions.

Name Meaning
3 S_IFMT File type mask
S_IFDIR Directory
S_IFIFO FIFO special
S_IFCHR Character special
S_IFBLK Block special
S_IFREG Regular file

1194
3.1 Référence C++ RAD Studio C Runtime Library Reference

S_IREAD Owner can read


S_IWRITE Owner can write
S_IEXEC Owner can execute

3.1.5.31.2 _stati64, _tstati64, stati64, _wstati64


Header File

sys\stat.h, tchar.h

Category

Directory Control Routines

Prototype
int stati64(const char *pathname, struct stati64 *buff);
int _stati64(const char *__path, struct stati64 *__statbuf);
int _wstati64(const wchar_t *pathname, struct stati64 *buff);
// From tchar.h
#define _tstati64 _stati64

Description

Gather statistics about the file named by *pathP and place them in the buffer *bufP.

The statistics fields are set thus:

st_devset to -1 if S_IFCHR, else set to drive holding the file.

st_ino0

st_modeUnix-style bit-set for file access rights

st_nlink1

st_uid0

st_gid0

st_rdevsame as st_dev

st_sizefile size (0 if S_IFDIR or S_IFCHR)

st_atimetime file last changed (seconds since 1970)

st_mtimesame as st_atime

st_ctimesame as st_atime
3
The file access rights bit-set may contain S_IFCHR, S_IFDIR, S_IFREG, S_IREAD, S_IWRITE, or S_IEXEC.

If the name is for a device, the time fields will be zero and the size field is undefined.

Return Value

The return value is 0 if the call was successful, otherwise -1 is returned and errno contains the reason. The buffer is not touched
unless the call is successful.

Portability

1195
C Runtime Library Reference RAD Studio 3.1 Référence C++

POSIX Win32 ANSI C ANSI C++


+

3.1.5.31.3 fstat, stat, _wstat


Header File

sys\stat.h

Category

Input/output Routines

Prototype
int fstat(int handle, struct stat *statbuf);
int stat(const char *path, struct stat *statbuf);
int _wstat(const wchar_t *path, struct stat *statbuf);

Description

Gets open file information.

fstat stores information in the stat structure about the file or directory associated with handle.

stat stores information about a given file or directory in the stat structure. The name of the file is path.

statbuf points to the stat structure (defined in sys\stat.h). That structure contains the following fields:

st_mode Bit mask giving information about the file's mode


st_dev Drive number of disk containing the file or file handle if the file is on a device
st_rdev Same as st_dev
st_nlink Set to the integer constant 1
st_size Size of the file in bytes
st_atime Most recent access (Windows) or last time modified (DOS)
st_mtime Same as st_atime
st_ctime Same as st_atime

The stat structure contains three more fields not mentioned here. They contain values that are meaningful only in UNIX.

The st_mode bit mask that gives information about the mode of the open file includes the following bits:

One of the following bits will be set:

S_IFCHR If handle refers to a device.


3
S_IFREG If an ordinary file is referred to by handle.

One or both of the following bits will be set:

S_IWRITE If user has permission to write to file.


S_IREAD If user has permission to read to file.

The HPFS and NTFS file-management systems make the following distinctions:

1196
3.1 Référence C++ RAD Studio C Runtime Library Reference

st_atime Most recent access


st_mtime Most recent modify
st_ctime Creation time

Return Value

fstat and stat return 0 if they successfully retrieved the information about the open file.

On error (failure to get the information) these functions return -1 and set the global variable errno to

EBADF Bad file handle

Example
#include <sys\stat.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
struct stat statbuf;
FILE *stream;
/* open a file for update */
if ((stream = fopen("DUMMY.FIL", "w+"))
== NULL)
{
fprintf(stderr, "Cannot open output file.\n");
return(1);
}
fprintf(stream, "This is a test");
fflush(stream);
/* get information about the file */
fstat(fileno(stream), &statbuf);
fclose(stream);
/* display the information returned */
if (statbuf.st_mode & S_IFCHR)
printf("Handle refers to a device.\n");
if (statbuf.st_mode & S_IFREG)
printf("Handle refers to an ordinary file.\n");
if (statbuf.st_mode & S_IREAD)
printf("User has read permission on file.\n");
if (statbuf.st_mode & S_IWRITE)
printf("User has write permission on file.\n");
printf("Drive letter of file: %c\n", 'A'+statbuf.st_dev);
printf("Size of file in bytes: %ld\n", statbuf.st_size);
printf("Time file last opened: %s\n", ctime(&statbuf.st_ctime));
return 0;
}

3.1.5.32 sys\timeb.h
The following functions, macros, and classes are provided in sys\timeb.h: 3

1197
C Runtime Library Reference RAD Studio 3.1 Référence C++

Rubriques
Nom Description
ftime ( see page 1198) Header File
sys\timeb.h
Category
Time and Date Routines
Prototype
void ftime(struct timeb *buf)
Description
Stores current time in timeb structure.
On UNIX platforms ftime is available only on System V systems.
ftime determines the current time and fills in the fields in the timeb structure
pointed to by buf. The timeb structure contains four fields: time, millitm,
_timezone, and dstflag:
struct timeb {
long time ;
short millitm ;
short _timezone ;
short dstflag ;
};

• timeprovides the time in seconds since 00:00:00


Greenwich mean time (GMT) January 1 1970.
• millitmis the fractional part of a second in milliseconds....
suite ( see page 1198)

3.1.5.32.1 ftime
Header File

sys\timeb.h

Category

Time and Date Routines

Prototype
void ftime(struct timeb *buf)

Description

Stores current time in timeb structure.

On UNIX platforms ftime is available only on System V systems.

ftime determines the current time and fills in the fields in the timeb structure pointed to by buf. The timeb structure contains four
fields: time, millitm, _timezone, and dstflag:
struct timeb {
long time ;
3 short millitm ;
short _timezone ;
short dstflag ;
};

• timeprovides the time in seconds since 00:00:00 Greenwich mean time (GMT) January 1 1970.
• millitmis the fractional part of a second in milliseconds.

1198
3.1 Référence C++ RAD Studio C Runtime Library Reference

• _timezoneis the difference in minutes between GMT and the local time. This value is computed going west from GMT. ftime
gets this field from the global variable _timezone which is set by tzset.
• dstflagis set to nonzero if daylight saving time is taken into account during time calculations.
Remarque: ftime calls tzset. Therefore it isn't necessary to call tzset explicitly when you use ftime.
Return Value
None.
Example
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys\timeb.h>
/* pacific standard & daylight savings */
char *tzstr = "TZ=PST8PDT";
int main(void)
{
struct timeb t;
putenv(tzstr);
tzset();
ftime(&t);
printf("Seconds since 1/1/1970 GMT: %ld\n", t.time);
printf("Thousandths of a second: %d\n", t.millitm);
printf("Difference between local time and GMT: %d\n", t._timezone);
printf("Daylight savings in effect (1) not (0): %d\n", t.dstflag);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+

3.1.5.33 sys\types.h
The following functions, macros, and classes are provided in sys\types.h:

Rubriques
Nom Description
time_t ( see page 1199) Header File
sys\types.h
time.h
Syntax
typedef long time_t;
Description
Defines the value used by the time functions declared in time.h.

3.1.5.33.1 time_t 3
Header File

sys\types.h

time.h

Syntax
typedef long time_t;

1199
C Runtime Library Reference RAD Studio 3.1 Référence C++

Description

Defines the value used by the time functions declared in time.h.

3.1.5.34 time.h
The following functions, macros, and classes are provided in time.h:

Rubriques
Nom Description
_strdate, _wstrdate ( see page 1204) Header File
time.h
Category
Conversion Routines, Time and Date Routines
Prototype
char *_strdate(char *buf);
wchar_t *_wstrdate(wchar_t *buf);
Description
Converts current date to string.
_strdate converts the current date to a string, storing the string in the buffer buf.
The buffer must be at least 9 characters long.
The string has the form MM/DD/YY where MM, DD, and YY are all two-digit
numbers representing the month, day, and year. The string is terminated by a
null character.
Return Value
_strdate returns buf, the address of the date string.
Example
_strtime, _wstrtime ( see page 1205) Header File
time.h
Category
Time and Date Routines
Prototype
char *_strtime(char *buf);
wchar_t *_wstrtime(wchar_t *buf);
Description
Converts current time to string.
_strtime converts the current time to a string, storing the string in the buffer buf.
The buffer must be at least 9 characters long.
The string has the following form:
HH:MM:SS
where HH, MM, and SS are all two-digit numbers representing the hour, minute,
and second, respectively. The string is terminated by a null character.
Return Value
_strtime returns buf, the address of the time string.
Example

1200
3.1 Référence C++ RAD Studio C Runtime Library Reference

asctime ( see page 1206) Header File


time.h
Category
Time and Date Routines
Prototype
char *asctime(const struct tm *tblock);
wchar_t *_wasctime(const struct tm *tblock);
Description
asctime converts date and time to ASCII.
_wasctime converts date and time to a wchar_t string.
asctime and _wasctime convert a time stored as a structure to a 26 (wide)
character string in the following form:
Mon Nov 21 11:31:54 1983\n\0
All the fields have a constant width. The output string day-of-the-week and month
correspond to the following:
tm parameterValid value rangeOutput
tm.mon (month)0-110=Jan, 1=Feb, and so on
tm.day (day-of-the-week)0-60=Sun, 1=Mon, and so on
Return Value
asctime and _wasctime return... suite ( see page 1206)
clock ( see page 1207) Header File
time.h
Category
Time and Date Routines
Prototype
clock_t clock(void);
Description
Determines processor time.
clock can be used to determine the time interval between two events. To
determine the time in seconds, the value returned by clock should be divided by
the value of the macro CLK_TCK.
Return Value
On success, clock returns the processor time elapsed since the beginning of the
program invocation.
On error (if the processor time is not available or its value cannot be
represented), clock returns -1.
Example
clock_t ( see page 1208) Header File
time.h
Syntax
typedef long clock_t;
Description
Defines the data type returned by the clock function.
Portability
ctime, _wctime ( see page 1208) Header File
time.h
Category
Time and Date Routines
Prototype
char *ctime(const time_t *time);
wchar_t *_wctime(const time_t *time);
Description
Converts date and time to a string.
ctime converts a time value pointed to by time (the value returned by the function
time) into a 26-character string in the following form, terminating with a newline 3
character and a null character:
Mon Nov 21 11:31:54 1983\n\0
All the fields have constant width.
The global long variable _timezone contains the difference in seconds between
GMT and local standard time (in PST, _timezone is 8*60*60). The global variable
_daylight is used to tell the RTL's... suite ( see page 1208)

1201
C Runtime Library Reference RAD Studio 3.1 Référence C++

_daylight ( see page 1209) Header File


time.h
Syntax
extern int _daylight;
Description
_daylight is used by the time and date functions. It is used to tell the RTL's
functions (mktime & localtime) whether they should take daylight saving time into
account if it runs into a date that would normally fall into that category. _daylight
is initialized from the values specified in the TZ environment variable and is set to
1 if the daylight savings time conversion should be applied. If TZ is not set, the
value of _daylight is obtained from the operating system.
difftime ( see page 1209) Header File
time.h
Category
Time and Date Routines
Prototype
double difftime(time_t time2, time_t time1);
Description
Computes the difference between two times.
difftime calculates the elapsed time in seconds, from time1 to time2.
Return Value
difftime returns the result of its calculation as a double.
Example
gmtime ( see page 1210) Header File
time.h
Category
Time and Date Routines
Prototype
struct tm *gmtime(const time_t *timer);
Description
Converts date and time to Greenwich mean time (GMT).
gmtime accepts the address of a value returned by time and returns a pointer to
the structure of type tm containing the time elements. gmtime converts directly to
GMT.
The global long variable _timezone should be set to the difference in seconds
between GMT and local standard time (in PST _timezone is 8 x 60 x 60). The
global variable _daylight should be set to nonzero only if the standard U.S.
daylight saving time conversion should... suite ( see page 1210)
localtime ( see page 1211) Header File
time.h
Category
Time and Date Routines
Prototype
struct tm *localtime(const time_t *timer);
Description
Converts date and time to a structure.
localtime accepts the address of a value returned by time and returns a pointer to
the structure of type tm containing the time elements. It corrects for the time zone
and possible daylight saving time.
The global long variable _timezone contains the difference in seconds between
GMT and local standard time (in PST, _timezone is 8 x 60 x 60). The global
variable _daylight is used to tell the RTL’s functions (mktime & localtime) whether
they should take... suite ( see page 1211)

1202
3.1 Référence C++ RAD Studio C Runtime Library Reference

mktime ( see page 1213) Header File


time.h
Category
Time and Date Routines
Prototype
time_t mktime(struct tm *t);
Description
Converts time to calendar format.
Converts the time in the structure pointed to by t into a calendar time with the
same format used by the time function. The original values of the fields tm_sec,
tm_min, tm_hour, tm_mday, and tm_mon are not restricted to the ranges
described in the tm structure. If the fields are not in their proper ranges, they are
adjusted. Values for fields tm_wday and tm_yday are computed after the other
fields have been adjusted.
The allowable range of calendar times is Jan... suite ( see page 1213)
stime ( see page 1214) Header File
time.h
Category
Time and Date Routines
Prototype
int stime(time_t *tp);
Description
Sets system date and time.
stime sets the system time and date. tp points to the value of the time as
measured in seconds from 00:00:00 GMT, January 1, 1970.
Return Value
stime returns a value of 0.
Example
strftime, wcsftime ( see page 1214) Header File
time.h
Category
Time and Date Routines
Prototype
size_t strftime(char *s, size_t maxsize, const char *fmt,
const struct tm *t);
size_t wcsftime(wchar_t *s, size_t maxsize, const wchar_t
*fmt, const struct tm *t);
Description
Formats time for output.
strftime formats the time in the argument t into the array pointed to by the
argument s according to the fmt specifications. All ordinary characters are copied
unchanged. No more than maxsize characters are placed in s.
The time is formatted according to the current locale's LC_TIME category.
Return Value
On success, strftime returns the number of characters placed into s.
On... suite ( see page 1214)
time ( see page 1215) Header File
time.h
Category
Time and Date Routines
Prototype
time_t time(time_t *timer);
Description
Gets time of day.
time gives the current time, in seconds, elapsed since 00:00:00 GMT, January 1,
1970, and stores that value in the location pointed to by timer, provided that timer 3
is not a NULL pointer.
Return Value
time returns the elapsed time in seconds.
Example

1203
C Runtime Library Reference RAD Studio 3.1 Référence C++

_timezone ( see page 1216) Header File


time.h
Syntax
extern long _timezone;
Description
_timezone is used by the time-and-date functions. It is calculated by the tzset
function; it is assigned a long value that is the difference, in seconds, between
the current local time and Greenwich mean time.
On Win32, the value of _timezone is obtained from the operating system.
tm ( see page 1216) Header File
time.h
Syntax
struct tm {
int tm_sec; /* Seconds */
int tm_min; /* Minutes */
int tm_hour; /* Hour (0--23) */
int tm_mday; /* Day of month (1--31) */
int tm_mon; /* Month (0--11) */
int tm_year; /* Year (calendar year minus 1900) */
int tm_wday; /* Weekday (0--6; Sunday = 0) */
int tm_yday; /* Day of year (0--365) */
int tm_isdst; /* 0 if daylight savings time is not in
effect) */
};
Description
A structure defining the time, broken down into increments.
tm is used by the functions asctime, gmtime, localtime, mktime, and strftime.
Example... suite ( see page 1216)
_tzname,_wtzname ( see page 1217) Header File
time.h
Syntax
extern char * _tzname[2]
extern wchar_t *const _wtzname[2]
Description
The global variable _tzname is an array of pointers to strings containing
abbreviations for time zone names. _tzname[0] points to a three-character string
with the value of the time zone name from the TZ environment string. The global
variable _tzname[1] points to a three-character string with the value of the
daylight saving time zone name from the TZ environment string. If no daylight
saving name is present, _tzname[1] points to a null string.
On Win32, the value of _tzname is obtained from the operating system.
_tzset, _wtzset ( see page 1217) Header File
time.h
Category
Time and Date Routines
Prototype
void _tzset(void)
void _wtzset(void)
Description
Sets value of global variables _daylight, _timezone, and _tzname.
_tzset is available on XENIX systems.
_tzset sets the _daylight, _timezone, and _tzname global variables based on the
environment variable TZ. _wtzset sets the _daylight, _timezone, and _wtzname
global variables. The library functions ftime and localtime use these global
variables to adjust Greenwich Mean Time (GMT) to the local time zone. The
format of the TZ environment string is:
3 TZ = zzz[+/-]d[d][lll]
where zzz is a three-character string representing the name of the current time
zone. All... suite ( see page 1217)

3.1.5.34.1 _strdate, _wstrdate


Header File

time.h

1204
3.1 Référence C++ RAD Studio C Runtime Library Reference

Category

Conversion Routines, Time and Date Routines

Prototype
char *_strdate(char *buf);
wchar_t *_wstrdate(wchar_t *buf);

Description

Converts current date to string.

_strdate converts the current date to a string, storing the string in the buffer buf. The buffer must be at least 9 characters long.

The string has the form MM/DD/YY where MM, DD, and YY are all two-digit numbers representing the month, day, and year. The
string is terminated by a null character.

Return Value

_strdate returns buf, the address of the date string.

Example
#include <time.h>
#include <stdio.h>
void main(void)
{
char datebuf[9];
char timebuf[9];
_strdate(datebuf);
_strtime(timebuf);
printf("Date: %s Time: %s\n",datebuf,timebuf);
}
Portability

POSIX Win32 ANSI C ANSI C++


strdate +
_wstrdate +

3.1.5.34.2 _strtime, _wstrtime


Header File

time.h

Category

Time and Date Routines

Prototype
3
char *_strtime(char *buf);
wchar_t *_wstrtime(wchar_t *buf);

Description

Converts current time to string.

_strtime converts the current time to a string, storing the string in the buffer buf. The buffer must be at least 9 characters long.

1205
C Runtime Library Reference RAD Studio 3.1 Référence C++

The string has the following form:


HH:MM:SS

where HH, MM, and SS are all two-digit numbers representing the hour, minute, and second, respectively. The string is
terminated by a null character.

Return Value

_strtime returns buf, the address of the time string.

Example
#include <time.h>
#include <stdio.h>
void main(void)
{
char datebuf[9];
char timebuf[9];
_strdate(datebuf);
_strtime(timebuf);
printf("Date: %s Time: %s\n",datebuf,timebuf);
}
Portability

POSIX Win32 ANSI C ANSI C++


_strtime +
_wstrtime +

3.1.5.34.3 asctime
Header File

time.h

Category

Time and Date Routines

Prototype
char *asctime(const struct tm *tblock);
wchar_t *_wasctime(const struct tm *tblock);

Description

asctime converts date and time to ASCII.

_wasctime converts date and time to a wchar_t string.

asctime and _wasctime convert a time stored as a structure to a 26 (wide) character string in the following form:
3
Mon Nov 21 11:31:54 1983\n\0

All the fields have a constant width. The output string day-of-the-week and month correspond to the following:

tm parameterValid value rangeOutput

tm.mon (month)0-110=Jan, 1=Feb, and so on

tm.day (day-of-the-week)0-60=Sun, 1=Mon, and so on

1206
3.1 Référence C++ RAD Studio C Runtime Library Reference

Return Value

asctime and _wasctime return a pointer to the (wide) character string containing the date and time. This string is a static which is
overwritten with each call. asctime converts a time stored as a structure in *tblock to a 26-character string of the same form as
the ctime string:
Sun Sep 16 01:03:52 1973\n\0

Example
#include <string.h>
#include <time.h>
#include <stdio.h>
int main(void)
{
struct tm t;
char str[80];
/* sample loading of tm structure */
t.tm_sec = 1; /* Seconds */
t.tm_min = 30; /* Minutes */
t.tm_hour = 9; /* Hour */
t.tm_mday = 22; /* Day of the Month */
t.tm_mon = 11; /* Month */
t.tm_year = 56; /* Year - does not include century */
t.tm_wday = 4; /* Day of the week */
t.tm_yday = 0; /* Does not show in asctime */
t.tm_isdst = 0; /* Is Daylight SavTime; does not show in asctime */
/* converts structure to null terminated string */
strcpy(str, asctime(&t));
printf("%s\n", str);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


asctime + + + +
_wasctime +

3.1.5.34.4 clock
Header File

time.h

Category

Time and Date Routines

Prototype
clock_t clock(void);
3
Description

Determines processor time.

clock can be used to determine the time interval between two events. To determine the time in seconds, the value returned by
clock should be divided by the value of the macro CLK_TCK.

Return Value

On success, clock returns the processor time elapsed since the beginning of the program invocation.

1207
C Runtime Library Reference RAD Studio 3.1 Référence C++

On error (if the processor time is not available or its value cannot be represented), clock returns -1.

Example
#include <time.h>
#include <stdio.h>
#include <dos.h>
int main(void)
{
clock_t start, end;
start = clock();
delay(2000);
end = clock();
printf("The time was: %f\n", (end - start) / CLK_TCK);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.34.5 clock_t
Header File

time.h

Syntax
typedef long clock_t;

Description

Defines the data type returned by the clock function.

Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.34.6 ctime, _wctime


Header File

time.h

Category

Time and Date Routines


3
Prototype
char *ctime(const time_t *time);
wchar_t *_wctime(const time_t *time);

Description

Converts date and time to a string.

1208
3.1 Référence C++ RAD Studio C Runtime Library Reference

ctime converts a time value pointed to by time (the value returned by the function time) into a 26-character string in the following
form, terminating with a newline character and a null character:
Mon Nov 21 11:31:54 1983\n\0

All the fields have constant width.

The global long variable _timezone contains the difference in seconds between GMT and local standard time (in PST, _timezone
is 8*60*60). The global variable _daylight is used to tell the RTL's functions (mktime & localtime) whether they should take
daylight saving time into account if it runs into a date that would normally fall into that category. It is set to 1 if the daylight
savings time conversion should be applied.. These variables are set by the tzset function, not by the user program directly.

Return Value

ctime returns a pointer to the character string containing the date and time. The return value points to static data that is
overwritten with each call to ctime.

Example
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t t;
time(&t);
printf("Today's date and time: %s\n", ctime(&t));
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


ctime + + + +
_wctime +

3.1.5.34.7 _daylight
Header File

time.h

Syntax
extern int _daylight;

Description

_daylight is used by the time and date functions. It is used to tell the RTL's functions (mktime & localtime) whether they should
take daylight saving time into account if it runs into a date that would normally fall into that category. _daylight is initialized from
the values specified in the TZ environment variable and is set to 1 if the daylight savings time conversion should be applied. If TZ
is not set, the value of _daylight is obtained from the operating system. 3

3.1.5.34.8 difftime
Header File

time.h

Category

1209
C Runtime Library Reference RAD Studio 3.1 Référence C++

Time and Date Routines

Prototype
double difftime(time_t time2, time_t time1);

Description

Computes the difference between two times.

difftime calculates the elapsed time in seconds, from time1 to time2.

Return Value

difftime returns the result of its calculation as a double.

Example
#include <time.h>
#include <stdio.h>
#include <dos.h>
#include <conio.h>
int main(void)
{
time_t first, second;
clrscr();
first = time(NULL); /* Gets system
time */
delay(2000); /* Waits 2 secs */
second = time(NULL); /* Gets system time
again */
printf("The difference is: %f seconds\n",difftime(second,first));
getch();
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.34.9 gmtime
Header File

time.h

Category

Time and Date Routines

Prototype
struct tm *gmtime(const time_t *timer);
3
Description

Converts date and time to Greenwich mean time (GMT).

gmtime accepts the address of a value returned by time and returns a pointer to the structure of type tm containing the time
elements. gmtime converts directly to GMT.

The global long variable _timezone should be set to the difference in seconds between GMT and local standard time (in PST
_timezone is 8 x 60 x 60). The global variable _daylight should be set to nonzero only if the standard U.S. daylight saving time

1210
3.1 Référence C++ RAD Studio C Runtime Library Reference

conversion should be applied.

This is the tm structure declaration from the time.h header file:


struct tm {
int tm_sec; /* Seconds */
int tm_min; /* Minutes */
int tm_hour; /* Hour (0 - 23) */
int tm_mday; /* Day of month (1 - 31) */
int tm_mon; /* Month (0 - 11) */
int tm_year; /* Year (calendar year minus 1900) */
int tm_wday; /* Weekday (0 - 6; Sunday is 0) */
int tm_yday; /* Day of year (0 -365) */
int tm_isdst; /* Nonzero if daylight saving time is in effect. */
};

These quantities give the time on a 24-hour clock, day of month (1 to 31), month (0 to 11), weekday (Sunday equals 0), year -
1900, day of year (0 to 365), and a flag that is nonzero if daylight saving time is in effect.

Return Value

gmtime returns a pointer to the structure containing the time elements. This structure is a static that is overwritten with each call.

Example
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Pacific Standard Time & Daylight Savings */
char *tzstr = "TZ=PST8PDT";
int main(void)
{
time_t t;
struct tm *gmt, *area;
putenv(tzstr);
tzset();
t = time(NULL);
area = localtime(&t);
printf("Local time is: %s", asctime(area));
gmt = gmtime(&t);
printf("GMT is: %s", asctime(gmt));
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + + 3

3.1.5.34.10 localtime
Header File

time.h

Category

1211
C Runtime Library Reference RAD Studio 3.1 Référence C++

Time and Date Routines

Prototype
struct tm *localtime(const time_t *timer);

Description

Converts date and time to a structure.

localtime accepts the address of a value returned by time and returns a pointer to the structure of type tm containing the time
elements. It corrects for the time zone and possible daylight saving time.

The global long variable _timezone contains the difference in seconds between GMT and local standard time (in PST, _timezone
is 8 x 60 x 60). The global variable _daylight is used to tell the RTL’s functions (mktime & localtime) whether they should take
daylight saving time into account if it runs into a date that would normally fall into that category. It is set to 1 if the daylight
savings time conversion should be applied. These values are set by tzset, not by the user program directly.

This is the tm structure declaration from the time.h header file:


struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};

These quantities give the time on a 24-hour clock, day of month (1 to 31), month (0 to 11), weekday (Sunday equals 0), year -
1900, day of year (0 to 365), and a flag that is nonzero if the daylight saving time conversion should be applied.

Return Value

localtime returns a pointer to the structure containing the time elements. This structure is a static that is overwritten with each call.

Example
#include <time.h>
#include <stdio.h>
int main(void)
{
time_t timer;
struct tm *tblock;
3 /* gets time of day */
timer = time(NULL);
/* converts date/time to a structure */
tblock = localtime(&timer);
printf("Local time is: %s", asctime(tblock));
return 0;
}
Portability

1212
3.1 Référence C++ RAD Studio C Runtime Library Reference

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.34.11 mktime
Header File

time.h

Category

Time and Date Routines

Prototype
time_t mktime(struct tm *t);

Description

Converts time to calendar format.

Converts the time in the structure pointed to by t into a calendar time with the same format used by the time function. The
original values of the fields tm_sec, tm_min, tm_hour, tm_mday, and tm_mon are not restricted to the ranges described in the tm
structure. If the fields are not in their proper ranges, they are adjusted. Values for fields tm_wday and tm_yday are computed
after the other fields have been adjusted.

The allowable range of calendar times is Jan 1 1970 00:00:00 to Jan 19 2038 03:14:07.

Return Value

On success, mktime returns calendar time as described above.

On error (if the calendar time cannot be represented), mktime returns -1.

Example
#include <stdio.h>
#include <time.h>
char *wday[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Unknown"};
int main(void)
{
struct tm time_check;
int year, month, day;
/* Input a year, month and day to find the weekday for */
printf("Year: ");
scanf("%d", &year);
printf("Month: ");
scanf("%d", &month);
printf("Day: ");
scanf("%d", &day);
/* load the time_check structure with the data */ 3
time_check.tm_year = year - 1900;
time_check.tm_mon = month - 1;
time_check.tm_mday = day;
time_check.tm_hour = 0;
time_check.tm_min = 0;
time_check.tm_sec = 1;
time_check.tm_isdst = -1;
/* call mktime to fill in the weekday field of the structure */
if (mktime(&time_check) == -1)
time_check.tm_wday = 7;

1213
C Runtime Library Reference RAD Studio 3.1 Référence C++

/* print out the day of the week */


printf("That day is a %s\n", wday[time_check.tm_wday]);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.34.12 stime
Header File

time.h

Category

Time and Date Routines

Prototype
int stime(time_t *tp);

Description

Sets system date and time.

stime sets the system time and date. tp points to the value of the time as measured in seconds from 00:00:00 GMT, January 1,
1970.

Return Value

stime returns a value of 0.

Example
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t t;
t = time(NULL);
printf("Current date is %s", ctime(&t));
t -= 24L*60L*60L; /* Back up to same time previous day */
stime(&t);
printf("\nNew date is %s", ctime(&t));
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


3 +

3.1.5.34.13 strftime, wcsftime


Header File

time.h

1214
3.1 Référence C++ RAD Studio C Runtime Library Reference

Category

Time and Date Routines

Prototype
size_t strftime(char *s, size_t maxsize, const char *fmt, const struct tm *t);
size_t wcsftime(wchar_t *s, size_t maxsize, const wchar_t *fmt, const struct tm *t);

Description

Formats time for output.

strftime formats the time in the argument t into the array pointed to by the argument s according to the fmt specifications. All
ordinary characters are copied unchanged. No more than maxsize characters are placed in s.

The time is formatted according to the current locale's LC_TIME category.

Return Value

On success, strftime returns the number of characters placed into s.

On error (if the number of characters required is greater than maxsize), strftime returns 0.

More about strftime

Example
#include <stdio.h>
#include <time.h>
#include <dos.h>
int main(void)
{
struct tm *time_now;
time_t secs_now;
char str[80];
tzset();
time(&secs_now);
time_now = localtime(&secs_now);
strftime(str, 80,
"It is %M minutes after %I o'clock (%Z) %A, %B %d 19%y",
time_now);
printf("%s\n",str);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


strftime + + + +
wcsftime + + +

3.1.5.34.14 time 3
Header File

time.h

Category

Time and Date Routines

Prototype

1215
C Runtime Library Reference RAD Studio 3.1 Référence C++

time_t time(time_t *timer);

Description

Gets time of day.

time gives the current time, in seconds, elapsed since 00:00:00 GMT, January 1, 1970, and stores that value in the location
pointed to by timer, provided that timer is not a NULL pointer.

Return Value

time returns the elapsed time in seconds.

Example
#include <time.h>
#include <stdio.h>
int main(void)
{
time_t t;
t = time(NULL);
printf("The number of seconds since January 1, 1970 is %ld",t);
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


+ + + +

3.1.5.34.15 _timezone
Header File

time.h

Syntax
extern long _timezone;

Description

_timezone is used by the time-and-date functions. It is calculated by the tzset function; it is assigned a long value that is the
difference, in seconds, between the current local time and Greenwich mean time.

On Win32, the value of _timezone is obtained from the operating system.

3.1.5.34.16 tm
Header File

3 time.h

Syntax
struct tm {
int tm_sec; /* Seconds */
int tm_min; /* Minutes */
int tm_hour; /* Hour (0--23) */

1216
3.1 Référence C++ RAD Studio C Runtime Library Reference

int tm_mday; /* Day of month (1--31) */


int tm_mon; /* Month (0--11) */
int tm_year; /* Year (calendar year minus 1900) */
int tm_wday; /* Weekday (0--6; Sunday = 0) */
int tm_yday; /* Day of year (0--365) */
int tm_isdst; /* 0 if daylight savings time is not in effect) */
};

Description

A structure defining the time, broken down into increments.

tm is used by the functions asctime, gmtime, localtime, mktime, and strftime.

Example

3.1.5.34.17 _tzname,_wtzname
Header File

time.h

Syntax
extern char * _tzname[2]
extern wchar_t *const _wtzname[2]

Description

The global variable _tzname is an array of pointers to strings containing abbreviations for time zone names. _tzname[0] points to
a three-character string with the value of the time zone name from the TZ environment string. The global variable _tzname[1]
points to a three-character string with the value of the daylight saving time zone name from the TZ environment string. If no
daylight saving name is present, _tzname[1] points to a null string.

On Win32, the value of _tzname is obtained from the operating system.

3.1.5.34.18 _tzset, _wtzset


Header File

time.h

Category

Time and Date Routines

Prototype
3
void _tzset(void)
void _wtzset(void)

Description

Sets value of global variables _daylight, _timezone, and _tzname.

_tzset is available on XENIX systems.

1217
C Runtime Library Reference RAD Studio 3.1 Référence C++

_tzset sets the _daylight, _timezone, and _tzname global variables based on the environment variable TZ. _wtzset sets the
_daylight, _timezone, and _wtzname global variables. The library functions ftime and localtime use these global variables to
adjust Greenwich Mean Time (GMT) to the local time zone. The format of the TZ environment string is:
TZ = zzz[+/-]d[d][lll]

where zzz is a three-character string representing the name of the current time zone. All three characters are required. For
example, the string “PST” could be used to represent Pacific standard time.

[+/-]d[d] is a required field containing an optionally signed number with 1 or more digits. This number is the local time zone’s
difference from GMT in hours. Positive numbers adjust westward from GMT. Negative numbers adjust eastward from GMT. For
example, the number 5 = EST, +8 = PST, and -1 = continental Europe. This number is used in the calculation of the global
variable _timezone. _timezone is the difference in seconds between GMT and the local time zone.

lll is an optional three-character field that represents the local time zone, daylight saving time. For example, the string “PDT”
could be used to represent pacific daylight saving time. If this field is present, it causes the global variable _daylight to be set
nonzero. If this field is absent, _daylight is set to zero.

If the TZ environment string isn’t present or isn’t in the preceding form, a default TZ = “EST5EDT” is presumed for the purposes
of assigning values to the global variables _daylight, _timezone, and _tzname. On a Win32 system, none of these global
variables are set if TZ is null.

The global variables _tzname[0] and _wtzname[1] point to a three-character string with the value of the time-zone name from the
TZ environment string. _tzname[1] and _wtzname[1] point to a three-character string with the value of the daylight saving
time-zone name from the TZ environment string. If no daylight saving name is present, _tzname[1] and _wtzname[1] point to a
null string.

Return Value

None.

Example
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
time_t td;
putenv("TZ=PST8PDT");
tzset();
time(&td);
printf("Current time = %s\n", asctime(localtime(&td)));
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_tzset + +
_wtzset +
3

3.1.5.35 typeinfo.h
The following functions, macros, and classes are provided in typeinfo.h:

1218
3.1 Référence C++ RAD Studio C Runtime Library Reference

Rubriques
Nom Description
bad_cast class ( see page 1219) Header File
typeinfo.h
Description
When dynamic_cast fails to make a cast to reference, the expression can throw
bad_cast. Note that when dynamic_cast fails to make a cast to pointer type, the
result is the null pointer.
bad_typeid class ( see page 1219) Header File
typeinfo.h
Description
When the operand of typeid is a dereferenced null pointer, the typeid operator
can throw bad_typeid.
type_info class ( see page 1219) Header File
typeinfo.h
Description
Provides information about a type.
Constructor
Only a private constructor is provided. You cannot create type_info objects. By
declaring your objects to be _ _rtti types, or by using the -RT compiler switch, the
compiler provides your objects with the elements of type_info. type_info
references are generated by the typeid operator.
Public Member Functions
Operators

3.1.5.35.1 bad_cast class


Header File

typeinfo.h

Description

When dynamic_cast fails to make a cast to reference, the expression can throw bad_cast. Note that when dynamic_cast fails to
make a cast to pointer type, the result is the null pointer.

3.1.5.35.2 bad_typeid class


Header File

typeinfo.h

Description

When the operand of typeid is a dereferenced null pointer, the typeid operator can throw bad_typeid.

3.1.5.35.3 type_info class


Header File
3
typeinfo.h

Description

Provides information about a type.

Constructor

Only a private constructor is provided. You cannot create type_info objects. By declaring your objects to be _ _rtti types, or by
using the -RT compiler switch, the compiler provides your objects with the elements of type_info. type_info references are

1219
C Runtime Library Reference RAD Studio 3.1 Référence C++

generated by the typeid operator.

Public Member Functions

Operators

3.1.5.36 utime.h
The following functions, macros, and classes are provided in utime.h:

Rubriques
Nom Description
_utime, _wutime ( see page 1220) Header File
utime.h
Category
Input/output Routines
Prototype
int _utime(char *path, struct utimbuf *times);
int _wutime(wchar_t *path, struct _utimbuf *times);
Description
Sets file time and date.
_utime sets the modification time for the file path. The modification time is
contained in the utimbuf structure pointed to by times. This structure is defined in
utime.h, and has the following format:
struct utimbuf {
time_t actime; /* access time */
time_t modtime; /* modification time */
};
The FAT (file allocation table) file system supports only a modification time;
therefore, on FAT file systems _utime ignores actime and uses only modtime to
set... suite ( see page 1220)

3.1.5.36.1 _utime, _wutime


Header File

utime.h

Category

Input/output Routines

Prototype
int _utime(char *path, struct utimbuf *times);
int _wutime(wchar_t *path, struct _utimbuf *times);

Description

Sets file time and date.

3 _utime sets the modification time for the file path. The modification time is contained in the utimbuf structure pointed to by times.
This structure is defined in utime.h, and has the following format:
struct utimbuf {
time_t actime; /* access time */
time_t modtime; /* modification time */
};

1220
3.1 Référence C++ RAD Studio C Runtime Library Reference

The FAT (file allocation table) file system supports only a modification time; therefore, on FAT file systems _utime ignores actime
and uses only modtime to set the file’s modification time.

If times is NULL, the file’s modification time is set to the current time.

_wutime is the Unicode version of _utime. The Unicode version accepts a filename that is a wchar_t character string. Otherwise,
the functions perform identically.

Return Value

On success, _utime returns 0.

On error, it returns -1, and sets the global variable errno to one of the following values:

EACCES Permission denied


EMFILE Too many open files
ENOENT Path or file name not found

Example
/* Copy timestamp from one file to another */
#include <sys\stat.h>
#include <utime.h>
#include <stdio.h>

int main( int argc, char *argv[] )


{
struct stat src_stat;
struct utimbuf times;
if(argc != 3) {
printf( "Usage: copytime <source file> <dest file>\n" );
return 1;
}

if (stat(argv[1],&src_stat) != 0) {
perror("Unable to get status of source file");
return 1;
}

times.modtime = times.actime = src_stat.st_mtime;


if (utime(argv[2],&times) != 0) {
perror("Unable to set time of destination file");
return 1;
}
return 0;
}
Portability

POSIX Win32 ANSI C ANSI C++


_utime + +
_wutime +
3

3.1.5.37 values.h
The following functions, macros, and classes are provided in values.h:

1221
C Runtime Library Reference RAD Studio 3.1 Référence C++

Rubriques
Nom Description
BITSPERBYTE #define ( see page 1222) Header File
values.h
Description
Number of bits in a byte.
HIBITx #defines ( see page 1222) Header File
values.h
Description
Bit mask for the high (sign) bit of standard integer types.
MAXxxxx #defines (integer data types) ( see page 1222) Header File
values.h
Description
Maximum values for integer data types
Float and Double Limits ( see page 1223) Header File
values.h
Description
UNIX System V compatible:

3.1.5.37.1 BITSPERBYTE #define


Header File

values.h

Description

Number of bits in a byte.

3.1.5.37.2 HIBITx #defines


Header File

values.h

Description

Bit mask for the high (sign) bit of standard integer types.

Name Meaning
HIBITS For type short
HIBITI For type int
HIBITL For type long

3.1.5.37.3 MAXxxxx #defines (integer data types)


3
Header File

values.h

Description

Maximum values for integer data types

1222
3.1 Référence C++ RAD Studio C Runtime Library Reference

Name Meaning
MAXSHORT Largest short
MAXINT Largest int
MAXLONG Largest long

3.1.5.37.4 Float and Double Limits


Header File

values.h

Description

UNIX System V compatible:

_LENBASE Base to which exponent applies

Limits for double float values

_DEXPLEN Number of bits in exponent


DMAXEXP Maximum exponent allowed
DMAXPOWTWO Largest power of two allowed
DMINEXP Minimum exponent allowed
DSIGNIF Number of significant bits
MAXDOUBLE Largest magnitude double value
MINDOUBLE Smallest magnitude double value

Limits for float values

_FEXPLEN Number of bits in exponent


FMAXEXP Maximum exponent allowed
FMAXPOWTWO Largest power of two allowed
FMINEXP Minimum exponent allowed
FSIGNIF Number of significant bits
MAXFLOAT Largest magnitude float value
MINFLOAT Smallest magnitude float value

1223
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2 Guide du développeur Win32


Cette section contient les rubriques du Guide du développeur Win32 relatives à la personnalité Delphi Win32 de RAD Studio.

Rubriques
Nom Description
Guide du concepteur de composants ( see page 1224) Le Guide du concepteur de composants couvre toutes les informations relatives
à la création de composants VCL dans la personnalité Delphi.
Développement d'applications COM ( see page 1400) Contient les rubriques du Guide du développeur relatives à la création
d'applications COM dans Delphi.
Développement d'applications de bases de données ( see page 1496) Contient les rubriques du Guide du développeur relatives à la programmation
d'applications de base de données.
Programmation avec Delphi ( see page 1939) Contient les rubriques du Guide du développeur relatives à la programmation
avec Delphi.
Ecriture d'applications Internet ( see page 2318) Contient les rubriques du Guide du développeur relatives à l'écriture
d'applications internet dans Delphi.

3.2.1 Guide du concepteur de composants


Le Guide du concepteur de composants couvre toutes les informations relatives à la création de composants VCL dans la
personnalité Delphi.

Rubriques
Nom Description
Création d'un composant graphique ( see page 1225)
Création d'événements ( see page 1239)
Création de méthodes ( see page 1250)
Création de propriétés ( see page 1255)
Personnalisation d'une grille ( see page 1268)
Extensions de l'EDI ( see page 1287)
Gestion des messages ( see page 1310)
Présentation de la création d'un composant ( see page 1323)
Contrôles orientés données ( see page 1339)
Accessibilité des composants au moment de la conception ( see page 1355)
Transformation d'une boîte de dialogue en composant ( see page 1375)
Modification d'un composant existant ( see page 1380)
Programmation orientée objet et écriture des composants ( see page 1384)
Graphiques et composants ( see page 1394)

1224
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.1 Création d'un composant graphique


Rubriques
Nom Description
Ajout de fonctionnalités graphiques ( see page 1227) Lorsque votre composant graphique a été déclaré et qu'ont été publiées toutes
les propriétés reçues en héritage que vous voulez rendre disponibles, vous
pouvez ajouter les fonctionnalités graphiques qui caractériseront votre
composant. La création d'un contrôle graphique se compose de deux tâches :

1. Détermination de ce qui doit être dessiné. ( see page


1231)
2. Dessin de l'image du composant. ( see page 1231)
En outre, s'agissant du contrôle forme de notre exemple,
vous allez ajouter certaines propriétés qui serviront aux
développeurs d'applications pour personnaliser
l'apparence du contrôle lors de la conception.
Création d'un composant graphique ( see page 1227) Un contrôle graphique est un composant simple. Un contrôle purement
graphique ne reçoit jamais la focalisation et n'a donc pas besoin de son propre
handle de fenêtre. Les utilisateurs peuvent quand même manipuler le contrôle
avec la souris, mais il n'y a pas d'interface clavier.
TShape, le contrôle graphique présenté dans les rubriques suivantes,
correspond au composant forme inclus dans la page Supplément de la palette
d'outils. Bien que le composant que nous allons créer soit identique au
composant forme standard, vous devrez lui donner un nom différent pour éviter
des doublons d'identificateur. Les rubriques suivantes utilisent le nom... suite (
see page 1227)
Création et recensement du composant ( see page 1227) La création d'un composant se fait toujours de la même façon : vous créez une
unité et vous recensez le composant avant de l'installer dans la palette d'outils.
Ce processus est décrit dans Création d'un nouveau composant ( see page
1330).
Déclaration des propriétés d'accès ( see page 1228) Vous pouvez fournir les accès aux objets appartenant à un composant en
déclarant des propriétés de même type que ces objets. Cela offre aux
développeurs un moyen d'accéder aux objets lors de la conception ou de
l'exécution. Généralement, la partie read de la propriété ne fait que référencer le
champ de classe, alors que la partie write appelle une méthode qui permet au
composant de réagir aux changements apportés à l'objet.
Ajoutez des propriétés à votre contrôle forme pour fournir les accès aux champs
du crayon et du pinceau. Vous allez également déclarer les méthodes pour réagir
aux changements de... suite ( see page 1228)
Déclaration des champs de classe ( see page 1229) Chaque classe appartenant à un composant doit avoir un champ déclaré dans ce
composant. Le champ de classe garantit que le composant dispose toujours d'un
pointeur sur l'objet qui lui appartient afin de lui permettre de le détruire avant de
se détruire lui-même. Généralement, un composant initialise les objets dont il est
propriétaire dans son constructeur et les détruit dans son destructeur.
Les champs de classe des objets ayant un propriétaire sont presque toujours
déclarés private. Si des applications (ou d'autres composants) ont besoin
d'accéder aux objets ayant un propriétaire, vous devez pour cela déclarer des
propriétés published ou public... suite ( see page 1229)
Déclaration de la propriété ( see page 1230) Généralement, pour déclarer une propriété, vous déclarez un champ privé pour
stocker les données de la propriété puis vous spécifiez les méthodes pour lire et
écrire sa valeur. Souvent, la méthode pour lire la valeur n'est pas nécessaire car
un simple pointage sur la valeur stockée suffit.
S'agissant de notre contrôle forme, vous aurez à déclarer un champ contenant la
forme courante, puis à déclarer une propriété qui lit ce champ et l'écrit via un
appel de méthode. 3
Ajoutez les déclarations suivantes dans TSampleShape :
Déclaration du type de la propriété ( see page 1230) Lorsque vous déclarez une propriété dont le type est défini par l'utilisateur, le
type de la propriété doit être déclaré avant la classe qui inclut cette propriété. Les
types énumérés sont fréquemment employés par les propriétés.
S'agissant de notre contrôle forme, vous aurez besoin d'un type énuméré avec
un élément défini pour chaque forme que le contrôle est en mesure de dessiner.
Ajoutez la définition de type suivante avant la déclaration de classe du contrôle
forme.

1225
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Détermination de ce qui doit être dessiné ( see page 1231) Un contrôle graphique est capable de changer son apparence pour refléter un
changement de condition, y compris une intervention de l'utilisateur. Un contrôle
graphique qui aurait toujours le même aspect ne devrait pas être un composant.
Si vous voulez une image statique, importez une image au lieu d'utiliser un
contrôle.
Généralement, l'apparence d'un contrôle graphique dépend de plusieurs
propriétés. Par exemple, le contrôle jauge dispose de propriétés qui déterminent
sa forme et son orientation et si la représentation de la progression est
numérique ou graphique. De même, notre contrôle forme doit disposer d'une
propriété qui détermine le type de forme... suite ( see page 1231)
Dessin de l'image du composant ( see page 1231) L'essentiel d'un contrôle graphique se résume à sa façon de dessiner son image
à l'écran. Le type abstrait TGraphicControl définit une méthode appelée Paint
que vous devez redéfinir pour peindre l'image voulue dans votre contrôle.
La méthode Paint de votre contrôle forme doit accomplir plusieurs tâches :

• Utiliser le crayon et le pinceau sélectionnés par


l'utilisateur.
• Utiliser la forme sélectionnée.
• Ajuster les coordonnées pour que les carrés et les cercles
utilisent une largeur et une hauteur identiques.
Initialisation des classes ayant un propriétaire ( see page 1233) Si vous ajoutez des classes dans votre composant, le constructeur de ce dernier
doit les initialiser pour que l'utilisateur puisse interagir avec ces objets lors de
l'exécution. De même, le destructeur du composant doit également détruire les
objets appartenant au composant avant de détruire ce dernier.
Redéfinition du constructeur et du destructeur ( see page 1234) Pour changer les valeurs par défaut des propriétés et initialiser les classes
appartenant à votre composant, vous devez redéfinir le constructeur et le
destructeur reçus en héritage. Dans les deux cas, n'oubliez pas d'appeler la
méthode reçue en héritage.
Publication des propriétés héritées ( see page 1235) Lorsque vous dérivez un type de composant, vous choisissez parmi les
propriétés et les événements déclarés dans la partie protected de la classe
ancêtre ceux que vous voulez rendre disponibles aux utilisateurs du nouveau
composant. TGraphicControl publie toutes les propriétés qui permettent au
composant de fonctionner en tant que contrôle, donc les seules fonctionnalités
que vous devez publier sont celles dont vous avez besoin pour répondre aux
événements de souris et aux opérations glisser-déplacer.
La publication des propriétés et des événements reçus en héritage est expliquée
dans Publication des propriétés héritées ( see page 1260) et Rendre visible
des événements ( see page 1247). Ces deux processus... suite ( see page
1235)
Publication du crayon et du pinceau ( see page 1235) Par défaut, un canevas dispose d'un crayon fin et noir et d'un pinceau plein et
blanc. Pour permettre aux développeurs de changer le crayon et le pinceau,
vous devez leur fournir des classes pour les manipuler lors de la conception, puis
copier les classes dans le canevas lors des opérations de dessin. Des classes
telles qu'un crayon ou un pinceau auxiliaire sont appelées classes ayant un
propriétaire car elles appartiennent au composant qui est responsable de leur
création et de leur destruction.
La gestion des classes ayant un propriétaire se déroule en quatre étapes :

1. Déclaration des champs de la classe. ( see page


1229)... suite ( see page 1235)
Adaptation du dessin de la forme ( see page 1236) Le contrôle forme standard effectue une tâche supplémentaire que ne fait pas
encore le contrôle forme de notre exemple : il gère les carrés et les cercles ainsi
que les rectangles et les ellipses. Pour ce faire, vous devez écrire le code qui
trouve le côté le plus petit et centre l'image.
Voici une méthode Paint parfaitement adaptée aux carrés et aux ellipses :
Définition des propriétés des classes ayant un propriétaire ( see page 1237) L'une des dernières étapes de la gestion des classes crayon et pinceau consiste
à provoquer un nouveau dessin du contrôle forme si le crayon ou le pinceau est
3 modifié. Comme les classes crayon et pinceau disposent toutes les deux d'un
événement OnChange, vous pouvez créer une méthode dans le contrôle forme
et faire pointer les deux événements OnChange sur cette méthode.
Ajoutez la méthode suivante au contrôle forme et effectuez la mise à jour du
constructeur du composant pour affecter aux événements du crayon et du
pinceau cette nouvelle méthode :
Ecriture de la méthode d'implémentation ( see page 1238) Lorsque la partie read ou write d'une définition de propriété utilise une méthode
plutôt qu'un accès direct aux données stockées de la propriété, vous devez
implémenter ces méthodes.
Ajoutez l'implémentation de la méthode SetShape à la partie implementation de
l'unité :

1226
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.1.1 Ajout de fonctionnalités graphiques


Lorsque votre composant graphique a été déclaré et qu'ont été publiées toutes les propriétés reçues en héritage que vous
voulez rendre disponibles, vous pouvez ajouter les fonctionnalités graphiques qui caractériseront votre composant. La création
d'un contrôle graphique se compose de deux tâches :

1. Détermination de ce qui doit être dessiné. ( see page 1231)


2. Dessin de l'image du composant. ( see page 1231)
En outre, s'agissant du contrôle forme de notre exemple, vous allez ajouter certaines propriétés qui serviront aux développeurs
d'applications pour personnaliser l'apparence du contrôle lors de la conception.

3.2.1.1.2 Création d'un composant graphique


Un contrôle graphique est un composant simple. Un contrôle purement graphique ne reçoit jamais la focalisation et n'a donc pas
besoin de son propre handle de fenêtre. Les utilisateurs peuvent quand même manipuler le contrôle avec la souris, mais il n'y a
pas d'interface clavier.

TShape, le contrôle graphique présenté dans les rubriques suivantes, correspond au composant forme inclus dans la page
Supplément de la palette d'outils. Bien que le composant que nous allons créer soit identique au composant forme standard,
vous devrez lui donner un nom différent pour éviter des doublons d'identificateur. Les rubriques suivantes utilisent le nom
TSampleShape et illustrent toutes les étapes de sa création :

• Création et recensement du composant ( see page 1381).


• Publication des propriétés héritées ( see page 1235).
• Ajout de fonctionnalités graphiques ( see page 1227).

3.2.1.1.3 Création et recensement du composant


La création d'un composant se fait toujours de la même façon : vous créez une unité et vous recensez le composant avant de
l'installer dans la palette d'outils. Ce processus est décrit dans Création d'un nouveau composant ( see page 1330).

Pour notre exemple, suivez la procédure générale de création d'un composant en tenant compte des spécificités
suivantes :
1. Appelez l'unité du composant Shapes.
2. Dérivez un nouveau type de composant appelé TSampleShape, descendant de TGraphicControl.
3. Recensez TSampleShape dans la catégorie Exemples de la palette d'outils.
L'unité que vous obtenez doit ressembler à ceci :
unit Shapes;
interface
uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms;
type
TSampleShape = class(TGraphicControl) 3
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponent('Exemples', [TSampleShape]);
end;
end.
//---------------------------------------------------------------------------
#include <vcl.h>

1227
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

#pragma hdrstop
#include "Shapes.h"
//---------------------------------------------------------------------------
#pragma package(smart_init);
//---------------------------------------------------------------------------
// ValidCtrCheck permet de vérifier que les composants créés ne comportent pas
// de fonctions virtuelles pures.
//
static inline void ValidCtrCheck(TSampleShape *)
{
new TSampleShape(NULL);
}
//---------------------------------------------------------------------------
__fastcall TSampleShape::TGraphicControl(TComponent* Owner)
: TGraphicControl(Owner)
{
}
//---------------------------------------------------------------------------
namespace Shapes
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TSampleShape)};
RegisterComponents("Exemples", classes, 0);
}
}
//---------------------------------------------------------------------------
#ifndef ShapesH
#define ShapesH
//---------------------------------------------------------------------------
#include <sysutils.hpp>
#include <controls.hpp>
#include <classes.hpp>
#include <forms.hpp>
//---------------------------------------------------------------------------
class PACKAGE TSampleShape : public TGraphicControl
{
private:
protected:
public:
__published:
};
//---------------------------------------------------------------------------
#endif

3.2.1.1.4 Déclaration des propriétés d'accès


Vous pouvez fournir les accès aux objets appartenant à un composant en déclarant des propriétés de même type que ces
objets. Cela offre aux développeurs un moyen d'accéder aux objets lors de la conception ou de l'exécution. Généralement, la
partie read de la propriété ne fait que référencer le champ de classe, alors que la partie write appelle une méthode qui permet au
composant de réagir aux changements apportés à l'objet.

Ajoutez des propriétés à votre contrôle forme pour fournir les accès aux champs du crayon et du pinceau. Vous allez également
déclarer les méthodes pour réagir aux changements de crayon ou de pinceau.
3
type
TSampleShape = class(TGraphicControl)
.
.
.
private { ces méthodes doivent être privées }
procedure SetBrush(Value: TBrush);
procedure SetPen(Value: TPen);
published { les rend disponibles lors de la

1228
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

conception }
property Brush: TBrush read FBrush write SetBrush;
property Pen: TPen read FPen write SetPen;
end;
class PACKAGE TSampleShape : public TGraphicControl
{
.
.
.
private:
TPen *FPen;
TBrush *FBrush;
void __fastcall SetBrush(TBrush *Value);
void __fastcall SetPen(TPen *Value);
.
.
.
__published:
__property TBrush* Brush = {read=FBrush, write=SetBrush, nodefault};
__property TPen* Pen = {read=FPen, write=SetPen, nodefault};
};
Vous devez ensuite écrire les méthodes SetBrush et SetPen dans la partie implémentation de l'unité :
procedure TSampleShape.SetBrush(Value: TBrush);
begin
FBrush.Assign(Value); { remplacer le pinceau existant par le
paramètre }
end;
procedure TSampleShape.SetPen(Value: TPen);
begin
FPen.Assign(Value); { remplacer le crayon existant par le
paramètre }
end;
void __fastcall TSampleShape::SetBrush( TBrush* Value)
{
FBrush->Assign(Value);
}
void __fastcall TSampleShape::SetPen( TPen* Value)
{
FPen->Assign(Value);
}
Affecter directement le contenu de Value à FBrush-
FBrush := Value;
FBrush = Value;
• écraserait le pointeur interne de FBrush, ferait perdre de la mémoire et créerait une série de problèmes de propriété.

3.2.1.1.5 Déclaration des champs de classe


Chaque classe appartenant à un composant doit avoir un champ déclaré dans ce composant. Le champ de classe garantit que
le composant dispose toujours d'un pointeur sur l'objet qui lui appartient afin de lui permettre de le détruire avant de se détruire
lui-même. Généralement, un composant initialise les objets dont il est propriétaire dans son constructeur et les détruit dans son
destructeur.
3
Les champs de classe des objets ayant un propriétaire sont presque toujours déclarés private. Si des applications (ou d'autres
composants) ont besoin d'accéder aux objets ayant un propriétaire, vous devez pour cela déclarer des propriétés published ou
public.

Ajoutez des champs de classe pour le crayon et le pinceau de votre contrôle forme :
type
TSampleShape = class(TGraphicControl)

1229
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

private { les données membres sont presque toujours privées }


FPen: TPen; { donnée membre pour l'objet crayon }
FBrush: TBrush; { donnée membre pour l'objet pinceau }
.
.
.
end;
class PACKAGE TSampleShape : public TGraphicControl
{
private: // les données membres sont toujours privées
TPen *FPen; // une donnée membre pour l'objet crayon
TBrush *FBrush; // une donnée membre pour l'objet pinceau
.
.
.
};

3.2.1.1.6 Déclaration de la propriété


Généralement, pour déclarer une propriété, vous déclarez un champ privé pour stocker les données de la propriété puis vous
spécifiez les méthodes pour lire et écrire sa valeur. Souvent, la méthode pour lire la valeur n'est pas nécessaire car un simple
pointage sur la valeur stockée suffit.

S'agissant de notre contrôle forme, vous aurez à déclarer un champ contenant la forme courante, puis à déclarer une propriété
qui lit ce champ et l'écrit via un appel de méthode.

Ajoutez les déclarations suivantes dans TSampleShape :


type
TSampleShape = class(TGraphicControl)
private
FShape: TSampleShapeType; { champ pour contenir la valeur de la propriété }
procedure SetShape(Value: TSampleShapeType);
published
property Shape: TSampleShapeType read FShape write SetShape;
end;
class PACKAGE TSampleShape : public TGraphicControl
{
private:
TSampleShapeType FShape;
void __fastcall SetShape(TSampleShapeType Value);
__published:
__property TSampleShapeType Shape = {read=FShape, write=SetShape, nodefault};
};
Il ne vous reste plus qu'à ajouter l'implémentation de SetShape.

3.2.1.1.7 Déclaration du type de la propriété


Lorsque vous déclarez une propriété dont le type est défini par l'utilisateur, le type de la propriété doit être déclaré avant la
classe qui inclut cette propriété. Les types énumérés sont fréquemment employés par les propriétés.

3 S'agissant de notre contrôle forme, vous aurez besoin d'un type énuméré avec un élément défini pour chaque forme que le
contrôle est en mesure de dessiner.

Ajoutez la définition de type suivante avant la déclaration de classe du contrôle forme.


type
TSampleShapeType = (sstRectangle, sstSquare, sstRoundRect, sstRoundSquare,
sstEllipse, sstCircle);
TSampleShape = class(TGraphicControl) { existe déjà }
enum TSampleShapeType { sstRectangle, sstSquare, sstRoundRect, sstRoundSquare, sstEllipse,
sstCircle };

1230
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

class PACKAGE TSampleShape : public TGraphicControl // existe déjà


Vous pouvez maintenant utiliser ce type pour déclarer une nouvelle propriété dans la classe.

3.2.1.1.8 Détermination de ce qui doit être dessiné


Un contrôle graphique est capable de changer son apparence pour refléter un changement de condition, y compris une
intervention de l'utilisateur. Un contrôle graphique qui aurait toujours le même aspect ne devrait pas être un composant. Si vous
voulez une image statique, importez une image au lieu d'utiliser un contrôle.

Généralement, l'apparence d'un contrôle graphique dépend de plusieurs propriétés. Par exemple, le contrôle jauge dispose de
propriétés qui déterminent sa forme et son orientation et si la représentation de la progression est numérique ou graphique. De
même, notre contrôle forme doit disposer d'une propriété qui détermine le type de forme qu'il doit dessiner.

Pour donner à votre contrôle une propriété qui détermine la forme dessinée, ajoutez une propriété intitulée Shape. Cela implique
les tâches suivantes :

1. Déclaration du type de la propriété. ( see page 1230)


2. Déclaration de la propriété. ( see page 1230)
3. Ecriture de la méthode d'implémentation. ( see page 1238)
La création de propriété est expliquée en détail dans Création de propriétés ( see page 1258).

3.2.1.1.9 Dessin de l'image du composant


L'essentiel d'un contrôle graphique se résume à sa façon de dessiner son image à l'écran. Le type abstrait TGraphicControl
définit une méthode appelée Paint que vous devez redéfinir pour peindre l'image voulue dans votre contrôle.

La méthode Paint de votre contrôle forme doit accomplir plusieurs tâches :

• Utiliser le crayon et le pinceau sélectionnés par l'utilisateur.


• Utiliser la forme sélectionnée.
• Ajuster les coordonnées pour que les carrés et les cercles utilisent une largeur et une hauteur identiques.

La redéfinition de la méthode Paint nécessite deux étapes :


1. Ajout de Paint dans la déclaration du composant.
2. Insertion de la méthode Paint dans la partie implementation de l'unité.
S'agissant de notre contrôle forme, vous devez ajouter la déclaration suivante à la déclaration de classe :
type
TSampleShape = class(TGraphicControl)
.
.
.
protected
procedure Paint; override;
.
. 3
.
end;
class PACKAGE TSampleShape : public TGraphicControl
{
.
.
.
protected:
virtual void __fastcall Paint();

1231
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

.
.
.
};
Vous devez ensuite écrire la méthode dans la partie implementation de l'unité :
procedure TSampleShape.Paint;
begin
with Canvas do
begin
Pen := FPen; { copier le crayon du composant }
Brush := FBrush; { copier le pinceau du composant }
case FShape of
sstRectangle, sstSquare:
Rectangle(0, 0, Width, Height); { dessiner les rectangles et carrés
}
sstRoundRect, sstRoundSquare:
RoundRect(0, 0, Width, Height, Width div 4, Height div 4); { dessiner des formes
arrondies }
sstCircle, sstEllipse:
Ellipse(0, 0, Width, Height); { dessiner des formes
arrondies }
end;
end;
end;
void __fastcall TSampleShape::Paint()
{
int X,Y,W,H,S;
Canvas->Pen = FPen; // copie le crayon du composant
Canvas->Brush = FBrush; // copie le pinceau du composant
W=Width; // utilise la largeur du composant
H=Height; // utilise la hauteur du composant
X=Y=0; // sauvegarde du plus petit pour les
cercles/carrés
if( W<H )
S=W;
else
S=H;
switch(FShape)
{
case sstRectangle: // dessine les rectangles et les carrés
case sstSquare:
Canvas->Rectangle(X,Y,X+W,Y+H);
break;
case sstRoundRect: // dessine les rectangles et les carrés
arrondis
case sstRoundSquare:
Canvas->RoundRect(X,Y,X+W,Y+H,S/4,S/4);
break;
case sstCircle: // dessine les cercles et les ellipses
case sstEllipse:
Canvas->Ellipse(X,Y,X+W,Y+H);
break;
default:
break;
3 }
}
Paint est appelée à chaque fois que le contrôle doit mettre à jour son image. Les contrôles sont dessinés lorsqu'ils s'affichent
pour la première fois ou lorsqu'une fenêtre qui se trouvait au-dessus disparaît. En outre, vous pouvez forcer le dessin en
appelant Invalidate, comme le fait la méthode StyleChanged.

1232
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.1.10 Initialisation des classes ayant un propriétaire


Si vous ajoutez des classes dans votre composant, le constructeur de ce dernier doit les initialiser pour que l'utilisateur puisse
interagir avec ces objets lors de l'exécution. De même, le destructeur du composant doit également détruire les objets
appartenant au composant avant de détruire ce dernier.

Comme vous avez déclaré un crayon et un pinceau dans le contrôle forme, vous devez les initialiser dans le constructeur
du contrôle forme et les détruire dans son destructeur :
1. Construisez le crayon et le pinceau dans le constructeur du contrôle forme :
constructor TSampleShape.Create(AOwner: TComponent);
begin
inherited Create(AOwner); { appeler toujours le constructeur hérité }
Width := 65;
Height := 65;
FPen := TPen.Create; { construire le crayon }
FBrush := TBrush.Create; { construire le pinceau }
end;
__fastcall TSampleShape::TSampleShape(TComponent* Owner) : TGraphicControl(Owner)
{
Width = 65;
Height = 65;
FBrush = new TBrush(); // construit le crayon
FPen = new TPen(); // construit le pinceau
}
2. Ajoutez le destructeur redéfini dans la déclaration de la classe composant :
type
TSampleShape = class(TGraphicControl)
public { les destructeurs sont toujours
publics}
constructor Create(AOwner: TComponent); override;
destructor Destroy; override; { ne pas oublier la directive
override }
end;
class PACKAGE TSampleShape : public TGraphicControl
{
.
.
.
public: // les destructeurs sont toujours
publics
virtual __fastcall TSampleShape(TComponent* Owner);
__fastcall ~TSampleShape(); // le destructeur
.
.
.
};
3. Ecrivez le nouveau destructeur dans la partie implementation de l'unité :
destructor TSampleShape.Destroy;
begin
FPen.Free; { détruire l'objet crayon }
3
FBrush.Free; { détruire l'objet pinceau }
inherited Destroy; { appeler toujours le destructeur hérité }
end;
__fastcall TSampleShape::~TSampleShape()
{
delete FPen; // détruit l'objet crayon
delete FBrush; // détruit l'objet pinceau
}

1233
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.1.11 Redéfinition du constructeur et du destructeur


Pour changer les valeurs par défaut des propriétés et initialiser les classes appartenant à votre composant, vous devez redéfinir
le constructeur et le destructeur reçus en héritage. Dans les deux cas, n'oubliez pas d'appeler la méthode reçue en héritage.

Modification des valeurs par défaut des propriétés


La taille par défaut d'un contrôle graphique étant réduite, vous pouvez modifier sa largeur et sa hauteur dans le constructeur. La
modification des valeurs par défaut des propriétés est abordée plus en détail dans Modification d'un composant existant ( see
page 1382).

Dans notre exemple, le contrôle forme définit sa taille par un carré de 65 pixels de côté.
1. Ajoutez le constructeur redéfini dans la déclaration de la classe composant :
type
TSampleShape = class(TGraphicControl)
public { constructeurs toujours publics }
constructor Create(AOwner: TComponent); override { ne pas oublier la directive
override }
end;
class PACKAGE TSampleShape : public TGraphicControl
{
public:
virtual __fastcall TSampleShape(TComponent* Owner);
};
2. Redéclarez les propriétés Height et Width avec leurs nouvelles valeurs par défaut :
type
TSampleShape = class(TGraphicControl)
.
.
.
published
property Height default 65;
property Width default 65;
end;
class PACKAGE TSampleShape : public TGraphicControl
{
.
.
.
__published:
__property Height;
__property Width;
}
3. Ecrivez le nouveau constructeur dans la partie implementation de l'unité :
constructor TSampleShape.Create(AOwner: TComponent);
begin
inherited Create(AOwner); { appeler toujours le constructeur hérité }
Width := 65;
Height := 65;
3 end;
__fastcall TSampleShape::TSampleShape(TComponent* Owner) : TGraphicControl(Owner)
{
Width = 65;
Height = 65;
}

1234
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.1.12 Publication des propriétés héritées


Lorsque vous dérivez un type de composant, vous choisissez parmi les propriétés et les événements déclarés dans la partie
protected de la classe ancêtre ceux que vous voulez rendre disponibles aux utilisateurs du nouveau composant.
TGraphicControl publie toutes les propriétés qui permettent au composant de fonctionner en tant que contrôle, donc les seules
fonctionnalités que vous devez publier sont celles dont vous avez besoin pour répondre aux événements de souris et aux
opérations glisser-déplacer.

La publication des propriétés et des événements reçus en héritage est expliquée dans Publication des propriétés héritées ( see
page 1260) et Rendre visible des événements ( see page 1247). Ces deux processus impliquent la redéclaration du nom des
propriétés dans la partie published de la déclaration de classe.

S'agissant de notre contrôle forme, vous devez publier les trois événements associés à la souris ainsi que les deux propriétés
associées aux opérations glisser-déplacer :
type
TSampleShape = class(TGraphicControl)
published
property DragCursor; { propriétés glisser-déplacer }
property DragMode;
property OnDragDrop; { événements glisser-déplacer }
property OnDragOver;
property OnEndDrag;
property OnMouseDown; { événements de souris }
property OnMouseMove;
property OnMouseUp;
end;
class PACKAGE TSampleShape : public TGraphicControl
{
private:
__published:
__property DragCursor ;
__property DragMode ;
__property OnDragDrop ;
__property OnDragOver ;
__property OnEndDrag ;
__property OnMouseDown ;
__property OnMouseMove ;
__property OnMouseUp ;
};
Le contrôle forme de notre exemple rend les interactions associées à la souris et aux opérations glisser-déplacer accessibles à
l'utilisateur.

3.2.1.1.13 Publication du crayon et du pinceau


Par défaut, un canevas dispose d'un crayon fin et noir et d'un pinceau plein et blanc. Pour permettre aux développeurs de
changer le crayon et le pinceau, vous devez leur fournir des classes pour les manipuler lors de la conception, puis copier les
classes dans le canevas lors des opérations de dessin. Des classes telles qu'un crayon ou un pinceau auxiliaire sont appelées
classes ayant un propriétaire car elles appartiennent au composant qui est responsable de leur création et de leur destruction. 3
La gestion des classes ayant un propriétaire se déroule en quatre étapes :

1. Déclaration des champs de la classe. ( see page 1229)


2. Déclaration des propriétés d'accès. ( see page 1228)
3. Initialisation des classes ayant un propriétaire. ( see page 1233)
4. Définition des propriétés des classes ayant un propriétaire. ( see page 1237)

1235
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.1.14 Adaptation du dessin de la forme


Le contrôle forme standard effectue une tâche supplémentaire que ne fait pas encore le contrôle forme de notre exemple : il
gère les carrés et les cercles ainsi que les rectangles et les ellipses. Pour ce faire, vous devez écrire le code qui trouve le côté le
plus petit et centre l'image.

Voici une méthode Paint parfaitement adaptée aux carrés et aux ellipses :
procedure TSampleShape.Paint;
var
X, Y, W, H, S: Integer;
begin with Canvas do
begin
Pen := FPen; { copier le crayon du composant }
Brush := FBrush; { copier le pinceau du composant }
W := Width; { utiliser la largeur du
composant }
H := Height; { utiliser la hauteur du
composant }
if W < H then S := W else S := H; { enregistrer du plus petit pour les
cercles/carrés }
case FShape of { ajuster la hauteur, la largeur et la
position }
sstRectangle, sstRoundRect, sstEllipse:
begin
X := 0; { l'origine est l'angle supérieur gauche de
ces formes }
Y := 0;
end;
sstSquare, sstRoundSquare, sstCircle:
begin
X := (W - S) div 2; { centrer horizontalement... }
Y := (H - S) div 2; { ...puis verticalement }
W := S; { utiliser la dimension la plus petite pour
la largeur... }
H := S; { ...et pour la hauteur }
end;
end;
case FShape of
sstRectangle, sstSquare:
Rectangle(X, Y, X + W, Y + H); { dessiner les rectangles et les
carrés }
sstRoundRect, sstRoundSquare:
RoundRect(X, Y, X + W, Y + H, S div 4, S div 4); { dessiner des formes
arrondies }
sstCircle, sstEllipse:
Ellipse(X, Y, X + W, Y + H); { dessiner les formes
arrondies }
end;
end;
end;
void __fastcall TSampleShape::Paint(void)
{
3 int X,Y,W,H,S;
Canvas->Pen = FPen; // copie le crayon du composant
Canvas->Brush = FBrush; // copie le pinceau du composant
W=Width; // utilise la largeur du composant
H=Height; // utilise la hauteur du composant
X=Y=0; // sauvegarde du plus petit pour les
cercles/carrés
if( W<H )
S=W;
else
S=H;

1236
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

switch(FShape) // ajuste la hauteur, la largeur et la position


{
case sstRectangle:
case sstRoundRect:
case sstEllipse:
Y=X=0; // l'origine est l'angle supérieur gauche de ces
formes
break;
case sstSquare:
case sstRoundSquare:
case sstCircle:
X= (W-S)/2; // centre horizontalement
Y= (H-S)/2; // puis verticalement
break;
default:
break;
}
switch(FShape)
{
case sstSquare: // dessine les rectangles et les carrés
W=H=S; // utilise la dimension la plus petite pour la
largeur et la hauteur
case sstRectangle:
Canvas->Rectangle(X,Y,X+W,Y+H);
break;
case sstRoundSquare: // dessine les rectangles et les carrés arrondis
W=H=S;
case sstRoundRect:
Canvas->RoundRect(X,Y,X+W,Y+H,S/4,S/4);
break;
case sstCircle: // dessine les cercles et les ellipses
W=H=S;
case sstEllipse:
Canvas->Ellipse(X,Y,X+W,Y+H);
break;
default:
break;
}
}

3.2.1.1.15 Définition des propriétés des classes ayant un propriétaire


L'une des dernières étapes de la gestion des classes crayon et pinceau consiste à provoquer un nouveau dessin du contrôle
forme si le crayon ou le pinceau est modifié. Comme les classes crayon et pinceau disposent toutes les deux d'un événement
OnChange, vous pouvez créer une méthode dans le contrôle forme et faire pointer les deux événements OnChange sur cette
méthode.

Ajoutez la méthode suivante au contrôle forme et effectuez la mise à jour du constructeur du composant pour affecter aux
événements du crayon et du pinceau cette nouvelle méthode :
type
TSampleShape = class(TGraphicControl)
published
procedure StyleChanged(Sender: TObject);
end; 3
.
.
.
implementation
.
.
.
constructor TSampleShape.Create(AOwner: TComponent);
begin

1237
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

inherited Create(AOwner); { appeler toujours le constructeur hérité }


Width := 65;
Height := 65;
FPen := TPen.Create; { construire le crayon }
FPen.OnChange := StyleChanged; { affecter la méthode à l'événement
OnChange }
FBrush := TBrush.Create; { construire le pinceau }
FBrush.OnChange := StyleChanged; { affecter la méthode à l'événement
OnChange }
end;
procedure TSampleShape.StyleChanged(Sender: TObject);
begin
Invalidate; { effacer et redessiner le composant }
end;
// fichier en-tête
class PACKAGE TSampleShape : public TGraphicControl
{
.
.
.
public:
void __fastcall StyleChanged(TObject* Owner);
.
.
.
};
// fichier d'implémentation
__fastcall TSampleShape::TSampleShape(TComponent* Owner) : TGraphicControl(Owner)
{
Width = 65;
Height = 65;
FBrush = new TBrush();
FBrush->OnChange = StyleChanged;
FPen = new TPen();
FPen->OnChange = StyleChanged;
}
//inclut également la méthode StyleChanged dans le fichier d'implémentation
void __fastcall TSampleShape::StyleChanged( TObject* Sender)
{
Invalidate(); // redessine le composant
}
Ces modifications faites, le composant se redessine pour refléter tout changement du crayon ou du pinceau.

3.2.1.1.16 Ecriture de la méthode d'implémentation


Lorsque la partie read ou write d'une définition de propriété utilise une méthode plutôt qu'un accès direct aux données stockées
de la propriété, vous devez implémenter ces méthodes.

Ajoutez l'implémentation de la méthode SetShape à la partie implementation de l'unité :


procedure TSampleShape.SetShape(Value: TSampleShapeType);
begin
if FShape <> Value then { ignore s'il n'y a pas eu de changement }
3 begin
FShape := Value; { stocker la nouvelle valeur }
Invalidate; { forcer le dessin avec la nouvelle forme }
end;
end;
void __fastcall TSampleShape::SetShape(TSampleShapeType Value)
{
if (FShape != Value) // ignore s'il n'y a pas eu de changement
{
FShape = Value; // stocke la nouvelle valeur
Invalidate(); // force le dessin avec la nouvelle forme

1238
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

}
}

3.2.1.2 Création d'événements


Rubriques
Nom Description
Création d'événements : Vue globale ( see page 1242) Un événement est un lien entre une occurrence du système (une action de
l'utilisateur ou un changement de focalisation, par exemple) et le fragment de
code qui assure effectivement la réponse. Le code de réponse est un
gestionnaire d'événement, dont l'écriture est presque toujours du ressort du
développeur de l'application. Grâce aux événements, les développeurs peuvent
personnaliser le comportement des composants sans avoir besoin de modifier
les classes elles-mêmes. Cela s'appelle la délégation.
Les événements associés aux actions utilisateur les plus usuelles (par exemple,
les actions de la souris) sont intégrés dans les composants standard, mais vous
pouvez... suite ( see page 1242)
Qu'est-ce qu'un événement ? ( see page 1242) Un événement est un mécanisme qui établit un lien entre une occurrence et une
partie de code. Plus précisément, un événement est un pointeur de méthode qui
pointe sur une méthode dans une instance de classe spécifique.
Du point de vue du développeur d'applications, l'événement est simplement un
nom relié à une occurrence du système, comme OnClick, auquel du code peut
être attaché. Par exemple, un bouton-poussoir appelé Button1 dispose d'une
méthode OnClick. Par défaut, lorsque vous attribuez une valeur à l'événement
OnClick, le concepteur de fiche génère l'événement appelé Button1Click dans la
fiche contenant le bouton... suite ( see page 1242)
Les événements sont des closures (C++) ( see page 1242) Les closures sont utilisés pour implémenter les événements. Un closure est un
type particulier de pointeur qui pointe sur une méthode précise située dans une
instance de classe. En tant qu'auteur de composant, vous pouvez voir les
closures comme des marques de réservation. Après la détection d'un événement
par votre code, vous appelez la méthode (si elle existe) définie par l'utilisateur
pour gérer cet événement.
Les closures assurent la maintenance d'un pointeur caché sur une instance de
classe. Quand l'utilisateur associe un gestionnaire à un événement du
composant, l'association ne s'effectue pas seulement avec une méthode ayant
un nom particulier,... suite ( see page 1242)
Les événements sont des pointeurs de méthodes ( see page 1243) Delphi utilise les pointeurs de méthodes pour implémenter les événements. Un
pointeur de méthode est un type particulier de pointeur qui pointe sur une
méthode précise située dans une instance de classe. En tant qu'auteur de
composant, vous pouvez voir les pointeurs de méthodes comme des marques de
réservation. Après la détection d'un événement par votre code, vous appelez la
méthode (si elle existe) définie par l'utilisateur pour gérer cet événement.
Les pointeurs de méthodes fonctionnent comme les autres types procéduraux,
mais ils maintiennent un pointeur caché sur une instance de classe. Quand le
développeur d'applications associe un gestionnaire à... suite ( see page 1243)
Appel du gestionnaire d'événement de clic ( see page 1243) Tous les contrôles, par exemple, héritent d'une méthode dynamique appelée
Click pour la gestion des événements de clic avec la souris :
Les événements sont des propriétés ( see page 1243) Ces composants utilisent les propriétés pour implémenter les événements. Mais,
contrairement à la plupart des propriétés, les propriétés événement ne font pas
appel à des méthodes pour implémenter leurs parties read et write. Elles utilisent
plutôt un champ de classe privé de même type que la propriété.
Par convention, le nom de la donnée membre est le même que celui de la
propriété précédé de la lettre F. Par exemple, le pointeur de la méthode OnClick
est stocké dans une donnée membre intitulée FOnClick de type TNotifyEvent ; la
déclaration de la propriété de l'événement OnClick ressemble à ceci :... suite (
see page 1243)
Les types d'événements sont des types de pointeurs de méthodes ( see page Comme un événement est un pointeur sur un gestionnaire d'événement, le type
1244) d'une propriété événement correspond nécessairement à un pointeur de
méthode. De même, tout code utilisé comme gestionnaire d'événements doit être
3
de type méthode de classe.
Toutes les méthodes gestionnaire d'événement sont des procédures. Pour être
compatible avec un événement d'un type particulier, une méthode gestionnaire
d'événements doit avoir le même nombre de paramètres, les paramètres étant
de même type et transmis dans le même ordre.
Delphi définit des types de méthode pour tous les événements standard. Lorsque
vous créez vos propres événements, vous pouvez utiliser un type existant... suite
( see page 1244)

1239
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Les types gestionnaire d'événement sont des procédures ( see page 1244) Bien que le compilateur vous permet de déclarer des types pointeur de méthode
qui sont des fonctions, vous ne devrez jamais le faire pour la gestion
d'événements. Comme une fonction vide renvoie un résultat non défini, un
gestionnaire d'événement vide qui était une fonction ne pourra pas toujours être
correct. Pour cette raison, tous vos événements et leurs gestionnaires
d'événements associés doivent être des procédures.
Bien qu'un gestionnaire d'événement ne puisse pas être une fonction, vous
pouvez toujours obtenir les informations à partir du code du développeur de
l'application en utilisant les paramètres var. Lorsque vous effectuerez ceci,
vérifiez... suite ( see page 1244)
Le type de renvoi des gestionnaires d'événements est void (C++) ( see page Le type de renvoi des gestionnaires d'événements doit être void. Mais cela ne
1245) vous empêche pas de récupérer des informations en provenance du code de
l'utilisateur : il suffit de passer les arguments par référence. Si vous procédez
ainsi, n'oubliez pas d'attribuer à l'argument une valeur correcte avant d'appeler le
gestionnaire, de façon à ne pas rendre obligatoire la modification de la valeur par
le code de l'utilisateur.
L'événement frappe de touche de type TKeyPressEvent est un exemple de
transmission d'arguments à un gestionnaire d'événements, par référence.
TKeyPressEvent définit deux arguments : l'un indique l'objet ayant généré
l'événement et l'autre... suite ( see page 1245)
Les types d'événements sont des types closure (C++) ( see page 1245) Comme un événement est un pointeur sur un gestionnaire d'événement, le type
d'une propriété événement correspond nécessairement à un type closure. De
même, tout code utilisé comme gestionnaire d'événements doit être de type
méthode de classe.
Pour être compatible avec un événement d'un type particulier, une méthode
gestionnaire d'événements doit avoir le même nombre de paramètres, les
paramètres étant de même type et transmis dans le même ordre.
C++Builder définit des closures pour tous ses événements standard. Lorsque
vous créez vos propres événements, vous pouvez utiliser un closure existant s'il
est approprié ou en définir un vous-même.
Les gestionnaires d'événements sont facultatifs ( see page 1245) Lorsque vous créez des composants, n'oubliez pas que les développeurs qui les
utilisent ne vont pas forcément leur associer des gestionnaires. Cela signifie que
l'exécution de vos composants ne doit pas échouer ni générer d'erreur parce que
l'utilisateur n'a pas associé un gestionnaire à un événement. Le mécanisme pour
appeler un gestionnaire et gérer les événements, alors que l'utilisateur n'a pas
associé de gestionnaire, est décrit dans Appel de l'événement ( see page
1249).
Des événements se produisent en permanence dans une application GUI. Le
simple fait de déplacer le pointeur de la souris sur un composant visuel envoie de
nombreux messages de... suite ( see page 1245)
Implémentation des événements standard ( see page 1246) Les contrôles fournis avec la bibliothèque de composants héritent des
événements correspondant aux occurrences les plus courantes. Ces
événements sont appelés événements standard. Bien que tous ces événements
soient intégrés aux contrôles standard, ils sont souvent déclarés protected, pour
que les développeurs ne puissent pas leur associer de gestionnaire. Lorsque
vous créez un contrôle, vous pouvez choisir de rendre visibles certains
événements aux utilisateurs de votre contrôle.
Les trois points suivants sont à prendre en compte pour incorporer des
événements standard dans vos contrôles :

• Identification des événements standard ( see page


1246)
• Rendre visibles des événements ( see page 1247)
• Changement de la gestion des événements ( see page
1247)... suite ( see page 1246)
Identification des événements standard ( see page 1246) Il existe deux catégories d'événements standard : ceux définis pour tous les
contrôles et ceux définis uniquement pour les contrôles fenêtrés standard.
Rendre visibles des événements ( see page 1247) Les événements standard de TControl et TWinControl sont déclarés protected,
3 de même que les méthodes correspondantes. Si vous héritez de l'une de ces
classes abstraites et voulez rendre leurs événements accessibles à l'exécution
ou pendant la conception, vous devez redéclarer les événements soit public, soit
published.
La redéclaration d'une propriété sans spécifier d'implémentation conserve les
mêmes méthodes d'implémentation en ne modifiant que leur niveau de
protection. Vous pouvez donc prendre en compte un événement défini dans
TControl mais non visible, et le rendre visible en le déclarant public ou published.

1240
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Changement de la gestion des événements standard ( see page 1247) Pour modifier la façon dont votre composant répond à un certain type
d'événement, vous pouvez être tenté d'écrire un fragment de code pour
l'associer à l'événement en question. C'est précisément ce que ferait le
développeur d'applications. Mais lorsque vous créez un composant, vous devez
faire en sorte que l'événement reste disponible pour les développeurs qui vont
utiliser le composant.
C'est ce qui justifie les méthodes protégées de l'implémentation associées à
chaque événement standard. En redéfinissant la méthode d'implémentation,
vous pouvez modifier la gestion interne de l'événement et en appelant la
méthode reçue en héritage, vous préservez la gestion standard, y... suite ( see
page 1247)
Définition de vos propres événements ( see page 1247) Il est relativement rare de définir des événements entièrement nouveaux.
Toutefois, il peut arriver qu'un comportement complètement différent soit introduit
par un composant et il faut alors lui définir un événement.
Voici les étapes qui interviennent dans la définition d'un événement :

• Déclenchement de l'événement ( see page 1247)


• Définition du type de gestionnaire ( see page 1248)
• Déclaration de l'événement ( see page 1249)
• Appel de l'événement ( see page 1249)
Déclenchement de l'événement ( see page 1247) Vous avez besoin de savoir ce qui a déclenché l'événement. Pour certains
événements, la réponse est évidente. Par exemple, un événement associé à
l'enfoncement du bouton de souris se produit lorsque l'utilisateur clique avec le
bouton gauche de la souris provoquant l'envoi par Windows d'un message
WM_LBUTTONDOWN à l'application. La réception de ce message provoque
l'appel de la méthode MouseDown d'un composant qui à son tour appelle le code
que l'utilisateur a associé à l'événement OnMouseDown.
Néanmoins, certains événements sont liés de façon moins évidente à des
occurrences externes moins spécifiques. Par exemple, une barre de défilement
dispose d'un... suite ( see page 1247)
Deux sortes d'événements ( see page 1248) Il existe deux types d'occurrence pour lesquels vous pouvez être amené à fournir
des événements : les interactions utilisateur et les modifications d'état. Les
événements de type interaction utilisateur sont pratiquement toujours déclenchés
par un message issu de Windows indiquant que l'utilisateur a agi sur votre
composant d'une façon qui peut nécessiter une réponse de votre part. Les
événements de modification d'état peuvent aussi être le fait de messages issus
de Windows (par exemple, des changements de focalisation ou d'activation).
Cependant, ils peuvent également survenir à la suite d'une modification de
propriété ou de l'exécution d'une autre partie de code.
Vous... suite ( see page 1248)
Définition du type de gestionnaire ( see page 1248) Après avoir détecté que l'un de vos événements s'est produit, vous devez définir
la façon de le gérer. Cela implique que vous devez déterminer le type du
gestionnaire d'événement. Dans la plupart des cas, les gestionnaires
d'événements que vous définissez vous-même seront des notifications simples
ou spécifiques à des événements particuliers. Il est également possible de
récupérer de l'information en provenance du gestionnaire.
Déclaration de l'événement ( see page 1249) Une fois déterminé le type de votre gestionnaire d'événement, vous pouvez
déclarer le pointeur de méthode et la propriété pour l'événement. N'oubliez pas
d'attribuer un nom à l'événement qui soit à la fois significatif et descriptif pour que
l'utilisateur puisse comprendre son rôle. Dans la mesure du possible, choisissez
des noms de propriétés qui ressemblent à ceux de composants déjà définis.
Appel de l'événement ( see page 1249) Il est préférable de centraliser tous les appels à un événement. Autrement dit,
créez une méthode virtuelle dans votre composant qui appelle le gestionnaire
d'événement de l'application (s'il a été défini) et qui fournit une gestion par défaut.
Le fait de rassembler tous les appels à un événement en un seul endroit vous
permet d'être sûr qu'un programmeur, qui dérive un nouveau composant à partir
du vôtre, pourra personnaliser la gestion de l'événement en redéfinissant cette
méthode sans avoir à parcourir votre code pour repérer les endroits où
l'événement est appelé. 3
Deux autres considérations sont à prendre en compte concernant... suite ( see
page 1249)
Les gestionnaires vides doivent être valides ( see page 1249) Vous ne devez jamais créer une situation dans laquelle un gestionnaire
d'événement vide provoque une erreur, ou dans laquelle le bon fonctionnement
d'un composant dépend d'une réponse spécifique provenant du code de gestion
d'un événement dans l'application.

1241
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Les utilisateurs peuvent redéfinir la gestion par défaut ( see page 1249) Pour certains types d'événements, les développeurs peuvent vouloir remplacer la
gestion par défaut ou même supprimer l'ensemble des réponses. Pour permettre
cela, vous devez transmettre au gestionnaire un argument par référence et
vérifier si le gestionnaire renvoie une certaine valeur.
Cela reste dans la lignée de l'affirmation qu'un gestionnaire vide doit produire le
même effet qu'un gestionnaire absent : Puisqu'un gestionnaire vide ne modifie en
rien la valeur des arguments passés par référence, la gestion par défaut se
déroule toujours après l'appel du gestionnaire vide.

3.2.1.2.1 Création d'événements : Vue globale


Un événement est un lien entre une occurrence du système (une action de l'utilisateur ou un changement de focalisation, par
exemple) et le fragment de code qui assure effectivement la réponse. Le code de réponse est un gestionnaire d'événement, dont
l'écriture est presque toujours du ressort du développeur de l'application. Grâce aux événements, les développeurs peuvent
personnaliser le comportement des composants sans avoir besoin de modifier les classes elles-mêmes. Cela s'appelle la
délégation.

Les événements associés aux actions utilisateur les plus usuelles (par exemple, les actions de la souris) sont intégrés dans les
composants standard, mais vous pouvez aussi définir de nouveaux événements. Pour être capable de créer des événements
dans un composant, vous devez avoir compris ce qui suit :

• Qu'est-ce qu'un événement ? ( see page 1242)


• Implémentation des événements standard ( see page 1246)
• Définition de vos propres événements ( see page 1247)
Les événements étant implémentés en tant que propriétés, il vaut mieux avoir bien compris la Création des propriétés ( see
page 1258) avant de créer ou de modifier les événements d'un composant.

3.2.1.2.2 Qu'est-ce qu'un événement ?


Un événement est un mécanisme qui établit un lien entre une occurrence et une partie de code. Plus précisément, un
événement est un pointeur de méthode qui pointe sur une méthode dans une instance de classe spécifique.

Du point de vue du développeur d'applications, l'événement est simplement un nom relié à une occurrence du système, comme
OnClick, auquel du code peut être attaché. Par exemple, un bouton-poussoir appelé Button1 dispose d'une méthode OnClick.
Par défaut, lorsque vous attribuez une valeur à l'événement OnClick, le concepteur de fiche génère l'événement appelé
Button1Click dans la fiche contenant le bouton et l'associe à l'événement OnClick. Lorsqu'un événement clic de souris se produit
sur le bouton, ce dernier appelle la méthode associée à OnClick qui est pour notre exemple Button1Click.

Pour écrire un événement, vous devez comprendre ceci :

• Les événements sont des pointeurs de méthodes ( see page 1243).


• Les événements sont des propriétés ( see page 1243).
3 • Les types d'événements sont des types de pointeurs de méthodes ( see page 1244).
• Les types gestionnaire d'événement sont des procédures ( see page 1244).
• Les gestionnaires d'événements sont facultatifs ( see page 1245).

3.2.1.2.3 Les événements sont des closures (C++)


Les closures sont utilisés pour implémenter les événements. Un closure est un type particulier de pointeur qui pointe sur une

1242
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

méthode précise située dans une instance de classe. En tant qu'auteur de composant, vous pouvez voir les closures comme des
marques de réservation. Après la détection d'un événement par votre code, vous appelez la méthode (si elle existe) définie par
l'utilisateur pour gérer cet événement.

Les closures assurent la maintenance d'un pointeur caché sur une instance de classe. Quand l'utilisateur associe un
gestionnaire à un événement du composant, l'association ne s'effectue pas seulement avec une méthode ayant un nom
particulier, mais avec une méthode spécifique d'une instance de classe spécifique. Même si ce n'est pas obligatoire, cette
instance correspond généralement à la fiche contenant le composant.

3.2.1.2.4 Les événements sont des pointeurs de méthodes


Delphi utilise les pointeurs de méthodes pour implémenter les événements. Un pointeur de méthode est un type particulier de
pointeur qui pointe sur une méthode précise située dans une instance de classe. En tant qu'auteur de composant, vous pouvez
voir les pointeurs de méthodes comme des marques de réservation. Après la détection d'un événement par votre code, vous
appelez la méthode (si elle existe) définie par l'utilisateur pour gérer cet événement.

Les pointeurs de méthodes fonctionnent comme les autres types procéduraux, mais ils maintiennent un pointeur caché sur une
instance de classe. Quand le développeur d'applications associe un gestionnaire à un événement du composant, l'association
ne s'effectue pas seulement avec une méthode ayant un nom particulier, mais avec une méthode d'une instance de classe
particulière. Sans être obligatoire, cette instance correspond généralement à la fiche contenant le composant.

3.2.1.2.5 Appel du gestionnaire d'événement de clic


Tous les contrôles, par exemple, héritent d'une méthode dynamique appelée Click pour la gestion des événements de clic avec
la souris :
procedure Click; dynamic;
virtual void __fastcall Click(void);
L'implémentation de Click appelle le gestionnaire utilisateur des événements liés aux clics de la souris, s'il existe. Si l'utilisateur a
affecté un gestionnaire à l'événement OnClick d'un contrôle, le fait de cliquer sur ce dernier génère l'appel de la méthode. Si
aucun gestionnaire n'est affecté, rien ne se produit.

3.2.1.2.6 Les événements sont des propriétés


Ces composants utilisent les propriétés pour implémenter les événements. Mais, contrairement à la plupart des propriétés, les
propriétés événement ne font pas appel à des méthodes pour implémenter leurs parties read et write. Elles utilisent plutôt un
champ de classe privé de même type que la propriété.

Par convention, le nom de la donnée membre est le même que celui de la propriété précédé de la lettre F. Par exemple, le
pointeur de la méthode OnClick est stocké dans une donnée membre intitulée FOnClick de type TNotifyEvent ; la déclaration de
la propriété de l'événement OnClick ressemble à ceci :
type
TControl = class(TComponent)
private
FOnClick: TNotifyEvent; { déclarer un champ pour contenir le pointeur de 3
méthode }
.
.
.
protected
property OnClick: TNotifyEvent read FOnClick write FOnClick;
end;
class PACKAGE TControl : public TComponent
{

1243
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

private:
TNotifyEvent FOnClick;
.
.
.
protected:
__property TnotifyEvent OnClick = {read=FOnClick, write=FOnClick};
.
.
.
};
Pour plus d'informations sur TNotifyEvent et sur les autres types d'événements, voir la prochaine section Les types
d'événements sont des types de pointeurs de méthodes ( see page 1244).

Comme pour toute autre propriété, vous pouvez définir ou modifier la valeur d'un événement au moment de l'exécution.
L'avantage principal des événements implémentés sous la forme de propriétés est que l'utilisateur de composant peut lui
associer un gestionnaire au moment de la conception à l'aide de l'inspecteur d'objets.

3.2.1.2.7 Les types d'événements sont des types de pointeurs de méthodes


Comme un événement est un pointeur sur un gestionnaire d'événement, le type d'une propriété événement correspond
nécessairement à un pointeur de méthode. De même, tout code utilisé comme gestionnaire d'événements doit être de type
méthode de classe.

Toutes les méthodes gestionnaire d'événement sont des procédures. Pour être compatible avec un événement d'un type
particulier, une méthode gestionnaire d'événements doit avoir le même nombre de paramètres, les paramètres étant de même
type et transmis dans le même ordre.

Delphi définit des types de méthode pour tous les événements standard. Lorsque vous créez vos propres événements, vous
pouvez utiliser un type existant s'il est approprié ou définir votre propre type.

3.2.1.2.8 Les types gestionnaire d'événement sont des procédures


Bien que le compilateur vous permet de déclarer des types pointeur de méthode qui sont des fonctions, vous ne devrez jamais
le faire pour la gestion d'événements. Comme une fonction vide renvoie un résultat non défini, un gestionnaire d'événement vide
qui était une fonction ne pourra pas toujours être correct. Pour cette raison, tous vos événements et leurs gestionnaires
d'événements associés doivent être des procédures.

Bien qu'un gestionnaire d'événement ne puisse pas être une fonction, vous pouvez toujours obtenir les informations à partir du
code du développeur de l'application en utilisant les paramètres var. Lorsque vous effectuerez ceci, vérifiez que vous affectez
une valeur correcte au paramètre avant d'appeler le gestionnaire afin de ne pas rendre obligatoire la modification de la valeur
par le code de l'utilisateur.

Un exemple de transmission des paramètres var à un gestionnaire d'événement est fourni par l'événement OnKeyPress, de
type TKeyPressEvent. TKeyPressEvent définit deux paramètres, l'un indiquant l'objet ayant généré l'événement et l'autre la
touche enfoncée :
3 type
TKeyPressEvent = procedure(Sender: TObject; var Key: Char) of object;
Normalement, le paramètre Key contient le caractère enfoncé par l'utilisateur. Toutefois dans certaines circonstances,
l'utilisateur de composant peut souhaiter changer ce caractère. Par exemple, pour forcer tous les caractères en majuscules dans
un éditeur. Dans un cas comme celui-là, l'utilisateur doit définir le gestionnaire suivant pour gérer les frappes de touche :
procedure TForm1.Edit1KeyPressed(Sender: TObject; var Key: Char);
begin
Key := UpCase(Key);

1244
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

end;
Vous pouvez également utiliser les paramètres var pour permettre à l'utilisateur de redéfinir la gestion par défaut.

3.2.1.2.9 Le type de renvoi des gestionnaires d'événements est void (C++)


Le type de renvoi des gestionnaires d'événements doit être void. Mais cela ne vous empêche pas de récupérer des informations
en provenance du code de l'utilisateur : il suffit de passer les arguments par référence. Si vous procédez ainsi, n'oubliez pas
d'attribuer à l'argument une valeur correcte avant d'appeler le gestionnaire, de façon à ne pas rendre obligatoire la modification
de la valeur par le code de l'utilisateur.

L'événement frappe de touche de type TKeyPressEvent est un exemple de transmission d'arguments à un gestionnaire
d'événements, par référence. TKeyPressEvent définit deux arguments : l'un indique l'objet ayant généré l'événement et l'autre
la touche enfoncée :
typedef void __fastcall (__closure *TKeyPressEvent)(TObject *Sender, Char &Key);
Normalement, le paramètre Key contient le caractère enfoncé par l'utilisateur. Toutefois, dans certaines circonstances,
l'utilisateur de composants peut souhaiter changer ce caractère. Par exemple, ce peut être pour forcer tous les caractères en
majuscule dans un éditeur. Dans un cas comme celui-là, l'utilisateur doit définir le gestionnaire suivant pour gérer les frappes de
touches :
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, Char &Key)
{
Key = UpCase(Key);
}
Vous pouvez également utiliser des arguments passés par référence pour permettre à l'utilisateur de redéfinir la gestion par
défaut.

3.2.1.2.10 Les types d'événements sont des types closure (C++)


Comme un événement est un pointeur sur un gestionnaire d'événement, le type d'une propriété événement correspond
nécessairement à un type closure. De même, tout code utilisé comme gestionnaire d'événements doit être de type méthode de
classe.

Pour être compatible avec un événement d'un type particulier, une méthode gestionnaire d'événements doit avoir le même
nombre de paramètres, les paramètres étant de même type et transmis dans le même ordre.

C++Builder définit des closures pour tous ses événements standard. Lorsque vous créez vos propres événements, vous pouvez
utiliser un closure existant s'il est approprié ou en définir un vous-même.

3.2.1.2.11 Les gestionnaires d'événements sont facultatifs


Lorsque vous créez des composants, n'oubliez pas que les développeurs qui les utilisent ne vont pas forcément leur associer
des gestionnaires. Cela signifie que l'exécution de vos composants ne doit pas échouer ni générer d'erreur parce que l'utilisateur
n'a pas associé un gestionnaire à un événement. Le mécanisme pour appeler un gestionnaire et gérer les événements, alors
que l'utilisateur n'a pas associé de gestionnaire, est décrit dans Appel de l'événement ( see page 1249). 3
Des événements se produisent en permanence dans une application GUI. Le simple fait de déplacer le pointeur de la souris sur
un composant visuel envoie de nombreux messages de déplacement de la souris que le composant traduit en événements
OnMouseMove. Dans la plupart des cas, les développeurs ne veulent pas gérer les événements déplacement de souris et il ne
faut pas que cela pose un problème. Aussi, les composants que vous créez doivent posséder des gestionnaires pour ces
événements.

Mais surtout, les développeurs d'applications peuvent écrire le code qu'ils veulent dans un gestionnaire d'événement. Les

1245
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

gestionnaires d'événements des composants de la bibliothèque de classes sont écrits de façon à minimiser le risque de
génération d'erreurs. Evidemment, vous ne pouvez pas empêcher les erreurs de logique dans le code de l'application, mais vous
pouvez vous assurer que les structures de données sont initialisées avant que les événements ne soient appelés, de sorte que
les développeurs ne tentent pas d'accéder à des données incorrectes.

3.2.1.2.12 Implémentation des événements standard


Les contrôles fournis avec la bibliothèque de composants héritent des événements correspondant aux occurrences les plus
courantes. Ces événements sont appelés événements standard. Bien que tous ces événements soient intégrés aux contrôles
standard, ils sont souvent déclarés protected, pour que les développeurs ne puissent pas leur associer de gestionnaire.
Lorsque vous créez un contrôle, vous pouvez choisir de rendre visibles certains événements aux utilisateurs de votre contrôle.

Les trois points suivants sont à prendre en compte pour incorporer des événements standard dans vos contrôles :

• Identification des événements standard ( see page 1246)


• Rendre visibles des événements ( see page 1247)
• Changement de la gestion des événements standard ( see page 1247)

3.2.1.2.13 Identification des événements standard


Il existe deux catégories d'événements standard : ceux définis pour tous les contrôles et ceux définis uniquement pour les
contrôles fenêtrés standard.

Evénements standard pour tous les contrôles


Les événements de base sont définis dans la classe TControl. Tous les contrôles, qu'ils soient fenêtrés, graphiques ou
personnalisés, héritent de ces événements. Les événements suivants sont disponibles pour l'ensemble des contrôles :

• OnClick
• OnDblClick
• OnDragDrop
• OnDragOver
• OnEndDrag
• OnMouseMove
• OnMouseDown
• OnMouseUp
Les événements standard disposent de méthodes virtuelles protégées, déclarées dans TControl, dont les noms correspondent
aux noms des événements. Par exemple, les événements OnClick appellent une méthode nommée Click, et les événements
OnEndDrag appellent une méthode nommée DoEndDrag.
Evénements standard pour les contrôles standard
Outre les événements communs à tous les contrôles, les contrôles fenêtrés standard (ceux descendant de TWinControl)
3 disposent des événements suivants :

• OnEnter
• OnKeyPress
• OnKeyDown
• OnKeyUp
• OnExit
Comme les événements standard de TControl, les événements des contrôles fenêtrés disposent de méthodes correspondantes.

1246
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Les événements de touches standard présentés ci-dessus répondent à toutes les frappes de touches normales.
Remarque: Pour répondre aux frappes de touches spéciales (comme la touche Alt
), vous devez répondre au message WM_GETDLGCODE ou CM_WANTSPECIALKEYS de Windows. Voir Gestion des
messages et des notifications système ( see page 1320) pour plus d'informations sur l'écriture de gestionnaires de
messages.

3.2.1.2.14 Rendre visibles des événements


Les événements standard de TControl et TWinControl sont déclarés protected, de même que les méthodes correspondantes. Si
vous héritez de l'une de ces classes abstraites et voulez rendre leurs événements accessibles à l'exécution ou pendant la
conception, vous devez redéclarer les événements soit public, soit published.

La redéclaration d'une propriété sans spécifier d'implémentation conserve les mêmes méthodes d'implémentation en ne
modifiant que leur niveau de protection. Vous pouvez donc prendre en compte un événement défini dans TControl mais non
visible, et le rendre visible en le déclarant public ou published.

3.2.1.2.15 Changement de la gestion des événements standard


Pour modifier la façon dont votre composant répond à un certain type d'événement, vous pouvez être tenté d'écrire un fragment
de code pour l'associer à l'événement en question. C'est précisément ce que ferait le développeur d'applications. Mais lorsque
vous créez un composant, vous devez faire en sorte que l'événement reste disponible pour les développeurs qui vont utiliser le
composant.

C'est ce qui justifie les méthodes protégées de l'implémentation associées à chaque événement standard. En redéfinissant la
méthode d'implémentation, vous pouvez modifier la gestion interne de l'événement et en appelant la méthode reçue en héritage,
vous préservez la gestion standard, y compris la gestion de l'événement par le code du développeur d'applications.

L'ordre dans lequel vous appelez les méthodes est significatif. En règle générale, vous appelez d'abord la méthode héritée pour
que le gestionnaire d'événement du développeur d'applications s'exécute avant vos modifications (et parfois, empêche
l'exécution de vos modifications). Toutefois, dans certaines situations, vous voulez exécuter votre code avant d'appeler la
méthode héritée. Par exemple, si le code reçu en héritage dépend d'une façon ou d'une autre de l'état de composant et si votre
code agit sur cet état, vous devez d'abord effectuer ces changements d'état avant d'autoriser le code de l'utilisateur à y répondre.

3.2.1.2.16 Définition de vos propres événements


Il est relativement rare de définir des événements entièrement nouveaux. Toutefois, il peut arriver qu'un comportement
complètement différent soit introduit par un composant et il faut alors lui définir un événement.

Voici les étapes qui interviennent dans la définition d'un événement :

• Déclenchement de l'événement ( see page 1247)


• Définition du type de gestionnaire ( see page 1248)
• Déclaration de l'événement ( see page 1249)
• Appel de l'événement ( see page 1249) 3

3.2.1.2.17 Déclenchement de l'événement


Vous avez besoin de savoir ce qui a déclenché l'événement. Pour certains événements, la réponse est évidente. Par exemple,
un événement associé à l'enfoncement du bouton de souris se produit lorsque l'utilisateur clique avec le bouton gauche de la
souris provoquant l'envoi par Windows d'un message WM_LBUTTONDOWN à l'application. La réception de ce message
provoque l'appel de la méthode MouseDown d'un composant qui à son tour appelle le code que l'utilisateur a associé à

1247
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

l'événement OnMouseDown.

Néanmoins, certains événements sont liés de façon moins évidente à des occurrences externes moins spécifiques. Par
exemple, une barre de défilement dispose d'un événement OnChange qui peut être déclenché par plusieurs occurrences, telles
des frappes de touche, des clics de souris, ou des modifications dans d'autres contrôles. Lorsque vous définissez vos
événements, assurez-vous que les occurrences appellent tous les événements appropriés.

3.2.1.2.18 Deux sortes d'événements


Il existe deux types d'occurrence pour lesquels vous pouvez être amené à fournir des événements : les interactions utilisateur et
les modifications d'état. Les événements de type interaction utilisateur sont pratiquement toujours déclenchés par un message
issu de Windows indiquant que l'utilisateur a agi sur votre composant d'une façon qui peut nécessiter une réponse de votre part.
Les événements de modification d'état peuvent aussi être le fait de messages issus de Windows (par exemple, des
changements de focalisation ou d'activation). Cependant, ils peuvent également survenir à la suite d'une modification de
propriété ou de l'exécution d'une autre partie de code.

Vous disposez d'un contrôle total sur le déclenchement des événements que vous avez vous-même définis. Définissez les
événements avec soin de sorte que les développeurs soient capables de les comprendre et de les utiliser.

3.2.1.2.19 Définition du type de gestionnaire


Après avoir détecté que l'un de vos événements s'est produit, vous devez définir la façon de le gérer. Cela implique que vous
devez déterminer le type du gestionnaire d'événement. Dans la plupart des cas, les gestionnaires d'événements que vous
définissez vous-même seront des notifications simples ou spécifiques à des événements particuliers. Il est également possible
de récupérer de l'information en provenance du gestionnaire.

Notifications simples
Un événement de type notification ne fait qu'indiquer qu'un événement particulier s'est produit sans fournir aucune information
sur le moment et l'endroit où il s'est produit. Les notifications utilisent le type TNotifyEvent, qui véhiculent un paramètre unique
correspondant à l'émetteur de l'événement. Les seuls éléments "connus" du gestionnaire associé à une notification sont donc le
type d'événement et le composant impliqué. Par exemple, les événements clic de souris sont des notifications. Lorsque vous
écrivez un gestionnaire pour un événement de ce type, vous ne récupérez que deux informations : le fait qu'un clic s'est produit
et le composant impliqué.

Une notification est un processus à sens unique. Il n'existe aucun mécanisme pour renvoyer une information en retour ou pour
inhiber la gestion d'une notification.

Gestionnaires d'événements spécifiques


Dans certains cas, savoir qu'un événement s'est produit et connaître le composant impliqué n'est pas suffisant. Par exemple, si
l'événement correspond à l'enfoncement d'une touche, le gestionnaire voudra savoir quelle est cette touche. Dans un cas
comme celui-là, vous devez disposer d'un gestionnaire qui accepte des paramètres pour ces informations supplémentaires.

Si votre événement a été généré en réponse à un message, les paramètres transmis au gestionnaire d'événement seront
vraisemblablement issus des paramètres du message.
3 Renvoi d'informations à partir du gestionnaire
Comme tous les gestionnaires d'événements sont des procédures, la seule façon de renvoyer des informations à partir d'un
gestionnaire consiste à faire appel à un paramètre var. Vos composants peuvent utiliser les informations ainsi récupérées pour
déterminer le traitement éventuel d'un événement après l'exécution du gestionnaire de l'utilisateur.

Par exemple, tous les événements liés aux touches (OnKeyDown, OnKeyUp et OnKeyPress) transmettent par référence la
valeur de la touche enfoncée dans un paramètre intitulé Key. Le gestionnaire d'événement peut changer Key de façon à donner
l'impression à l'application qu'une touche différente est impliquée dans l'événement. Cela permet par exemple de forcer en

1248
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

majuscules les caractères tapés.

3.2.1.2.20 Déclaration de l'événement


Une fois déterminé le type de votre gestionnaire d'événement, vous pouvez déclarer le pointeur de méthode et la propriété pour
l'événement. N'oubliez pas d'attribuer un nom à l'événement qui soit à la fois significatif et descriptif pour que l'utilisateur puisse
comprendre son rôle. Dans la mesure du possible, choisissez des noms de propriétés qui ressemblent à ceux de composants
déjà définis.

Les noms d'événement débutent par "On"


Dans Delphi, les noms de la plupart des événements commencent par "On". Il s'agit d'une simple convention ; le compilateur
n'impose pas cette restriction. L'inspecteur d'objets détermine qu'une propriété est un événement en examinant le type de la
propriété : toutes les propriétés de type pointeur de méthode sont interprétées comme des événements et apparaissent donc
dans la page Evénements.

Les développeurs s'attendent à trouver les événements dans la liste alphabétique à l'endroit des noms commençant par "On".
Vous risquez d'introduire une certaine confusion en utilisant une autre convention.

Remarque: Exception principale à cette règle : les nombreux événements qui se produisent avant ou après certaines
occurrences commencent par "Before" ou "After".

3.2.1.2.21 Appel de l'événement


Il est préférable de centraliser tous les appels à un événement. Autrement dit, créez une méthode virtuelle dans votre
composant qui appelle le gestionnaire d'événement de l'application (s'il a été défini) et qui fournit une gestion par défaut.

Le fait de rassembler tous les appels à un événement en un seul endroit vous permet d'être sûr qu'un programmeur, qui dérive
un nouveau composant à partir du vôtre, pourra personnaliser la gestion de l'événement en redéfinissant cette méthode sans
avoir à parcourir votre code pour repérer les endroits où l'événement est appelé.

Deux autres considérations sont à prendre en compte concernant l'appel de l'événement :

• Les gestionnaires vides doivent être valides. ( see page 1249)


• Les utilisateurs peuvent redéfinir la gestion par défaut. ( see page 1249)

3.2.1.2.22 Les gestionnaires vides doivent être valides


Vous ne devez jamais créer une situation dans laquelle un gestionnaire d'événement vide provoque une erreur, ou dans laquelle
le bon fonctionnement d'un composant dépend d'une réponse spécifique provenant du code de gestion d'un événement dans
l'application.

3.2.1.2.23 Les utilisateurs peuvent redéfinir la gestion par défaut


Pour certains types d'événements, les développeurs peuvent vouloir remplacer la gestion par défaut ou même supprimer
3
l'ensemble des réponses. Pour permettre cela, vous devez transmettre au gestionnaire un argument par référence et vérifier si le
gestionnaire renvoie une certaine valeur.

Cela reste dans la lignée de l'affirmation qu'un gestionnaire vide doit produire le même effet qu'un gestionnaire absent :
Puisqu'un gestionnaire vide ne modifie en rien la valeur des arguments passés par référence, la gestion par défaut se déroule
toujours après l'appel du gestionnaire vide.

1249
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.3 Création de méthodes


Rubriques
Nom Description
Méthodes abstraites ( see page 1251) Une méthode est parfois déclarée abstract dans un composant Delphi. Dans la
bibliothèque de composants, les méthodes abstraites se produisent
habituellement dans les classes dont les noms commencent par "custom",
comme TCustomGrid. De telles classes sont elles-mêmes abstraites, au sens où
elles ne servent qu'à la dérivation de classes descendantes.
Bien que vous puissiez créer un objet instance d'une classe contenant un
membre abstrait, ce n'est pas recommandé. L'appel du membre abstrait entraîne
une exception EAbstractError.
La directive abstract est utilisée pour indiquer des parties de classes qui doivent
être surfacées et définies dans des composants descendants ; cela... suite (
see page 1251)
Eviter les interdépendances ( see page 1251) Lorsque vous écrivez un composant, vous devez réduire au minimum les
conditions préalables imposées aux développeurs. Dans toute la mesure du
possible, les développeurs doivent pouvoir faire ce qu'ils veulent de votre
composant, et à tout moment. Il existe des situations où vous ne pourrez
répondre à cette exigence mais le but n'en demeure pas moins de s'en
approcher au plus près.
La liste suivante donne quelques indications sur ce qu'il faut éviter :

• Les méthodes qu'un utilisateur doit obligatoirement


appeler pour utiliser un composant.
• Les méthodes qui doivent s'exécuter selon un ordre défini.
• Les méthodes qui placent le composant dans... suite (
see page 1251)
Création de méthodes : Vue globale ( see page 1252) Les méthodes des composants sont des procédures et des fonctions intégrées
dans la structure d'une classe. Il n'existe pratiquement aucune restriction sur ce
que peuvent réaliser les méthodes d'un composant, mais Delphi n'en respecte
pas moins un certain nombre de standards qu'il est préférable de suivre. Ce sont :

• Eviter les interdépendances ( see page 1251)


• Nommer les méthodes ( see page 1254)
• Protéger les méthodes ( see page 1254)
• Rendre virtuelles des méthodes ( see page 1254)
• Déclarer des méthodes ( see page 1252)
En général, les composants ne doivent pas contenir
beaucoup de méthodes et vous devez chercher à
minimiser le nombre des méthodes appelées par une
application. Il est préférable d'encapsuler sous la forme de
propriétés des caractéristiques qu'il... suite ( see page
1252)
Déclaration des méthodes ( see page 1252) La déclaration d'une méthode dans un composant ne diffère en rien de celle
d'une méthode d'une autre classe.
Pour déclarer une nouvelle méthode dans un composant, vous devez :

3 • Ajouter la déclaration à la déclaration de type du


composant dans le fichier en-tête de ce dernier.
• Implémenter la méthode dans la partie implementation
de l'unité du composant.
Exemple de déclaration de méthodes ( see page 1252) Le code suivant montre un composant qui définit deux nouvelles méthodes, l'une
est déclarée protected et l'autre public virtuelle.

1250
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Méthodes qui doivent être protégées ( see page 1253) Toute méthode d'implémentation d'un composant doit être déclarée protected
afin d'empêcher les applications de les appeler à un moment inopportun. Si vous
avez défini des méthodes qui doivent demeurer inaccessibles au code, tout en
restant accessibles aux classes dérivées, vous devez les déclarer protected.
Par exemple, supposons une méthode dont l'exécution dépend de l'initialisation
préalable d'une donnée. Si cette méthode est déclarée public, il peut arriver que
les applications tentent de l'appeler avant l'initialisation de la donnée. Mais, en la
déclarant protected, les applications ne peuvent le faire directement. Vous
pouvez alors définir d'autres méthodes public qui... suite ( see page 1253)
Méthodes qui doivent être publiques ( see page 1254) Toutes les méthodes qui peuvent être appelées par les développeurs
d'applications doivent être déclarées public. N'oubliez pas que la plupart des
appels aux méthodes ont lieu dans les gestionnaires d'événements, aussi les
méthodes doivent éviter de gaspiller les ressources système ou de placer le
système d'exploitation dans un état où il n'est plus en mesure de répondre à
l'utilisateur.
Remarque: Les constructeurs et destructeurs sont toujours déclarés public.
Noms des méthodes ( see page 1254) Delphi n'impose aucune restriction quant à la façon de nommer les méthodes et
leurs paramètres. Toutefois, certaines conventions facilitent l'exploitation des
méthodes par les développeurs d'applications. Souvenez-vous que l'architecture
même d'un composant a son influence sur les différents types de personnes qui
pourront utiliser ce composant.
Si vous avez l'habitude d'écrire du code qui ne s'adresse qu'à un nombre
restreint de programmeurs, vous ne vous êtes sans doute jamais interrogé sur le
choix du nom des entités que vous manipulez. Il est souhaitable de choisir des
noms compréhensibles car vos composants s'adressent à tous, y compris à ceux
qui ne... suite ( see page 1254)
Protection des méthodes ( see page 1254) Toutes les parties des classes, y compris les champs, les méthodes et les
propriétés, ont différents niveaux de protection ou de "visibilité", comme
l'explique Contrôle des accès ( see page 1390). Il est facile de choisir le niveau
qui convient.
La plupart des méthodes écrites dans vos composants sont publiques ou
protégées. Il n'y a généralement pas lieu de déclarer une méthode private, à
moins qu'elle soit réellement spécifique à ce type de composant, au point que
même les composants dérivés ne peuvent pas y accéder.
Rendre virtuelles des méthodes ( see page 1254) Vous rendrez virtuelles les méthodes lorsque vous souhaitez que des types
différents puissent exécuter des codes différents en réponse au même appel de
méthode.
Si vous créez des composants pour qu'ils soient exploitables par les
développeurs d'applications directement, vous voudrez probablement rendre non
virtuelles vos méthodes. D'autre part, si vous créez des composants abstraits
desquels d'autres composants vont dériver, vous devez envisager de rendre
virtuelles les méthodes ajoutées. De cette façon, les composants dérivés
pourront redéfinir les méthodes virtuelles reçues en héritage.

3.2.1.3.1 Méthodes abstraites


Une méthode est parfois déclarée abstract dans un composant Delphi. Dans la bibliothèque de composants, les méthodes
abstraites se produisent habituellement dans les classes dont les noms commencent par "custom", comme TCustomGrid. De
telles classes sont elles-mêmes abstraites, au sens où elles ne servent qu'à la dérivation de classes descendantes.

Bien que vous puissiez créer un objet instance d'une classe contenant un membre abstrait, ce n'est pas recommandé. L'appel
du membre abstrait entraîne une exception EAbstractError.

La directive abstract est utilisée pour indiquer des parties de classes qui doivent être surfacées et définies dans des
composants descendants ; cela force les écrivains de composants à redéclarer le membre abstrait dans des classes
descendantes avant que des instances actuelles de la classe puissent être créées.
3

3.2.1.3.2 Eviter les interdépendances


Lorsque vous écrivez un composant, vous devez réduire au minimum les conditions préalables imposées aux développeurs.
Dans toute la mesure du possible, les développeurs doivent pouvoir faire ce qu'ils veulent de votre composant, et à tout moment.
Il existe des situations où vous ne pourrez répondre à cette exigence mais le but n'en demeure pas moins de s'en approcher au
plus près.

1251
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

La liste suivante donne quelques indications sur ce qu'il faut éviter :

• Les méthodes qu'un utilisateur doit obligatoirement appeler pour utiliser un composant.
• Les méthodes qui doivent s'exécuter selon un ordre défini.
• Les méthodes qui placent le composant dans un état ou un mode pour lequel certains événements ou certaines méthodes
deviennent incorrectes.
La meilleure façon de gérer les situations de ce type est de fournir le moyen d'en sortir. Par exemple, si l'appel d'une méthode a
pour effet de placer votre composant dans un état où l'appel d'une autre méthode s'avère incorrect, vous devez modifier cette
seconde méthode de telle manière que si elle est appelée alors que le composant se trouve dans un état impropre, elle
corrige cet état avant d'exécuter son propre code principal. Faute de mieux, vous devrez déclencher une exception si
l'utilisateur appelle une méthode non valide.
En d'autres termes, si vous générez une situation dans laquelle il existe des interdépendances entre certaines parties de votre
code, il est de votre responsabilité de vous assurer qu'une utilisation incorrecte du code n'engendre pas de problème. Un
message d'avertissement, par exemple, est préférable à une fin d'exécution anormale si l'utilisateur n'a pas respecté ces
interdépendances.

3.2.1.3.3 Création de méthodes : Vue globale


Les méthodes des composants sont des procédures et des fonctions intégrées dans la structure d'une classe. Il n'existe
pratiquement aucune restriction sur ce que peuvent réaliser les méthodes d'un composant, mais Delphi n'en respecte pas moins
un certain nombre de standards qu'il est préférable de suivre. Ce sont :

• Eviter les interdépendances ( see page 1251)


• Nommer les méthodes ( see page 1254)
• Protéger les méthodes ( see page 1254)
• Rendre virtuelles des méthodes ( see page 1254)
• Déclarer des méthodes ( see page 1252)
En général, les composants ne doivent pas contenir beaucoup de méthodes et vous devez chercher à minimiser le nombre des
méthodes appelées par une application. Il est préférable d'encapsuler sous la forme de propriétés des caractéristiques qu'il
serait tentant d'implémenter sous forme de méthodes. Les propriétés fournissent une interface qui s'inscrit parfaitement dans
Delphi et sont accessibles au moment de la conception.

3.2.1.3.4 Déclaration des méthodes


La déclaration d'une méthode dans un composant ne diffère en rien de celle d'une méthode d'une autre classe.

Pour déclarer une nouvelle méthode dans un composant, vous devez :

• Ajouter la déclaration à la déclaration de type du composant dans le fichier en-tête de ce dernier.


• Implémenter la méthode dans la partie implementation de l'unité du composant.

3.2.1.3.5 Exemple de déclaration de méthodes


3 Le code suivant montre un composant qui définit deux nouvelles méthodes, l'une est déclarée protected et l'autre public
virtuelle.

C++
Il s'agit de la définition d'interface contenue dans le fichier .H :
class PACKAGE TSampleComponent : public TControl
{
protected:

1252
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

void __fastcall MakeBigger();


public:
virtual int __fastcall CalculateArea();
.
.
.
};
Voici le code qui figure dans le fichier .CPP de l'unité qui implémente les méthodes :
void __fastcall TSampleComponent::MakeBigger()
{
Height = Height + 5;
Width = Width + 5;
}
int __fastcall TSampleComponent::CalculateArea()
{
return Width * Height;
}
Delphi
type
TSampleComponent = class(TControl)
protected
procedure MakeBigger; { déclare la méthode protected static }
public
function CalculateArea: Integer; virtual; { déclare la méthode public virtual }
end;
.
.
.
implementation
.
.
.
procedure TSampleComponent.MakeBigger; { implémente la première méthode }
begin
Height := Height + 5;
Width := Width + 5;
end;
function TSampleComponent.CalculateArea: Integer; { implémente la deuxième méthode }
begin
Result := Width * Height;
end;

3.2.1.3.6 Méthodes qui doivent être protégées


Toute méthode d'implémentation d'un composant doit être déclarée protected afin d'empêcher les applications de les appeler à
un moment inopportun. Si vous avez défini des méthodes qui doivent demeurer inaccessibles au code, tout en restant
accessibles aux classes dérivées, vous devez les déclarer protected.

Par exemple, supposons une méthode dont l'exécution dépend de l'initialisation préalable d'une donnée. Si cette méthode est
déclarée public, il peut arriver que les applications tentent de l'appeler avant l'initialisation de la donnée. Mais, en la déclarant
protected, les applications ne peuvent le faire directement. Vous pouvez alors définir d'autres méthodes public qui se chargent
3
d'initialiser la donnée avant d'appeler la méthode protected.

Les méthodes d'implémentation des propriétés doivent être déclarées comme virtuelles et protected. Les méthodes ainsi
déclarées permettent aux développeurs d'applications de redéfinir l'implémentation des propriétés, augmentant leurs
fonctionalités ou les remplaçant complètement. De telles propriétés sont complètement polymorphes. Instaurer un accès
protected à ces méthodes garantit que les développeurs ne pourront pas les appeler par accident ni modifier la propriété par
inadvertance.

1253
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.3.7 Méthodes qui doivent être publiques


Toutes les méthodes qui peuvent être appelées par les développeurs d'applications doivent être déclarées public. N'oubliez pas
que la plupart des appels aux méthodes ont lieu dans les gestionnaires d'événements, aussi les méthodes doivent éviter de
gaspiller les ressources système ou de placer le système d'exploitation dans un état où il n'est plus en mesure de répondre à
l'utilisateur.

Remarque: Les constructeurs et destructeurs sont toujours déclarés public.

3.2.1.3.8 Noms des méthodes


Delphi n'impose aucune restriction quant à la façon de nommer les méthodes et leurs paramètres. Toutefois, certaines
conventions facilitent l'exploitation des méthodes par les développeurs d'applications. Souvenez-vous que l'architecture même
d'un composant a son influence sur les différents types de personnes qui pourront utiliser ce composant.

Si vous avez l'habitude d'écrire du code qui ne s'adresse qu'à un nombre restreint de programmeurs, vous ne vous êtes sans
doute jamais interrogé sur le choix du nom des entités que vous manipulez. Il est souhaitable de choisir des noms
compréhensibles car vos composants s'adressent à tous, y compris à ceux qui ne connaissent pas bien votre code (ou qui
maîtrisent imparfaitement la programmation).

Voici quelques suggestions pour définir des noms de méthode compréhensibles :

• Choisissez des noms descriptifs. Utilisez des verbes d'action. Un nom tel que CollerPressePapiers est plus explicite que
Coller ou CPP.
• Les noms de fonctions doivent refléter la nature de ce qu'elles renvoient.
Bien qu'il puisse paraître évident, à vous programmeur, que le rôle d'une fonction intitulée X soit de renvoyer la coordonnée
horizontale d'un élément, un nom tel que ObtenirPositionHorizontale sera compris par tout le monde.
Comme dernière considération, assurez-vous que votre méthode ait réellement besoin d'être créée comme telle. Que le nom de
votre méthode puisse être un verbe est un bon repère. Si ce n'est pas le cas, demandez-vous s'il ne serait pas préférable de
transformer votre méthode en propriété.

3.2.1.3.9 Protection des méthodes


Toutes les parties des classes, y compris les champs, les méthodes et les propriétés, ont différents niveaux de protection ou de
"visibilité", comme l'explique Contrôle des accès ( see page 1390). Il est facile de choisir le niveau qui convient.

La plupart des méthodes écrites dans vos composants sont publiques ou protégées. Il n'y a généralement pas lieu de déclarer
une méthode private, à moins qu'elle soit réellement spécifique à ce type de composant, au point que même les composants
dérivés ne peuvent pas y accéder.

3.2.1.3.10 Rendre virtuelles des méthodes


Vous rendrez virtuelles les méthodes lorsque vous souhaitez que des types différents puissent exécuter des codes différents en
3 réponse au même appel de méthode.

Si vous créez des composants pour qu'ils soient exploitables par les développeurs d'applications directement, vous voudrez
probablement rendre non virtuelles vos méthodes. D'autre part, si vous créez des composants abstraits desquels d'autres
composants vont dériver, vous devez envisager de rendre virtuelles les méthodes ajoutées. De cette façon, les composants
dérivés pourront redéfinir les méthodes virtuelles reçues en héritage.

1254
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.4 Création de propriétés


Rubriques
Nom Description
Création de propriétés : Vue globale ( see page 1258) Les propriétés sont la partie la plus visible des composants. Le développeur
d'applications a la possibilité de les voir et de les manipuler au moment de la
conception et dispose d'un retour immédiat au fur et à mesure que réagissent les
composants dans le concepteur de fiches. Des propriétés bien conçues
simplifient l'utilisation de vos composants par d'autres programmeurs et en
facilitent la maintenance.
Pour utiliser de façon optimale les propriétés de vos composants, vous devez
connaître les points suivants :

• Pourquoi créer des propriétés ? ( see page 1259)


• Types de propriétés ( see page 1259)
• Publication des propriétés héritées ( see page 1260)
• Définition des propriétés ( see page 1260)
• Création de propriétés tableau ( see page 1263)
• Stockage et ( see page 1264)... suite ( see page 1258)
Pourquoi créer des propriétés ? ( see page 1259) Du point de vue du développeur d'applications, les propriétés ressemblent à des
variables. Les développeurs peuvent définir ou lire les valeurs des propriétés
comme s'il s'agissait de champs. La seule opération interdite avec une propriété
et autorisée avec une variable consiste à la transmettre comme paramètre var.
Les propriétés ont une puissance bien supérieure à celle de simples champs car

• Les développeurs d'applications peuvent définir des


propriétés au moment de la conception. Contrairement
aux méthodes, qui ne sont accessibles qu'à l'exécution,
les propriétés permettent au développeur de
personnaliser les composants avant l'exécution de
l'application. Les propriétés apparaissent dans
l'inspecteur... suite ( see page 1259)
Types de propriétés ( see page 1259) Une propriété peut avoir un type quelconque. Les divers types sont affichés de
manière différente dans l'inspecteur d'objets, ce qui valide l'affectation des
propriétés effectuées au moment de la conception.
Affichage des propriétés dans l'inspecteur d'objets
Publication des propriétés héritées ( see page 1260) Tous les composants héritent des propriétés de leurs classes ancêtre. Lorsque
vous dérivez un composant à partir d'un composant existant, le nouveau
composant hérite de toutes les propriétés de l'ancêtre immédiat. Si vous
effectuez la dérivation à partir d'une des classes abstraites, aucune des
propriétés héritées n'est published, la plupart sont protected ou public.
Pour rendre disponible dans l'inspecteur d'objets une propriété protected ou
private au moment de la conception, vous devez redéclarer published la
propriété. Redéclarer une propriété signifie ajouter la déclaration d'une propriété
héritée à la déclaration de la classe descendante.
Définition des propriétés ( see page 1260) Cette section montre comment déclarer de nouvelles propriétés et explique
certaines conventions respectées par les composants standard. Ces rubriques
comprennent :

• Déclarations des propriétés ( see page 1260)


3
• Stockage interne des données ( see page 1261)
• Accès direct ( see page 1261)
• Méthodes d'accès ( see page 1261)
• Valeurs par défaut d'une propriété ( see page 1262)

1255
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Déclarations des propriétés ( see page 1260) Une propriété est déclarée dans la déclaration de sa classe composant. Pour
déclarer une propriété, vous devez spécifier les trois éléments suivants :

• Le nom de la propriété.
• Le type de la propriété.
• Les méthodes utilisées pour lire et écrire la valeur de la
propriété. Si aucune méthode d'écriture n'est déclarée, la
propriété est accessible uniquement en lecture.
Les propriétés déclarées dans une section published de la
déclaration de classe du composant sont modifiables
dans l'inspecteur d'objets lors de la conception. La valeur
d'une propriété published est enregistrée avec le
composant dans le fichier fiche. Les propriétés déclarées
dans une section... suite ( see page 1260)
Stockage interne des données ( see page 1261) Il n'existe aucune restriction quant au stockage des données d'une propriété.
Toutefois, les composants Delphi respectent généralement les conventions
suivantes :

• Les données des propriétés sont stockées dans des


champs.
• Les champs utilisés pour stocker les données d'une
propriété sont déclarés private et ne peuvent être
accédées qu'à partir du composant lui-même. Les
composants dérivés doivent utiliser la propriété héritée ;
ils ne nécessitent pas un accès direct au stockage interne
des données de la propriété.
• Les identificateurs de ces champs sont composés de la
lettre F suivie du nom de la propriété. Par exemple, la
donnée brute de la propriété Width... suite ( see page
1261)
Accès direct ( see page 1261) L'accès direct est le moyen le plus simple d'accéder aux données d'une
propriété. Autrement dit, les parties read et write de la déclaration d'une
propriété spécifient que l'affectation ou la lecture de la valeur de la propriété
s'effectue directement dans le champ de stockage interne sans appel à une
méthode d'accès. L'accès direct est utile lorsque vous voulez rendre une
propriété accessible dans l'inspecteur d'objets, mais que vous ne voulez pas que
le changement de sa valeur déclenche un processus immédiatement.
En général, vous définirez un accès direct pour la partie read d'une déclaration
de propriété et utiliserez une... suite ( see page 1261)
Méthodes d'accès (propriétés) ( see page 1261) Vous pouvez spécifier une méthode d'accès plutôt qu'un champ dans les parties
read et write d'une déclaration de propriété. Les méthodes d'accès doivent être
protected, et sont habituellement déclarées comme virtual ; cela autorise les
composants descendants à redéfinir l'implémentation de la propriété.
Evitez de rendre publiques les méthodes d'accès. Les conserver protected vous
prémunit contre toute modification accidentelle d'une propriété par un
développeur d'applications qui appellerait ces méthodes.
Méthode Read ( see page 1261) La méthode read d'une propriété est une fonction qui n'accepte aucun paramètre
(sauf pour ce qui est mentionné ci-après) et renvoie une valeur du même type
que la propriété. Par convention, le nom de la fonction est Get suivi du nom de la
propriété. Par exemple, la méthode read pour une propriété intitulée Count serait
GetCount. La méthode read manipule les données internes afin de générer une
valeur de la propriété respectant le type demandé.
3 Les seules exceptions à la règle "aucun paramètre" sont les propriétés tableau et
les propriétés qui utilisent un spécificateur d'index (voir Création de propriétés (
see page 1263)... suite ( see page 1261)
Méthode Write ( see page 1262) La méthode write d'une propriété est une procédure acceptant un seul paramètre
(sauf pour ce qui est mentionné ci-après) du même type que la propriété. Le
paramètre peut être transmis par référence ou par valeur et peut porter le nom
de votre choix. Par convention, le nom de la méthode write est Set suivi du nom
de la propriété. Par exemple, la méthode write d'une propriété intitulée Count
serait SetCount. La valeur transmise en paramètre devient la nouvelle valeur de
la propriété ; la méthode write doit accomplir les manipulations nécessaires pour
placer les données concernées à l'emplacement de stockage... suite ( see
page 1262)

1256
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Valeurs par défaut d'une propriété ( see page 1262) Lorsque vous déclarez une propriété, vous pouvez déclarer une valeur par
défaut. La VCL utilise cette valeur par défaut pour déterminer si une propriété
doit être stockée dans un fichier fiche. Si vous ne donnez pas de valeur par
défaut à une propriété, la VCL stocke toujours cette propriété.
Pour spécifier une valeur par défaut pour une propriété, ajoutez la directive
default à la déclaration (ou à la redéclaration) de la propriété, suivie par la valeur
par défaut. Par exemple,
Spécification d'aucune valeur par défaut ( see page 1262) Lorsque vous redéclarez une propriété, vous pouvez indiquer que la propriété ne
possède pas de valeur par défaut, même si une telle valeur est définie pour la
propriété reçue en héritage.
Pour indiquer qu'une propriété n'a pas de valeur par défaut, ajoutez la directive
nodefault à la déclaration de la propriété. Par exemple,
Création de propriétés tableau ( see page 1263) Certaines propriétés se prêtent à l'indexation. Par exemple, la propriété Lines de
TMemo est la liste indexée des chaînes qui constituent le texte du mémo et vous
pouvez la traiter comme un tableau de chaînes. Lines fournit un accès à un
élément particulier (une chaîne) dans un ensemble plus large de données (le
texte du mémo).
Les propriétés tableau sont déclarées comme les autres propriétés. Les seules
différences sont les suivantes :

• La déclaration de la propriété doit comprendre un ou


plusieurs index ayant chacun un type défini. Les index
peuvent avoir n'importe quel type.
• Les parties read et write de... suite ( see page 1263)
Création des propriétés pour interfaces ( see page 1263) Vous pouvez utiliser une interface comme valeur d'une propriété publiée,
presque comme si vous utilisiez un objet. Cependant, le mécanisme par lequel
votre composant reçoit les notifications de l'implémentation de l'interface est
différent. Dans Création de propriétés pour sous-composants ( see page
1264), le setter de la propriété appelait la méthode FreeNotification du
composant assigné comme valeur à la propriété. Cela permettait au composant
de se mettre à jour lorsqu'était libéré le composant servant de valeur à la
propriété. Mais, lorsque la valeur de la propriété est une interface, vous n'avez
pas accès au composant implémentant cette interface. Il s'ensuit que vous ne...
suite ( see page 1263)
Création de propriétés pour sous-composants ( see page 1264) Par défaut, lorsque la valeur d'une propriété est un autre composant, vous lui
attribuez une valeur en ajoutant à la fiche ou au module de données une
instance de cet autre composant et en assignant ensuite le composant comme
valeur à la propriété. Mais, il est aussi possible que votre composant crée sa
propre instance de l'objet qui implémente la valeur de la propriété. Un tel
composant dédié s'appelle un sous-composant.
Les sous-composants peuvent être constitué de n'importe quel objet persistant
(tout descendant de TPersistent). Au contraire des composants séparés qui
peuvent se trouver assignés comme valeur d'une propriété,... suite ( see page
1264)
Stockage et chargement des propriétés ( see page 1264) Delphi stocke les fiches et leurs composants dans des fichiers fiche (.dfm dans
les applications VCL). Un fichier fiche stocke les propriétés d'une fiche et de ses
composants. Lorsque les développeurs Delphi ajoutent à leurs fiches les
composants que vous avez écrits, vos composants doivent être capables
d'enregistrer leurs propriétés dans le fichier fiche lors de sa sauvegarde. De
même, lorsqu'ils sont chargés dans Delphi ou exécutés comme éléments d'une
application, vos composants doivent être capables de se restituer eux-mêmes à
partir du fichier fiche.
La plupart du temps, vous n'aurez rien à faire pour que vos composants
fonctionnent avec... suite ( see page 1264)
Utilisation du mécanisme de stockage et de chargement ( see page 1265) La description d'une fiche est la liste des propriétés de la fiche accompagnée
d'une liste semblable pour chacun de ses composants. Chaque composant, y
compris la fiche elle-même, est responsable du stockage et du chargement de sa
propre description.
Lorsqu'il se stocke lui-même, un composant écrit implicitement les valeurs de
toutes ses propriétés publiées si celles-ci sont différentes de leurs valeurs par 3
défaut, en respectant l'ordre dans lequel ont été déclarées ces valeurs. Au
chargement, le composant commence par se construire lui-même, toutes les
propriétés récupérant leurs valeurs par défaut, puis il lit les valeurs stockées des
propriétés dont les... suite ( see page 1265)

1257
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Spécification des valeurs par défaut ( see page 1265) Les composants Delphi ne stockent la valeur des propriétés que si elles diffèrent
des valeurs par défaut. Sauf indication contraire, Delphi suppose qu'une
propriété n'a pas de valeur par défaut, ce qui a pour conséquence que le
composant stocke toujours la propriété, quelle que soit sa valeur.
Pour spécifier une valeur par défaut pour une propriété, ajoutez la directive
default et la nouvelle valeur par défaut à la fin de la déclaration de la propriété.
Vous pouvez également spécifier une valeur par défaut en redéclarant une
propriété. De fait, l'attribution d'une autre valeur par défaut est l'une des raisons
qui... suite ( see page 1265)
Détermination du stockage ( see page 1265) Vous pouvez choisir si Delphi stocke ou non chacune des propriétés de vos
composants. Par défaut, sont stockées toutes les propriétés de la partie
published de la déclaration de classe. Vous pouvez choisir de ne pas stocker
une propriété ou de désigner une fonction qui décidera, de manière dynamique,
du stockage de la propriété.
Pour contrôler le stockage par Delphi d'une propriété, ajoutez la directive stored
à la déclaration de propriété, suivie par True, False ou le nom d'une fonction
booléenne.
Initialisation après chargement ( see page 1266) Après qu'un composant a lu les valeurs de toutes ses propriétés dans sa
description stockée, il appelle une méthode virtuelle appelée Loaded, qui
effectue toutes les initialisations nécessaires. L'appel de Loaded s'exécute avant
que ne s'affichent la fiche et ses contrôles, ainsi vous n'avez pas à vous soucier
du scintillement de l'écran provoqué par ces initialisations.
Pour initialiser un composant après le chargement des valeurs des propriétés,
vous devez redéfinir la méthode Loaded.
Remarque: La première opération à accomplir dans une méthode Loaded
consiste à appeler la méthode Loaded reçue en héritage. Ceci afin d'être sûr que
toutes... suite ( see page 1266)
Stockage et chargement des propriétés non publiées ( see page 1266) Par défaut, seules les propriétés publiées sont chargées et enregistrées avec un
composant. Cependant, il est possible de charger et d'enregistrer des propriétés
non publiées. Ceci permet d'obtenir des propriétés persistantes n'apparaissant
pas dans l'inspecteur d'objets. Cela permet aussi le stockage et le chargement
des valeurs de propriétés par les composants, valeurs de propriétés que Delphi
ne sait pas comment lire ni écrire car elles sont trop complexes. Par exemple,
l'objet TStrings ne peut pas compter sur le comportement automatique de Delphi
pour stocker et charger les chaînes qu'il représente et doit utiliser le mécanisme
suivant.
Vous pouvez enregistrer des... suite ( see page 1266)
Création de méthodes pour le stockage et le chargement de valeurs de Pour stocker et charger des propriétés non publiées, vous devez d'abord créer
propriétés ( see page 1266) une méthode afin de stocker la valeur de propriété et une autre méthode pour la
charger. Deux possibilités s'offrent à vous :

• Créer une méthode de type TWriterProc afin de stocker la


valeur de propriété et une méthode de type TReaderProc
pour la charger. Cette approche vous permet de profiter
des capacités intégrées de Delphi concernant
l'enregistrement et le chargement de types simples. Si la
valeur de votre propriété est construite à partir de types
que Delphi sait enregistrer et charger, utilisez cette
approche.
• Créer deux méthodes de type... suite ( see page 1266)
Redéfinition de la méthode DefineProperties ( see page 1267) Après avoir créé des méthodes de stockage et de chargement de la valeur de
propriété, vous pouvez redéfinir la méthode DefineProperties du composant.
Delphi appelle cette méthode lors du chargement ou du stockage du composant.
Dans la méthode DefineProperties, vous devez appeler la méthode
DefineProperty ou DefineBinaryProperty du filer en cours, en lui transmettant la
méthode à utiliser pour le chargement ou l'enregistrement de la valeur de
propriété. Si vos méthodes de chargement et de stockage sont des types
TWriterProc et TReaderProc, vous appelez alors la méthode DefineProperty du
3 filer. Si vous avez créé des méthodes de type... suite ( see page 1267)

3.2.1.4.1 Création de propriétés : Vue globale


Les propriétés sont la partie la plus visible des composants. Le développeur d'applications a la possibilité de les voir et de les
manipuler au moment de la conception et dispose d'un retour immédiat au fur et à mesure que réagissent les composants dans
le concepteur de fiches. Des propriétés bien conçues simplifient l'utilisation de vos composants par d'autres programmeurs et en
facilitent la maintenance.

1258
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Pour utiliser de façon optimale les propriétés de vos composants, vous devez connaître les points suivants :

• Pourquoi créer des propriétés ? ( see page 1259)


• Types de propriétés ( see page 1259)
• Publication des propriétés héritées ( see page 1260)
• Définition des propriétés ( see page 1260)
• Création de propriétés tableau ( see page 1263)
• Stockage et chargement des propriétés ( see page 1264)

3.2.1.4.2 Pourquoi créer des propriétés ?


Du point de vue du développeur d'applications, les propriétés ressemblent à des variables. Les développeurs peuvent définir ou
lire les valeurs des propriétés comme s'il s'agissait de champs. La seule opération interdite avec une propriété et autorisée avec
une variable consiste à la transmettre comme paramètre var.

Les propriétés ont une puissance bien supérieure à celle de simples champs car

• Les développeurs d'applications peuvent définir des propriétés au moment de la conception. Contrairement aux méthodes,
qui ne sont accessibles qu'à l'exécution, les propriétés permettent au développeur de personnaliser les composants avant
l'exécution de l'application. Les propriétés apparaissent dans l'inspecteur d'objets, ce qui simplifie le travail du programmeur ;
au lieu de traiter plusieurs paramètres pour construire un objet, l'inspecteur d'objets fournit les valeurs. L'inspecteur d'objets
valide les affectations des valeurs aux propriétés dès qu'elles sont effectuées.
• Les propriétés peuvent masquer les détails de l'implémentation. Par exemple, des données stockées de façon interne sous
une forme cryptée peuvent apparaître non cryptées en tant que la valeur d'une propriété ; bien que la valeur puisse être un
simple nombre, le composant peut rechercher cette valeur dans une base de données ou effectuer des calculs complexes
afin de la récupérer. Les propriétés permettent d'associer des opérations complexes à une simple affectation ; ce qui apparaît
comme l'affectation d'un champ correspond en fait à un appel de méthode et cette dernière peut accomplir à peu près
n'importe quelle tâche.
• Les propriétés peuvent être virtuelles. Ce qui paraît être une seule propriété pour le développeur d'applications peut être
implémenté de manière différente dans des composants différents.
Un exemple simple est la propriété Top que tous les contrôles possèdent. L'attribution d'une nouvelle valeur à Top n'a pas pour
seul effet de modifier une valeur mémorisée ; elle provoque aussi le déplacement et le réaffichage du contrôle. Les effets de
la définition d'une propriété ne se limitent pas nécessairement à un composant unique ; par exemple, donner la valeur True à
la propriété Down d'un turbobouton a pour effet d'attribuer la valeur False à la propriété Down de tous les autres turboboutons
du même groupe.

3.2.1.4.3 Types de propriétés


Une propriété peut avoir un type quelconque. Les divers types sont affichés de manière différente dans l'inspecteur d'objets, ce
qui valide l'affectation des propriétés effectuées au moment de la conception.

Affichage des propriétés dans l'inspecteur d'objets

Type de traitement
propriété
3
Simple Les propriétés de type numérique, caractère et chaîne apparaissent dans l'inspecteur d'objets comme des
nombres, caractères et chaînes. Le développeur d'applications peut modifier directement la valeur de ces
propriétés.
Enuméré Les propriétés de type énuméré (y compris le type Boolean) apparaissent comme des chaînes éditables. Le
développeur peut également passer en revue toutes les valeurs possibles en double-cliquant sur la colonne
contenant la valeur et il existe une liste déroulante montrant toutes les valeurs possibles.

1259
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Ensemble Les propriétés de type ensemble apparaissent dans l'inspecteur d'objets comme des ensembles. En
double-cliquant sur la propriété, le développeur peut développer l'ensemble et traiter chacun des éléments comme
une valeur booléenne (true si cet élément appartient à l'ensemble).
Objet Les propriétés qui sont elles-mêmes des classes ont souvent leur propre éditeur de propriétés, qui est spécifié
dans la procédure de recensement du composant. Si la classe d'une propriété a ses propres propriétés publiées
(published), l'inspecteur d'objets permet au développeur d'étendre la liste (en double-cliquant) afin d'inclure ces
propriétés et de les modifier individuellement. Les propriétés doivent descendre de TPersistent.
Interface Les propriétés qui sont des interfaces peuvent apparaître dans l'inspecteur d'objets tant que la valeur est une
interface implémentée par un composant (un descendant de TComponent). Les propriétés interface ont souvent
leur propre éditeur de propriétés.
Tableau Les propriétés tableau doivent disposer d'un éditeur de propriétés spécifique. L'inspecteur d'objets ne dispose
d'aucune fonction intégrée permettant de modifier les propriétés de ce type. Vous pouvez spécifier un éditeur de
propriétés lorsque vous recensez vos composants.

3.2.1.4.4 Publication des propriétés héritées


Tous les composants héritent des propriétés de leurs classes ancêtre. Lorsque vous dérivez un composant à partir d'un
composant existant, le nouveau composant hérite de toutes les propriétés de l'ancêtre immédiat. Si vous effectuez la dérivation
à partir d'une des classes abstraites, aucune des propriétés héritées n'est published, la plupart sont protected ou public.

Pour rendre disponible dans l'inspecteur d'objets une propriété protected ou private au moment de la conception, vous devez
redéclarer published la propriété. Redéclarer une propriété signifie ajouter la déclaration d'une propriété héritée à la déclaration
de la classe descendante.

3.2.1.4.5 Définition des propriétés


Cette section montre comment déclarer de nouvelles propriétés et explique certaines conventions respectées par les
composants standard. Ces rubriques comprennent :

• Déclarations des propriétés ( see page 1260)


• Stockage interne des données ( see page 1261)
• Accès direct ( see page 1261)
• Méthodes d'accès ( see page 1261)
• Valeurs par défaut d'une propriété ( see page 1262)

3.2.1.4.6 Déclarations des propriétés


Une propriété est déclarée dans la déclaration de sa classe composant. Pour déclarer une propriété, vous devez spécifier les
trois éléments suivants :

• Le nom de la propriété.
3 • Le type de la propriété.
• Les méthodes utilisées pour lire et écrire la valeur de la propriété. Si aucune méthode d'écriture n'est déclarée, la propriété
est accessible uniquement en lecture.
Les propriétés déclarées dans une section published de la déclaration de classe du composant sont modifiables dans
l'inspecteur d'objets lors de la conception. La valeur d'une propriété published est enregistrée avec le composant dans le
fichier fiche. Les propriétés déclarées dans une section public sont accessibles à l'exécution et peuvent être lues ou définies
par le code du programme.

1260
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.4.7 Stockage interne des données


Il n'existe aucune restriction quant au stockage des données d'une propriété. Toutefois, les composants Delphi respectent
généralement les conventions suivantes :

• Les données des propriétés sont stockées dans des champs.


• Les champs utilisés pour stocker les données d'une propriété sont déclarés private et ne peuvent être accédées qu'à partir du
composant lui-même. Les composants dérivés doivent utiliser la propriété héritée ; ils ne nécessitent pas un accès direct au
stockage interne des données de la propriété.
• Les identificateurs de ces champs sont composés de la lettre F suivie du nom de la propriété. Par exemple, la donnée brute
de la propriété Width définie pour TControl est stockée dans un champ appelé FWidth.
Le principe qui sous-tend ces conventions est le suivant : seules les méthodes d'implémentation d'une propriété doivent pouvoir
accéder aux données associées à cette propriété. Si une méthode ou une autre propriété a besoin de changer ces données,
elle doit le faire via la propriété et non directement par un accès aux données stockées. Cela garantit que l'implémentation
d'une propriété héritée puisse être modifiée sans invalider les composants dérivés.

3.2.1.4.8 Accès direct


L'accès direct est le moyen le plus simple d'accéder aux données d'une propriété. Autrement dit, les parties read et write de la
déclaration d'une propriété spécifient que l'affectation ou la lecture de la valeur de la propriété s'effectue directement dans le
champ de stockage interne sans appel à une méthode d'accès. L'accès direct est utile lorsque vous voulez rendre une propriété
accessible dans l'inspecteur d'objets, mais que vous ne voulez pas que le changement de sa valeur déclenche un processus
immédiatement.

En général, vous définirez un accès direct pour la partie read d'une déclaration de propriété et utiliserez une méthode d'accès
pour la partie write. Cela permet de mettre à jour l'état du composant lorsque la valeur de la propriété change.

3.2.1.4.9 Méthodes d'accès (propriétés)


Vous pouvez spécifier une méthode d'accès plutôt qu'un champ dans les parties read et write d'une déclaration de propriété.
Les méthodes d'accès doivent être protected, et sont habituellement déclarées comme virtual ; cela autorise les composants
descendants à redéfinir l'implémentation de la propriété.

Evitez de rendre publiques les méthodes d'accès. Les conserver protected vous prémunit contre toute modification accidentelle
d'une propriété par un développeur d'applications qui appellerait ces méthodes.

3.2.1.4.10 Méthode Read


La méthode read d'une propriété est une fonction qui n'accepte aucun paramètre (sauf pour ce qui est mentionné ci-après) et
renvoie une valeur du même type que la propriété. Par convention, le nom de la fonction est Get suivi du nom de la propriété.
Par exemple, la méthode read pour une propriété intitulée Count serait GetCount. La méthode read manipule les données
internes afin de générer une valeur de la propriété respectant le type demandé.
3
Les seules exceptions à la règle "aucun paramètre" sont les propriétés tableau et les propriétés qui utilisent un spécificateur
d'index (voir Création de propriétés tableau ( see page 1263)), pour lesquelles cet index est transmis comme paramètre.
Utilisez des spécificateurs d'index pour créer une méthode read unique partagée par plusieurs propriétés. Pour plus
d'informations sur les spécificateurs d'index, voir le Guide du langage Delphi.)

Si vous ne déclarez aucune méthode read, la propriété fonctionne uniquement en écriture. Les propriétés fonctionnant en
écriture uniquement sont très rares.

1261
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.4.11 Méthode Write


La méthode write d'une propriété est une procédure acceptant un seul paramètre (sauf pour ce qui est mentionné ci-après) du
même type que la propriété. Le paramètre peut être transmis par référence ou par valeur et peut porter le nom de votre choix.
Par convention, le nom de la méthode write est Set suivi du nom de la propriété. Par exemple, la méthode write d'une propriété
intitulée Count serait SetCount. La valeur transmise en paramètre devient la nouvelle valeur de la propriété ; la méthode write
doit accomplir les manipulations nécessaires pour placer les données concernées à l'emplacement de stockage interne de la
propriété.

Les seules exceptions à la règle “paramètre unique” sont les propriétés tableau et les propriétés qui utilisent un spécificateur
d'index, pour lesquelles cet index est transmis comme second paramètre. Utilisez des spécificateurs d'index pour créer une
méthode read unique partagée par plusieurs propriétés. Pour plus d'informations sur les spécificateurs d'index, voir le Guide du
langage Delphi.)

Si vous ne déclarez aucune méthode write, la propriété fonctionne uniquement en lecture.

Les méthodes write testent normalement si une nouvelle valeur diffère de la valeur actuelle avant de modifier la propriété. Par
exemple, voici une méthode write simple d'une propriété de type entier appelée Count stockant sa valeur courante dans un
champ appelé FCount.
procedure TMyComponent.SetCount(Value: Integer);
begin
if Value <> FCount then
begin
FCount := Value;
Update;
end;
end;
void __fastcall TMyComponent::SetCount( int Value )
{
if ( Value != FCount )
{
FCount := Value;
Update();
}

3.2.1.4.12 Valeurs par défaut d'une propriété


Lorsque vous déclarez une propriété, vous pouvez déclarer une valeur par défaut. La VCL utilise cette valeur par défaut pour
déterminer si une propriété doit être stockée dans un fichier fiche. Si vous ne donnez pas de valeur par défaut à une propriété, la
VCL stocke toujours cette propriété.

Pour spécifier une valeur par défaut pour une propriété, ajoutez la directive default à la déclaration (ou à la redéclaration) de la
propriété, suivie par la valeur par défaut. Par exemple,
property Cool Boolean read GetCool write SetCool default True;
__property bool IsTrue = {read=GetIsTrue, write=SetIsTrue, default=true};
Remarque: Déclarer une valeur par défaut pour une propriété n'a pas pour effet de définir cette propriété par cette valeur. La
3 méthode constructeur du composant doit initialiser la valeur des propriétés lorsque c'est nécessaire. Toutefois, comme les objets
initialisent toujours leurs champs à 0, il n'est pas nécessaire que le constructeur initialise les propriétés entières à 0, les
propriétés chaînes à null ni les propriétés booléennes à False.

3.2.1.4.13 Spécification d'aucune valeur par défaut


Lorsque vous redéclarez une propriété, vous pouvez indiquer que la propriété ne possède pas de valeur par défaut, même si
une telle valeur est définie pour la propriété reçue en héritage.

1262
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Pour indiquer qu'une propriété n'a pas de valeur par défaut, ajoutez la directive nodefault à la déclaration de la propriété. Par
exemple,
property FavoriteFlavor string nodefault;
__property int NewInteger = {nodefault};
Lorsque vous déclarez une propriété pour la première fois, vous n'êtes pas obligé de spécifier nodefault. L'absence d'une valeur
par défaut déclarée indique l'inexistence d'une valeur par défaut.

3.2.1.4.14 Création de propriétés tableau


Certaines propriétés se prêtent à l'indexation. Par exemple, la propriété Lines de TMemo est la liste indexée des chaînes qui
constituent le texte du mémo et vous pouvez la traiter comme un tableau de chaînes. Lines fournit un accès à un élément
particulier (une chaîne) dans un ensemble plus large de données (le texte du mémo).

Les propriétés tableau sont déclarées comme les autres propriétés. Les seules différences sont les suivantes :

• La déclaration de la propriété doit comprendre un ou plusieurs index ayant chacun un type défini. Les index peuvent avoir
n'importe quel type.
• Les parties read et write de la déclaration de la propriété, lorsqu'elles sont spécifiées, doivent être des méthodes. Il ne peut
s'agir de champs.
Les méthodes read et write d'une propriété tableau acceptent des paramètres supplémentaires correspondant aux index. Les
paramètres doivent respecter l'ordre et le type des index spécifiés dans la déclaration.
Bien qu'ils se ressemblent, il existe quelques différences importantes entre les tableaux et les propriétés tableau. Contrairement
aux indices d'un tableau, l'index d'une propriété tableau n'est pas obligatoirement de type entier. Par exemple, vous pouvez
indexer une propriété en utilisant une chaîne. En outre, vous ne pouvez référencer qu'un seul élément d'une propriété et non
une plage d'éléments.

3.2.1.4.15 Création des propriétés pour interfaces


Vous pouvez utiliser une interface comme valeur d'une propriété publiée, presque comme si vous utilisiez un objet. Cependant,
le mécanisme par lequel votre composant reçoit les notifications de l'implémentation de l'interface est différent. Dans Création de
propriétés pour sous-composants ( see page 1264), le setter de la propriété appelait la méthode FreeNotification du
composant assigné comme valeur à la propriété. Cela permettait au composant de se mettre à jour lorsqu'était libéré le
composant servant de valeur à la propriété. Mais, lorsque la valeur de la propriété est une interface, vous n'avez pas accès au
composant implémentant cette interface. Il s'ensuit que vous ne pouvez pas appeler sa méthode FreeNotification.

Pour gérer une telle situation, vous pouvez appeler la méthode ReferenceInterface de votre composant :
procedure TDemoComponent.SetMyIntfProp(const Value: IMyInterface);
begin
ReferenceInterface(FIntfField, opRemove);
FIntfField := Value;
ReferenceInterface(FIntfField, opInsert);
end;
Appeler ReferenceInterface avec une interface est équivalent à appeler la méthode FreeNotification d'un autre composant.
Donc, après l'appel de ReferenceInterface depuis le setter de la propriété, vous pouvez redéfinir la méthode Notification pour
3
gérer les notifications depuis l'implémenteur de l'interface :
procedure TDemoComponent.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Assigned(MyIntfProp)) and (AComponent.IsImplementorOf(MyInftProp)) then
MyIntfProp := nil;
end;
Notez que le code de Notification assigne la valeur nil à la propriété MyIntfProp, et non au champ privé (FIntfField). Cela garantit

1263
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

que Notification appelle le setter de la propriété, qui appelle ReferenceInterface pour annuler la demande de notification établie
lorsque la valeur de la propriété a été définie au préalable. Toutes les assignations de la propriété interface doivent se faire via le
setter de la propriété.

3.2.1.4.16 Création de propriétés pour sous-composants


Par défaut, lorsque la valeur d'une propriété est un autre composant, vous lui attribuez une valeur en ajoutant à la fiche ou au
module de données une instance de cet autre composant et en assignant ensuite le composant comme valeur à la propriété.
Mais, il est aussi possible que votre composant crée sa propre instance de l'objet qui implémente la valeur de la propriété. Un tel
composant dédié s'appelle un sous-composant.

Les sous-composants peuvent être constitué de n'importe quel objet persistant (tout descendant de TPersistent). Au contraire
des composants séparés qui peuvent se trouver assignés comme valeur d'une propriété, les propriétés publiées des
sous-composants sont enregistrées avec le composant qui les crée. Mais, pour que cela fonctionne, les conditions suivantes
doivent être respectées :

• Le Owner du sous-composant doit être le composant qui le crée et l'utilise comme valeur d'une propriété publiée. Pour les
sous-composants descendant de TComponent, vous pouvez réaliser cela en définissant la propriété Owner du
sous-composant. Pour les autres sous-composants, vous devez redéfinir la méthode GetOwner de l'objet persistant de façon
à ce qu'elle renvoie le composant créateur.
• Si le sous-composant est un descendant de TComponent, il doit indiquer qu'il est un sous-composant en appelant la méthode
SetSubComponent. Habituellement, cet appel est effectué par le propriétaire lorsqu'il crée le sous-composant ou par le
constructeur du sous-composant.
Remarque: Lorsqu'un composant à sous-composants est mis en flux, les sous-composants ont désormais leur indicateur
csLoading défini et leur méthode Loaded appelée. Cela peut compliquer l'utilisation des propriétés de sous-composants qui
sont accessibles en écriture. Si vous permettez que la propriété de votre sous-composant soit attribuée à une référence de
composant externe, alors vous ne pouvez pas libérer votre sous-composant jusqu'à l'appel de la méthode Loaded de son
propriétaire. Sinon, le système de flux tentera d'appeler la méthode Loaded du sous-composant après la libération du
sous-composant.
En général, les propriétés dont les valeurs sont des sous-composants sont accessibles en lecture seulement. Si vous
autorisez la modification d'une propriété dont la valeur est un sous-composant, la méthode définissant la propriété, le setter,
doit libérer le sous-composant lorsqu'un autre composant est assigné comme valeur à la propriété. De plus, le composant
ré-instancie souvent son sous-composant lorsque la propriété est définie par nil. Sinon, lorsque la propriété a été définie par
un autre composant, le sous-composant ne peut plus être restauré à la conception.
Remarquez que le setter de la propriété a appelé la méthode FreeNotification du composant défini comme valeur de la
propriété. Cet appel garantit que le composant servant de valeur à la propriété envoie une notification au moment où il est sur
le point d'être détruit. Il envoie cette notification en appelant la méthode Notification. Vous gérez cet appel en redéfinissant la
méthode Notification.

3.2.1.4.17 Stockage et chargement des propriétés


Delphi stocke les fiches et leurs composants dans des fichiers fiche (.dfm dans les applications VCL). Un fichier fiche stocke les
propriétés d'une fiche et de ses composants. Lorsque les développeurs Delphi ajoutent à leurs fiches les composants que vous
avez écrits, vos composants doivent être capables d'enregistrer leurs propriétés dans le fichier fiche lors de sa sauvegarde. De
même, lorsqu'ils sont chargés dans Delphi ou exécutés comme éléments d'une application, vos composants doivent être
3
capables de se restituer eux-mêmes à partir du fichier fiche.

La plupart du temps, vous n'aurez rien à faire pour que vos composants fonctionnent avec un fichier fiche car la fonction de
stockage et de chargement d'une représentation fait partie du comportement reçu en héritage par tous les composants.
Toutefois, dans certaines circonstances, vous pouvez souhaiter modifier le stockage d'un composant ou son initialisation au
chargement. C'est pourquoi il est conseillé de comprendre les mécanismes sous-jacents.

Les aspects du stockage de propriétés qu'il est nécessaire d'expliquer sont les suivants :

1264
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

• Utilisation du mécanisme de stockage et de chargement ( see page 1265)


• Spécification des valeurs par défaut ( see page 1265)
• Détermination du stockage ( see page 1265)
• Initialisation après chargement ( see page 1266)
• Stockage et chargement des propriétés non publiées ( see page 1266)

3.2.1.4.18 Utilisation du mécanisme de stockage et de chargement


La description d'une fiche est la liste des propriétés de la fiche accompagnée d'une liste semblable pour chacun de ses
composants. Chaque composant, y compris la fiche elle-même, est responsable du stockage et du chargement de sa propre
description.

Lorsqu'il se stocke lui-même, un composant écrit implicitement les valeurs de toutes ses propriétés publiées si celles-ci sont
différentes de leurs valeurs par défaut, en respectant l'ordre dans lequel ont été déclarées ces valeurs. Au chargement, le
composant commence par se construire lui-même, toutes les propriétés récupérant leurs valeurs par défaut, puis il lit les valeurs
stockées des propriétés dont les valeurs ne correspondent pas aux valeurs par défaut.

Ce mécanisme implicite répond à la plupart des besoins des composants et ne nécessite aucune intervention particulière de la
part de l'auteur du composant. Néanmoins, il existe plusieurs moyens de personnaliser le processus de stockage et de
chargement pour répondre aux besoins particuliers d'un composant.

3.2.1.4.19 Spécification des valeurs par défaut


Les composants Delphi ne stockent la valeur des propriétés que si elles diffèrent des valeurs par défaut. Sauf indication
contraire, Delphi suppose qu'une propriété n'a pas de valeur par défaut, ce qui a pour conséquence que le composant stocke
toujours la propriété, quelle que soit sa valeur.

Pour spécifier une valeur par défaut pour une propriété, ajoutez la directive default et la nouvelle valeur par défaut à la fin de la
déclaration de la propriété.

Vous pouvez également spécifier une valeur par défaut en redéclarant une propriété. De fait, l'attribution d'une autre valeur par
défaut est l'une des raisons qui peut vous amener à redéclarer une propriété.
__property Alignment = {default=taCenter};
Remarque: La spécification d'une valeur par défaut n'a pas pour effet d'attribuer cette valeur à la propriété lorsque l'objet est
créé. Le constructeur du composant doit s'en charger. Une propriété dont la valeur n'est pas définie par le constructeur du
composant, a la valeur zéro, ou la valeur affichée par la propriété quand son stockage en mémoire est 0. Par défaut, les
nombres valent donc 0, les booléens False, les pointeurs nil, etc. En cas de doute, affectez une valeur dans la méthode du
constructeur.

3.2.1.4.20 Détermination du stockage


Vous pouvez choisir si Delphi stocke ou non chacune des propriétés de vos composants. Par défaut, sont stockées toutes les
propriétés de la partie published de la déclaration de classe. Vous pouvez choisir de ne pas stocker une propriété ou de
3
désigner une fonction qui décidera, de manière dynamique, du stockage de la propriété.

Pour contrôler le stockage par Delphi d'une propriété, ajoutez la directive stored à la déclaration de propriété, suivie par True,
False ou le nom d'une fonction booléenne.

1265
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.4.21 Initialisation après chargement


Après qu'un composant a lu les valeurs de toutes ses propriétés dans sa description stockée, il appelle une méthode virtuelle
appelée Loaded, qui effectue toutes les initialisations nécessaires. L'appel de Loaded s'exécute avant que ne s'affichent la fiche
et ses contrôles, ainsi vous n'avez pas à vous soucier du scintillement de l'écran provoqué par ces initialisations.

Pour initialiser un composant après le chargement des valeurs des propriétés, vous devez redéfinir la méthode Loaded.

Remarque: La première opération à accomplir dans une méthode Loaded consiste à appeler la méthode Loaded reçue en
héritage. Ceci afin d'être sûr que toutes les propriétés reçues en héritage sont correctement initialisées avant d'effectuer
l'initialisation de votre propre composant.

Le code suivant provient du composant TDatabase. Après chargement, la base de données essaie de rétablir toutes les
connexions ouvertes au moment du stockage, et spécifie comment gérer toutes les exceptions qui se produisent pendant la
connexion.
procedure TDatabase.Loaded;
begin
inherited Loaded; { appeler d'abord la méthode héritée }
try
if FStreamedConnected then Open { rétablir les connexions }
else CheckSessionName(False);
except
if csDesigning in ComponentState then { lors de la
conception... }
Application.HandleException(Self) { permet à Delphi de gérer l'exception }
else raise; { sinon, redéclencher }
end;
end;

3.2.1.4.22 Stockage et chargement des propriétés non publiées


Par défaut, seules les propriétés publiées sont chargées et enregistrées avec un composant. Cependant, il est possible de
charger et d'enregistrer des propriétés non publiées. Ceci permet d'obtenir des propriétés persistantes n'apparaissant pas dans
l'inspecteur d'objets. Cela permet aussi le stockage et le chargement des valeurs de propriétés par les composants, valeurs de
propriétés que Delphi ne sait pas comment lire ni écrire car elles sont trop complexes. Par exemple, l'objet TStrings ne peut pas
compter sur le comportement automatique de Delphi pour stocker et charger les chaînes qu'il représente et doit utiliser le
mécanisme suivant.

Vous pouvez enregistrer des propriétés non publiées en ajoutant du code indiquant à Delphi comment charger et enregistrer la
valeur de propriété.

Pour écrire votre propre code afin de charger et d'enregistrer des propriétés, utilisez les étapes suivantes :

1. Création de méthodes pour le stockage et le chargement de valeurs de propriétés ( see page 1266).
2. Redéfinissez la méthode DefineProperties ( see page 1267), en transmettant ces méthodes à un objet filer.

3 3.2.1.4.23 Création de méthodes pour le stockage et le chargement de valeurs


de propriétés
Pour stocker et charger des propriétés non publiées, vous devez d'abord créer une méthode afin de stocker la valeur de
propriété et une autre méthode pour la charger. Deux possibilités s'offrent à vous :

• Créer une méthode de type TWriterProc afin de stocker la valeur de propriété et une méthode de type TReaderProc pour la
charger. Cette approche vous permet de profiter des capacités intégrées de Delphi concernant l'enregistrement et le
chargement de types simples. Si la valeur de votre propriété est construite à partir de types que Delphi sait enregistrer et
charger, utilisez cette approche.

1266
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

• Créer deux méthodes de type TStreamProc, une pour stocker et une pour charger la valeur de propriété. TStreamProc
accepte un flux comme argument et vous pouvez utiliser les méthodes du flux afin d'écrire et lire les valeurs de propriétés.
Prenons pour exemple une propriété représentant un composant créé à l'exécution. Delphi sait comment écrire cette valeur,
mais ne le fait pas automatiquement car le composant n'est pas créé dans le concepteur de fiches. Puisque le système de
flux peut dès à présent charger et enregistrer des composants, vous pouvez utiliser la première approche. Les méthodes
suivantes chargent et stockent le composant créé dynamiquement qui représente la valeur d'une propriété appelée
MyCompProperty :
procedure TSampleComponent.LoadCompProperty(Reader: TReader);
begin
if Reader.ReadBoolean then
MyCompProperty := Reader.ReadComponent(nil);
end;
procedure TSampleComponent.StoreCompProperty(Writer: TWriter);
begin
Writer.WriteBoolean(MyCompProperty <> nil);
if MyCompProperty <> nil then
Writer.WriteComponent(MyCompProperty);
end;
void __fastcall TSampleComponent::LoadCompProperty(TReader *Reader)
{
if (Reader->ReadBoolean())
MyCompProperty = Reader->ReadComponent(NULL);
}
void __fastcall TSampleComponent::StoreCompProperty(TWriter *Writer)
{
if (MyCompProperty)
{
Writer->WriteBoolean(true);
Writer->WriteComponent(MyCompProperty);
}
else
Writer->WriteBoolean(false);
}

3.2.1.4.24 Redéfinition de la méthode DefineProperties


Après avoir créé des méthodes de stockage et de chargement de la valeur de propriété, vous pouvez redéfinir la méthode
DefineProperties du composant. Delphi appelle cette méthode lors du chargement ou du stockage du composant. Dans la
méthode DefineProperties, vous devez appeler la méthode DefineProperty ou DefineBinaryProperty du filer en cours, en lui
transmettant la méthode à utiliser pour le chargement ou l'enregistrement de la valeur de propriété. Si vos méthodes de
chargement et de stockage sont des types TWriterProc et TReaderProc, vous appelez alors la méthode DefineProperty du filer.
Si vous avez créé des méthodes de type TStreamProc, appelez plutôt DefineBinaryProperty.

Peu importe la méthode utilisée pour définir la propriété, vous lui transmettez les méthodes enregistrant et chargeant votre
valeur de propriété ainsi qu'une valeur booléenne indiquant si la valeur de propriété doit être écrite ou non. S'il peut s'agir d'une
valeur héritée ou si elle a une valeur par défaut, il n'est pas nécessaire de l'écrire.

Soit par exemple la méthode LoadCompProperty du type TReaderProc et la méthode StoreCompProperty du type TWriterProc,
vous redéfiniriez DefineProperties de la manière suivante :
procedure TSampleComponent.DefineProperties(Filer: TFiler);
function DoWrite: Boolean; 3
begin
if Filer.Ancestor <> nil then { tester Ancestor pour une valeur héritée }
begin
if TSampleComponent(Filer.Ancestor).MyCompProperty = nil then
Result := MyCompProperty <> nil
else if (MyCompProperty = nil) or
(TMy5Comp(Filer.Ancestor).MyCompProperty.Name <> MyCompProperty.Name) then
Result := True
else Result := False;

1267
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

end
else { pas de valeur héritée – tester pour une valeur par défaut nil) }
Result := MyCompProperty <> nil;
end;
begin
inherited; { autoriser les classes de base pour définir les propriétés }
Filer.DefineProperty('MyCompProperty', LoadCompProperty, StoreCompProperty, DoWrite);
end;
void __fastcall TSampleComponent::DefineProperties(TFiler *Filer)
{
// autorise au préalable les classes de base à définir leurs propriétés.
// Dans le cadre de cet exemple, TSampleComponent dérive directement de TComponent
TComponent::DefineProperties(Filer);
bool WriteValue;
if (Filer->Ancestor) // teste pour une valeur héritée
{
if ((TSampleComponent *)Filer->Ancestor)->MyCompProperty == NULL)
WriteValue = (MyCompProperty != NULL);
else if ((MyCompProperty == NULL) ||
(((TSampleComponent *)Filer->Ancestor)->MyCompProperty->Name !=
MyCompProperty->Name))
WriteValue = true;
else WriteValue = false;
}
else // si aucune valeur héritée, écrit la propriété si différente de NULL
WriteValue = (MyCompProperty != NULL);
Filer->DefineProperty("MyCompProperty ",LoadCompProperty,StoreCompProperty, WriteValue);
end;

3.2.1.5 Personnalisation d'une grille


Rubriques
Nom Description
Accès au jour, au mois et à l'année ( see page 1270) Une date encodée numériquement est adaptée aux applications, mais l'utilisateur
préférera manipuler jour, mois et année. En créant des propriétés, vous offrez un
accès aux dates stockées et encodées numériquement.
Les éléments d'une date (jour, mois, année) sont des entiers. La modification de
chacun d'entre eux nécessite l'encodage de la date. Vous pouvez éviter la
duplication du code en partageant les méthodes d'implémentation entre les trois
propriétés. Autrement dit, vous pouvez écrire deux méthodes, l'une pour lire un
élément et l'autre pour l'écrire, et utiliser ces méthodes pour lire et écrire les trois
propriétés.
Modification des valeurs initiales ( see page 1272) Un calendrier est essentiellement une grille avec un nombre fixe de lignes et de
colonnes, ne contenant pas nécessairement des dates. Les propriétés ColCount
et RowCount de la grille n'ont donc pas été publiées, car il est peu probable que
les utilisateurs du calendrier voudront afficher autre chose que les sept jours de
la semaine. Vous devez néanmoins définir les valeurs initiales de ces propriétés
en fonction des sept jours de la semaine.
Pour changer les valeurs initiales des propriétés du composant, vous devez
redéfinir le constructeur afin qu'il affecte les valeurs voulues. Le constructeur doit
être virtuel.
Souvenez-vous que... suite ( see page 1272)
Création et recensement du composant ( see page 1273) La création d'un composant se fait toujours de la même façon : vous créez une
unité et vous recensez le composant avant de l'installer dans la palette d'outils.
Création d'un nouveau composant. ( see page 1330)
3

1268
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Personnalisation d'une grille : Vue globale ( see page 1275) La bibliothèque de composants fournit plusieurs composants abstraits que vous
pouvez utiliser comme points de départ pour personnaliser vos composants. Les
grilles et les boîtes liste sont les plus importants. Les rubriques suivantes
décrivent comment créer un petit calendrier en partant du composant grille de
base TCustomGrid :

• Création et recensement du composant ( see page


1273)
• Publication des propriétés héritées ( see page 1282)
• Modification des valeurs initiales ( see page 1272)
• Redimensionnement des cellules ( see page 1283)
• Remplissage des cellules ( see page 1275)
• Navigation de mois en mois et d'année en année ( see
page 1280)
• Navigation de jour en jour ( see page 1279)
Dans les applications VCL, le composant calendrier résultant
est pratiquement identique au composant TCalendar
contenu dans la catégorie Exemples... suite ( see page
1275)
Exclusion des cellules vides ( see page 1275) Tel qu'il est actuellement, le calendrier déplace la sélection vers une cellule vide
sans changer la date. Il devient intéressant d'empêcher la sélection des cellules
vides.
Pour déterminer si une cellule est sélectionnable, vous devez redéfinir la
méthode SelectCell de la grille.
SelectCell est une fonction qui accepte deux paramètres ligne et colonne et qui
renvoie une valeur booléenne indiquant si la cellule spécifiée est sélectionnable.
Vous pouvez redéfinir SelectCell pour qu'elle renvoie False si la cellule ne
contient pas une date valide :
Remplissage des cellules ( see page 1275) Un contrôle grille se remplit cellule par cellule. S'agissant du calendrier, cela
revient à calculer une date (si elle existe) pour chaque cellule. Le dessin par
défaut des cellules de la grille s'opère dans une méthode virtuelle intitulée
DrawCell.
Pour remplir le contenu des cellules de la grille, vous devez redéfinir la méthode
DrawCell.
Les cellules de titre de la ligne fixe sont ce qu'il y a de plus facile à remplir. La
bibliothèque d'exécution contient un tableau avec l'intitulé raccourci des jours et il
vous faut donc insérer l'intitulé approprié à chaque colonne :
Génération des numéros de jours ( see page 1276) Insérer les numéros des jours dans le calendrier nécessite plusieurs
considérations. Le nombre de jours dans le mois dépend à la fois du mois et de
l'année. Le jour de la semaine qui débute le mois dépend aussi du mois et de
l'année. Utilisez la fonction IsLeapYear pour déterminer si l'année est bissextile.
Utilisez le tableau MonthDays dans l'unité SysUtils pour obtenir le nombre de
jours dans le mois.
Une fois récupérées les informations concernant les années bissextiles et le
nombre de jours par mois, vous pouvez calculer l'endroit de la grille où s'insère
chaque date. Le calcul dépend... suite ( see page 1276)
Déplacement de la sélection ( see page 1279) Le comportement reçu en héritage d'une grille gère le déplacement de la
sélection en réponse aux touches de direction enfoncées ou aux clics de souris.
Pour modifier le jour sélectionné, vous devez modifier le comportement implicite.
Pour gérer les déplacements à l'intérieur du calendrier, vous devez redéfinir la
méthode Click de la grille.
Lorsque vous redéfinissez une méthode telle que Click, en dépendance étroite
avec les interactions de l'utilisateur, vous devez pratiquement toujours inclure un
appel à la méthode reçue en héritage pour ne pas perdre le comportement 3
standard.
Le code suivant est une méthode Click redéfinie pour la... suite ( see page
1279)

1269
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Navigation de jour en jour ( see page 1279) A l'intérieur d'un même mois, il existe deux moyens évidents pour naviguer parmi
les jours. Le premier consiste à utiliser les touches de direction et le deuxième à
répondre aux clics de la souris. Le composant grille standard les gère tous les
deux indistinctement en tant que clics de souris. Autrement dit, le déplacement
avec les touches de direction est pris en compte comme un clic sur une cellule
adjacente.
Le processus de navigation de jour en jour comprend :

• Déplacement de la sélection ( see page 1279)


• Fourniture d'un événement OnChange ( see page 1281)
• Exclusion des cellules vides ( see page 1275)
Navigation de mois en mois et d'année en année ( see page 1280) Les propriétés sont particulièrement utiles pour manipuler les composants, en
particulier lors de la conception. Mais lorsque des manipulations fréquentes ou
instinctives font intervenir plusieurs propriétés, il paraît judicieux de fournir des
méthodes pour les gérer. Le passage au "mois suivant" dans notre calendrier est
un exemple de ce type. Le bouclage sur les douze mois avec l'incrémentation de
l'année est à la fois une caractéristique simple et commode pour le programmeur
qui utilise le composant.
Le seul inconvénient à l'encapsulation des manipulations les plus fréquentes
sous la forme de méthodes est le suivant : les méthodes ne sont accessibles
qu'à... suite ( see page 1280)
Fourniture d'un événement OnChange ( see page 1281) Les utilisateurs de votre calendrier ont maintenant la possibilité de changer la
date. Il paraît donc judicieux de répondre à ces changements.
Publication des propriétés héritées ( see page 1282) Le composant grille abstrait, TCustomGrid, fournit de nombreuses propriétés
protected. Vous pouvez choisir parmi ces propriétés celles que vous voulez
rendre accessibles aux utilisateurs du contrôle calendrier.
Pour rendre accessibles aux utilisateurs de vos composants les propriétés
protégées qu'ils reçoivent en héritage, vous devez redéclarer ces propriétés dans
la partie published de la déclaration de vos composants.
S'agissant du contrôle calendrier, vous devez publier les propriétés et les
événements, comme ci-dessous :
Redimensionnement des cellules ( see page 1283) Remarque: Lorsqu'un utilisateur ou une application modifie la taille d'une
fenêtre ou d'un contrôle, Windows envoie le message WM_SIZE à la fenêtre ou
au contrôle concerné pour lui permettre d'ajuster les paramètres nécessaires afin
de dessiner ultérieurement son image dans la nouvelle taille. Votre composant
VCL peut répondre à ce message en modifiant la taille des cellules de façon à ce
qu'elles s'inscrivent dans les limites du contrôle. Pour répondre au message
WM_SIZE, vous devez ajouter au composant une méthode de gestion du
message.
La création d'une méthode de gestion de message est décrite en détail dans la
section... suite ( see page 1283)
Sélection du jour en cours ( see page 1285) Maintenant que les numéros des jours s'affichent dans les cellules du calendrier,
il devient intéressant de savoir positionner la surbrillance sur le jour en cours.
Comme la sélection se positionne implicitement sur la cellule située en haut et à
gauche, vous devez définir les propriétés Row et Column au moment de la
construction initiale du calendrier ainsi qu'à chaque changement de date.
Pour positionner la sélection dans la cellule du jour en cours, modifiez la
méthode UpdateCalendar pour définir Row et Column avant d'appeler Refresh :
Stockage interne de la date ( see page 1285) Pour stocker la date du calendrier, vous devez avoir un champ contenant la date,
ainsi qu'une propriété accessible à l'exécution seulement qui fournit un accès à
cette date.
Suivi de la date ( see page 1286) Pour que le contrôle calendrier soit utile, les utilisateurs ainsi que les applications
doivent disposer d'un moyen de définir la date, le mois et l'année. Delphi stocke
les dates et les heures dans des variables de type TDateTime. TDateTime est
une représentation numérique encodée des dates et des heures particulièrement
pratique pour être manipulée par un programme mais peu commode à interpréter
par un utilisateur.
Vous pouvez donc stocker la date du calendrier sous une forme encodée et
3 fournir un accès direct à cette valeur lors de l'exécution, mais vous pouvez aussi
fournir les propriétés Day, Month et... suite ( see page 1286)

3.2.1.5.1 Accès au jour, au mois et à l'année


Une date encodée numériquement est adaptée aux applications, mais l'utilisateur préférera manipuler jour, mois et année. En
créant des propriétés, vous offrez un accès aux dates stockées et encodées numériquement.

Les éléments d'une date (jour, mois, année) sont des entiers. La modification de chacun d'entre eux nécessite l'encodage de la

1270
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

date. Vous pouvez éviter la duplication du code en partageant les méthodes d'implémentation entre les trois propriétés.
Autrement dit, vous pouvez écrire deux méthodes, l'une pour lire un élément et l'autre pour l'écrire, et utiliser ces méthodes pour
lire et écrire les trois propriétés.

Pour fournir un accès lors de la conception aux éléments jour, mois et année, procédez de la façon suivante :
1. Déclarez les trois propriétés, en attribuant à chacune un numéro unique d'index :
type
TSampleCalendar = class(TCustomGrid)
public
property Day: Integer index 3 read GetDateElement write SetDateElement;
property Month: Integer index 2 read GetDateElement write SetDateElement;
property Year: Integer index 1 read GetDateElement write SetDateElement;
.
.
.
class PACKAGE TSampleCalendar : public TCustomGrid
{
.
.
.
public:
__property int Day = {read=GetDateElement, write=SetDateElement, index=3,
nodefault};
__property int Month = {read=GetDateElement, write=SetDateElement, index=2,
nodefault};
__property int Year = {read=GetDateElement, write=SetDateElement, index=1,
nodefault};
};
2. Déclarez et écrivez les méthodes d'implémentation, définissant les différents éléments pour chaque valeur d'index :
type
TSampleCalendar = class(TCustomGrid)
private
function GetDateElement(Index: Integer): Integer; { notez le paramètre Index }
procedure SetDateElement(Index: Integer; Value: Integer);
.
.
.
function TSampleCalendar.GetDateElement(Index: Integer): Integer;
var
AYear, AMonth, ADay: Word;
begin
DecodeDate(FDate, AYear, AMonth, ADay); { éclate la date encodée en éléments }
case Index of
1: Result := AYear;
2: Result := AMonth;
3: Result := ADay;
else Result := -1;
end;
end;
procedure TSampleCalendar.SetDateElement(Index: Integer; Value: Integer);
var
AYear, AMonth, ADay: Word;
begin 3
if Value > 0 then { tous les éléments doivent être
positifs }
begin
DecodeDate(FDate, AYear, AMonth, ADay); { récupère les éléments courants
de la date }
case Index of { définit le nouvel élément selon l'index }
1: AYear := Value;
2: AMonth := Value;
3: ADay := Value;

1271
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

else Exit;
end;
FDate := EncodeDate(AYear, AMonth, ADay); { encode la date modifiée }
Refresh; { mise à jour du calendrier visible
}
end;
end;
// fichier en-tête
class PACKAGE TSampleCalendar : public TCustomGrid
{
private:
int __fastcall GetDateElement(int Index); // remarquez le paramètre Index
void __fastcall SetDateElement(int Index, int Value);
.
.
.
};
// fichier d'implémentation
int __fastcall TSampleCalendar::GetDateElement(int Index)
{
unsigned short AYear, AMonth, ADay;
int result;
FDate.DecodeDate(&AYear, &AMonth, &ADay); // décompose la date codée en éléments
switch (Index)
{
case 1: result = AYear; break;
case 2: result = AMonth; break;
case 3: result = ADay; break;
default: result = -1;
}
return result;
}
void __fastcall TSampleCalendar::SetDateElement(int Index, int Value)
{
unsigned short AYear, AMonth, ADay;
if (Value > 0) // tous les éléments doivent être positifs
{
FDate.DecodeDate(&AYear, &AMonth, &ADay); // récupère les éléments de la date en cours
switch (Index)
{
case 1: AYear = Value; break;
case 2: AMonth = Value; break;
case 3: ADay = Value; break;
default: return;
}
}
FDate = TDateTime(AYear, AMonth, ADay); // code la date modifiée
Refresh(); // met à jour le calendrier visible
}
Vous pouvez maintenant définir le jour, le mois et l'année du calendrier lors de la conception à partir de l'inspecteur d'objets, ou
à l'exécution à partir du code. Bien que vous n'ayez pas encore ajouté le code pour dessiner les dates dans les cellules, vous
disposez maintenant de toutes les données nécessaires.

3 3.2.1.5.2 Modification des valeurs initiales


Un calendrier est essentiellement une grille avec un nombre fixe de lignes et de colonnes, ne contenant pas nécessairement des
dates. Les propriétés ColCount et RowCount de la grille n'ont donc pas été publiées, car il est peu probable que les utilisateurs
du calendrier voudront afficher autre chose que les sept jours de la semaine. Vous devez néanmoins définir les valeurs initiales
de ces propriétés en fonction des sept jours de la semaine.

Pour changer les valeurs initiales des propriétés du composant, vous devez redéfinir le constructeur afin qu'il affecte les valeurs
voulues. Le constructeur doit être virtuel.

1272
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Souvenez-vous que vous devez ajouter le constructeur à la partie public de la déclaration de la classe du composant, puis
écrire le nouveau constructeur dans la partie implémentation de l'unité du composant. La première instruction du nouveau
constructeur doit toujours être un appel au constructeur hérité. Ensuite, ajoutez l'unité StdCtrls à la clause uses.
type
TSampleCalendar = class(TCustomGrid)
public
constructor Create(AOwner: TComponent); override;
.
.
.
end;
.
.
.
constructor TSampleCalendar.Create(AOwner: TComponent);
begin
inherited Create(AOwner); { appelle le constructeur hérité }
ColCount := 7; { toujours 7 jours/semaine }
RowCount := 7; { toujours 6 semaines plus les titres }
FixedCols := 0; { aucun libellé de
ligne }
FixedRows := 1; { une ligne pour les noms de
jour }
ScrollBars := ssNone; { pas de défilement
nécessaire }
Options := Options - [goRangeSelect] + [goDrawFocusSelected]; {désactive la sélection
d'intervalle}
end;
// fichier en-tête
class PACKAGE TSampleCalendar : public TCustomGrid
{
protected:
virtual void __fastcall DrawCell(int ACol, int ARow, const Windows::TRect &Rect,
TGridDrawState AState);
.
.
.
public:
__fastcall TSampleCalendar(TComponent *Owner); // le constructeur ajouté
.
.
.
};
// fichier d'implémentation
__fastcall TSampleCalendar::TSampleCalendar(TComponent *Owner) : TCustomGrid(Owner)
{
ColCount = 7;
RowCount = 7;
FixedCols = 0;
FixedRows = 1;
ScrollBars = ssNone;
Options = (Options >> goRangeSelect) << goDrawFocusSelected;
}
void __fastcall TSampleCalendar::DrawCell(int ACol, int ARow, const Windows::TRect
&ARect, TGridDrawState AState) 3
{
}
Le calendrier a dorénavant sept colonnes et sept lignes, avec la ligne de titre fixe (ou qui ne défile pas).

3.2.1.5.3 Création et recensement du composant


La création d'un composant se fait toujours de la même façon : vous créez une unité et vous recensez le composant avant de

1273
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

l'installer dans la palette d'outils. Création d'un nouveau composant. ( see page 1330)

Pour notre exemple, suivez la procédure générale de création d'un composant en tenant compte des spécificités
suivantes :
1. Enregistrez l'unité du composant sous CalSamp.
2. Dérivez un nouveau type de composant appelé TSampleCalendar, descendant de TCustomGrid.
3. Recensez TSampleCalendar dans la catégorie Exemples de la palette d'outils.
L'unité résultante dérivée de TCustomGrid dans une application VCL doit ressembler à ceci :
unit CalSamp;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids;
type
TSampleCalendar = class(TCustomGrid)
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Exemples', [TSampleCalendar]);
end;
end.
#include <vcl\vcl.h>
#pragma hdrstop
#include "CalSamp.h"
//---------------------------------------------------------------------------
#pragma package(smart_init);
//---------------------------------------------------------------------------
static inline TSampleCalendar *ValidCtrCheck()
{
return new TSampleCalendar(NULL);
}
//---------------------------------------------------------------------------
namespace Calsamp
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TSampleCalendar)};
RegisterComponents("Samples", classes, 0); //Utilisation d'une page différente dans les
applications CLX
}
}
#ifndef CalSampH
#define CalSampH
//---------------------------------------------------------------------------
#include <vcl\sysutils.hpp>
#include <vcl\controls.hpp>
#include <vcl\classes.hpp>
#include <vcl\forms.hpp>
#include <vcl\grids.hpp>
//---------------------------------------------------------------------------
class PACKAGE TSampleCalendar : public TCustomGrid
3 {
private:
protected:
public:
__published:
};
//---------------------------------------------------------------------------
#endif
Si vous installez le composant calendrier maintenant, vous verrez qu'il apparaît sur la catégorie Exemples. Les seules propriétés

1274
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

disponibles sont les propriétés de contrôle les plus basiques. L'étape suivante consiste à rendre disponible certaines des
propriétés plus spécialisées aux utilisateurs du calendrier.

Remarque: Bien que vous puissiez installer le composant calendrier exemple que vous venez de compiler, n'essayez pas de le
placer tout de suite sur une fiche. Le composant TCustomGrid contient une méthode DrawCell abstraite qui doit être redéclarée
avant que les objets d'instance puissent être créés. La redéfinition de la méthode DrawCell est décrite dans Remplissage des
cellules ( see page 1275)

3.2.1.5.4 Personnalisation d'une grille : Vue globale


La bibliothèque de composants fournit plusieurs composants abstraits que vous pouvez utiliser comme points de départ pour
personnaliser vos composants. Les grilles et les boîtes liste sont les plus importants. Les rubriques suivantes décrivent comment
créer un petit calendrier en partant du composant grille de base TCustomGrid :

• Création et recensement du composant ( see page 1273)


• Publication des propriétés héritées ( see page 1282)
• Modification des valeurs initiales ( see page 1272)
• Redimensionnement des cellules ( see page 1283)
• Remplissage des cellules ( see page 1275)
• Navigation de mois en mois et d'année en année ( see page 1280)
• Navigation de jour en jour ( see page 1279)
Dans les applications VCL, le composant calendrier résultant est pratiquement identique au composant TCalendar contenu dans
la catégorie Exemples de la palette d'outils. Voir Spécification de la page de palette ( see page 1373).

3.2.1.5.5 Exclusion des cellules vides


Tel qu'il est actuellement, le calendrier déplace la sélection vers une cellule vide sans changer la date. Il devient intéressant
d'empêcher la sélection des cellules vides.

Pour déterminer si une cellule est sélectionnable, vous devez redéfinir la méthode SelectCell de la grille.

SelectCell est une fonction qui accepte deux paramètres ligne et colonne et qui renvoie une valeur booléenne indiquant si la
cellule spécifiée est sélectionnable.

Vous pouvez redéfinir SelectCell pour qu'elle renvoie False si la cellule ne contient pas une date valide :
function TSampleCalendar.SelectCell(ACol, ARow: Longint): Boolean;
begin
if DayNum(ACol, ARow) = -1 then Result := False { -1 indique une date incorrecte }
else Result := inherited SelectCell(ACol, ARow); { sinon, utilise la valeur héritée }
end;
bool __fastcall TSampleCalendar::SelectCell(int ACol, int ARow)
{
if (DayNum(ACol,ARow) == -1) return false; // -1 indique une date incorrecte
else return TCustomGrid::SelectCell(ACol, ARow); // sinon, utilise la valeur héritée
} 3
Désormais, si l'utilisateur clique sur une cellule vide ou tente de s'y déplacer à l'aide des touches de direction, le calendrier ne
modifie pas la sélection en cours.

3.2.1.5.6 Remplissage des cellules


Un contrôle grille se remplit cellule par cellule. S'agissant du calendrier, cela revient à calculer une date (si elle existe) pour
chaque cellule. Le dessin par défaut des cellules de la grille s'opère dans une méthode virtuelle intitulée DrawCell.

1275
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Pour remplir le contenu des cellules de la grille, vous devez redéfinir la méthode DrawCell.

Les cellules de titre de la ligne fixe sont ce qu'il y a de plus facile à remplir. La bibliothèque d'exécution contient un tableau avec
l'intitulé raccourci des jours et il vous faut donc insérer l'intitulé approprié à chaque colonne :
type
TSampleCalendar = class(TCustomGrid)
protected
procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
override;
end;
.
.
.
procedure TSampleCalendar.DrawCell(ACol, ARow: Longint; ARect: TRect;
AState: TGridDrawState);
begin
if ARow = 0 then
Canvas.TextOut(ARect.Left, ARect.Top, ShortDayNames[ACol + 1]); { utilise les chaînes
RTL }
end;
void __fastcall TSampleCalendar::DrawCell(int ACol, int ARow, const Windows::TRect &ARect,
TGridDrawState AState)
{
String TheText;
int TempDay;
if (ARow == 0) TheText = ShortDayNames[ACol + 1];
else
{
TheText = "";
TempDay = DayNum(ACol, ARow); // DayNum est défini après
if (TempDay != -1) TheText = IntToStr(TempDay);
}
Canvas->TextRect(ARect, ARect.Left + (ARect.Right - ARect.Left
- Canvas->TextWidth(TheText)) / 2,
ARect.Top + (ARect.Bottom - ARect.Top - Canvas->TextHeight(TheText)) / 2, TheText);
}

3.2.1.5.7 Génération des numéros de jours


Insérer les numéros des jours dans le calendrier nécessite plusieurs considérations. Le nombre de jours dans le mois dépend à
la fois du mois et de l'année. Le jour de la semaine qui débute le mois dépend aussi du mois et de l'année. Utilisez la fonction
IsLeapYear pour déterminer si l'année est bissextile. Utilisez le tableau MonthDays dans l'unité SysUtils pour obtenir le nombre
de jours dans le mois.

Une fois récupérées les informations concernant les années bissextiles et le nombre de jours par mois, vous pouvez calculer
l'endroit de la grille où s'insère chaque date. Le calcul dépend du premier jour du mois.

Comme vous devez considérer le décalage du premier jour du mois, par rapport à l'origine de la grille, pour chaque cellule à
remplir, le meilleur choix consiste à calculer ce nombre après chaque changement de mois ou d'année, et de s'y reporter à
chaque fois. Vous pouvez stocker cette valeur dans un champ de classe, puis mettre à jour ce champ à chaque modification de
la date.
3
Pour remplir les cellules avec les numéros de jour appropriés, procédez de la façon suivante :
1. Ajoutez à la classe un champ décalage du premier jour du mois, ainsi qu'une méthode pour mettre à jour la valeur du champ :
type
TSampleCalendar = class(TCustomGrid)
private
FMonthOffset: Integer; { stocke le décalage }
.
.

1276
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

.
protected
procedure UpdateCalendar; virtual; { propriété pour l'accès au
décalage }
end;
.
.
.
procedure TSampleCalendar.UpdateCalendar;
var
AYear, AMonth, ADay: Word;
FirstDate: TDateTime; { date du premier jour du mois }
begin
if FDate <> 0 then { ne calcule le décalage que si la date est
valide }
begin
DecodeDate(FDate, AYear, AMonth, ADay); { récupère les éléments de
la date }
FirstDate := EncodeDate(AYear, AMonth, 1); { date du premier jour du
mois }
FMonthOffset := 2 - DayOfWeek(FirstDate); { génère le décalage dans la grille }
end;
Refresh; { toujours repeindre le contrôle }
end;
class PACKAGE TSampleCalendar : public TCustomGrid
{
private:
int FMonthOffset; // stocke le décalage
.
.
.
protected:
virtual void __fastcall UpdateCalendar(void);
.
.
.
};
void __fastcall TSampleCalendar::UpdateCalendar(void)
{
unsigned short AYear, AMonth, ADay;
TDateTime FirstDate; // date du premier jour du mois
if ((int)FDate != 0) // ne calcule le décalage que si la date est
valide
{
FDate.DecodeDate(&AYear, &AMonth, &ADay); // récupère les éléments de la date
FirstDate = TDateTime(AYear, AMonth, 1); // date du premier jour du mois
FMonthOffset = 2 - FirstDate.DayOfWeek(); // génère le décalage dans la grille
}
Refresh(); // toujours repeindre le contrôle
}
2. Ajoutez les instructions au constructeur et aux méthodes SetCalendarDate et SetDateElement qui appellent la nouvelle
méthode de mise à jour à chaque changement de date :
constructor TSampleCalendar.Create(AOwner: TComponent);
begin
inherited Create(AOwner); { existait déjà } 3
. { d'autres initialisations ici }
.
.
UpdateCalendar; { définit le bon décalage
}
end;
procedure TSampleCalendar.SetCalendarDate(Value: TDateTime);
begin FDate := Value; { existait déjà }
UpdateCalendar; { appelait précédemment Refresh }
end;

1277
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

procedure TSampleCalendar.SetDateElement(Index: Integer; Value: Integer);


begin
.
.
.
FDate := EncodeDate(AYear, AMonth, ADay); { encode la date modifiée }
UpdateCalendar; { appelait précédemment Refresh }
end;
end;
__fastcall TSampleCalendar::TSampleCalendar(TComponent *Owner)
: TCustomGrid(Owner)
{
.
.
.
UpdateCalendar();
}
void __fastcall TSampleCalendar::SetCalendarDate(TDateTime Value)
{
FDate = Value; // existait déjà
UpdateCalendar(); // appelait précédemment Refresh
}
void __fastcall TSampleCalendar::SetDateElement(int Index, int Value)
{
.
.
.
FDate = TDateTime(AYear, AMonth, ADay); // existait déjà
UpdateCalendar(); // appelait précédemment Refresh
}
3. Ajoutez une méthode au calendrier renvoyant le numéro du jour à partir des coordonnées ligne/colonne d'une cellule qui lui
sont transmises :
function TSampleCalendar.DayNum(ACol, ARow: Integer): Integer;
begin
Result := FMonthOffset + ACol + (ARow - 1) * 7; { calcule le jour pour cette
cellule }
if (Result < 1) or (Result > MonthDays[IsLeapYear(Year), Month]) then
Result := -1; { renvoie -1 si incorrect }
end;
int __fastcall TSampleCalendar::DayNum(int ACol, int ARow)
{
int result = FMonthOffset + ACol + (ARow - 1) * 7; // calcule le jour pour cette
cellule
if ((result < 1)||(result > MonthDays[IsLeapYear(Year)][Month]))
result = -1; // renvoie -1 si incorrect
return result;
}
Pensez à ajouter la déclaration de DayNum à la déclaration de type du composant.

4. Vous pouvez désormais calculer l'endroit où s'affichent les dates, et mettre à jour DrawCell pour remplir les cellules :
procedure TCalendar.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
var
TheText: string;
3 TempDay: Integer;
begin
if ARow = 0 then { s'il s'agit de la ligne de titre
...}
TheText := ShortDayNames[ACol + 1] { utilise le nom du jour }
else begin
TheText := ''; { cellule vide par défaut }
TempDay := DayNum(ACol, ARow); { récupère le numéro de cette
cellule }
if TempDay <> -1 then TheText := IntToStr(TempDay); { utilise ce numéro s'il est
valide }

1278
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

end;
with ARect, Canvas do
TextRect(ARect, Left + (Right - Left - TextWidth(TheText)) div 2,
Top + (Bottom - Top - TextHeight(TheText)) div 2, TheText);
end;
void __fastcall TSampleCalendar::DrawCell(int ACol, int ARow, const TRect &ARect,
TGridDrawState AState)
{
String TheText;
int TempDay;
if (ARow == 0) // ligne de titre
TheText = ShortDayNames[ACol + 1]; // utilisez le nom du jour
else
{
TheText = ""; // cellule vide par défaut
TempDay = DayNum(ACol, ARow); // récupère le numéro pour cette cellule
if (TempDay != -1) TheText = IntToStr(TempDay); // utilise ce numéro s'il est valide
}
Canvas->TextRect(ARect, ARect.Left + (ARect.Right - ARect.Left -
Canvas->TextWidth(TheText)) / 2,
ARect.Top + (ARect.Bottom - ARect.Top - Canvas->TextHeight(TheText)) / 2, TheText);
}
Si maintenant vous réinstallez le composant calendrier et le placez dans une fiche, les informations correspondant au mois en
cours apparaîtront.

3.2.1.5.8 Déplacement de la sélection


Le comportement reçu en héritage d'une grille gère le déplacement de la sélection en réponse aux touches de direction
enfoncées ou aux clics de souris. Pour modifier le jour sélectionné, vous devez modifier le comportement implicite.

Pour gérer les déplacements à l'intérieur du calendrier, vous devez redéfinir la méthode Click de la grille.

Lorsque vous redéfinissez une méthode telle que Click, en dépendance étroite avec les interactions de l'utilisateur, vous devez
pratiquement toujours inclure un appel à la méthode reçue en héritage pour ne pas perdre le comportement standard.

Le code suivant est une méthode Click redéfinie pour la grille calendrier. N'oubliez pas d'ajouter la déclaration de Click à
TSampleCalendar, en incluant après la directive override.
procedure TSampleCalendar.Click;
var
TempDay: Integer;
begin
inherited Click; { n'oubliez pas d'appeler la méthode héritée !
}
TempDay := DayNum(Col, Row); { récupère le numéro du jour de la cellule
cliquée }
if TempDay <> -1 then Day := TempDay; { change le jour s'il est
valide }
end;
void __fastcall TSampleCalendar::Click()
{
int TempDay = DayNum(Col, Row); // récupère le numéro du jour de la cellule
cliquée 3
if (TempDay != -1) Day = TempDay; // change le jour s'il est valide
}

3.2.1.5.9 Navigation de jour en jour


A l'intérieur d'un même mois, il existe deux moyens évidents pour naviguer parmi les jours. Le premier consiste à utiliser les
touches de direction et le deuxième à répondre aux clics de la souris. Le composant grille standard les gère tous les deux
indistinctement en tant que clics de souris. Autrement dit, le déplacement avec les touches de direction est pris en compte

1279
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

comme un clic sur une cellule adjacente.

Le processus de navigation de jour en jour comprend :

• Déplacement de la sélection ( see page 1279)


• Fourniture d'un événement OnChange ( see page 1281)
• Exclusion des cellules vides ( see page 1275)

3.2.1.5.10 Navigation de mois en mois et d'année en année


Les propriétés sont particulièrement utiles pour manipuler les composants, en particulier lors de la conception. Mais lorsque des
manipulations fréquentes ou instinctives font intervenir plusieurs propriétés, il paraît judicieux de fournir des méthodes pour les
gérer. Le passage au "mois suivant" dans notre calendrier est un exemple de ce type. Le bouclage sur les douze mois avec
l'incrémentation de l'année est à la fois une caractéristique simple et commode pour le programmeur qui utilise le composant.

Le seul inconvénient à l'encapsulation des manipulations les plus fréquentes sous la forme de méthodes est le suivant : les
méthodes ne sont accessibles qu'à l'exécution. Néanmoins, de telles manipulations ne sont fastidieuses que lorsqu'elles sont
souvent répétées, ce qui est rarement le cas au moment de la conception.

S'agissant du calendrier, ajoutez les quatre méthodes suivantes pour gérer le passage de mois en mois et d'année en année.
Chacune de ces méthodes utilise la fonction IncMonth de façon légèrement différente pour incrémenter ou décrémenter
CalendarDate de mois en mois ou d'année en année.
procedure TCalendar.NextMonth;
begin
CalendarDate := IncMonth(CalendarDate, 1);
end;
procedure TCalendar.PrevMonth;
begin
CalendarDate := IncMonth(CalendarDate, -1);
end;
procedure TCalendar.NextYear;
begin
CalendarDate := IncMonth(CalendarDate, 12);
end;
procedure TCalendar.PrevYear;
begin
CalendarDate := DecodeDate(IncMonth(CalendarDate, -12);
end;
void __fastcall TSampleCalendar::NextMonth()
{
CalendarDate = IncMonth(CalendarDate, 1);
}
void __fastcall TSampleCalendar::PrevMonth()
{
CalendarDate = IncMonth(CalendarDate, -1);
}
void __fastcall TSampleCalendar::NextYear()
{
CalendarDate = IncMonth(CalendarDate, 12);
}
3 void __fastcall TSampleCalendar::PrevYear()
{
CalendarDate = IncMonth(CalendarDate, -12);
}
N'oubliez pas d'ajouter les déclarations des nouvelles méthodes à la déclaration de la classe.

Désormais, si vous créez une application qui utilise le composant calendrier, vous pourrez facilement implémenter le passage de
mois en mois ou d'année en année.

1280
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.5.11 Fourniture d'un événement OnChange


Les utilisateurs de votre calendrier ont maintenant la possibilité de changer la date. Il paraît donc judicieux de répondre à ces
changements.

Ajoutez un événement OnChange à TSampleCalendar.


1. Déclarez l'événement ainsi qu'un champ pour le stocker et une méthode virtuelle pour l'appeler :
type
TSampleCalendar = class(TCustomGrid)
private
FOnChange: TNotifyEvent;
protected
procedure Change; dynamic;
.
.
.
published
property OnChange: TNotifyEvent read FOnChange write FOnChange;
.
.
.
class PACKAGE TSampleCalendar : public TCustomGrid
{
private:
TNotifyEvent FOnChange;
.
.
.
protected:
virtual void __fastcall Change();
__published:
__property TNotifyEvent OnChange = {read=FOnChange, write=FOnChange};
.
.
.
}
2. Ecrivez la méthode Change :
procedure TSampleCalendar.Change;
begin
if Assigned(FOnChange) then FOnChange(Self);
end;
void __fastcall TSampleCalendar::Change()
{
if(FOnChange != NULL) FOnChange(this);
}
3. Ajoutez les instructions appelant Change à la fin des méthodes SetCalendarDate et SetDateElement :
procedure TSampleCalendar.SetCalendarDate(Value: TDateTime);
begin
FDate := Value;
UpdateCalendar; 3
Change; { seule nouvelle instruction }
end;
procedure TSampleCalendar.SetDateElement(Index: Integer; Value: Integer);
begin
. { instructions définissant les valeurs des
éléments }
.
.
FDate := EncodeDate(AYear, AMonth, ADay);
UpdateCalendar;

1281
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Change; { ceci est nouveau }


end;
end;
void __fastcall TSampleCalendar::SetCalendarDate(TDateTime Value)
{
FDate = Value;
UpdateCalendar();
Change(); // seule nouvelle instruction
}
void __fastcall TSampleCalendar::SetDateElement(int Index, int Value)
{
.
.
. // instructions définissant les valeurs des éléments
FDate = TDateTime(AYear, AMonth, ADay);
UpdateCalendar();
Change(); // ceci est nouveau
}
Les applications qui utilisent le composant calendrier peuvent maintenant répondre aux changements en associant des
gestionnaires à l'événement OnChange.

3.2.1.5.12 Publication des propriétés héritées


Le composant grille abstrait, TCustomGrid, fournit de nombreuses propriétés protected. Vous pouvez choisir parmi ces
propriétés celles que vous voulez rendre accessibles aux utilisateurs du contrôle calendrier.

Pour rendre accessibles aux utilisateurs de vos composants les propriétés protégées qu'ils reçoivent en héritage, vous devez
redéclarer ces propriétés dans la partie published de la déclaration de vos composants.

S'agissant du contrôle calendrier, vous devez publier les propriétés et les événements, comme ci-dessous :
type
TSampleCalendar = class(TCustomGrid)
published
property Align; { propriétés publiées }
property BorderStyle;
property Color;
property Font;
property GridLineWidth;
property ParentColor;
property ParentFont;
property OnClick; { événements publiés }
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
end;
class PACKAGE TSampleCalendar : public TCustomGrid
{
.
3 .
.
__published:
__property Align ; // publication des propriétés
__property BorderStyle ;
__property Color ;
__property Font ;
__property GridLineWidth ;
__property ParentColor ;
__property ParentFont ;

1282
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

__property OnClick ; // publication des événements


__property OnDblClick ;
__property OnDragDrop ;
__property OnDragOver ;
__property OnEndDrag ;
__property OnKeyDown ;
__property OnKeyPress ;
__property OnKeyUp ;
};
Il existe bien d'autres propriétés ne s'appliquant pas à un calendrier qui sont publiables, par exemple la propriété Options qui
permet à l'utilisateur de choisir les lignes de la grille à dessiner.

Si vous installez le composant calendrier modifié dans la palette d'outils et l'utilisez dans une application, vous trouverez bien
d'autres propriétés et événements opérationnels. Nous allons maintenant commencer à ajouter de nouvelles fonctionnalités au
composant.

3.2.1.5.13 Redimensionnement des cellules


Remarque: Lorsqu'un utilisateur ou une application modifie la taille d'une fenêtre ou d'un contrôle, Windows envoie le message
WM_SIZE à la fenêtre ou au contrôle concerné pour lui permettre d'ajuster les paramètres nécessaires afin de dessiner
ultérieurement son image dans la nouvelle taille. Votre composant VCL peut répondre à ce message en modifiant la taille des
cellules de façon à ce qu'elles s'inscrivent dans les limites du contrôle. Pour répondre au message WM_SIZE, vous devez
ajouter au composant une méthode de gestion du message.

La création d'une méthode de gestion de message est décrite en détail dans la section Création de nouveaux gestionnaires de
messages ( see page 1317).

Dans notre exemple, le contrôle calendrier devant répondre au message WM_SIZE, vous devez ajouter une méthode protégée
appelée WMSize au contrôle indexé sur le message WM_SIZE, puis écrire la méthode de calcul de la taille des cellules qui
permettra à toutes d'être visibles :
type
TSampleCalendar = class(TCustomGrid)
protected
procedure WMSize(var Message: TWMSize); message WM_SIZE;
.
.
.
end;
.
.
.
procedure TSampleCalendar.WMSize(var Message: TWMSize);
var
GridLines: Integer; { variable locale temporaire }
begin
GridLines := 6 * GridLineWidth; { calculer la taille combinée de toutes les
lignes }
DefaultColWidth := (Message.Width - GridLines) div 7; { définir la nouvelle largeur de
cellule par défaut }
DefaultRowHeight := (Message.Height - GridLines) div 7; { ainsi que sa hauteur } 3
end;
// fichier en-tête
class PACKAGE TSampleCalendar : public TCustomGrid
{
.
.
.
protected:
void __fastcall WMSize(TWMSize &Message);
BEGIN_MESSAGE_MAP

1283
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

MESSAGE_HANDLER(WM_SIZE, TWMSize, WMSize)


END_MESSAGE_MAP(TCustomGrid)
};
// fichier d'implémentation
void __fastcall TSampleCalendar::WMSize(TWMSize &Message)
{
int GridLines; // variable locale temporaire
GridLines = 6 * GridLineWidth; // calcul de la taille combinée de toutes
les lignes
DefaultColWidth = (Message.Width - GridLines) / 7; // nouvelle largeur de cellule par
défaut
DefaultRowHeight = (Message.Height - GridLines) / 7; // et nouvelle hauteur de cellule par
défaut
}
Maintenant lorsque le calendrier est redimensionné, il affiche toutes les cellules dans la taille maximum avec laquelle ils peuvent
rentrer dans le contrôle.

Dans ce cas, le contrôle calendrier doit redéfinir BoundsChanged afin qu'elle calcule la taille de cellule adéquate pour que toutes
les cellules soient visibles avec la nouvelle taille :
type
TSampleCalendar = class(TCustomGrid)
protected
procedure BoundsChanged; override;
.
.
.
end;
.
.
.
procedure TSampleCalendar.BoundsChanged;
var
GridLines: Integer; { variable locale temporaire }
begin
GridLines := 6 * GridLineWidth; { calculer la taille combinée de toutes les
lignes }
DefaultColWidth := (Width - GridLines) div 7; { définir la nouvelle largeur de cellule
par défaut }
DefaultRowHeight := (Height - GridLines) div 7; { ainsi que sa hauteur }
inherited; {appeler maintenant la méthode dérivée }
end;
// fichier en-tête
class PACKAGE TSampleCalendar : public TCustomGrid
{
.
.
.
protected:
void __fastcall BoundsChanged(void);
};
// fichier d'implémentation
void __fastcall TSampleCalendar::BoundsChanged(void)
{
int GridLines; // variable locale temporaire
3 GridLines = 6 * GridLineWidth; // calcul de la taille combinée de toutes
les lignes
DefaultColWidth = (Width - GridLines) / 7; // nouvelle largeur de cellule par défaut
DefaultRowHeight = (Height - GridLines) / 7; // nouvelle hauteur de cellule par défaut
TCustomGrid::BoundsChanged(); // appelle la méthode héritée
}

1284
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.5.14 Sélection du jour en cours


Maintenant que les numéros des jours s'affichent dans les cellules du calendrier, il devient intéressant de savoir positionner la
surbrillance sur le jour en cours. Comme la sélection se positionne implicitement sur la cellule située en haut et à gauche, vous
devez définir les propriétés Row et Column au moment de la construction initiale du calendrier ainsi qu'à chaque changement de
date.

Pour positionner la sélection dans la cellule du jour en cours, modifiez la méthode UpdateCalendar pour définir Row et Column
avant d'appeler Refresh :
procedure TSampleCalendar.UpdateCalendar;
begin
if FDate <> 0 then
begin
. { instructions définissant FMonthOffset }
.
.
Row := (ADay - FMonthOffset) div 7 + 1;
Col := (ADay - FMonthOffset) mod 7;
end;
Refresh; { déjà ici }
end;
void __fastcall TSampleCalendar::UpdateCalendar(void)
{
unsigned short AYear, AMonth, ADay;
TDateTime FirstDate;
if ((int) FDate != 0)
{
.
.
. // instructions définissant FMonthOffset
Row = (ADay - FMonthOffset) / 7 + 1;
Col = (ADay - FMonthOffset) % 7;
}
Refresh(); // déjà ici
}
Notez que vous réutilisez la variable ADay précédemment définie lors du décodage de la date.

3.2.1.5.15 Stockage interne de la date


Pour stocker la date du calendrier, vous devez avoir un champ contenant la date, ainsi qu'une propriété accessible à l'exécution
seulement qui fournit un accès à cette date.

L'ajout de la date interne au calendrier requiert trois étapes :


1. Déclarez un champ privé pour contenir la date :
type
TSampleCalendar = class(TCustomGrid)
private
FDate: TDateTime; 3
.
.
.
class PACKAGE TSampleCalendar : public TCustomGrid
{
public:
__property TDateTime CalendarDate = {read=FDate, write=SetCalendarDate, nodefault};
.
.
.

1285
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

};
class PACKAGE TSampleCalendar : public TCustomGrid
{
private:
TDateTime FDate;
.
.
.
};
2. Initialisez le champ date dans le constructeur :
constructor TSampleCalendar.Create(AOwner: TComponent);
begin
inherited Create(AOwner); { existait déjà }
. { d'autres initialisations ici }
.
.
FDate := Date; { prendre la date active du RTL }
end;
__fastcall TSampleCalendar::TSampleCalendar(TComponent *Owner) : TCustomGrid(Owner)
{
.
.
.
FDate = FDate.CurrentDate();
}
3. Déclarez une propriété à l'exécution pour accéder à la date encodée. Vous aurez besoin d'une méthode pour définir la date
car sa définition entraîne la mise à jour de l'image sur l'écran du contrôle :
type
TSampleCalendar = class(TCustomGrid)
private
procedure SetCalendarDate(Value: TDateTime);
public
property CalendarDate: TDateTime read FDate write SetCalendarDate;
.
.
.
procedure TSampleCalendar.SetCalendarDate(Value: TDateTime);
begin
FDate := Value; { définir la nouvelle valeur date }
Refresh; { mettre à jour l'image à l'écran }
end;
class PACKAGE TSampleCalendar : public TCustomGrid
{
private:
void __fastcall SetCalendarDate(TDateTime Value);
.
.
.
};
void __fastcall TSampleCalendar::SetCalendarDate(TDateTime Value)
{
FDate = Value; // définit la nouvelle valeur de la date
Refresh(); // met à jour l'image sur l'écran
3 }

3.2.1.5.16 Suivi de la date


Pour que le contrôle calendrier soit utile, les utilisateurs ainsi que les applications doivent disposer d'un moyen de définir la date,
le mois et l'année. Delphi stocke les dates et les heures dans des variables de type TDateTime. TDateTime est une
représentation numérique encodée des dates et des heures particulièrement pratique pour être manipulée par un programme
mais peu commode à interpréter par un utilisateur.

1286
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Vous pouvez donc stocker la date du calendrier sous une forme encodée et fournir un accès direct à cette valeur lors de
l'exécution, mais vous pouvez aussi fournir les propriétés Day, Month et Year que l'utilisateur du composant peut définir lors de
la conception.

Le suivi de la date dans le calendrier comprend les traitements suivants :

• Stockage interne de la date ( see page 1285)


• Accès au jour ( see page 1270)
• Génération des numéros de jours ( see page 1276)
• Sélection du jour en cours ( see page 1285)

3.2.1.6 Extensions de l'EDI


Rubriques
Nom Description
Ajout d'une action à la liste d'actions ( see page 1289) L'indice de l'image obtenu dans la rubrique Ajout d'une image à la liste d'images
( see page 1290) est utilisé pour créer une action, comme indiqué ci-dessous.
L'expert utilise les événements OnExecute et OnUpdate. Généralement un
expert utilise l'événement OnUpdate pour activer ou désactiver l'action. Attention,
l'événement OnUpdate doit rendre la main rapidement, sinon l'utilisateur
remarquera que l'EDI devient plus lent une fois votre expert chargé. L'événement
OnExecute de l'action est similaire à la méthode Execute de l'expert. Si vous
utilisez un élément de menu pour appeler un expert fiche ou projet, vous pouvez
appeler directement Execute dans l'événement OnExecute.
Ajout d'une image à la liste d'images ( see page 1290) Supposons que vous vouliez ajouter un élément de menu pour appeler votre
expert. Vous voudrez également permettre à l'utilisateur d'ajouter un bouton de
barre d'outils qui appelle l'expert. La première étape est donc l'ajout d'une image
à la liste d'images de l'EDI. Vous pouvez ensuite utiliser l'indice de cette image
dans l'action qui est à son tour utilisée par l'élément de menu et un bouton de
barre d'outils. Créez un fichier ressource contenant une ressource bitmap 16 par
16. Ajoutez le code suivant au constructeur de l'expert :
Création de fiches et de projets ( see page 1291) Delphi propose de nombreux experts fiche et projet préinstallés et vous pouvez
également écrire les vôtres. Le référentiel d'objets vous permet de créer des
modèles statiques que vous pouvez utiliser dans un projet, mais un expert est
beaucoup plus puissant car il est dynamique. L'expert peut interroger l'utilisateur
et créer différents types de fichiers selon les réponses de l'utilisateur.
Généralement, un expert fiche ou projet crée un ou plusieurs nouveaux fichiers.
En fait, au lieu de fichiers réels, mieux vaut créer des modules sans nom et non
enregistrés. Lorsque l'utilisateur les enregistre, l'EDI lui demande le nom de
fichier. Un... suite ( see page 1291)
Débogage d'un expert ( see page 1295) L'API Tools permet à votre expert d'interagir avec l'EDI de manière très flexible.
Cependant, avec la flexibilité vient également la responsabilité. Vous pouvez
facilement produire des pointeurs flottants ou d'autres violations d'accès.
Lors de l'écriture d'experts utilisant les outils natifs, vous pouvez écrire du code
provoquant le blocage de l'EDI. Vous pouvez également concevoir un expert qui
s'installe mais sans agir de la manière prévue. Le débogage est l'une des
difficultés de l'utilisation du code s'exécutant pendant la conception. C'est
néanmoins un problème facile à résoudre. Comme l'expert est installé dans
Delphi même, il vous suffit de définir l'exécutable Delphi... suite ( see page
1295)
Suppression de boutons de barres d'outils ( see page 1296) Il n'y a pas de moyen simple de retirer un bouton d'une barre d'outils; vous devez
envoyer le message CM_CONTROLCHANGE, le premier paramètre indique le
contrôle à modifier et le second a la valeur zéro pour le retirer ou une valeur non
nulle pour l'ajouter à la barre d'outils. Après avoir retiré les boutons de barre
d'outils, le destructeur supprime l'action et l'élément de menu. La suppression de 3
ces éléments les retire automatiquement des objets ActionList et MainMenu de
l'EDI.

1287
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Extensions de l'EDI ( see page 1297) Vous pouvez étendre et personnaliser l'EDI avec vos propres éléments de menu,
boutons de barres d'outils, experts création de fiches dynamiques et davantage
en utilisant l'API Open Tools (souvent abrégée en API Tools). L'API Tools est un
ensemble d'une centaine d'interfaces qui interagissent et contrôlent l'EDI, y
compris le menu principal, les barres d'outils, les listes principales d'actions et
d'images, les tampons internes de l'éditeur de code source, les macros et
liaisons clavier, les fiches et leurs composants dans l'éditeur de fiches, le
débogueur et le processus en cours de débogage, l'achèvement de code, la vue
des messages et la... suite ( see page 1297)
Implémentation des interfaces de l'expert ( see page 1297) Chaque classe expert doit implémenter au minimum IOTAWizard, ce qui
nécessite également d'implémenter ses ancêtres : IOTANotifier et IInterface. Les
experts fiche et projet doivent implémenter toutes leurs interfaces ancêtres, soit,
IOTARepositoryWizard, IOTAWizard, IOTANotifier et IInterface.
Pour C++, pour employer NotifierObject comme classe de base, vous devez
utiliser l'héritage multiple. Votre classe expert doit hériter de NotifierObject et des
interfaces expert que vous devez implémenter, comme IOTAWizard. Comme
IOTAWizard hérite de IOTANotifier et de IInterface, il y a une ambiguïté dans la
classe dérivée : des fonctions comme AddRef() sont déclarées dans chaque
branche du graphe d'héritage... suite ( see page 1297)
Installation du package de l'expert ( see page 1299) Comme pour tous les packages de conception, le package d'un expert doit
disposer de la fonction Register. Pour plus d'informations sur la fonction
Register, voir Recensement des composants ( see page 1369). Dans la
fonction Register vous pouvez recenser plusieurs experts en appelant
RegisterPackageWizard en lui transmettant comme seul argument l'objet expert,
comme indiqué ci-dessous :
Numéros de version de l'interface ( see page 1300) Si vous regardez attentivement la déclaration de certaines interfaces, comme
IOTAMessageServices, vous constaterez qu'elle hérite d'une autre interface de
nom similaire, comme IOTAMessageServices50, qui hérite à son tour de
IOTAMessageServices40. Cette utilisation des numéros de version isole votre
code des changements entre les versions de Delphi.
L'API Tools utilise le même principe de base que COM, à savoir qu'une interface
et son GUID ne changent jamais. Si une nouvelle version ajoute des
caractéristiques à une interface, l'API Tools déclare une nouvelle interface qui
hérite de l'ancienne. Le GUID ne change pas et reste attaché à l'ancienne
interface... suite ( see page 1300)
Notification d'un expert des événements de l'EDI ( see page 1300) Un aspect important pour bien concevoir un expert consiste à le faire réagir aux
événements de l'EDI. En particulier, si un expert suit les interfaces de module, il
doit savoir quand l'utilisateur ferme le module, afin que l'expert puisse libérer
l'interface. Pour ce faire, l'expert a besoin d'un notificateur, ce qui signifie que
vous devez écrire une classe de notification.
Toutes les classes de notification implémentent une ou plusieurs interfaces de
notification. Une interface de notification définit des méthodes de rappel ; l'expert
recense un objet notificateur dans l'API Tools, et l'EDI rappelle le notificateur
quand il se produit quelque chose... suite ( see page 1300)
Accès aux services de l'API Tools ( see page 1305) Pour servir à quelque chose, un expert doit accéder à l'EDI : ses éditeurs,
fenêtres, menus, etc. C'est le rôle des interfaces de service. L'API Tools propose
de nombreux services, dont des services action pour effectuer des actions sur
les fichiers, des services d'édition pour accéder à l'éditeur de code source, des
services de débogage pour accéder au débogueur, etc. Le tableau suivant
résume toutes les interfaces de service.
Interfaces de service de l'API Tools
Présentation de l'API Tools ( see page 1306) Toutes les déclarations de l'API Tools se trouvent dans une seule unité,
ToolsAPI. Pour utiliser l'API Tools, il faut généralement employer un package de
conception, c'est-à-dire que vous devez concevoir un complément API Tools
comme un package de conception ou comme une DLL utilisant des packages
d'exécution. Pour plus d'informations sur les packages et les bibliothèques, voir
Installation du package de l'expert ( see page 1299).
L'interface principale dans l'écriture d'une extension API est IOTAWizard, la
plupart des compléments de l'EDI sont donc appelés des experts. Pour
l'essentiel, les experts C++Builder et Delphi sont compatibles. Vous pouvez ainsi
écrire et compiler un... suite ( see page 1306)
3 Utilisation des interfaces d'éditeur ( see page 1307) Chaque module dispose d'au moins une interface d'éditeur. Certains modules ont
plusieurs éditeurs, tels qu'un fichier source (.pas) et un fichier description de
fiche (.dfm). Comme tous les éditeurs implémentent l'interface IOTAEditor ;
transtypez l'éditeur vers un type spécifique pour savoir quel est le type de
l'éditeur. Par exemple, le code suivant permet d'obtenir l'interface de l'éditeur de
fiche d'une unité :

1288
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Utilisation des interfaces de module ( see page 1308) Pour obtenir une interface de module, démarrez le service de module
(IOTAModuleServices). Vous pouvez demander aux services de module tous les
modules qui sont ouverts, rechercher un module à partir d'un nom de fichier ou
de fiche ou ouvrir un fichier pour obtenir son interface de module.
Il existe différents types de modules correspondant aux différents types de
fichiers : projets, ressources ou bibliothèques de types. Transtypez une interface
de module vers une interface de module spécifique pour savoir si le module est
de ce type. Par exemple, voici un moyen de déterminer l'interface du groupe de
projets en... suite ( see page 1308)
Utilisation d'objets natifs de l'EDI ( see page 1309) Les experts ont un accès complet au menu principal, aux barres d'outils, à la liste
d'actions et la liste d'images de l'EDI. Par contre, les divers menus contextuels
de l'EDI ne sont pas accessibles via l'API Tools.
L'interface INTAServices sert de point de départ à la manipulation des objets
natifs de l'EDI. Utilisez cette interface pour ajouter une image à la liste d'images,
une action à la liste d'actions, un élément de menu au menu principal ou un
bouton à une barre d'outils. Vous pouvez lier l'action à l'élément de menu ou un
bouton de barre d'outils. Quand l'expert est... suite ( see page 1309)
Utilisation des fichiers et des éditeurs ( see page 1309) Il est important de comprendre comment l'API Tools manipule les fichiers.
L'interface principale est IOTAModule. Un module représente un ensemble de
fichiers ouverts liés logiquement. Ainsi, une unité est représentée par un seul
module. A son tour, le module comprend un ou des éditeurs, chaque éditeur
représentant un fichier, par exemple le fichier source de l'unité (.pas) ou le fichier
fiche (.dfm ou .xfm). Comme les interfaces éditeur reflètent l'état interne des
éditeurs de l'EDI, un expert peut voir le code modifié et les fiches que l'utilisateur
voit, même si l'utilisateur n'a pas enregistré les modifications.
Les rubriques suivantes... suite ( see page 1309)
Conception d'une classe expert ( see page 1309) Il y a quatre types d'experts, le type d'un expert dépendant des interfaces
qu'implémente la classe de l'expert. Le tableau suivant décrit les quatre types
d'experts.
Les quatre types d'expert

3.2.1.6.1 Ajout d'une action à la liste d'actions


L'indice de l'image obtenu dans la rubrique Ajout d'une image à la liste d'images ( see page 1290) est utilisé pour créer une
action, comme indiqué ci-dessous. L'expert utilise les événements OnExecute et OnUpdate. Généralement un expert utilise
l'événement OnUpdate pour activer ou désactiver l'action. Attention, l'événement OnUpdate doit rendre la main rapidement,
sinon l'utilisateur remarquera que l'EDI devient plus lent une fois votre expert chargé. L'événement OnExecute de l'action est
similaire à la méthode Execute de l'expert. Si vous utilisez un élément de menu pour appeler un expert fiche ou projet, vous
pouvez appeler directement Execute dans l'événement OnExecute.
NewAction := TAction.Create(nil);
NewAction.ActionList := Services.ActionList;
NewAction.Caption := GetMenuText();
NewAction.Hint := 'Afficher une boîte de dialogue inutile';
NewAction.ImageIndex := ImageIndex;
NewAction.OnUpdate := action_update;
NewAction.OnExecute := action_execute;
action = new TAction(0);
action->ActionList = services->ActionList;
action->Caption = GetMenuText();
action->Hint = "Affiche une boîte de dialogue inutile";
action->ImageIndex = image;
action->OnUpdate = action_update;
action->OnExecute = action_execute;
L'élément de menu initialise sa propriété Action avec l'action qui vient d'être créée. Le problème dans la création d'un élément de 3
menu, c'est de savoir où l'insérer. L'exemple suivant recherche le menu Voir et insère le nouvel élément de menu comme
premier élément du menu Voir. En général, il n'est pas judicieux de se baser sur une position absolue : en effet, vous ne savez
jamais quand un autre expert va s'ajouter au menu. De plus, les versions ultérieures de Delphi peuvent également réorganiser
les menus. Il est préférable de rechercher dans le menu un élément de nom donné. Dans un souci de clarté l'approche simpliste
suit.
for I := 0 to Services.MainMenu.Items.Count - 1 do
begin
with Services.MainMenu.Items[I] do

1289
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

begin
if CompareText(Name, 'ViewsMenu') = 0 then
begin
NewItem := TMenuItem.Create(nil);
NewItem.Action := NewAction;
Insert(0, NewItem);
end;
end;
end;
for (int i = 0; i < services->MainMenu->Items->Count; ++i)
{
TMenuItem* item = services->MainMenu->Items->Items[i];
if (CompareText(item->Name, "ViewsMenu") == 0)
{
menu_item = new TMenuItem(0);
menu_item->Action = action;
item->Insert(0, menu_item);
}
}
Une fois l'action ajoutée à la liste d'actions de l'EDI, l'utilisateur peut voir l'action quand il personnalise les barres d'outils.
L'utilisateur peut sélectionner l'action et l'ajouter à une barre d'outils. Cela peut poser un problème quand votre expert est
déchargé : tous les boutons de barre d'outils se retrouvent avec des pointeurs flottants sur une action et un gestionnaire
d'événement OnClick inexistants. Pour éviter des violations d'accès, votre expert doit trouver tous les boutons d'outils faisant
référence à ses actions et les supprimer.

Voir aussi
Ajout d'une image à la liste d'images ( see page 1290)

Suppression de boutons de barres d'outils ( see page 1296)

3.2.1.6.2 Ajout d'une image à la liste d'images


Supposons que vous vouliez ajouter un élément de menu pour appeler votre expert. Vous voudrez également permettre à
l'utilisateur d'ajouter un bouton de barre d'outils qui appelle l'expert. La première étape est donc l'ajout d'une image à la liste
d'images de l'EDI. Vous pouvez ensuite utiliser l'indice de cette image dans l'action qui est à son tour utilisée par l'élément de
menu et un bouton de barre d'outils. Créez un fichier ressource contenant une ressource bitmap 16 par 16. Ajoutez le code
suivant au constructeur de l'expert :
constructor MyWizard.Create;
var
Services: INTAServices;
Bmp: TBitmap;
ImageIndex: Integer;
begin
inherited;
Supports(BorlandIDEServices, INTAServices, Services);
{ Ajouter une image à la liste d'images. }
Bmp := TBitmap.Create;
Bmp.LoadFromResourceName(HInstance, 'Bitmap1');
ImageIndex := Services.AddMasked(Bmp, Bmp.TransparentColor,
3 'Tempest Software.intro wizard image');
Bmp.Free;
end;
_di_INTAServices services;
BorlandIDEServices->Supports(services);
// Ajoute une image à la liste d'images.
Graphics::TBitmap* bitmap(new Graphics::TBitmap());
bitmap->LoadFromResourceName(reinterpret_cast<unsigned>(HInstance), "Bitmap1");
int image = services->AddMasked(bitmap, bitmap->TransparentColor,
"Tempest Software.intro wizard image");
delete bitmap;

1290
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Assurez-vous de charger la ressource en utilisant le nom ou l'identificateur spécifié dans le fichier ressource. Vous devez choisir
une couleur qui sera interprétée comme la couleur de fond de l'image. Si vous ne voulez pas utiliser de couleur de fond,
choisissez une couleur n'existant pas dans le bitmap.

Voir aussi
Ajout d'une action à la liste d'actions ( see page 1289)

Suppression de boutons de barres d'outils ( see page 1296)

3.2.1.6.3 Création de fiches et de projets


Delphi propose de nombreux experts fiche et projet préinstallés et vous pouvez également écrire les vôtres. Le référentiel
d'objets vous permet de créer des modèles statiques que vous pouvez utiliser dans un projet, mais un expert est beaucoup plus
puissant car il est dynamique. L'expert peut interroger l'utilisateur et créer différents types de fichiers selon les réponses de
l'utilisateur.

Généralement, un expert fiche ou projet crée un ou plusieurs nouveaux fichiers. En fait, au lieu de fichiers réels, mieux vaut
créer des modules sans nom et non enregistrés. Lorsque l'utilisateur les enregistre, l'EDI lui demande le nom de fichier. Un
expert utilise un objet créateur pour créer de tels modules.

Une classe créateur implémente une interface de création qui hérite de IOTACreator. L'expert transmet l'objet créateur à la
méthode CreateModule du service de module, et l'EDI rappelle l'objet créateur pour obtenir les paramètres nécessaires à la
création du module.

Ainsi, un expert fiche qui crée une nouvelle fiche implémente généralement GetExisting pour renvoyer false et GetUnnamed
pour renvoyer true. Cela crée un module sans nom (l'utilisateur doit donc spécifier un nom avant de pouvoir enregistrer le fichier)
et sans fichier existant correspondant (l'utilisateur doit donc enregistrer le fichier même s'il ne l'a pas modifié). D'autres méthodes
du créateur indiquent à l'EDI le type de fichier créé (un projet, une unité ou une fiche), spécifient le contenu du fichier ou
renvoient le nom de la fiche, le nom de l'ancêtre ou d'autres informations importantes. D'autres rappels permettent à un expert
d'ajouter des modules à un projet qui vient d'être créé, ou d'ajouter des composants à une fiche qui vient d'être créée.

Pour créer un nouveau fichier, ce qui est généralement nécessaire avec un expert fiche ou projet, il faut spécifier le contenu du
nouveau fichier. Pour ce faire, écrivez une nouvelle classe implémentant l'interface IOTAFile. Si votre expert se contente du
contenu de fichier par défaut, vous pouvez renvoyer nil depuis toute fonction qui renvoie IOTAFile.

Par exemple, votre société peut utiliser un bloc de commentaire standardisé devant apparaître au début de chaque fichier
source. Vous pouvez obtenir ceci avec un modèle statique du référentiel d'objets, mais il faut alors modifier manuellement le bloc
de commentaire pour indiquer l'auteur et la date de création. Vous pouvez utiliser à la place un créateur pour remplir
dynamiquement le bloc de commentaire lors de la création du fichier.

Il faut tout d'abord écrire un expert qui crée de nouvelles fiches et unités. La plupart des fonctions d'un créateur renvoient zéro,
des chaînes vides ou d'autres valeurs par défaut, ce qui indique à l'API Tools d'utiliser le comportement par défaut pour créer
une nouvelle unité ou une fiche. Redéfinissez GetCreatorType pour indiquer à l'API Tools le type de module à créer : une unité
ou une fiche. Pour créer une unité, renvoyez sUnit. Pour créer une fiche, renvoyez sForm. Pour simplifier le code, utilisez une
seule classe utilisant le type de créateur comme argument du constructeur. Enregistrez le type du créateur dans une donnée
membre afin que GetCreatorType puisse renvoyer sa valeur. Implémentez NewImplSource et NewIntfSource pour renvoyer le
contenu souhaité dans le fichier. 3
TCreator = class(TInterfacedObject, IOTAModuleCreator)
public
constructor Create(const CreatorType: string);
{ IOTAModuleCreator }
function GetAncestorName: string;
function GetImplFileName: string;
function GetIntfFileName: string;
function GetFormName: string;
function GetMainForm: Boolean;

1291
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

function GetShowForm: Boolean;


function GetShowSource: Boolean;
function NewFormFile(const FormIdent, AncestorIdent: string): IOTAFile;
function NewImplSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
function NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
procedure FormCreated(const FormEditor: IOTAFormEditor);
{ IOTACreator }
function GetCreatorType: string;
function GetExisting: Boolean;
function GetFileSystem: string;
function GetOwner: IOTAModule;
function GetUnnamed: Boolean;
private
FCreatorType: string;
end;
class PACKAGE Creator : public IOTAModuleCreator {
public:
__fastcall Creator(const AnsiString creator_type)
: ref_count(0), creator_type(creator_type) {}
virtual __fastcall ~Creator();
// IOTAModuleCreator
virtual AnsiString __fastcall GetAncestorName();
virtual AnsiString __fastcall GetImplFileName();
virtual AnsiString __fastcall GetIntfFileName();
virtual AnsiString __fastcall GetFormName();
virtual bool __fastcall GetMainForm();
virtual bool __fastcall GetShowForm();
virtual bool __fastcall GetShowSource();
virtual _di_IOTAFile __fastcall NewFormFile(
const AnsiString FormIdent, const AnsiString AncestorIdent);
virtual _di_IOTAFile __fastcall NewImplSource(
const AnsiString ModuleIdent, const AnsiString FormIdent,
const AnsiString AncestorIdent);
virtual _di_IOTAFile __fastcall NewIntfSource(
const AnsiString ModuleIdent, const AnsiString FormIdent,
const AnsiString AncestorIdent);
virtual void __fastcall FormCreated(
const _di_IOTAFormEditor FormEditor);
// IOTACreator
virtual AnsiString __fastcall GetCreatorType();
virtual bool __fastcall GetExisting();
virtual AnsiString __fastcall GetFileSystem();
virtual _di_IOTAModule __fastcall GetOwner();
virtual bool __fastcall GetUnnamed();
protected:
// IInterface
virtual HRESULT __stdcall QueryInterface(const GUID&, void**);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
private:
long ref_count;
const AnsiString creator_type;
};
La plupart des membres de TCreator renvoient zéro, nil ou des chaînes vides. Les méthodes booléennes renvoient true, sauf
GetExisting qui renvoie false. La méthode la plus intéressante est GetOwner qui renvoie un pointeur sur le module du projet en
3
cours ou nil s'il n'y a pas de projet. Il n'y a pas de moyen simple de déterminer le projet ou le groupe de projets en cours. Il faut à
la place utiliser GetOwner pour parcourir tous les modules ouverts. Si un groupe de projets est trouvé, ce doit être le seul groupe
de projets ouvert, donc GetOwner renvoie son projet en cours. Sinon la fonction renvoie le premier module de projet trouvé ou
nil s'il n'y a pas de projet ouvert.
function TCreator.GetOwner: IOTAModule;
var
I: Integer;
Svc: IOTAModuleServices;

1292
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Module: IOTAModule;
Project: IOTAProject;
Group: IOTAProjectGroup;
begin
{ Renvoyer le projet en cours. }
Supports(BorlandIDEServices, IOTAModuleServices, Svc);
Result := nil;
for I := 0 to Svc.ModuleCount - 1 do
begin
Module := Svc.Modules[I];
if Supports(Module, IOTAProject, Project) then
begin
{ Mémoriser le premier module de projet}
if Result = nil then
Result := Project;
end
else if Supports(Module, IOTAProjectGroup, Group) then
begin
{ Trouver le groupe de projets et renvoyer son projet actif}
Result := Group.ActiveProject;
Exit;
end;
end;
end;
_di_IOTAModule __fastcall Creator::GetOwner()
{
// Renvoie le projet en cours.
_di_IOTAProject result = 0;
_di_IOTAModuleServices svc = interface_cast<IOTAModuleServices>(BorlandIDEServices);
for (int i = 0; i < svc->ModuleCount; ++i)
begin
_di_IOTAModule module = svc->Modules[i];
_di_IOTAProject project;
_di_IOTAProjectGroup group;
if (module->Supports(project)) {
// Mémoriser le premier module de projet.
if (result == 0)
result = project;
} else if (module->Supports(group)) {
// Trouve le groupe de projets et renvoie son projet actif.
result = group->ActiveProject;
break;
}
}
return result;
}
Le créateur renvoie nil depuis NewFormSource pour générer un fichier fiche par défaut. Les méthodes intéressantes sont
NewImplSource et NewIntfSource qui créent une instance de IOTAFile renvoyant le contenu du fichier.

La classe TFile implémente l'interface IOTAFile. Elle renvoie -1 comme âge du fichier (cela signifie que le fichier n'existe pas) et
renvoie le contenu du fichier dans une chaîne. Pour garder la classe TFile simple, le créateur génère la chaîne, la classe TFile
se contenant de la transmettre.
TFile = class(TInterfacedObject, IOTAFile)
public 3
constructor Create(const Source: string);
function GetSource: string;
function GetAge: TDateTime;
private
FSource: string;
end;
constructor TFile.Create(const Source: string);
begin
FSource := Source;
end;

1293
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

function TFile.GetSource: string;


begin
Result := FSource;
end;
function TFile.GetAge: TDateTime;
begin
Result := TDateTime(-1);
end;
class File : public IOTAFile {
public:
__fastcall File(const AnsiString source);
virtual __fastcall ~File();
AnsiString __fastcall GetSource();
System::TDateTime __fastcall GetAge();
protected:
// IInterface
virtual HRESULT __stdcall QueryInterface(const GUID&, void**);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
private:
long ref_count;
AnsiString source;
};
__fastcall File::File(const AnsiString source)
: ref_count(0), source(source)
{}
AnsiString __fastcall File::GetSource()
{
return source;
}
System::TDateTime __fastcall File::GetAge()
{
return -1;
}
Vous pouvez stocker le texte du contenu du fichier dans une ressource afin d'en simplifier la modification, mais dans un souci de
simplicité, dans cet exemple le texte est codé directement dans l'expert. L'exemple suivant génère le code source en supposant
l'existence d'une fiche. Vous pouvez facilement gérer le cas encore plus simple d'une unité de base. Testez FormIdent et, si elle
est vide, créez une unité de base, sinon créez une unité de fiche. Le squelette de base du code est le même que celui par défaut
de l'EDI (avec bien entendu l'ajout des commentaires au début), mais vous pouvez le modifier à votre guise.
function TCreator.NewImplSource(
const ModuleIdent, FormIdent, AncestorIdent: string): IOTAFile;
var
FormSource: string;
begin
FormSource :=
'{ ----------------------------------------------------------------- ' + #13#10 +
'%s - description'+ #13#10 +
'Copyright © %y Votre société, inc.'+ #13#10 +
'Créé le %d'+ #13#10 +
'Par %u'+ #13#10 +
' ----------------------------------------------------------------- }' + #13#10 + #13#10;
return TFile.Create(Format(FormSource, ModuleIdent, FormIdent,
AncestorIdent));
3 }
_di_IOTAFile __fastcall Creator::NewImplSource(
const AnsiString ModuleIdent,
const AnsiString FormIdent,
const AnsiString AncestorIdent)
{
const AnsiString form_source =
"/*-----------------------------------------------------------------\n"
" %m - description\n"
" Copyright \xa9 %y Votre société, inc.\n"
" Créée le %d\n"

1294
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

" Par %u\n"


" ---------------------------------------------------------------*/\n"
"\n"
"#include <vcl.h>\n"
"#pragma hdrstop\n"
"\n"
"#include \"%m.h\"\n"
"//-----------------------------------------------------------------\n"
"#pragma package(smart_init)\n"
"#pragma resource \"*.dfm\"\n"
"T%f *%f;\n"
"//-----------------------------------------------------------------\n"
"__fastcall T%m::T%m(TComponent* Owner)\n"
" : T%a(Owner)\n"
"{\n"
"}\n"
"//----------------------------------------------------------------\n";
return new File(expand(form_source, ModuleIdent, FormIdent,
AncestorIdent));
}
La dernière étape consiste à créer deux experts fiche : un qui utilise sUnit comme type de créateur et l'autre utilisant sForm.
Pour proposer un avantage supplémentaire à l'utilisateur, vous pouvez utiliser INTAServices pour ajouter un élément au menu
Fichier Nouveau permettant d'appeler chaque expert. Le gestionnaire d'événement OnClick de l'élément de menu peut
appeler la fonction Execute de l'expert.

Certains experts ont besoin d'activer ou de désactiver des éléments de menu en fonction de ce qui se passe dans l'EDI. Ainsi,
un expert qui archive un projet dans un système de contrôle du code source doit désactiver son élément de menu Archiver s'il
n'y a pas de fichier ouvert dans l'EDI. Vous pouvez ajouter cette fonctionnalité à votre expert en utilisant les notificateurs ( see
page 1300).

Voir aussi
Utilisation des fichiers et des éditeurs ( see page 1309)

3.2.1.6.4 Débogage d'un expert


L'API Tools permet à votre expert d'interagir avec l'EDI de manière très flexible. Cependant, avec la flexibilité vient également la
responsabilité. Vous pouvez facilement produire des pointeurs flottants ou d'autres violations d'accès.

Lors de l'écriture d'experts utilisant les outils natifs, vous pouvez écrire du code provoquant le blocage de l'EDI. Vous pouvez
également concevoir un expert qui s'installe mais sans agir de la manière prévue. Le débogage est l'une des difficultés de
l'utilisation du code s'exécutant pendant la conception. C'est néanmoins un problème facile à résoudre. Comme l'expert est
installé dans Delphi même, il vous suffit de définir l'exécutable Delphi comme Application hôte du package grâce à l'élément de
menu Exécuter Paramètres....

Quand vous voulez (ou avez besoin) de déboguer le package, ne l'installez pas. Choisissez à la place Exécuter Exécuter
dans la barre de menus. Cela démarre une nouvelle instance de Delphi. Dans la nouvelle instance, installez le package déjà
compilé en choisissant Composants Installer le package... dans la barre de menus. Si vous revenez dans l'instance d'origine
de Delphi, vous voyez maintenant les points bleus vous indiquant que vous pouvez définir des points d'arrêt dans le code source
de l'expert. Si ce n'est pas le cas, vérifiez les options du compilateur pour vous assurer que vous avez activé le débogage ; 3
vérifiez que vous avez chargé le bon package ; et revérifiez les modules de processus pour être sûr et certain que vous avez
bien chargé le fichier .bpl souhaité.

En procédant ainsi, vous ne pouvez pas déboguer dans le code VCL ou RTL mais pour l'expert même vous disposez de toutes
les fonctions de débogage, ce qui devrait suffire pour trouver le problème.

Voir aussi
Utilisation d'objets natifs de l'EDI ( see page 1309)

1295
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.6.5 Suppression de boutons de barres d'outils


Il n'y a pas de moyen simple de retirer un bouton d'une barre d'outils; vous devez envoyer le message CM_CONTROLCHANGE,
le premier paramètre indique le contrôle à modifier et le second a la valeur zéro pour le retirer ou une valeur non nulle pour
l'ajouter à la barre d'outils. Après avoir retiré les boutons de barre d'outils, le destructeur supprime l'action et l'élément de menu.
La suppression de ces éléments les retire automatiquement des objets ActionList et MainMenu de l'EDI.
procedure remove_action (Action: TAction; ToolBar: TToolBar);
var
I: Integer;
Btn: TToolButton;
begin
for I := ToolBar.ButtonCount - 1 downto 0 do
begin
Btn := ToolBar.Buttons[I];
if Btn.Action = Action then
begin
{ Retirer "Btn" de "ToolBar" }
ToolBar.Perform(CM_CONTROLCHANGE, WPARAM(Btn), 0);
Btn.Free;
end;
end;
end;
destructor MyWizard.Destroy;
var
Services: INTAServices;
Btn: TToolButton;
begin
Supports(BorlandIDEServices, INTAServices, Services);
{ Vérifier toutes les barres d'outils et retirer tous les boutons utilisant cette action. }
remove_action(NewAction, Services.ToolBar[sCustomToolBar]);
remove_action(NewAction, Services.ToolBar[sDesktopToolBar]);
remove_action(NewAction, Services.ToolBar[sStandardToolBar]);
remove_action(NewAction, Services.ToolBar[sDebugToolBar]);
remove_action(NewAction, Services.ToolBar[sViewToolBar]);
remove_action(NewAction, Services.ToolBar[sInternetToolBar]);
NewItem.Free;
NewAction.Free;
end;
void __fastcall remove_action (TAction* action, TToolBar* toolbar)
{
for (int i = toolbar->ButtonCount; --i >= 0; )
{
TToolButton* button = toolbar->Buttons[i];
if (button->Action == action)
{
// Retire "button" de "toolbar".
toolbar->Perform(CM_CONTROLCHANGE, WPARAM(button), 0);
delete button;
}
}
}
__fastcall MyWizard::~MyWizard()
3 {
_di_INTAServices services;
BorlandIDEServices->Supports(services);
// Vérifier toutes les barres d'outils et retirer tous les boutons utilisant
// cette action.
remove_action(action, services->ToolBar[sCustomToolBar]);
remove_action(action, services->ToolBar[sDesktopToolBar]);
remove_action(action, services->ToolBar[sStandardToolBar]);
remove_action(action, services->ToolBar[sDebugToolBar]);
remove_action(action, services->ToolBar[sViewToolBar]);
remove_action(action, services->ToolBar[sInternetToolBar]);

1296
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

delete menu_item;
delete action;
}
Voir aussi
Ajout d'une image à la liste d'images ( see page 1290)

Ajout d'une action à la liste d'actions ( see page 1289)

3.2.1.6.6 Extensions de l'EDI


Vous pouvez étendre et personnaliser l'EDI avec vos propres éléments de menu, boutons de barres d'outils, experts création de
fiches dynamiques et davantage en utilisant l'API Open Tools (souvent abrégée en API Tools). L'API Tools est un ensemble
d'une centaine d'interfaces qui interagissent et contrôlent l'EDI, y compris le menu principal, les barres d'outils, les listes
principales d'actions et d'images, les tampons internes de l'éditeur de code source, les macros et liaisons clavier, les fiches et
leurs composants dans l'éditeur de fiches, le débogueur et le processus en cours de débogage, l'achèvement de code, la vue
des messages et la liste de tâches.

Pour utiliser l'API Tools, il suffit d'écrire des classes qui implémentent certaines interfaces et d'appeler les services proposés par
d'autres interfaces. Votre code API Tools doit être compilé et chargé dans l'EDI lors de la conception sous la forme d'un package
de conception ou d'une DLL. Ainsi l'écriture d'une extension API Tools ressemble à la conception d'un éditeur de propriété ou de
composant. Avant d'aborder ce sujet, vous devez vous être familiarisé avec l'utilisation des packages ( see page 2285) et le
recensement des composants ( see page 1367).

Remarque: Pour activer l'utilisation de l'API Tools, vous devez effectuer une liaison avec les packages d'exécution et vous
assurer que "designide" est listé comme un des packages de la liaison. Dans l'EDI, il est possible de le faire sur la boîte de
dialogue Projet->Options->Packages

. Si vous effectuez la construction à partir de la ligne de commande, assurez-vous que -LUdesignide est transmis à
dcc32.exe. Les rubriques suivantes décrivent l'utilisation de l'API Tools :

• Présentation de l'API Tools ( see page 1306)


• Conception d'une classe expert ( see page 1309)
• Accès aux services de l'API Tools ( see page 1305)
• Utilisation des fichiers et des éditeurs ( see page 1309)
• Création de fiches et de projets ( see page 1291)
• Notification d'un expert des événements de l'EDI ( see page 1300)
Voir aussi
Accessibilité des composants au moment de la conception : Vue globale ( see page 1367)

3.2.1.6.7 Implémentation des interfaces de l'expert


Chaque classe expert doit implémenter au minimum IOTAWizard, ce qui nécessite également d'implémenter ses ancêtres :
IOTANotifier et IInterface. Les experts fiche et projet doivent implémenter toutes leurs interfaces ancêtres, soit, 3
IOTARepositoryWizard, IOTAWizard, IOTANotifier et IInterface.

Pour C++, pour employer NotifierObject comme classe de base, vous devez utiliser l'héritage multiple. Votre classe expert doit
hériter de NotifierObject et des interfaces expert que vous devez implémenter, comme IOTAWizard. Comme IOTAWizard hérite
de IOTANotifier et de IInterface, il y a une ambiguïté dans la classe dérivée : des fonctions comme AddRef() sont déclarées
dans chaque branche du graphe d'héritage ancestral. Pour résoudre ce problème, choisissez l'une des classes de base comme
classe de base primaire et déléguez tous les appels de fonction ambigus à cette classe. Vous pouvez, par exemple, utiliser la
déclaration de classe suivante :

1297
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

class PACKAGE MyWizard : public NotifierObject, public IOTAMenuWizard {


typedef NotifierObject inherited;
public:
// IOTAWizard
virtual AnsiString __fastcall GetIDString();
virtual AnsiString __fastcall GetName();
virtual TWizardState __fastcall GetState();
virtual void __fastcall Execute();
// IOTAMenuWizard
virtual AnsiString __fastcall GetMenuText();
void __fastcall AfterSave();
void __fastcall BeforeSave();
void __fastcall Destroyed();
void __fastcall Modified();
protected:
// IInterface
virtual HRESULT __stdcall QueryInterface(const GUID&, void**);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
};
// implémentation
ULONG __stdcall MyWizard::AddRef() { return inherited::AddRef(); }
ULONG __stdcall MyWizard::Release() { return inherited::Release(); }
HRESULT __stdcall MyWizard::QueryInterface(const GUID& iid, void** obj)
{
if (iid == __uuidof(IOTAMenuWizard)) {
*obj = static_cast<IOTAMenuWizard*>(this);
static_cast<IOTAMenuWizard*>(*obj)->AddRef();
return S_OK;
}
if (iid == __uuidof(IOTAWizard)) {
*obj = static_cast<IOTAWizard*>(this);
static_cast<IOTAWizard*>(*obj)->AddRef();
return S_OK;
}
return inherited::QueryInterface(iid, obj);
}
Votre implémentation de IInterface suit les mêmes règles que celles des interfaces Delphi, qui sont les mêmes que celles des
interfaces COM. C'est-à-dire que QueryInterface effectue les transtypages et que _AddRef et _Release gèrent le comptage de
références. Vous pouvez utiliser une classe de base commune pour simplifier l'écriture des classes d'experts et de notificateurs.
A cette fin, l'unité ToolsAPI définit une classe, TNotifierObject, qui implémente l'interface IOTANotifier avec des corps de
méthode vides.

Vous pouvez écrire en C++ une classe similaire à la classe TNotifierObject.


class PACKAGE NotifierObject : public IOTANotifier {
public:
__fastcall NotifierObject() : ref_count(0) {}
virtual __fastcall ~NotifierObject();
void __fastcall AfterSave();
void __fastcall BeforeSave();
void __fastcall Destroyed();
void __fastcall Modified();
protected:
3 // IInterface
virtual HRESULT __stdcall QueryInterface(const GUID&, void**);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
private:
long ref_count;
};
// implémentation
ULONG __stdcall NotifierObject::AddRef()
{
return InterlockedIncrement(&ref_count);

1298
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

}
ULONG __stdcall NotifierObject::Release()
{
ULONG result = InterlockedDecrement(&ref_count);
if (ref_count == 0)
delete this;
return result;
}
HRESULT __stdcall NotifierObject::QueryInterface(const GUID& iid, void** obj)
{
if (iid == __uuidof(IInterface)) {
*obj = static_cast<IInterface*>(this);
static_cast<IInterface*>(*obj)->AddRef();
return S_OK;
}
if (iid == __uuidof(IOTANotifier)) {
*obj = static_cast<IOTANotifier*>(this);
static_cast<IOTANotifier*>(*obj)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
Bien que les experts héritent de IOTANotifier et doivent donc implémenter toutes ses fonctions, l'EDI n'utilise généralement pas
ces fonctions et votre implémentation peut rester vide (comme c'est le cas dans TNotifierObject). Par conséquent, lorsque vous
écrivez votre classe expert, vous devez uniquement déclarer et implémenter les méthodes d'interface introduites par les
interfaces expert, en acceptant l'implémentation TNotifierObject de IOTANotifier.
// Implémentations C++ vides
void __fastcall NotifierObject::AfterSave() {}
void __fastcall NotifierObject::BeforeSave() {}
void __fastcall NotifierObject::Destroyed() {}
void __fastcall NotifierObject::Modified() {}
Voir aussi
Installation du package de l'expert ( see page 1299)

3.2.1.6.8 Installation du package de l'expert


Comme pour tous les packages de conception, le package d'un expert doit disposer de la fonction Register. Pour plus
d'informations sur la fonction Register, voir Recensement des composants ( see page 1369). Dans la fonction Register vous
pouvez recenser plusieurs experts en appelant RegisterPackageWizard en lui transmettant comme seul argument l'objet expert,
comme indiqué ci-dessous :
procedure Register;
begin
RegisterPackageWizard(MyWizard.Create);
RegisterPackageWizard(MyOtherWizard.Create);
end;
namespace Example {
void __fastcall PACKAGE Register()
{
RegisterPackageWizard(new MyWizard()); 3
RegisterPackageWizard(new MyOtherWizard());
}
}
Vous pouvez également recenser des éditeurs de propriété, des composants, etc. dans le même package.

N'oubliez pas qu'un package de conception fait partie de l'application RAD Studio principale, ce qui implique que tout nom de
fiche doit être unique dans toute l'application et tous les autres packages de conception. C'est le principal inconvénient de
l'utilisation des packages : vous ne pouvez pas prévoir comment quelqu'un d'autre va appeler ses fiches.

1299
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Lors du développement, installez le package de l'expert de la même manière que les autres packages de conception : cliquez
sur le bouton Installer dans le gestionnaire de packages. L'EDI compile et lie alors le package puis tente de le charger. L'EDI
affiche une boîte de dialogue vous indiquant si le chargement du package s'est bien effectué.

Voir aussi
Implémentation des interfaces de l'expert ( see page 1297)

Installation d'une DLL expert

3.2.1.6.9 Numéros de version de l'interface


Si vous regardez attentivement la déclaration de certaines interfaces, comme IOTAMessageServices, vous constaterez qu'elle
hérite d'une autre interface de nom similaire, comme IOTAMessageServices50, qui hérite à son tour de
IOTAMessageServices40. Cette utilisation des numéros de version isole votre code des changements entre les versions de
Delphi.

L'API Tools utilise le même principe de base que COM, à savoir qu'une interface et son GUID ne changent jamais. Si une
nouvelle version ajoute des caractéristiques à une interface, l'API Tools déclare une nouvelle interface qui hérite de l'ancienne.
Le GUID ne change pas et reste attaché à l'ancienne interface qui n'est pas modifiée. La nouvelle interface obtient un nouveau
GUID. Les anciens experts qui utilisent les anciens GUID continuent à fonctionner.

L'API Tools modifie également le nom des interfaces afin de préserver la compatibilité du code source. Pour comprendre
comment cela fonctionne, il est important de faire la distinction entre les deux types d'interfaces de l'API Tools : implémentées
par Borland ou implémentées par l'utilisateur. Si l'EDI implémente l'interface, le nom reste attaché à la version la plus récente de
l'interface. La nouvelle fonctionnalité n'affecte pas le code existant. L'ancien numéro de version est alors ajouté au nom des
anciennes interfaces.

Par contre, dans le cas d'une interface implémentée par l'utilisateur, les nouvelles fonctions membre de l'interface de base
nécessitent de nouvelles fonctions dans votre code. Dans ce cas, le nom reste attaché à l'ancienne interface, et le numéro de
version est ajouté à la fin du nom de la nouvelle version.

Soit, par exemple, les services de message. Delphi 6 introduit une nouvelle caractéristique : les groupes de messages. De ce
fait, l'interface de base des messages a besoin de nouvelles fonctions membre. Ces fonctions sont déclarées dans une nouvelle
classe d'interface, qui conserve le nom IOTAMessageServices. L'ancienne interface des services de message est renommée en
IOTAMessageServices50 (pour la version 5). Le GUID de l'ancienne interface IOTAMessageServices est le même que le GUID
de la nouvelle interface IOTAMessageServices50 car les fonctions membre sont les mêmes.

Prenons IOTAIDENotifier comme exemple d'une interface implémentée par l'utilisateur. Delphi 5 ajoute de nouvelles fonctions :
AfterCompile et BeforeCompile. Le code existant qui utilisait IOTAIDENotifier n'a pas à être modifié, mais le nouveau code
utilisant les nouvelles fonctionnalités doit être modifié pour redéfinir les nouvelles fonctions héritées de IOTAIDENotifier50. La
version 6 n'a pas ajouté de nouvelles fonctions, la version en cours à utiliser est donc IOTAIDENotifier50.

Le principe de base consiste à utiliser la classe la plus dérivée lors de l'écriture de nouveau code. Ne changez rien au code si
vous recompilez simplement un expert existant avec une nouvelle version de Delphi.

Voir aussi
3 Accès aux services de l'API Tools ( see page 1305)

3.2.1.6.10 Notification d'un expert des événements de l'EDI


Un aspect important pour bien concevoir un expert consiste à le faire réagir aux événements de l'EDI. En particulier, si un expert
suit les interfaces de module, il doit savoir quand l'utilisateur ferme le module, afin que l'expert puisse libérer l'interface. Pour ce
faire, l'expert a besoin d'un notificateur, ce qui signifie que vous devez écrire une classe de notification.

Toutes les classes de notification implémentent une ou plusieurs interfaces de notification. Une interface de notification définit

1300
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

des méthodes de rappel ; l'expert recense un objet notificateur dans l'API Tools, et l'EDI rappelle le notificateur quand il se
produit quelque chose d'important.

Chaque interface de notification hérite de IOTANotifier même si toutes ses méthodes ne sont pas utilisées dans un même
notificateur. Le tableau suivant liste toutes les interfaces de notification en les décrivant brièvement.

Interfaces de notification

Interface Description
IOTANotifier Classe de base abstraite de tous les notificateurs
IOTABreakpointNotifier Déclenchement ou modification d'un point d'arrêt dans le débogueur
IOTADebuggerNotifier Exécution d'un programme dans le débogueur, ou l'ajout ou la suppression d'un point d'arrêt
IOTAEditLineNotifier Suit le déplacement des lignes dans l'éditeur de code source
IOTAEditorNotifier Modification ou enregistrement d'un fichier source ou passage d'un fichier à l'autre dans l'éditeur
IOTAFormNotifier Enregistrement d'une fiche ou modification de la fiche ou de ses composants (ou d'un module de
données)
IOTAIDENotifier Chargement de projets, installation de packages et autres événements de l'EDI de portée globale
IOTAMessageNotifier Ajout ou suppression d'onglets (groupes de messages) dans la vue des messages
IOTAModuleNotifier Modification, enregistrement ou changement de nom d'un module
IOTAProcessModNotifier Chargement d'un module de processus dans le débogueur
IOTAProcessNotifier Création ou destruction de threads ou de processus dans le débogueur
IOTAThreadNotifier Modification de l'état d'un thread dans le débogueur
IOTAToolsFilterNotifier Appel d'un outil de filtrage

Pour voir comment utiliser des notificateurs, reportez-vous à l'exemple proposé dans Création de fiches et de projets ( see
page 1291). Grâce à des créateurs de module, l'exemple crée un expert qui ajoute un commentaire à chaque fichier source. Le
commentaire comprend le nom initial du fichier de l'unité, mais l'utilisateur enregistre presque toujours le fichier sous un nom
différent. Dans ce cas, ce serait un avantage pour l'utilisateur que l'expert actualise le commentaire pour correspondre au
véritable nom du fichier.

Pour ce faire, vous devez utiliser un notificateur de module. L'expert enregistre l'interface de module que renvoie CreateModule
et l'utilise pour recenser un notificateur de module. Le notificateur de module reçoit une notification quand l'utilisateur modifie le
fichier ou l'enregistre, mais comme ces événements ne concernent pas l'expert, AfterSave et les fonctions associées sont
laissées vides. La fonction importante est ModuleRenamed, elle est appelée par l'EDI quand l'utilisateur enregistre le fichier sous
un nouveau nom. Voici la déclaration de la classe du notificateur de module :
TModuleIdentifier = class(TNotifierObject, IOTAModuleNotifier)
public
constructor Create(const Module: IOTAModule);
destructor Destroy; override;
function CheckOverwrite: Boolean;
procedure ModuleRenamed(const NewName: string);
procedure Destroyed;
private 3
FModule: IOTAModule;
FName: string;
FIndex: Integer;
end;
class ModuleNotifier : public NotifierObject, public IOTAModuleNotifier
{
typedef NotifierObject inherited;
public:
__fastcall ModuleNotifier(const _di_IOTAModule module);
__fastcall ~ModuleNotifier();

1301
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

// IOTAModuleNotifier
virtual bool __fastcall CheckOverwrite();
virtual void __fastcall ModuleRenamed(const AnsiString NewName);
// IOTANotifier
void __fastcall AfterSave();
void __fastcall BeforeSave();
void __fastcall Destroyed();
void __fastcall Modified();
protected:
// IInterface
virtual HRESULT __stdcall QueryInterface(const GUID&, void**);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
private:
_di_IOTAModule module;
AnsiString name; // Stocke l'ancien nom du module.
int index; // Indice du notificateur.
};
L'un des moyens d'écrire un notificateur consiste à le faire se recenser lui-même dans son constructeur. Le destructeur annule le
recensement du notificateur. Dans le cas d'un notificateur de module, l'EDI appelle la méthode Destroyed quand l'utilisateur
ferme le fichier. Dans ce cas, le notificateur doit lui-même annuler son recensement et libérer sa référence à l'interface de
module. L'EDI libère sa référence au notificateur, ce qui ramène à zéro son compteur de références et libère l'objet. Il n'est donc
pas nécessaire d'écrire le destructeur défensivement : le notificateur n'est peut être déjà plus recensé.
constructor TModuleNotifier.Create( const Module: IOTAModule);
begin
FIndex := -1;
FModule := Module;
{ Recenser ce notificateur. }
FIndex := Module.AddNotifier(self);
{ Stocker l'ancien nom du module. }
FName := ChangeFileExt(ExtractFileName(Module.FileName), '');
end;
destructor TModuleNotifier.Destroy;
begin
{ Annuler le recensement du notificateur si ce n'est pas déjà fait. }
if Findex >= 0 then
FModule.RemoveNotifier(FIndex);
end;
procedure TModuleNotifier.Destroyed;
begin
{ L'interface du module est détruite, nettoyage du notificateur. }
if Findex >= 0 then
begin
{ Annuler le recensement du notificateur. }
FModule.RemoveNotifier(FIndex);
FIndex := -1;
end;
FModule := nil;
end;
__fastcall ModuleNotifier::ModuleNotifier(const _di_IOTAModule module)
: index(-1), module(module)
{
// Recense ce notificateur.
3 index = module->AddNotifier(this);
// Stocke l'ancien nom du module.
name = ChangeFileExt(ExtractFileName(module->FileName), "");
}
__fastcall ModuleNotifier::~ModuleNotifier()
{
// Annule le recensement du notificateur si ce n'est pas déjà fait.
if (index >= 0)
module->RemoveNotifier(index);
}
void __fastcall ModuleNotifier::Destroyed()

1302
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

{
// L'interface du module est détruite, nettoyage du notificateur.
if (index >= 0)
{
// Annule le recensement du notificateur.
module->RemoveNotifier(index);
index = -1;
}
module = 0;
}
L'EDI rappelle la fonction ModuleRenamed du notificateur quand l'utilisateur renomme le fichier. La fonction attend comme
paramètre le nouveau nom qui est utilisé par l'expert pour actualiser le commentaire dans le fichier. Pour modifier le tampon
source, l'expert utilise une interface de position d'édition. L'expert recherche la position appropriée, vérifie si le texte trouvé est le
bon et remplace ce texte par le nouveau nom.
procedure TModuleNotifier.ModuleRenamed(const NewName: string);
var
ModuleName: string;
I: Integer;
Editor: IOTAEditor;
Buffer: IOTAEditBuffer;
Pos: IOTAEditPosition;
Check: string;
begin
{ Obtenir le nom du module à partir du nouveau nom de fichier. }
ModuleName := ChangeFileExt(ExtractFileName(NewName), '');
for I := 0 to FModule.GetModuleFileCount - 1 do
begin
{ Mettre à jour tous les tampons de l'éditeur de code source. }
Editor := FModule.GetModuleFileEditor(I);
if Supports(Editor, IOTAEditBuffer, Buffer) then
begin
Pos := Buffer.GetEditPosition;
{ Le nom du module se trouve dans la ligne 2 du commentaire.
Sauter les espaces de début et copie l'ancien nom de module,
pour vérifier si c'est le bon emplacement. }
Pos.Move(2, 1);
Pos.MoveCursor(mmSkipWhite or mmSkipRight);
Check := Pos.RipText('', rfIncludeNumericChars or rfIncludeAlphaChars);
if Check = FName then
begin
Pos.Delete(Length(Check)); // Supprimer l'ancien nom.
Pos.InsertText(ModuleName); // Insérer le nouveau nom.
FName := ModuleName; // Mémoriser le nouveau nom.
end;
end;
end;
end;
void __fastcall ModuleNotifier::ModuleRenamed(const AnsiString NewName)
{
// Obtient le nom du module à partir du nouveau nom de fichier.
AnsiString ModuleName = ChangeFileExt(ExtractFileName(NewName), "");
for (int i = 0; i < module->GetModuleFileCount(); ++i)
{
// Actualise tous les tampons de l'éditeur de code source. 3
_di_IOTAEditor editor = module->GetModuleFileEditor(i);
_di_IOTAEditBuffer buffer;
if (editor->Supports(buffer))
{
_di_IOTAEditPosition pos = buffer->GetEditPosition();
// Le nom du module se trouve dans la ligne 2 du commentaire.
// Saute les espaces de début et copie l'ancien nom de module,
// pour vérifier si c'est le bon emplacement.
pos->Move(2, 1);
pos->MoveCursor(mmSkipWhite | mmSkipRight);

1303
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

AnsiString check = pos->RipText("", rfIncludeNumericChars | rfIncludeAlphaChars);


if (check == name)
{
pos->Delete(check.Length()); // Supprimer l'ancien nom.
pos->InsertText(ModuleName); // Insérer le nouveau nom.
name = ModuleName; // Mémoriser le nouveau nom.
}
}
}
}
Que se passe-t'il si l'utilisateur insère des commentaires au-dessus du nom de module ? Dans ce cas, vous devez utiliser le
notificateur de modification de ligne pour suivre le numéro de la ligne dans laquelle se trouve le nom du module. Pour ce faire,
utilisez les interfaces IOTAEditLineNotifier et IOTAEditLineTracker.

Il faut être prudent dans l'écriture de notificateurs. Vous devez vous assurer qu'aucun notificateur ne survit à son expert. Par
exemple, si l'utilisateur utilise l'expert pour créer une nouvelle unité, puis décharge l'expert, il y a toujours un notificateur attaché
à l'unité. Le résultat serait imprévisible mais provoquerait probablement un blocage de l'EDI. L'expert doit donc garder la trace de
tous ses notificateurs et doit annuler le recensement de chaque notificateur avant sa destruction. D'un autre côté, si l'utilisateur
ferme le fichier d'abord, le notificateur de module reçoit une notification Destroyed, ce qui signifie que le notificateur doit annuler
lui-même son recensement et libérer toutes ses références au module. Ensuite, le notificateur doit également se retirer de la liste
des notificateurs de l'expert.

Voici la version définitive de la fonction Execute de l'expert. Elle crée le nouveau module, utilise l'interface du module, crée un
notificateur de module puis enregistre le notificateur de module dans une liste d'interfaces (TInterfaceList).
procedure DocWizard.Execute;
var
Svc: IOTAModuleServices;
Module: IOTAModule;
Notifier: IOTAModuleNotifier;
begin
{ Renvoyer le projet en cours. }
Supports(BorlandIDEServices, IOTAModuleServices, Svc);
Module := Svc.CreateModule(TCreator.Create(creator_type));
Notifier := TModuleNotifier.Create(Module);
list.Add(Notifier);
end
void __fastcall DocWizard::Execute()
{
_di_IOTAModuleServices svc;
BorlandIDEServices->Supports(svc);
_di_IOTAModule module = svc->CreateModule(new Creator(creator_type));
_di_IOTAModuleNotifier notifier = new ModuleNotifier(module);
list->Add(notifier);
}
Le destructeur de l'expert parcourt la liste d'interfaces et annule le recensement de chaque notificateur de la liste. Il ne suffit pas
de laisser la liste d'interfaces libérer les interfaces qu'elle contient car l'EDI contient également les mêmes interfaces. Vous
devez demander à l'EDI de libérer les notificateurs d'interface afin de libérer les objets notificateur. Dans ce cas, le destructeur
fait croire aux notificateurs que leurs modules ont été détruits. Dans une situation plus compliquée, il peut s'avérer plus simple
d'écrire une fonction Unregister distincte pour la classe du notificateur.
3 destructor DocWizard.Destroy; override;
var
Notifier: IOTAModuleNotifier;
I: Integer;
begin
{ Annuler le recensement de tous les notificateurs de la liste. }
for I := list.Count - 1 downto 0 do
begin
Supports(list.Items[I], IOTANotifier, Notifier);
{ Faire comme si l'objet associé a été détruit.

1304
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Ce qui oblige le notificateur à se libérer lui-même. }


Notifier.Destroyed;
list.Delete(I);
end;
list.Free;
FItem.Free;
end;
__fastcall DocWizard::~DocWizard()
{
// Annule le recensement de tous les notificateurs de la liste.
for (int i = list->Count; --i >= 0; )
{
_di_IOTANotifier notifier;
list->Items[i]->Supports(notifier);
// Fait comme si l'objet associé a été détruit.
// Ce qui oblige le notificateur à se libérer lui-même.
notifier->Destroyed();
list->Delete(i);
}
delete list;
delete item;
}
Le reste de l'expert gère les détails du recensement de l'expert, l'installation des options de menu, etc.

Voir aussi
Accès aux services de l'API Tools ( see page 1305)

Utilisation des interfaces de module ( see page 1308)

3.2.1.6.11 Accès aux services de l'API Tools


Pour servir à quelque chose, un expert doit accéder à l'EDI : ses éditeurs, fenêtres, menus, etc. C'est le rôle des interfaces de
service. L'API Tools propose de nombreux services, dont des services action pour effectuer des actions sur les fichiers, des
services d'édition pour accéder à l'éditeur de code source, des services de débogage pour accéder au débogueur, etc. Le
tableau suivant résume toutes les interfaces de service.

Interfaces de service de l'API Tools

Interface Description
INTAServices Donne accès aux objets natifs de l'EDI : menu principal, liste d'actions, liste d'images et les
barres d'outils.
IOTAActionServices Effectue les actions de base sur les fichiers : ouverture, fermeture, enregistrement et
rechargement d'un fichier.
IOTACodeCompletionServices Donne accès à l'achèvement de code, ce qui permet à un expert d'installer un gestionnaire
personnalisé d'achèvement de code.
IOTADebuggerServices Donne accès au débogueur.
IOTAEditorServices Donne accès à l'éditeur de code source et aux tampons internes.
IOTAKeyBindingServices Permet à un expert de recenser des liaisons de clavier personnalisées. 3
IOTAKeyboardServices Donne accès aux macros et liaisons clavier.
IOTAKeyboardDiagnostics Inverse le débogage des frappes au clavier.
IOTAMessageServices Donne accès à la vue des messages.
IOTAModuleServices Donne accès aux fichiers ouverts.
IOTAPackageServices Obtient le nom de tous les packages installés et de leurs composants.

1305
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

IOTAServices Services divers.


IOTAToDoServices Donne accès à la liste des tâches, ce qui permet à un expert d'installer un gestionnaire
personnalisé de la liste de tâches.
IOTAToolsFilter Recense les notificateurs d'outils de filtrage.
IOTAWizardServices Recense ou annule le recensement d'un expert.

Pour utiliser une interface de service, transtypez la variable BorlandIDEServices dans le service souhaité à l'aide de la fonction
globale Supports, définie dans l'unité SysUtils. Par exemple,
procedure set_keystroke_debugging(debugging: Boolean);
var
diag: IOTAKeyboardDiagnostics
begin
if Supports(BorlandIDEServices, IOTAKeyboardDiagnostics, diag) then
diag.KeyTracing := debugging;
end;
void set_keystroke_debugging(bool debugging)
{
_di_IOTAKeyboardDiagnostics diag;
if (BorlandIDEServices->Supports(diag))
diag->KeyTracing = debugging;
}
Si votre expert a besoin d'utiliser fréquemment un service donné, vous pouvez conserver un pointeur sur ce service comme
donnée membre de la classe de votre expert.

Les rubriques suivantes décrivent en détail l'utilisation des services d'interfaces de l'API Tools :

• Utilisation d'objets natifs de l'EDI ( see page 1309)


• Débogage d'un expert ( see page 1295)
• Numéros de version de l'interface ( see page 1300)
Voir aussi
Utilisation des fichiers et des éditeurs ( see page 1309)

Création de fiches et de projets ( see page 1291)

Notification d'un expert des événements de l'EDI ( see page 1300)

3.2.1.6.12 Présentation de l'API Tools


Toutes les déclarations de l'API Tools se trouvent dans une seule unité, ToolsAPI. Pour utiliser l'API Tools, il faut généralement
employer un package de conception, c'est-à-dire que vous devez concevoir un complément API Tools comme un package de
conception ou comme une DLL utilisant des packages d'exécution. Pour plus d'informations sur les packages et les
bibliothèques, voir Installation du package de l'expert ( see page 1299).

L'interface principale dans l'écriture d'une extension API est IOTAWizard, la plupart des compléments de l'EDI sont donc appelés
3 des experts. Pour l'essentiel, les experts C++Builder et Delphi sont compatibles. Vous pouvez ainsi écrire et compiler un expert
avec Delphi puis l'utiliser dans C++Builder, et inversement. L'interopérabilité fonctionne mieux entre des versions ayant le même
numéro, mais il est aussi possible d'écrire des experts utilisables dans les versions futures des deux logiciels.

Pour utiliser l'API Tools, vous devez écrire des classes expert qui implémentent une ou plusieurs des interfaces définies dans
l'unité ToolsAPI.

Un expert utilise les services proposés par l'API Tools. Chaque service est une interface qui présente un ensemble de fonctions
associées. L'implémentation de l'interface est cachée dans l'EDI. L'API Tools ne publie que l'interface que vous pouvez utiliser
pour écrire vos experts sans avoir à vous préoccuper de l'implémentation des interfaces. Les divers services donnent accès à

1306
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

l'éditeur de code source, au concepteur de fiches, au débogueur, etc. Pour plus d'informations sur l'utilisation des interfaces
exposant des services à vos experts, voir Accès aux services de l'API Tools ( see page 1305).

Les services et autres interfaces sont regroupées dans deux catégories de base. Vous pouvez les distinguer par le préfixe utilisé
dans le nom de type :

• Le préfixe NTA (native tools API, API outils natifs) correspond à un accès direct à des objets réels de l'EDI, par exemple
l'objet TMainMenu de l'EDI. Pour utiliser ces interfaces, l'expert doit utiliser les packages CodeGear, cela signifie également
que l'expert est lié à une version spécifique de l'EDI. L'expert peut se trouver dans un package de conception ou dans une
DLL utilisant des packages d'exécution.
• Le préfixe OTA (Open Tools API) ne nécessite pas de packages et accède à l'EDI uniquement via des interfaces. En théorie,
vous pouvez concevoir un expert dans tout langage gérant les interfaces de style COM, dans la mesure où vous pouvez aussi
utiliser les conventions d'appel de Delphi et les types Delphi comme AnsiString. Les interfaces OTA ne donnent pas un accès
complet à l'EDI, mais presque toutes les fonctionnalités de l'API Tools sont accessibles via des interfaces OTA. Si un expert
n'utilise que des interfaces OTA , il est possible d'écrire une DLL qui ne dépend pas d'une version spécifique de l'EDI.
L'API Tools contient deux types d'interfaces : celles que le programmeur doit implémenter et celles qui sont implémentées par
l'EDI. La plupart des interfaces rentrent dans cette dernière catégorie : ces interfaces définissent les possibilités de l'EDI mais
masquent l'implémentation réelle. Il existe trois types d'interfaces que vous devez implémenter : les experts, les notificateurs
et les créateurs :
• Comme indiqué plus haut dans cette rubrique, une classe expert implémente l'interface IOTAWizard et éventuellement des
interfaces dérivées.
• Un notificateur est un autre type d'interface de l'API Tools. L'EDI utilise des notificateurs pour prévenir votre expert quand il se
produit quelque chose qui le concerne. Si vous écrivez une classe qui implémente l'interface de notification, recensez le
notificateur dans l'API Tools et l'EDI appelle votre objet notificateur quand l'utilisateur ouvre un fichier, modifie le code source,
change une fiche, démarre une session de débogage, etc. Les notificateurs sont décrits dans Notification d'un expert des
événements de l'EDI ( see page 1300).
• Un créateur est un autre type d'interface à implémenter. L'API Tools utilise des créateurs pour créer de nouvelles unités, des
fiches, des projets ou d'autres fichiers ou pour ouvrir des fichiers existants. Pour plus d'informations sur les interfaces de
création, voir Création de fiches et de projets ( see page 1291).
Les modules et les éditeurs sont d'autres interfaces importantes. Une interface module représente une unité ouverte ayant un ou
plusieurs fichiers. Une interface éditeur représente un fichier ouvert. Différentes interfaces éditeur vous donnent accès aux
différents aspects de l'EDI : l'éditeur de code source pour les fichiers source, le concepteur de fiche pour les fichiers fiche et
les ressources de projet pour les fichiers ressource. Pour plus d'informations sur les interfaces de module et d'éditeur, voir
Utilisation des fichiers et des éditeurs ( see page 1309).

3.2.1.6.13 Utilisation des interfaces d'éditeur


Chaque module dispose d'au moins une interface d'éditeur. Certains modules ont plusieurs éditeurs, tels qu'un fichier source
(.pas) et un fichier description de fiche (.dfm). Comme tous les éditeurs implémentent l'interface IOTAEditor ; transtypez l'éditeur
vers un type spécifique pour savoir quel est le type de l'éditeur. Par exemple, le code suivant permet d'obtenir l'interface de
l'éditeur de fiche d'une unité :
{ Renvoie l'éditeur de fiche d'un module ou nil si l'unité n'a pas de fiche. }
function GetFormEditor(Module: IOTAModule): IOTAFormEditor;
var
I: Integer;
Editor: IOTAEditor;
begin 3
for I := 0 to Module.ModuleFileCount - 1 do
begin
Editor := Module.ModuleFileEditors[I];
if Supports(Editor, IOTAFormEditor, Result) then
Exit;
end;
Result := nil;
end;
// Renvoie l'éditeur de fiche d'un module ou 0 si l'unité n'a pas de fiche.

1307
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

_di_IOTAFormEditor __fastcall GetFormEditor(_di_IOTAModule module)


{
for (int i = 0; i < module->ModuleFileCount; ++i)
{
_di_IOTAEditor editor = module->ModuleFileEditors[i];
_di_IOTAFormEditor formEditor;
if (editor->Supports(formEditor))
return formEditor;
}
return 0;
}
Les interfaces d'éditeur donnent accès à l'état interne de l'éditeur. Vous pouvez examiner le code source ou les composants que
l'utilisateur est en train de modifier, modifier le code source, les composants ou les propriétés, changer la sélection dans les
éditeurs de code source ou de fiche ou effectuer presque toute opération d'édition que l'utilisateur final peut mettre en oeuvre.

En utilisant une interface d'éditeur de fiche, un expert peut accéder à tous les composants d'une fiche. Chaque composant, y
compris la fiche racine ou le module de données, a une interface IOTAComponent associée. Un expert peut examiner ou
modifier la plupart des propriétés des composants. Si vous avez besoin d'un contrôle complet du composant, vous pouvez
transtyper l'interface IOTAComponent vers INTAComponent. L'interface de composant natif donne à l'expert un accès direct au
pointeur TComponent. Cela est important si vous avez besoin de lire ou de modifier une propriété de type classe, comme TFont,
ce qui ne peut se faire que via des interfaces de style NTA.

Voir aussi
Utilisation des interfaces de module ( see page 1308)

3.2.1.6.14 Utilisation des interfaces de module


Pour obtenir une interface de module, démarrez le service de module (IOTAModuleServices). Vous pouvez demander aux
services de module tous les modules qui sont ouverts, rechercher un module à partir d'un nom de fichier ou de fiche ou ouvrir un
fichier pour obtenir son interface de module.

Il existe différents types de modules correspondant aux différents types de fichiers : projets, ressources ou bibliothèques de
types. Transtypez une interface de module vers une interface de module spécifique pour savoir si le module est de ce type. Par
exemple, voici un moyen de déterminer l'interface du groupe de projets en cours :
{ Renvoie le groupe de projets en cours ou nil s'il n'y en a pas. }
function CurrentProjectGroup: IOTAProjectGroup;
var
I: Integer;
Svc: IOTAModuleServices;
Module: IOTAModule;
begin
Supports(BorlandIDEServices, IOTAModuleServices, Svc);
for I := 0 to Svc.ModuleCount - 1 do
begin
Module := Svc.Modules[I];
if Supports(Module, IOTAProjectGroup, Result) then
Exit;
end;
3 Result := nil;
end;
// Renvoie le groupe de projets en cours ou 0 s'il n'y en a pas.
_di_IOTAProjectGroup __fastcall CurrentProjectGroup()
{
_di_IOTAModuleServices svc;
BorlandIDEServices->Supports(svc);
for (int i = 0; i < svc->ModuleCount; ++i)
{
_di_IOTAModule module = svc->Modules[i];
_di_IOTAProjectGroup group;

1308
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

if (module->Supports(group))
return group;
}
return 0;
}
Voir aussi
Utilisation des interfaces d'éditeur ( see page 1307)

3.2.1.6.15 Utilisation d'objets natifs de l'EDI


Les experts ont un accès complet au menu principal, aux barres d'outils, à la liste d'actions et la liste d'images de l'EDI. Par
contre, les divers menus contextuels de l'EDI ne sont pas accessibles via l'API Tools.

L'interface INTAServices sert de point de départ à la manipulation des objets natifs de l'EDI. Utilisez cette interface pour ajouter
une image à la liste d'images, une action à la liste d'actions, un élément de menu au menu principal ou un bouton à une barre
d'outils. Vous pouvez lier l'action à l'élément de menu ou un bouton de barre d'outils. Quand l'expert est détruit, il doit nettoyer
les objets qu'il a créé mais il ne doit pas supprimer l'image qu'il a ajouté à la liste d'images. La suppression d'une image
perturberait l'indice de toutes les images ajoutées après cet expert.

L'expert utilise réellement les objets TMainMenu, TActionList, TImageList et TToolBar de l'EDI, vous pouvez donc écrire du code
de la même manière que dans une application normale. Cela signifie également que vous avez de nombreuses opportunités de
bloquer l'EDI ou de désactiver des caractéristiques importantes, par exemple en supprimant le menu Fichier. La section
Débogage d'un expert ( see page 1295) décrit les étapes du débogage d'un expert si vous rencontrez de tels problèmes.

Les rubriques suivantes décrivent comment effectuer ces tâches:

• Ajout d'une image à la liste d'images ( see page 1290)


• Ajout d'une action à la liste d'actions ( see page 1289)
• Suppression de boutons de barres d'outils ( see page 1296)

3.2.1.6.16 Utilisation des fichiers et des éditeurs


Il est important de comprendre comment l'API Tools manipule les fichiers. L'interface principale est IOTAModule. Un module
représente un ensemble de fichiers ouverts liés logiquement. Ainsi, une unité est représentée par un seul module. A son tour, le
module comprend un ou des éditeurs, chaque éditeur représentant un fichier, par exemple le fichier source de l'unité (.pas) ou le
fichier fiche (.dfm ou .xfm). Comme les interfaces éditeur reflètent l'état interne des éditeurs de l'EDI, un expert peut voir le code
modifié et les fiches que l'utilisateur voit, même si l'utilisateur n'a pas enregistré les modifications.

Les rubriques suivantes décrivent plus en détail les interfaces de module et d'éditeur :

• Utilisation des interfaces de module ( see page 1308)


• Utilisation des interfaces d'éditeur ( see page 1307)
Voir aussi
Accès aux services de l'API Tools ( see page 1305)
3
Création de fiches et de projets ( see page 1291)

Notification d'un expert des événements de l'EDI ( see page 1300)

3.2.1.6.17 Conception d'une classe expert


Il y a quatre types d'experts, le type d'un expert dépendant des interfaces qu'implémente la classe de l'expert. Le tableau suivant
décrit les quatre types d'experts.

1309
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Les quatre types d'expert

Interface Description
IOTAFormWizard Crée généralement une nouvelle unité, une fiche ou un autre fichier
IOTAMenuWizard Automatiquement ajoutée au menu Aide
IOTAProjectWizard Crée généralement une nouvelle application ou un projet
IOTAWizard Autres experts ne rentrant pas dans les autres catégories

La seule différence entre ces experts est la manière dont l'utilisateur fait appel à l'expert :

• Un expert menu est ajouté au menu Aide de l'EDI. Quand l'utilisateur sélectionne l'élément de menu, l'EDI appelle la fonction
Execute de l'expert. Les experts normaux étant beaucoup plus flexibles, on n'utilise généralement les experts menu
uniquement pour le prototypage ou la mise au point.
• Les experts fiche et projet sont également appelés experts du référentiel car ils sont placés dans le référentiel d'objets.
L'utilisateur accède à ces experts dans la boîte de dialogue Nouveaux éléments. L'utilisateur peut également voir ces experts
dans le référentiel d'objets (en choisissant l'élément de menu Outils Référentiel). L'utilisateur peut cocher la case Nouvelle
fiche d'un expert fiche, ce qui indique à l'EDI d'appeler l'expert fiche quand l'utilisateur choisit l'élément de menu
Fichier Nouveau Fiche. L'utilisateur peut également cocher la case Fiche principale. Celle-ci indique à l'EDI d'utiliser
l'expert fiche pour la fiche par défaut d'une nouvelle application. Pour un expert projet, l'utilisateur peut cocher la case
Nouveau projet. Dans ce cas, quand l'utilisateur choisit l'élément de menu Fichier Nouveau Application, l'EDI appelle
l'expert projet sélectionné.
• Le quatrième type d'expert correspond aux situations ne rentrant pas dans les autres catégories. A la base, un expert ne fait
rien automatiquement ou de lui-même. Vous devez donc définir comment l'expert est appelé.
L'API Tools ne définit aucune restriction sur les experts, par exemple imposer qu'un expert projet crée effectivement un projet.
Vous pouvez tout aussi bien concevoir un expert projet qui crée une fiche qu'un expert fiche qui crée un projet (du moins si
c'est vraiment ce que vous voulez).
Les rubriques suivantes fournissent des détails sur la façon d'implémenter et d'utiliser un expert :
• Implémentation des interfaces de l'expert ( see page 1297)
• Installation du package de l'expert ( see page 1299)
Voir aussi
Installation d'une DLL expert

3.2.1.7 Gestion des messages


Rubriques
Nom Description
Diffusion d'un message à tous les contrôles d'une fiche ( see page 1314) Quand votre composant modifie les paramètres globaux qui affectent tous les
contrôles d'une fiche ou d'un autre conteneur, vous pouvez envoyer un message
à ces contrôles pour qu'ils puissent se mettre à jour eux-mêmes en
conséquence. Les contrôles ne seront pas tous concernés par cette notification,
mais grâce à la diffusion du message, vous informez tous les contrôles qui
savent comment répondre tout en permettant aux autres d'ignorer le message.
3 Pour diffuser un message à tous les contrôles d'un autre contrôle, utilisez la
méthode Broadcast. Avant de diffuser un message, mettez dans un
enregistrement de message ( see page 1318) les informations que vous... suite
( see page 1314)

1310
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Appel direct du gestionnaire de message d'un contrôle ( see page 1314) Parfois, un seul contrôle a besoin de répondre à votre message. Si vous savez
quel contrôle doit recevoir le message, le moyen le plus simple et le plus court
d'envoyer le message est d'appeler la méthode Perform du contrôle.
Il existe deux raisons majeures d'appeler la méthode Perform d'un contrôle :

• Vous voulez que le contrôle fasse la même réponse qu'à


un message Windows (ou autre) standard. Par exemple,
quand un contrôle grille reçoit un message de frappe de
touche, il crée un contrôle d'édition en ligne puis envoie le
message de frappe de touche à ce contrôle d'édition.
• Vous... suite ( see page 1314)
Réponse aux événements système ( see page 1315) Quand la couche widget reçoit la notification d'un événement depuis le système
d'exploitation, elle génère un objet événement spécial (QEvent ou l'un de ses
descendants) pour représenter l'événement. L'objet événement contient des
informations en lecture seule sur l'événement qui s'est produit. Le type de l'objet
événement indique le type d'événement qui s'est produit.
La couche widget notifie les événements système à vos composants CLX en
utilisant un signal spécial de type événement. Elle passe l'objet QEvent au
gestionnaire de signal de l'événement. Le traitement du signal événement est un
petit peu plus compliqué que celui des autres signaux, car... suite ( see page
1315)
Envoi d'un message qui ne s'exécute pas immédiatement ( see page 1315) Dans certains cas, vous voulez envoyer un message mais vous ne savez pas si
l'exécution immédiate de la cible du message peut se faire en toute sécurité. Par
exemple, si le code qui envoie un message est appelé depuis un gestionnaire
d'événement du contrôle cible, il vous faudra vérifier que l'exécution du
gestionnaire d'événement est terminée avant que le contrôle exécute votre
message. Vous pouvez gérer cette situation pendant tout le temps où vous
n'avez pas besoin de connaître le résultat du message.
Utilisez l'appel à l'API Windows, PostMessage, pour envoyer un message à un
contrôle mais laisser au... suite ( see page 1315)
Envoi d'un message à l'aide de la file d'attente des messages Windows ( see Dans une application multithread, vous ne pouvez pas vous contenter d'appeler
page 1316) la méthode Perform car le contrôle cible se trouve dans un thread différent de
celui qui s'exécute. Mais, en utilisant la file d'attente des messages Windows,
vous pouvez communiquer en toute sécurité avec les autres threads. La gestion
des messages se passe toujours dans le thread VCL principal, mais vous pouvez
envoyer un message avec la file d'attente des messages Windows depuis
n'importe quel thread de l'application. Un appel à SendMessage est synchrone.
C'est-à-dire que SendMessage ne revient que lorsque le contrôle cible a géré le
message, même si... suite ( see page 1316)
Envoi des messages ( see page 1316) Généralement, une application émet un message pour envoyer des notifications
de changement d'état ou pour diffuser des informations. Votre composant peut
diffuser des messages vers tous les contrôles d'une fiche, envoyer des
messages à un contrôle particulier (ou à l'application elle-même), ou s'envoyer
des messages à lui-même.
Il existe plusieurs façons d'envoyer un message Windows. La méthode à utiliser
dépend de la raison pour laquelle vous envoyez le message. Les rubriques
suivantes décrivent les différentes façons d'envoyer des messages Windows :

• Diffusion d'un message à tous les contrôles d'une fiche.


( see page 1314)
• Appel direct du gestionnaire de message d'un contrôle. (
see page 1314)
• Envoi d'un message ( see page 1316)... suite ( see
page 1316)
Modification de la gestion des messages ( see page 1316) Avant de modifier la gestion des messages de vos composants, vous devez être
certain de ce que vous voulez effectivement faire. La VCL convertit la plupart des
messages en événements que l'auteur ou l'utilisateur du composant peut gérer. 3
Plutôt que de modifier le comportement de la gestion du message, vous
modifierez généralement le comportement de la gestion de l'événement.
Pour modifier la gestion d'un message dans les composants VCL, vous devez
redéfinir la méthode qui gère ce message. En outre, dans certaines
circonstances, vous pouvez empêcher un composant de gérer un message en
interceptant ce message.

1311
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Création de nouveaux gestionnaires de messages ( see page 1317) Puisque la VCL fournit des gestionnaires pour la plupart des messages standard,
vous avez à définir de nouveaux gestionnaires de message uniquement lorsque
vous définissez vous-mêmes vos propres messages. Pour travailler avec des
messages définis par l'utilisateur, nous allons étudier les trois points suivants :

• Définition de vos propres messages. ( see page 1319)


• Déclaration d'une nouvelle méthode de gestion d'un
message. ( see page 1318)
• Envoi des messages. ( see page 1316)
Déclaration d'un identificateur de message ( see page 1317) Un identificateur de message est une constante de la taille d'un entier. Windows
se réserve pour son propre usage les messages dont le numéro est inférieur
à 1 024. Lorsque vous déclarez vos propres messages, vous devez donc
toujours débuter par un numéro supérieur.
La constante WM_APP représente le numéro de départ pour les messages
définis par l'utilisateur. Lorsque vous définissez un identificateur de message,
utilisez WM_APP.
Notez que certains contrôles Windows standard utilisent des messages compris
dans la plage des messages utilisateur. Entre autres contrôles, il y a les boîtes
liste, les boîtes à options, les boîtes de saisie et... suite ( see page 1317)
Exemple : Messages définis par l'utilisateur ( see page 1317) Le code suivant définit deux messages utilisateur :
Exemple : Structure de message ( see page 1317) Par exemple, voici un enregistrement de message pour tous les messages de
souris, TWMMouse, qui utilisent un enregistrement variant pour définir deux
ensembles de noms pour les mêmes paramètres.
Déclaration d'un type structure de message ( see page 1318) Si vous voulez attribuer un nom explicite aux paramètres de votre message, vous
devez déclarer un type enregistrement pour le message. L'enregistrement de
message correspond au type du paramètre transmis à la méthode de gestion du
message. Si vous n'utilisez pas les paramètres du message ou si vous souhaitez
utiliser l'ancienne notation (wParam, lParam, etc.), utilisez l'enregistrement de
message implicite, TMessage.
Déclaration d'une nouvelle méthode de gestion d'un message ( see page 1318) Deux circonstances vous amènent à déclarer de nouvelles méthodes de gestion
des messages :

• Votre composant a besoin de gérer un message Windows


qui n'est pas pris en compte par les composants standard.
• Vous avez défini votre propre message et vous souhaitez
l'utiliser avec vos composants.
Exemple : Gestionnaire de message ( see page 1318) Voici la déclaration, par exemple, d'un gestionnaire de message pour un
message utilisateur intitulé CM_CHANGECOLOR.
Définition de vos propres messages ( see page 1319) De nombreux composants standard définissent des messages pour leur usage
interne. Définir des messages peut servir à émettre des informations qui ne sont
pas prises en compte par les messages standard ou à notifier un changement
d'état. Vous pouvez définir vos propres messages dans la VCL.
La définition d'un message est un processus à deux étapes : Les étapes sont les
suivantes :

1. Déclaration d'un identificateur de message. ( see page


1317)
2. Déclaration d'un type enregistrement de message. ( see
page 1318)
Répartition des messages ( see page 1319) Lorsqu'une application crée une fenêtre, elle recense une procédure fenêtre avec
le modèle Windows. La procédure fenêtre représente la routine qui gère les
messages pour la fenêtre. Habituellement, la procédure fenêtre contient une
instruction longue case avec des entrées pour chaque message devant être géré
par la fenêtre. N'oubliez pas que "fenêtre" dans ce sens signifie seulement
3 quelque chose sur l'écran : chaque fenêtre, chaque contrôle, etc. A chaque fois
que vous créez un nouveau type de fenêtre, vous devez créer une procédure
fenêtre complète.
La VCL simplifie la répartition des messages de plusieurs manières :

• Chaque composant hérite d'un système complet... suite


( see page 1319)
Exemple : Redéfinition d'un gestionnaire de message ( see page 1320) Par exemple, pour redéfinir la gestion du message WM_PAINT d'un composant,
redéclarez la méthode WMPaint :

1312
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Redéfinition de la méthode Handler ( see page 1320) Pour modifier la façon dont un composant gère un message en particulier, vous
devez redéfinir la méthode qui le gère. Si le composant ne gère pas le message
en question, vous devez déclarer une nouvelle méthode de gestion du message.
Pour redéfinir la méthode de gestion d'un message, déclarez une nouvelle
méthode dans votre composant avec le même index de message que la
méthode redéfinie. N'utilisez pas la directive override ; vous devez utiliser la
directive message et un index de message correspondant.
Remarquez qu'il n'est pas nécessaire que le nom de la méthode et le type du
paramètre var... suite ( see page 1320)
Gestion des messages et des notifications système : Vue globale ( see page Les composants ont souvent à répondre à des notifications émises par le
1320) système d'exploitation sous-jacent. Le système d'exploitation informe
l'application de ce qui se produit, par exemple ce que fait l'utilisateur avec la
souris et le clavier. Certains contrôles génèrent également des notifications,
comme le résultat des actions de l'utilisateur, par exemple la sélection d'un
élément dans une liste. La bibliothèque de composants gère déjà la majorité des
notifications les plus communes. Il est cependant possible que vous ayez à écrire
votre propre code de gestion de notifications.
Pour les applications VCL, les notifications se présentent sous la forme de...
suite ( see page 1320)
Interception des messages ( see page 1321) Dans certaines circonstances, vous pouvez souhaiter que certains messages
soient ignorés par vos composants. Autrement dit, vous voulez empêcher le
composant de répartir un message à son gestionnaire. Pour intercepter un
message de cette façon, vous devez redéfinir la méthode virtuelle WndProc.
Pour les composants VCL, la méthode WndProc sélectionne les messages avant
de les transmettre à la méthode Dispatch qui, à son tour, détermine la méthode
qui gère le message. En redéfinissant WndProc, votre composant a la possibilité
de filtrer certains messages avant qu'ils ne soient transmis. La redéfinition de
WndProc pour un contrôle dérivé de TWinControl ressemble à... suite ( see
page 1321)
La méthode WndProc ( see page 1321) Remarque: Cette information s'applique uniquement à l'écriture de composants
VCL.
Voici une partie de la méthode WndProc pour TControl, par exemple :
Compréhension du système de gestion des messages ( see page 1322) Toutes les classes VCL disposent d'un mécanisme intégré pour gérer les
messages : ce sont les méthodes de gestion des messages ou gestionnaires de
messages. L'idée sous-jacente aux gestionnaires de messages est la suivante :
un objet reçoit des messages qu'il répartit selon le message en appelant une
méthode choisie dans un ensemble de méthodes spécifiques. Un gestionnaire
par défaut est appelé si aucune méthode n'est définie pour le message.
Le diagramme suivant illustre le fonctionnement du système de répartition de
message :

La bibliothèque des composants visuels définit un système de répartition des


messages qui convertit tous les messages Windows (y... suite ( see page 1322)
Utilisation des paramètres d'un message ( see page 1322) Une fois à l'intérieur d'une méthode de gestion de message, votre composant
peut accéder à tous les paramètres de la structure du message. Puisque le
paramètre passé au gestionnaire message est un paramètre var, le gestionnaire
peut modifier la valeur du paramètre si c'est nécessaire. Le seul paramètre qui
change fréquemment est le champ Result du message : il s'agit de la valeur
renvoyée par l'appel de SendMessage qui a émis le message.
Comme le type du paramètre Message transmis à la méthode de gestion dépend
du message géré, vous devez vous reporter à la documentation des messages
Windows pour... suite ( see page 1322)
Que contient un message Windows ? ( see page 1322) Un message Windows est un enregistrement de données contenant plusieurs
données membres exploitables. Le plus important est celui qui contient une
3
valeur de la taille d'un entier identifiant le message. Windows définit de
nombreux messages et l'unité Messages déclare tous leurs identificateurs. Les
autres informations utiles d'un message figurent dans deux champs paramètre et
un champ résultat.
Un paramètre contient 16 bits, l'autre 32 bits. Vous voyez souvent du code
Windows qui fait référence à ces valeurs avec wParam et lParam, comme
paramètre de type word et paramètre de type long. Souvent, chaque paramètre
contient plusieurs informations, et... suite ( see page 1322)

1313
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.7.1 Diffusion d'un message à tous les contrôles d'une fiche


Quand votre composant modifie les paramètres globaux qui affectent tous les contrôles d'une fiche ou d'un autre conteneur,
vous pouvez envoyer un message à ces contrôles pour qu'ils puissent se mettre à jour eux-mêmes en conséquence. Les
contrôles ne seront pas tous concernés par cette notification, mais grâce à la diffusion du message, vous informez tous les
contrôles qui savent comment répondre tout en permettant aux autres d'ignorer le message.

Pour diffuser un message à tous les contrôles d'un autre contrôle, utilisez la méthode Broadcast. Avant de diffuser un message,
mettez dans un enregistrement de message ( see page 1318) les informations que vous voulez envoyer.
var
Msg: TMessage;
begin
Msg.Msg := MY_MYCUSTOMMESSAGE;
Msg.WParam := 0;
Msg.LParam := Longint(Self);
Msg.Result := 0;
TMessage Msg;
Msg.Msg = MY_MYCUSTOMMESSAGE;
Msg.WParam = 0;
Msg.LParam = (int)(this);
Msg.Result = 0;
Ensuite, passez l'enregistrement de ce message au parent de tous les contrôles qui doivent être notifiés. Cela peut être
n'importe quel contrôle de l'application. Par exemple, ce peut être le parent d'un contrôle que vous êtes en train d'écrire :
Parent.Broadcast(Msg);
Parent->Broadcast(Msg);
Ce peut être la fiche contenant votre contrôle :
GetParentForm(self).Broadcast(Msg);
GetParentForm(this)->Broadcast(Msg);
Ce peut être la fiche active :
Screen.ActiveForm.Broadcast(Msg);
Screen->ActiveForm->Broadcast(Msg);
Ce peut même être toutes les fiches de votre application :
for I:= 0 to Screen.FormCount - 1 do
Screen.Forms[I].Broadcast(Msg);
for (int i = 0; i < Screen->FormCount; i++)
Screen->Forms[i]->Broadcast(Msg);
Voir aussi
Envoi d'un message qui ne s'exécute pas immédiatement ( see page 1315)

Envoi d'un message à l'aide de la file d'attente des messages Windows ( see page 1316)

3.2.1.7.2 Appel direct du gestionnaire de message d'un contrôle


3
Parfois, un seul contrôle a besoin de répondre à votre message. Si vous savez quel contrôle doit recevoir le message, le moyen
le plus simple et le plus court d'envoyer le message est d'appeler la méthode Perform du contrôle.

Il existe deux raisons majeures d'appeler la méthode Perform d'un contrôle :

• Vous voulez que le contrôle fasse la même réponse qu'à un message Windows (ou autre) standard. Par exemple, quand un
contrôle grille reçoit un message de frappe de touche, il crée un contrôle d'édition en ligne puis envoie le message de frappe
de touche à ce contrôle d'édition.
• Vous pouvez savoir quel contrôle notifier, mais ne pas connaître son type. Comme vous ne connaissez pas le type du

1314
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

contrôle cible, vous ne pouvez utiliser aucune de ses méthodes spécialisées, mais étant donné que tous les contrôles offrent
des fonctionnalités de gestion des messages, vous pouvez toujours lui envoyer un message. Si le contrôle dispose d'un
gestionnaire pour le message que vous envoyez, il répondra de façon appropriée. Sinon, il ignorera le message envoyé et
renverra 0.
Pour appeler la méthode Perform, vous n'avez pas besoin de créer un enregistrement message. Il suffit de passer comme
paramètres l'identificateur du message, WParam et LParam. Perform renvoie le message résultant.
Voir aussi
Envoi d'un message qui ne s'exécute pas immédiatement ( see page 1315)

Diffusion d'un message à tous les contrôles d'une fiche ( see page 1314)

Envoi d'un message à l'aide de la file d'attente des messages Windows ( see page 1316)

3.2.1.7.3 Réponse aux événements système


Quand la couche widget reçoit la notification d'un événement depuis le système d'exploitation, elle génère un objet événement
spécial (QEvent ou l'un de ses descendants) pour représenter l'événement. L'objet événement contient des informations en
lecture seule sur l'événement qui s'est produit. Le type de l'objet événement indique le type d'événement qui s'est produit.

La couche widget notifie les événements système à vos composants CLX en utilisant un signal spécial de type événement. Elle
passe l'objet QEvent au gestionnaire de signal de l'événement. Le traitement du signal événement est un petit peu plus
compliqué que celui des autres signaux, car il va en premier vers l'objet application. Cela signifie qu'une application a deux
possibilités de répondre à un événement système : une fois au niveau de l'application (TApplication) et une fois au niveau du
composant individuel (votre descendant de TWidgetControl ou de THandleComponent.) Toutes ces classes (TApplication,
TWidgetControl et THandleComponent) affectent déjà un gestionnaire de signal pour l'événement depuis la couche widget.
C'est-à-dire que tous les événements système sont automatiquement dirigés vers la méthode EventFilter, qui joue un rôle
similaire à la méthode WndProc sur les contrôles VCL.

EventFilter gère la plupart des notifications système communément utilisées, les convertissant en événements introduits par les
classes de base de vos composants. Par exemple, la méthode EventFilter de TWidgetControl répond aux événements de souris
(QMouseEvent) en générant les événements OnMouseDown, OnMouseMove et OnMouseUp, aux événements de clavier
(QKeyEvent) en générant les événements OnKeyDown, OnKeyPress, OnKeyString et OnKeyUp, etc.

Les rubriques suivantes expliquent comment personnaliser la façon dont vos composants fonctionnent avec les événements
système :

• Evénements couramment utilisés


• Redéfinition de la méthode EventFilter
• Génération des événements Qt

3.2.1.7.4 Envoi d'un message qui ne s'exécute pas immédiatement


Dans certains cas, vous voulez envoyer un message mais vous ne savez pas si l'exécution immédiate de la cible du message
peut se faire en toute sécurité. Par exemple, si le code qui envoie un message est appelé depuis un gestionnaire d'événement
du contrôle cible, il vous faudra vérifier que l'exécution du gestionnaire d'événement est terminée avant que le contrôle exécute 3
votre message. Vous pouvez gérer cette situation pendant tout le temps où vous n'avez pas besoin de connaître le résultat du
message.

Utilisez l'appel à l'API Windows, PostMessage, pour envoyer un message à un contrôle mais laisser au contrôle le temps d'en
finir avec les autres messages avant de gérer le vôtre. PostMessage prend exactement les mêmes paramètres que
SendMessage.

Pour plus d'informations sur la fonction PostMessage, voir la documentation Microsoft MSDN.

1315
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Voir aussi
Diffusion d'un message à tous les contrôles d'une fiche ( see page 1314)

Envoi d'un message à l'aide de la file d'attente des messages Windows ( see page 1316)

3.2.1.7.5 Envoi d'un message à l'aide de la file d'attente des messages


Windows
Dans une application multithread, vous ne pouvez pas vous contenter d'appeler la méthode Perform car le contrôle cible se
trouve dans un thread différent de celui qui s'exécute. Mais, en utilisant la file d'attente des messages Windows, vous pouvez
communiquer en toute sécurité avec les autres threads. La gestion des messages se passe toujours dans le thread VCL
principal, mais vous pouvez envoyer un message avec la file d'attente des messages Windows depuis n'importe quel thread de
l'application. Un appel à SendMessage est synchrone. C'est-à-dire que SendMessage ne revient que lorsque le contrôle cible a
géré le message, même si cela se passe dans un autre thread.

Utilisez l'appel à l'API Windows, SendMessage, pour envoyer un message à un contrôle à l'aide de la file d'attente des
messages Windows. SendMessage prend les mêmes paramètres que la méthode Perform, sauf que vous devez identifier le
contrôle cible en passant son handle de fenêtre. Ainsi, au lieu d'écrire :
MsgResult := TargetControl.Perform(MY_MYMESSAGE, 0, 0);
MsgResult = TargetControl->Perform(MY_MYMESSAGE, 0, 0);
il faut écrire
MsgResult := SendMessage(TargetControl.Handle, MYMESSAGE, 0, 0);
MsgResult = SendMessage(TargetControl->Handle, MYMESSAGE, 0, 0);
Pour plus d'informations sur la fonction SendMessage, voir la documentation Microsoft MSDN. Pour plus d'informations sur
l'écriture de threads multiples pouvant être exécutés simultanément, voir Coordination de threads ( see page 2302).

Voir aussi
Envoi d'un message qui ne s'exécute pas immédiatement ( see page 1315)

Diffusion d'un message à tous les contrôles d'une fiche ( see page 1314)

3.2.1.7.6 Envoi des messages


Généralement, une application émet un message pour envoyer des notifications de changement d'état ou pour diffuser des
informations. Votre composant peut diffuser des messages vers tous les contrôles d'une fiche, envoyer des messages à un
contrôle particulier (ou à l'application elle-même), ou s'envoyer des messages à lui-même.

Il existe plusieurs façons d'envoyer un message Windows. La méthode à utiliser dépend de la raison pour laquelle vous envoyez
le message. Les rubriques suivantes décrivent les différentes façons d'envoyer des messages Windows :

• Diffusion d'un message à tous les contrôles d'une fiche. ( see page 1314)
• Appel direct du gestionnaire de message d'un contrôle. ( see page 1314)
3 • Envoi d'un message à l'aide de la file d'attente des messages Windows. ( see page 1316)
• Envoi d'un message qui ne s'exécute pas immédiatement. ( see page 1315)

3.2.1.7.7 Modification de la gestion des messages


Avant de modifier la gestion des messages de vos composants, vous devez être certain de ce que vous voulez effectivement
faire. La VCL convertit la plupart des messages en événements que l'auteur ou l'utilisateur du composant peut gérer. Plutôt que
de modifier le comportement de la gestion du message, vous modifierez généralement le comportement de la gestion de

1316
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

l'événement.

Pour modifier la gestion d'un message dans les composants VCL, vous devez redéfinir la méthode qui gère ce message. En
outre, dans certaines circonstances, vous pouvez empêcher un composant de gérer un message en interceptant ce message.

3.2.1.7.8 Création de nouveaux gestionnaires de messages


Puisque la VCL fournit des gestionnaires pour la plupart des messages standard, vous avez à définir de nouveaux gestionnaires
de message uniquement lorsque vous définissez vous-mêmes vos propres messages. Pour travailler avec des messages définis
par l'utilisateur, nous allons étudier les trois points suivants :

• Définition de vos propres messages. ( see page 1319)


• Déclaration d'une nouvelle méthode de gestion d'un message. ( see page 1318)
• Envoi des messages. ( see page 1316)

3.2.1.7.9 Déclaration d'un identificateur de message


Un identificateur de message est une constante de la taille d'un entier. Windows se réserve pour son propre usage les
messages dont le numéro est inférieur à 1 024. Lorsque vous déclarez vos propres messages, vous devez donc toujours
débuter par un numéro supérieur.

La constante WM_APP représente le numéro de départ pour les messages définis par l'utilisateur. Lorsque vous définissez un
identificateur de message, utilisez WM_APP.

Notez que certains contrôles Windows standard utilisent des messages compris dans la plage des messages utilisateur. Entre
autres contrôles, il y a les boîtes liste, les boîtes à options, les boîtes de saisie et les boutons de commande. Si vous dérivez un
composant à partir de l'un d'eux et si vous voulez lui associer un nouveau message, vérifiez le contenu de l'unité Messages pour
voir quels messages Windows sont déjà définis pour ce contrôle.

3.2.1.7.10 Exemple : Messages définis par l'utilisateur


Le code suivant définit deux messages utilisateur :
const
MY_MYFIRSTMESSAGE = WM_APP + 400;
MY_MYSECONDMESSAGE = WM_APP + 401;
#define MY_MYFIRSTMESSAGE (WM_APP + 400)
#define MY_MYSECONDMESSAGE (WM_APP + 401)

3.2.1.7.11 Exemple : Structure de message


Par exemple, voici un enregistrement de message pour tous les messages de souris, TWMMouse, qui utilisent un
enregistrement variant pour définir deux ensembles de noms pour les mêmes paramètres.
type
TWMMouse = record
Msg: TMsgParam; ( ID de message en premier ) 3
Keys: Word; ( ceci est le wParam )
case Integer of ( deux manières de voir lParam )
0: {
XPos: Integer; ( sous la forme de coordonnées x et y...)
YPos: Integer);
1: {
Pos: TPoint; ( ... ou d'un point unique )
Résultat : Longint); ( en dernier lieu, le champ résultat )
end;

1317
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

struct TWMKey
{
Cardinal Msg; // le premier paramètre est l'ID du message
Word CharCode; // ceci est le premier wParam
Word Unused;
Longint KeyData; // voici le Param 1
Longint Result; // voici la donnée membre résultat
};

3.2.1.7.12 Déclaration d'un type structure de message


Si vous voulez attribuer un nom explicite aux paramètres de votre message, vous devez déclarer un type enregistrement pour le
message. L'enregistrement de message correspond au type du paramètre transmis à la méthode de gestion du message. Si
vous n'utilisez pas les paramètres du message ou si vous souhaitez utiliser l'ancienne notation (wParam, lParam, etc.), utilisez
l'enregistrement de message implicite, TMessage.

Pour déclarer un type enregistrement de message, respectez les conventions suivantes :


1. Nommez le type enregistrement d'après le message en rajoutant le préfixe T à son nom.
2. Donnez au premier champ de l'enregistrement le nom Msg et le type TMsgParam.
3. Définissez les deux octets suivants pour qu'ils correspondent au paramètre Word, et les deux suivants inutilisés. Ou
Définissez les quatre octets suivants pour qu'ils correspondent au paramètre Longint.
4. Ajoutez un dernier champ intitulé Result de type Longint.

3.2.1.7.13 Déclaration d'une nouvelle méthode de gestion d'un message


Deux circonstances vous amènent à déclarer de nouvelles méthodes de gestion des messages :

• Votre composant a besoin de gérer un message Windows qui n'est pas pris en compte par les composants standard.
• Vous avez défini votre propre message et vous souhaitez l'utiliser avec vos composants.

Pour déclarer la méthode de gestion d'un message, suivez les étapes ci-après :
1. Déclarez la méthode dans une partie protected de la déclaration de la classe du composant.
2. Faites de la méthode une procédure.
3. Nommez la méthode suivant le message qu'elle gère en supprimant les caractères de soulignement de son nom.
4. Transmettez un seul paramètre var appelé Message, du type défini par l'enregistrement du message.
5. A l'intérieur de l'implémentation de la méthode message, écrivez le code de gestion spécifique au composant.
6. Appelez le gestionnaire de message transmis en héritage.

3.2.1.7.14 Exemple : Gestionnaire de message


Voici la déclaration, par exemple, d'un gestionnaire de message pour un message utilisateur intitulé CM_CHANGECOLOR.

3 const
CM_CHANGECOLOR = WM_APP + 400;
type
TMyComponent = class(TControl)
.
.
.
protected
procedure CMChangeColor(var Message: TMessage); message CM_CHANGECOLOR;
end;
procedure TMyComponent.CMChangeColor(var Message: TMessage);

1318
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

begin
Color := Message.lParam;
inherited;
end;
#define CM_CHANGECOLOR (WM_APP + 400)
class TMyControl : public TControl
{
protected:
void __fastcall CMChangeColor(TMessage &Message);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CM_CHANGECOLOR, TMessage, CMChangeColor)
END_MESSAGE_MAP(TControl)
};
void __fastcall TMyControl::CMChangeColor(TMessage &Message)
{
Color = Message.LParam; // définir la couleur dans un paramètre de type
long
TControl::CMChangeColor(Message); // appel du gestionnaire de message transmis en
héritage
}

3.2.1.7.15 Définition de vos propres messages


De nombreux composants standard définissent des messages pour leur usage interne. Définir des messages peut servir à
émettre des informations qui ne sont pas prises en compte par les messages standard ou à notifier un changement d'état. Vous
pouvez définir vos propres messages dans la VCL.

La définition d'un message est un processus à deux étapes : Les étapes sont les suivantes :

1. Déclaration d'un identificateur de message. ( see page 1317)


2. Déclaration d'un type enregistrement de message. ( see page 1318)

3.2.1.7.16 Répartition des messages


Lorsqu'une application crée une fenêtre, elle recense une procédure fenêtre avec le modèle Windows. La procédure fenêtre
représente la routine qui gère les messages pour la fenêtre. Habituellement, la procédure fenêtre contient une instruction longue
case avec des entrées pour chaque message devant être géré par la fenêtre. N'oubliez pas que "fenêtre" dans ce sens signifie
seulement quelque chose sur l'écran : chaque fenêtre, chaque contrôle, etc. A chaque fois que vous créez un nouveau type de
fenêtre, vous devez créer une procédure fenêtre complète.

La VCL simplifie la répartition des messages de plusieurs manières :

• Chaque composant hérite d'un système complet de répartition de message.


• Le système de répartition de message dispose d'une gestion par défaut. Vous ne définissez de gestionnaire que pour les
messages auxquels vous souhaitez spécifiquement répondre.
• Vous pouvez modifier des parties de la gestion de message en vous appuyant sur les méthodes reçues en héritage pour la
majeure partie du traitement.
Le bénéfice le plus évident de cette répartition de message est le suivant : à tout moment, vous pouvez envoyer n'importe quel
message à n'importe quel composant. Si le composant n'a pas de gestionnaire défini pour ce message, le système de gestion
par défaut s'en charge, généralement en ignorant le message.
3
Suivi du flux des messages
La méthode MainWndProc est recensée par la VCL comme procédure de fenêtre pour tous les types de composants d'une
application. MainWndProc contient un bloc de gestion des exceptions qui transmet la structure du message en provenance de
Windows à la méthode virtuelle WndProc, gérant les exceptions éventuelles à l'aide de la méthode HandleException de la classe
application.

MainWndProc est une méthode non virtuelle qui n'effectue aucune gestion particulière des messages. Cette gestion a lieu dans

1319
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

WndProc, chaque type de composant ayant la possibilité de redéfinir cette méthode pour répondre à ses besoins spécifiques.

Les méthodes WndProc vérifient les conditions spéciales qui peuvent affecter le traitement et "interceptent", s'il le faut, les
messages non souhaités. Par exemple, lorsque vous faites glisser un composant, celui-ci ignore les événements du clavier, et la
méthode WndProc de TWinControl ne transmet ces événements que si l'utilisateur ne fait pas glisser le composant. Enfin,
WndProc appelle Dispatch, une méthode non virtuelle héritée de TObject, qui détermine la méthode à appeler pour gérer le
message.

Dispatch utilise le champ Msg de l'enregistrement du message pour déterminer comment répartir le message particulier. Si le
composant définit un gestionnaire pour ce message, Dispatch appelle cette méthode. Si aucun gestionnaire n'est défini,
Dispatch appelle DefaultHandler.

3.2.1.7.17 Exemple : Redéfinition d'un gestionnaire de message


Par exemple, pour redéfinir la gestion du message WM_PAINT d'un composant, redéclarez la méthode WMPaint :
type
TMyComponent = class(...)
.
.
.
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
end;
class PACKAGE TMyComponent : public TComponent
{
protected:
void __fastcall WMPaint(TWMPaint* Message);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_PAINT, TWMPaint, WMPaint)
END_MESSAGE_MAP(TComponent)
};

3.2.1.7.18 Redéfinition de la méthode Handler


Pour modifier la façon dont un composant gère un message en particulier, vous devez redéfinir la méthode qui le gère. Si le
composant ne gère pas le message en question, vous devez déclarer une nouvelle méthode de gestion du message.

Pour redéfinir la méthode de gestion d'un message, déclarez une nouvelle méthode dans votre composant avec le même index
de message que la méthode redéfinie. N'utilisez pas la directive override ; vous devez utiliser la directive message et un index
de message correspondant.

Remarquez qu'il n'est pas nécessaire que le nom de la méthode et le type du paramètre var simple correspondent à la méthode
redéfinie. Seul l'index de message est significatif. Pour plus de clarté, cependant, il est préférable de suivre la convention d'appel
des méthodes de gestion de message après les messages qu'elles gèrent.
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(parameter1, parameter2, parameter3)
END_MESSAGE_MAP

3 3.2.1.7.19 Gestion des messages et des notifications système : Vue globale


Les composants ont souvent à répondre à des notifications émises par le système d'exploitation sous-jacent. Le système
d'exploitation informe l'application de ce qui se produit, par exemple ce que fait l'utilisateur avec la souris et le clavier. Certains
contrôles génèrent également des notifications, comme le résultat des actions de l'utilisateur, par exemple la sélection d'un
élément dans une liste. La bibliothèque de composants gère déjà la majorité des notifications les plus communes. Il est
cependant possible que vous ayez à écrire votre propre code de gestion de notifications.

Pour les applications VCL, les notifications se présentent sous la forme de messages. Ces messages peuvent provenir de

1320
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

n'importe quelle source, y compris de Windows, des composants VCL et des composants que vous avez définis. Il y a trois
aspects à prendre en considération lorsque vous travaillez avec des messages :

• Compréhension du système de gestion des messages. ( see page 1322)


• Modification de la gestion des messages. ( see page 1316)
• Création de nouveaux gestionnaires de messages. ( see page 1317)

3.2.1.7.20 Interception des messages


Dans certaines circonstances, vous pouvez souhaiter que certains messages soient ignorés par vos composants. Autrement dit,
vous voulez empêcher le composant de répartir un message à son gestionnaire. Pour intercepter un message de cette façon,
vous devez redéfinir la méthode virtuelle WndProc.

Pour les composants VCL, la méthode WndProc sélectionne les messages avant de les transmettre à la méthode Dispatch qui,
à son tour, détermine la méthode qui gère le message. En redéfinissant WndProc, votre composant a la possibilité de filtrer
certains messages avant qu'ils ne soient transmis. La redéfinition de WndProc pour un contrôle dérivé de TWinControl
ressemble à ceci :
procedure TMyControl.WndProc(var Message: TMessage);
begin
{ tests pour déterminer la poursuite du traitement }
inherited WndProc(Message);
end;
void __fastcall TMyControl::WndProc(TMessage& Message)
{
// tests pour déterminer la poursuite du traitement
if(Message.Msg != WM_LBUTTONDOWN)

}
Le composant TControl définit des plages entières de messages liés à la souris qu'il filtre lorsqu'un utilisateur fait glisser puis
lâche un contrôle. Une méthode WndProc redéfinie peut agir par deux moyens :

• Elle peut filtrer des plages entières de messages au lieu de spécifier un gestionnaire pour chacun d'eux.
• Elle peut inhiber totalement la répartition des messages de façon à ce que les gestionnaires ne soient jamais appelés.

3.2.1.7.21 La méthode WndProc


Remarque: Cette information s'applique uniquement à l'écriture de composants VCL.

Voici une partie de la méthode WndProc pour TControl, par exemple :


procedure TControl.WndProc(var Message: TMessage);
begin
.
.
.
if (Message.Msg >= WM_MOUSEFIRST) and (Message.Msg <= WM_MOUSELAST) then
if Dragging then { gestion spécifique d'une
opération glisser } 3
DragMouseMsg(TWMMouse(Message))
else
. { gestion normale des autres
opérations }
.
.
end;
. { autrement gestion normale }
.
.

1321
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

end;

3.2.1.7.22 Compréhension du système de gestion des messages


Toutes les classes VCL disposent d'un mécanisme intégré pour gérer les messages : ce sont les méthodes de gestion des
messages ou gestionnaires de messages. L'idée sous-jacente aux gestionnaires de messages est la suivante : un objet reçoit
des messages qu'il répartit selon le message en appelant une méthode choisie dans un ensemble de méthodes spécifiques. Un
gestionnaire par défaut est appelé si aucune méthode n'est définie pour le message.

Le diagramme suivant illustre le fonctionnement du système de répartition de message :

La bibliothèque des composants visuels définit un système de répartition des messages qui convertit tous les messages
Windows (y compris ceux définis par l'utilisateur) destinés à une classe spécifique en appels à des méthodes. Vous n'aurez sans
doute jamais besoin de modifier le mécanisme de répartition des messages. En revanche, vous aurez à écrire des méthodes de
gestion des messages. Voir la section Déclaration d'une nouvelle méthode de gestion d'un message ( see page 1318), pour
plus de détails sur ce sujet.

3.2.1.7.23 Utilisation des paramètres d'un message


Une fois à l'intérieur d'une méthode de gestion de message, votre composant peut accéder à tous les paramètres de la structure
du message. Puisque le paramètre passé au gestionnaire message est un paramètre var, le gestionnaire peut modifier la valeur
du paramètre si c'est nécessaire. Le seul paramètre qui change fréquemment est le champ Result du message : il s'agit de la
valeur renvoyée par l'appel de SendMessage qui a émis le message.

Comme le type du paramètre Message transmis à la méthode de gestion dépend du message géré, vous devez vous reporter à
la documentation des messages Windows pour connaître le nom et la signification de chaque paramètre. Si pour une raison ou
pour une autre, vous avez à vous référer aux paramètres d'un message en utilisant l'ancienne convention d'appellation
(WParam, LParam, etc.), vous devez transtyper Message vers le type générique TMessage, qui utilise ces noms de paramètres.

3.2.1.7.24 Que contient un message Windows ?


Un message Windows est un enregistrement de données contenant plusieurs données membres exploitables. Le plus important
est celui qui contient une valeur de la taille d'un entier identifiant le message. Windows définit de nombreux messages et l'unité
Messages déclare tous leurs identificateurs. Les autres informations utiles d'un message figurent dans deux champs paramètre
et un champ résultat.

Un paramètre contient 16 bits, l'autre 32 bits. Vous voyez souvent du code Windows qui fait référence à ces valeurs avec
wParam et lParam, comme paramètre de type word et paramètre de type long. Souvent, chaque paramètre contient plusieurs
3 informations, et vous voyez les références aux noms comme lParamHi, qui font référence au mot de poids fort dans le
paramètre de type long.

A l'origine, un programmeur Windows devait mémoriser le contenu de chaque paramètre ou consulter les API Windows.
Microsoft a désormais donné un nom aux paramètres. Ces décomposeurs de message ainsi appelés simplifient la
compréhension des informations accompagnant chaque message. Par exemple, les paramètres pour le message
WM_KEYDOWN maintenant appelés nVirtKey et lKeyData, donnent plus d'informations spécifiques que wParam et lParam.

Pour chaque type de message, Delphi définit un type d'enregistrement qui donne un nom mnémonique à chaque paramètre. Les

1322
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

messages souris transmettent par exemple les coordonnées x et y de l'événement souris dans le paramètre de type long, une
dans le mot de poids fort, et l'autre dans le mot de poids faible. Avec l'utilisation de la structure souris-message, vous n'avez pas
à vous soucier du mot dont il s'agit, car vous faites référence aux paramètres par les noms XPos et YPos au lieu de lParamLo et
lParamHi.
void MyKeyDownHandler( HWND hwnd, UINT nVirtKey, BOOL fDown, int CRepeat, UINT flags )
{
.
.
.
}
LRESULT MyWndProc( HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam )
{
switch( Message )
{
HANDLE_MSG( hwnd, WM_KEYDOWN, MyKeyDownHandler );
.
.
.
}

3.2.1.8 Présentation de la création d'un composant


Rubriques
Nom Description
Vue globale de la création d'un composant ( see page 1327) Cet ensemble de rubriques est une présentation générale de la conception des
composants et du processus d'écriture des composants pour les applications
Delphi. Vous devez toutefois être familier de Delphi et de ses composants
standard.
Les principaux sujets abordés sont les suivants :

• Bibliothèque de classes ( see page 1328)


• Composants et classes ( see page 1328)
• Création de composants ( see page 1329)
• Contenu d'un composant ( see page 1337)
• Création d'un nouveau composant ( see page 1330)
• Test des composants non installés ( see page 1338)
• Test des composants installés ( see page 1338)
Pour obtenir des informations sur l'installation de nouveaux
composants, voir Installation de packages de composants
( see page 2291).

1323
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Bibliothèque de classes ( see page 1328) Les composants Delphi résident dans la bibliothèque de composants visuels
(VCL). La figure suivante montre la relation qui existe entre les classes
sélectionnées qui composent la hiérarchie VCL. Pour plus de détails sur les
hiérarchies des classes et les relations d'héritage entre classes, voir
Programmation orientée objet et écriture des composants ( see page 1387)
La classe TComponent est l'ancêtre partagé de chaque composant de la
bibliothèque de composants. TComponent fournit les propriétés et les
événements de base nécessaires au fonctionnement d'un composant dans l'EDI.
Les différentes branches de la bibliothèque offrent d'autres possibilités plus
spécialisées.

Lorsque vous créez un composant, vous l'ajoutez à... suite ( see page 1328)
Composants et classes ( see page 1328) Comme les composants sont des classes, les créateurs de composants
manipulent les objets à un niveau différent de celui des développeurs
d'applications. La création de nouveaux composants nécessite de dériver de
nouvelles classes.
Brièvement, il existe deux différences principales entre la création des
composants et leur utilisation dans des applications. Pour la création de
composants,

• Vous avez accès à des parties de la classe qui sont


inaccessibles aux programmeurs d'applications.
• Vous ajoutez de nouvelles parties (des propriétés, par
exemple) aux composants.
A cause de ces différences, il faut prendre en compte un
plus grand nombre de conventions, et réfléchir à... suite
( see page 1328)
Création de composants ( see page 1329) Un composant peut quasiment constituer tout élément de programme
manipulable à la conception. La création d'un composant consiste à dériver une
nouvelle classe à partir d'une classe existante. Vous pouvez dériver un nouveau
composant de plusieurs façons :

• Modification de contrôles existants ( see page 1329)


• Création de contrôles fenêtrés ( see page 1330)
• Création de contrôles graphiques ( see page 1332)
• Sous-classement de contrôles Windows ( see page
1335)
• Création de composants non visuels ( see page 1332)
3
Le tableau suivant présente les différents types de
composants et les classes que vous utiliserez comme
point de départ pour chacun d'eux.
Points de départ de la création de composants

1324
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Modification de contrôles existants ( see page 1329) Le moyen le plus simple de créer un composant est de modifier un composant
existant. Vous pouvez dériver un nouveau composant depuis un composant
quelconque de la bibliothèque de composants
Certains contrôles, tels les boîtes liste et les grilles, possèdent plusieurs
variantes d'un thème de base. Dans ce cas, la bibliothèque de composants
comprend un type de classe abstraite (son nom contient le mot "custom", comme
TCustomGrid) à partir de laquelle il est possible de dériver les versions
personnalisées.
Vous pouvez, par exemple, créer un type particulier de boîte liste ne possédant
pas certaines propriétés de la classe TListBox... suite ( see page 1329)
Création de contrôles originaux ( see page 1330) Les contrôles fenêtrés de la bibliothèque de composants sont des objets qui
apparaissent à l'exécution et avec lesquels l'utilisateur peut interagir. Chaque
contrôle fenêtré possède un handle de fenêtre, accessible via sa propriété
Handle, qui permet au système d'exploitation de l'identifier et d'agir sur lui. Dans
le cas d'utilisation de contrôles VCL, le handle permet au contrôle de recevoir la
focalisation de saisie et peut être transmis aux fonctions de l'API Windows.
Chaque contrôle widget possède un handle, accessible via sa propriété Handle,
identifiant le widget sous-jacent.
Tous les contrôles fenêtrés descendent de la classe TWinControl. Ils... suite (
see page 1330)
Création d'un nouveau composant ( see page 1330) Cette rubrique explique comment créer et configurer un nouveau composant.
Création d'un fichier unité ( see page 1331) Une unité est un module de code Delphi compilé séparément. Delphi emploie les
unités pour plusieurs raisons. Chaque fiche possède sa propre unité et la plupart
des composants (ou des groupes logiques de composants) possèdent aussi
leurs propres unités
Lorsque vous créez un composant, vous créez une nouvelle unité pour ce
composant ou bien vous l'ajoutez à une unité existante.
Déclaration d'un nouveau constructeur (C++) ( see page 1331) Chaque nouveau composant doit avoir un constructeur qui surcharge le
constructeur de la classe dont il est dérivé. Quand vous écrivez le constructeur
de votre nouveau composant, il doit toujours appeler le constructeur dont il hérite.
A l'intérieur de la déclaration de classe, déclarez un constructeur virtuel dans la
section public de la classe.
Par exemple,
Dérivation du composant ( see page 1332) Chaque composant est une classe dérivée de TComponent, de l'un de ses
descendants plus spécialisés (tels que TControl ou TGraphicControl) ou d'une
classe composant existante. La section Comment créer un composant ( see
page 1329) décrit depuis quelle classe dériver les différentes sortes de
composants.
La dérivation des classes est expliquée plus en détail dans la section Définition
de nouvelles classes ( see page 1388).
Pour dériver un composant, ajoutez une déclaration de type objet à la partie
interface de l'unité qui contiendra le composant.
Une classe composant simple est un composant non visuel descendant
directement de TComponent.
Création de composants non visuels ( see page 1332) Les composants non visuels sont utilisés en tant qu'interfaces pour des éléments
comme les bases de données (TDataSet ou TSQLConnection) et les horloges
système (TTimer), et en tant que marques de réservation pour des boîtes de
dialogue (TCommonDialog et ses descendants). La plupart des composants que
vous écrivez sont des contrôles visuels. Les composants non visuels peuvent
être dérivés directement de TComponent, la classe abstraite de base de tous les
composants.
Création de contrôles graphiques ( see page 1332) Si votre contrôle n'a pas besoin de recevoir la focalisation de saisie, vous pouvez
en faire un contrôle graphique. Les contrôles graphiques sont semblables aux
contrôles fenêtrés, mais ils ne possèdent pas de handle de fenêtre et
consomment donc moins de ressources système. Les composants comme
TLabel, qui ne reçoivent jamais la focalisation de saisie, sont des contrôles
graphiques. Bien que ces contrôles ne puissent pas recevoir la focalisation, vous
pouvez les créer afin qu'ils réagissent aux messages souris.
Vous pouvez créer des contrôles personnalisés par l'intermédiaire du composant
TGraphicControl. TGraphicControl est une classe abstraite dérivée de TControl...
suite ( see page 1332) 3
Encapsulation des graphiques ( see page 1332) Delphi simplifie les graphiques Windows en encapsulant les différents outils
graphiques dans un canevas. Le canevas représente la surface de dessin d'une
fenêtre ou d'un contrôle ; il contient d'autres classes telles qu'un crayon, un
pinceau et une police de caractères. Un canevas est semblable à un contexte de
périphérique Windows, mais il prend à sa charge toutes les opérations de gestion.
Si vous avez déjà écrit une application Windows graphique, vous connaissez les
contraintes imposées par l'interface graphique Windows (GDI). Par exemple, GDI
limite le nombre de contextes de périphériques disponibles et requiert la
restauration de l'état initial des objets... suite ( see page 1332)

1325
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Définition des propriétés, des méthodes et des événements ( see page 1333) En dehors de l'image visible que l'utilisateur du composant manipule dans le
concepteur de fiches, les attributs les plus courants d'un composant sont les
propriétés, les événements et les méthodes. Une section est consacrée à chacun
d'eux, mais ce qui suit présente certaines raisons de les utiliser.
Recensement du composant ( see page 1334) Le recensement est une opération simple qui indique à l'EDI les composants à
ajouter à la bibliothèque des composants et les catégories de la palette d'outils
sur lesquelles ils doivent apparaître. Pour une présentation plus détaillée du
processus de recensement, voir Accessibilité des composants au moment de la
conseption ( see page 1369)
Suppression des dépendances ( see page 1335) Une des qualités qui favorisent l'utilisation des composants est le caractère
illimité des opérations que l'on peut programmer dans leur code. Par nature, les
composants peuvent être incorporés aux applications avec diverses
combinaisons, dans des ordres ou des contextes différents. Les composants
doivent être conçus pour pouvoir fonctionner dans n'importe quelle situation,
sans condition préalable.
La propriété Handle des composants TWinControl constitue un exemple de
suppression des dépendances dans les composants. Si vous avez déjà écrit des
applications Windows, vous savez que l'un des points les plus complexes à
traiter et les plus susceptibles de générer des erreurs lors de... suite ( see page
1335)
Recensement des composants ( see page 1335) Avant de pouvoir installer vos composants dans l'EDI, vous devez les recenser.
Le recensement indique à Delphi où placer le composant sur la palette d'outils.
Vous pouvez aussi personnaliser la manière dont Delphi stocke les composants
dans le fichier fiche. Le recensement est décrit dans Recensement des
composants ( see page 1369).
Sous-classement de contrôles Windows ( see page 1335) En programmation Windows traditionnelle, vous créez des contrôles
personnalisés en définissant une nouvelle classe fenêtre et en l'enregistrant dans
Windows. La classe fenêtre (semblable aux objets ou aux classes dans la
programmation orientée objet). Vous pouvez baser une nouvelle classe fenêtre
sur une classe existante : cette opération est appelée sous-classement. Vous
pouvez ensuite placer votre contrôle dans une bibliothèque dynamiquement liée
(DLL), comme les contrôles Windows standard, puis lui fournir une interface.
Vous pouvez créer une "enveloppe" de composant autour de n'importe quelle
classe fenêtre existante. Ainsi, si vous possédez déjà une bibliothèque de
contrôles personnalisés que vous souhaitez... suite ( see page 1335)
Création d'un composant avec l'expert composant ( see page 1335) L'expert composant simplifie les premières étapes de création d'un composant.
Lorsque vous utilisez l'expert composant, vous devez spécifier :

• La classe à partir de laquelle le composant est dérivé.


• Le nom de classe du nouveau composant.
• La catégorie de la palette d'outils où vous voulez qu'il
apparaisse.
• Le nom de l'unité dans laquelle le composant est créé.
• Le chemin d'accès à cette unité.
• Le nom du package dans lequel vous voulez placer le
composant.
L'expert composant exécute les opérations que vous
exécuteriez pour créer manuellement un composant :
• Création d'une unité.
• Dérivation du composant.
• Recensement du composant.
L'expert composant ne peut pas... suite ( see page 1335)
3
Contenu d'un composant ( see page 1337) Pour que vos composants s'intègrent de manière sûre à l'environnement de
Delphi, vous devez suivre certaines conventions. Dans cette section, vous allez
apprendre :

• Suppression des dépendances ( see page 1335)


• Définition des propriétés ( see page 1333)
• Encapsulation des graphiques ( see page 1332)
• Recensement des composants ( see page 1335)

1326
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Emplacement des fichiers du composant ( see page 1338) Les concepteurs de composants doivent faire en sorte que tous les fichiers
source utilisés par un composant soient placés dans le même répertoire. Ces
fichiers comprennent des fichiers de code source (.pas) et certains fichiers projet
(.dfm/.xfm, .res, .rc et .dcr).
Le processus d'ajout de composants entraîne la création de plusieurs fichiers.
Ces fichiers sont automatiquement placés dans les répertoires spécifiés par les
options d'environnement de l'EDI (utilisez la commande de menu
Outils Options, naviguez sur la page Options d'environnement Options
Delphi Bibliothèque). Les fichiers .lib sont placés dans le répertoire de
destination DCP. Si l'ajout de composant... suite ( see page 1338)
Test des composants installés ( see page 1338) Vous pouvez tester le comportement d'un composant à la conception après son
installation sur la palette d'outils. Cette technique est particulièrement utile pour
le débogage des composants nouvellement créés, mais vous pouvez l'utiliser
pour tester n'importe quel composant, que celui-ci apparaisse ou non sur la
palette d'outils. Pour plus d'informations sur le test des composants qui n'ont pas
encore été installés, voir Test des composants non installés ( see page 1338).
Le test de vos composants après l'installation vous permet de déboguer le
composant qui génère seulement des exceptions à la conception lorsqu'il est
déposé sur une fiche.
Test des composants non installés ( see page 1338) Vous pouvez tester le comportement d'un composant à l'exécution avant de
l'installer sur la palette d'outils. Cette technique est particulièrement utile pour le
débogage des composants nouvellement créés, mais vous pouvez l'utiliser pour
tester n'importe quel composant, que celui-ci apparaisse ou non sur la palette
d'outils. Pour plus d'informations sur le test des composants déjà installés, voir
Test des composants installés ( see page 1338).
Vous pouvez tester un composant non installé en émulant les actions exécutées
par Delphi quand le composant est sélectionné dans la palette et placé dans une
fiche.

3.2.1.8.1 Vue globale de la création d'un composant


Cet ensemble de rubriques est une présentation générale de la conception des composants et du processus d'écriture des
composants pour les applications Delphi. Vous devez toutefois être familier de Delphi et de ses composants standard.

Les principaux sujets abordés sont les suivants :

• Bibliothèque de classes ( see page 1328)


• Composants et classes ( see page 1328)
• Création de composants ( see page 1329)
• Contenu d'un composant ( see page 1337)
• Création d'un nouveau composant ( see page 1330)
• Test des composants non installés ( see page 1338)
• Test des composants installés ( see page 1338)
Pour obtenir des informations sur l'installation de nouveaux composants, voir Installation de packages de composants ( see
page 2291).
Voir aussi
Programmation orientée objet et écriture des composants : Vue globale ( see page 1387)

Création de propriétés : Vue globale ( see page 1258)

Création d'événements : Vue globale ( see page 1242) 3


Création de méthodes : Vue globale ( see page 1252)

Utilisation des graphiques et des composants : Vue globale ( see page 1399)

Réponse aux messages ( see page 1320)

Accessibilité des composants au moment de la conception : Vue globale ( see page 1367)

Manipulation des cadres ( see page 2081)

1327
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Création et utilisation des modèles de composants ( see page 2042)

Réutilisation des composants et des groupes de composants ( see page 2069)

3.2.1.8.2 Bibliothèque de classes


Les composants Delphi résident dans la bibliothèque de composants visuels (VCL). La figure suivante montre la relation qui
existe entre les classes sélectionnées qui composent la hiérarchie VCL. Pour plus de détails sur les hiérarchies des classes et
les relations d'héritage entre classes, voir Programmation orientée objet et écriture des composants ( see page 1387)

La classe TComponent est l'ancêtre partagé de chaque composant de la bibliothèque de composants. TComponent fournit les
propriétés et les événements de base nécessaires au fonctionnement d'un composant dans l'EDI. Les différentes branches de la
bibliothèque offrent d'autres possibilités plus spécialisées.

Lorsque vous créez un composant, vous l'ajoutez à la bibliothèque de composants en dérivant une nouvelle classe de l'un des
types de classes existant dans la hiérarchie.

Voir aussi
Composants et objets ( see page 1328)

Contenu d'un composant ( see page 1337)

Création d'un nouveau composant ( see page 1330)

Test des composants non installés ( see page 1338)

3.2.1.8.3 Composants et classes


Comme les composants sont des classes, les créateurs de composants manipulent les objets à un niveau différent de celui des
développeurs d'applications. La création de nouveaux composants nécessite de dériver de nouvelles classes.

Brièvement, il existe deux différences principales entre la création des composants et leur utilisation dans des applications. Pour
la création de composants,
3 • Vous avez accès à des parties de la classe qui sont inaccessibles aux programmeurs d'applications.
• Vous ajoutez de nouvelles parties (des propriétés, par exemple) aux composants.
A cause de ces différences, il faut prendre en compte un plus grand nombre de conventions, et réfléchir à la manière dont les
développeurs d'applications vont utiliser les composants.
Voir aussi
Composants et classes

Création de composants ( see page 1329)

1328
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Contenu d'un composant ( see page 1337)

Création d'un nouveau composant ( see page 1330)

Test des composants non installés ( see page 1338)

3.2.1.8.4 Création de composants


Un composant peut quasiment constituer tout élément de programme manipulable à la conception. La création d'un composant
consiste à dériver une nouvelle classe à partir d'une classe existante. Vous pouvez dériver un nouveau composant de plusieurs
façons :

• Modification de contrôles existants ( see page 1329)


• Création de contrôles fenêtrés ( see page 1330)
• Création de contrôles graphiques ( see page 1332)
• Sous-classement de contrôles Windows ( see page 1335)
• Création de composants non visuels ( see page 1332)
Le tableau suivant présente les différents types de composants et les classes que vous utiliserez comme point de départ pour
chacun d'eux.
Points de départ de la création de composants

Pour Démarrez avec le type suivant


Modifier un composant existant N'importe quel composant existant tel que TButton ou TListBox, ou un type
de composant abstrait tel que TCustomListBox
Création de contrôles fenêtrés TWinControl
Créer un contrôle graphique TGraphicControl
Sous-classer un contrôle Toutes les fenêtres
Créer un composant non visuel TComponent

Vous pouvez aussi dériver des classes qui ne sont pas des composants et qui ne peuvent pas être manipulées dans une fiche
comme TRegIniFile et TFont.

Voir aussi
La bibliothèque de composants visuels ( see page 1328)

Composants et classes ( see page 1328)

Contenu d'un composant ( see page 1337)

Création d'un nouveau composant ( see page 1330)

Test des composants non installés ( see page 1338)

3.2.1.8.5 Modification de contrôles existants 3


Le moyen le plus simple de créer un composant est de modifier un composant existant. Vous pouvez dériver un nouveau
composant depuis un composant quelconque de la bibliothèque de composants

Certains contrôles, tels les boîtes liste et les grilles, possèdent plusieurs variantes d'un thème de base. Dans ce cas, la
bibliothèque de composants comprend un type de classe abstraite (son nom contient le mot "custom", comme TCustomGrid) à
partir de laquelle il est possible de dériver les versions personnalisées.

1329
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Vous pouvez, par exemple, créer un type particulier de boîte liste ne possédant pas certaines propriétés de la classe TListBox.
Comme il n'est pas possible de retirer (masquer) une propriété héritée d'une classe ancêtre, il faut dériver le composant d'un
élément situé avant TListBox dans la hiérarchie. Au lieu de vous forcer à commencer depuis la classe abstraite TWinControl et à
réinventer toutes les fonctions de boîte liste, la bibliothèque de composants fournit TCustomListBox, qui implémente toutes les
propriétés des boîtes liste mais ne les rend pas toutes publiques. En dérivant un composant à partir de l'une des classes
abstraites telles que TCustomListBox, vous rendez publiques uniquement les propriétés que vous souhaitez mettre à disposition
dans votre composant et vous laissez les autres protégées.

La section Création de propriétés ( see page 1258) explique la publication des propriétés héritées. Les sections Modification
d'un composant existant ( see page 1382) et Personnalisation d'une grille ( see page 1275) montrent des exemples de
modification de contrôles existants.

Voir aussi
Composants génériques ( see page 1332)

Contrôles fenêtrés ( see page 1330)

Contrôles graphiques ( see page 1332)

Contrôles sous-classés ( see page 1335)

3.2.1.8.6 Création de contrôles originaux


Les contrôles fenêtrés de la bibliothèque de composants sont des objets qui apparaissent à l'exécution et avec lesquels
l'utilisateur peut interagir. Chaque contrôle fenêtré possède un handle de fenêtre, accessible via sa propriété Handle, qui permet
au système d'exploitation de l'identifier et d'agir sur lui. Dans le cas d'utilisation de contrôles VCL, le handle permet au contrôle
de recevoir la focalisation de saisie et peut être transmis aux fonctions de l'API Windows. Chaque contrôle widget possède un
handle, accessible via sa propriété Handle, identifiant le widget sous-jacent.

Tous les contrôles fenêtrés descendent de la classe TWinControl. Ils incluent la plupart des contrôles fenêtrés standard, tels les
boutons poussoirs, les boîtes liste et les boîtes de saisie. Bien que vous puissiez créer un contrôle original (un qui n'est relié à
aucun contrôle existant) en le dérivant directement de TWinControl, Delphi fournit pour cela le composant TCustomControl.
TCustomControl est un contrôle fenêtré spécialisé qui permet de réaliser facilement des images visuelles complexes.

La section Personnalisation d'une grille ( see page 1275) présente un exemple de création d'un contrôle fenêtre.

3.2.1.8.7 Création d'un nouveau composant


Cette rubrique explique comment créer et configurer un nouveau composant.

Pour créer un composant, effectuez les étapes suivantes :


1. Création d'un fichier unité ( see page 1331)
2. Dérivation du composant ( see page 1332)
3. Recensement du composant ( see page 1334)
3 Vous aurez maintenant un composant aux fonctions minimales, prêt à être installé sur la palette d'outils. Après l'installation, vous
pouvez placer votre nouveau composant sur une fiche et le tester à la fois en mode conception et en mode exécution. Vous
pouvez ensuite ajouter d'autres fonctionnalités au composant, mettre à jour la palette d'outils et poursuivre les tests.

Il y a quelques étapes de base à suivre chaque fois que vous créez un nouveau composant. Elles sont décrites ci-après ;
pour les autres exemples présentés dans ce document, nous supposerons que vous savez effectuer ces étapes.
1. Création d'une unité pour le nouveau composant.
2. Dérivation du composant à partir d'un type de composant existant.

1330
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3. Ajout de propriétés, méthodes et événements.


4. Recensement de votre composant dans l'EDI.
5. Création d'un bitmap pour le composant
6. Création d'un package (bibliothèque dynamiquement liée spéciale) pour pouvoir installer le composant dans l'EDI.
7. Création d'un fichier d'aide pour le composant et ses propriétés, méthodes et événements.
Remarque: Créer un fichier d'aide pour indiquer aux utilisateurs d'un composant comment utiliser celui-ci n'est pas
obligatoire.
Lorsque vous avez terminé, le composant complet est constitué des fichiers suivants :
• Un fichier package (.BPL) ou un fichier collection de packages (.DPC)
• Un fichier package compilé (.DCP)
• Un fichier unité compilé (.DCU)
• Un fichier bitmap pour la palette (.DCR)
• Un fichier d'aide (.HLP)
Vous pouvez également créer un bitmap pour représenter votre nouveau composant. .

3.2.1.8.8 Création d'un fichier unité


Une unité est un module de code Delphi compilé séparément. Delphi emploie les unités pour plusieurs raisons. Chaque fiche
possède sa propre unité et la plupart des composants (ou des groupes logiques de composants) possèdent aussi leurs propres
unités

Lorsque vous créez un composant, vous créez une nouvelle unité pour ce composant ou bien vous l'ajoutez à une unité
existante.

Pour créer une nouvelle unité pour un composant :


1. Choisissez l'une des commandes suivantes :
• Fichier Nouveau Unité.
• Fichier Nouveau Autre pour afficher la boîte de dialogue Nouveaux éléments, sélectionnez Projets Delphi Fichiers
Delphi Unité et choisissez OK. L'EDI crée un nouveau fichier unité et l'ouvre dans l'éditeur de code.
2. Enregistrez ce fichier sous un nom significatif.
3. Dérivez la classe composant.

Pour ouvrir une unité existante :


1. Choisissez Fichier Ouvrir et sélectionnez l'unité de code source dans laquelle vous voulez ajouter vos composants.
Remarque: Lorsque vous ajoutez un composant à une unité, vérifiez que cette unité ne contient que du code de composant.
L'ajout d'un code de composant à une unité qui contient, par exemple, une fiche, provoquera des erreurs dans la palette
d'outils.

3
2. Dérivez la classe composant.

3.2.1.8.9 Déclaration d'un nouveau constructeur (C++)


Chaque nouveau composant doit avoir un constructeur qui surcharge le constructeur de la classe dont il est dérivé. Quand vous
écrivez le constructeur de votre nouveau composant, il doit toujours appeler le constructeur dont il hérite.

A l'intérieur de la déclaration de classe, déclarez un constructeur virtuel dans la section public de la classe.

1331
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Par exemple,
class PACKAGE TNewComponent : public TComponent
{
public:
virtual __fastcall TNewComponent(TComponent* AOwner);
};
Dans le fichier .CPP, implémentez le constructeur :
__fastcall TNewComponent::TNewComponent(TComponent* AOwner): TComponent(AOwner)
{
}
A l'intérieur du constructeur, ajoutez le code que vous voulez exécuter lorsque le composant sera créé.

3.2.1.8.10 Dérivation du composant


Chaque composant est une classe dérivée de TComponent, de l'un de ses descendants plus spécialisés (tels que TControl ou
TGraphicControl) ou d'une classe composant existante. La section Comment créer un composant ( see page 1329) décrit
depuis quelle classe dériver les différentes sortes de composants.

La dérivation des classes est expliquée plus en détail dans la section Définition de nouvelles classes ( see page 1388).

Pour dériver un composant, ajoutez une déclaration de type objet à la partie interface de l'unité qui contiendra le composant.

Une classe composant simple est un composant non visuel descendant directement de TComponent.

3.2.1.8.11 Création de composants non visuels


Les composants non visuels sont utilisés en tant qu'interfaces pour des éléments comme les bases de données (TDataSet ou
TSQLConnection) et les horloges système (TTimer), et en tant que marques de réservation pour des boîtes de dialogue
(TCommonDialog et ses descendants). La plupart des composants que vous écrivez sont des contrôles visuels. Les composants
non visuels peuvent être dérivés directement de TComponent, la classe abstraite de base de tous les composants.

3.2.1.8.12 Création de contrôles graphiques


Si votre contrôle n'a pas besoin de recevoir la focalisation de saisie, vous pouvez en faire un contrôle graphique. Les contrôles
graphiques sont semblables aux contrôles fenêtrés, mais ils ne possèdent pas de handle de fenêtre et consomment donc moins
de ressources système. Les composants comme TLabel, qui ne reçoivent jamais la focalisation de saisie, sont des contrôles
graphiques. Bien que ces contrôles ne puissent pas recevoir la focalisation, vous pouvez les créer afin qu'ils réagissent aux
messages souris.

Vous pouvez créer des contrôles personnalisés par l'intermédiaire du composant TGraphicControl. TGraphicControl est une
classe abstraite dérivée de TControl. Bien qu'il soit possible de dériver des contrôles directement de TControl, il est préférable
de les dériver de TGraphicControl, qui procure un canevas de dessin et sur Windows gère les messages WM_PAINT ; il vous
suffit de redéfinir la méthode Paint.
3 La section Création d'un contrôle graphique ( see page 1227) présente un exemple de création d'un contrôle graphique.

3.2.1.8.13 Encapsulation des graphiques


Delphi simplifie les graphiques Windows en encapsulant les différents outils graphiques dans un canevas. Le canevas
représente la surface de dessin d'une fenêtre ou d'un contrôle ; il contient d'autres classes telles qu'un crayon, un pinceau et une
police de caractères. Un canevas est semblable à un contexte de périphérique Windows, mais il prend à sa charge toutes les
opérations de gestion.

1332
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Si vous avez déjà écrit une application Windows graphique, vous connaissez les contraintes imposées par l'interface graphique
Windows (GDI). Par exemple, GDI limite le nombre de contextes de périphériques disponibles et requiert la restauration de l'état
initial des objets graphiques avant de les détruire.

Avec Delphi, vous n'avez pas besoin de vous en préoccuper. Pour dessiner sur une fiche ou un autre composant, accédez à la
propriété Canvas du composant. Si vous voulez personnaliser un crayon ou un pinceau, définissez sa couleur et son style.
Lorsque vous avez terminé, Delphi dispose des ressources. Delphi conserve les ressources en mémoire cache pour éviter de
les recréer, si votre application utilise fréquemment le même type de ressources.

Vous pouvez toujours accéder à l'interface GDI Windows, mais votre code sera beaucoup plus simple et s'exécutera plus
rapidement si vous utilisez le canevas intégré aux composants Delphi.

La façon dont les images graphiques fonctionnent dans le composant dépend du canevas de l'objet à partir duquel votre
composant est dérivé. Les fonctionnalités graphiques sont détaillées dans la section Graphiques et composants ( see page
1399).

3.2.1.8.14 Définition des propriétés, des méthodes et des événements


En dehors de l'image visible que l'utilisateur du composant manipule dans le concepteur de fiches, les attributs les plus courants
d'un composant sont les propriétés, les événements et les méthodes. Une section est consacrée à chacun d'eux, mais ce qui
suit présente certaines raisons de les utiliser.

Propriétés
Les propriétés donnent au développeur d'applications l'illusion de définir ou de lire la valeur d'une variable, tout en permettant au
concepteur de composants de dissimuler la structure de données sous-jacente ou de définir un traitement spécial lorsque la
valeur est accédée.

L'utilisation des propriétés présente plusieurs avantages :

• Les propriétés sont disponibles au moment de la conception. Le développeur d'applications peut définir ou modifier les
valeurs initiales des propriétés sans écrire de code.
• Les propriétés peuvent contrôler les valeurs ou les formats au moment où le développeur les définit. La validation de la saisie
pendant la conception empêche de commettre des erreurs.
• Le composant peut construire les valeurs appropriées à la demande. L'erreur de programmation la plus fréquente est de
référencer une variable qui n'a été initialisée. En représentant les données par une propriété, vous êtes sûr qu'une valeur leur
est toujours disponible sur demande.
• Les propriétés vous permettent de cacher les données sous une interface simple et cohérente. Vous pouvez modifier la façon
dont les informations sont structurées dans une propriété sans que ce changement ne soit perçu par les développeurs
d'applications.
La section Présentation générale de la création d'un composant ( see page 1258) explique comment ajouter des propriétés à
vos composants.
Méthodes
Les méthodes de classes sont des fonctions et procédures qui opèrent sur une classe plutôt que sur des instances particulières
de cette classe. Par exemple, les méthodes constructeur de composants (Create) sont toutes des méthodes de classes. Les
méthodes de composants sont des procédures et fonctions qui opèrent sur les instances des composants elles-mêmes. Les 3
développeurs d'applications utilisent des méthodes pour que les composants effectuent des actions particulières ou renvoient
des valeurs non contenues par des propriétés.

Comme elles nécessitent une exécution de code, les méthodes ne sont disponibles qu'au moment de l'exécution. Elles sont
utiles pour plusieurs raisons :

• Les méthodes encapsulent la fonctionnalité d'un composant dans l'objet même où résident les données.
• Les méthodes peuvent cacher des procédures compliquées sous une interface simple et cohérente. Un développeur

1333
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

d'applications peut appeler la méthode AlignControls d'un composant sans savoir comment elle fonctionne ni si elle diffère de
la méthode AlignControls d'un autre composant.
• Les méthodes permettent de mettre à jour plusieurs propriétés avec un seul appel.
La section Création de méthodes ( see page 1252) explique comment ajouter des méthodes à vos composants.
Evénements
Un événement est une propriété spéciale qui appelle du code, pendant l'exécution, en réponse à une saisie ou à une autre
opération. Les événements permettent aux développeurs d'associer des blocs de code spécifiques à des actions spécifiques,
telles des manipulations de la souris ou des frappes au clavier. Le code qui s'exécute lorsqu'un événement survient est appelé le
gestionnaire de l'événement.

Les événements permettent aux développeurs d'applications de spécifier des réponses différentes en fonction des actions
possibles sans avoir à créer de nouveaux composants.

La section Création d'événements ( see page 1242) explique comment implémenter des événements standard et comment en
définir de nouveaux.

3.2.1.8.15 Recensement du composant


Le recensement est une opération simple qui indique à l'EDI les composants à ajouter à la bibliothèque des composants et les
catégories de la palette d'outils sur lesquelles ils doivent apparaître. Pour une présentation plus détaillée du processus de
recensement, voir Accessibilité des composants au moment de la conseption ( see page 1369)

Pour recenser un composant :


1. Ajoutez une procédure nommée Register à la partie interface de l'unité du composant. Register n'a pas de paramètres, la
déclaration est donc très simple :
procedure Register;
namespace Newcomp
{
void __fastcall PACKAGE Register()
{
}
}
TComponentClass classes[1] = {__classid(TNewComponent)};
Si vous ajoutez un composant à une unité qui contient déjà des composants, elle doit déjà avoir la procédure Register déclarée,
afin que vous ne soyez pas obligé de changer la déclaration.

Remarque: Bien que Delphi soit un langage qui ne tient pas compte de la distinction minuscules/majuscules, la procédure
Register en tient compte et doit être orthographiée avec un R majuscule.

2. Ecrivez la procédure Register dans la partie implementation de l'unité, en appelant RegisterComponents pour chaque
composant que vous voulez recenser. RegisterComponents est une procédure qui prend deux paramètres : le nom d'une
catégorie de palette d'outils et un ensemble de types de composants. Si vous ajoutez un composant à un recensement
existant, vous pouvez soit ajouter le nouveau composant à l'ensemble dans l'instruction existante, soit ajouter une nouvelle
instruction qui appelle RegisterComponents.
Voir aussi
3
Création d'un fichier unité ( see page 1331)

Dérivation de l'objet composant ( see page 1332)

Déclaration d'un nouveau constructeur ( see page 1331)

Recensement de l'exemple composant

1334
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.8.16 Suppression des dépendances


Une des qualités qui favorisent l'utilisation des composants est le caractère illimité des opérations que l'on peut programmer
dans leur code. Par nature, les composants peuvent être incorporés aux applications avec diverses combinaisons, dans des
ordres ou des contextes différents. Les composants doivent être conçus pour pouvoir fonctionner dans n'importe quelle situation,
sans condition préalable.

La propriété Handle des composants TWinControl constitue un exemple de suppression des dépendances dans les
composants. Si vous avez déjà écrit des applications Windows, vous savez que l'un des points les plus complexes à traiter et les
plus susceptibles de générer des erreurs lors de l'exécution d'un programme est l'interdiction d'accéder à un contrôle fenêtré
avant de l'avoir créé par un appel à la fonction API CreateWindow. Les contrôles fenêtrés de Delphi évitent cette difficulté en
garantissant qu'un handle de fenêtre correct sera toujours disponible dès que nécessaire. En utilisant une propriété pour
représenter le handle de fenêtre, le contrôle peut vérifier si la fenêtre a été créée ; si le handle n'est pas correct, le contrôle crée
une fenêtre et renvoie son handle. Ainsi, chaque fois que le code d'une application accède à la propriété Handle, il est sûr
d'obtenir un handle correct.

En les libérant des tâches d'arrière-plan telles que la création des fenêtres, les composants Delphi permettent aux développeurs
de se concentrer sur ce qu'ils veulent vraiment réaliser. Pour transmettre un handle de fenêtre à une fonction API, vous n'avez
pas besoin de vérifier que le handle existe ni de créer la fenêtre. Le programmeur est certain que les opérations vont se dérouler
correctement et n'a pas besoin de le contrôler sans cesse.

Bien que la création de composants sans dépendances soit un peu plus longue, le temps qui y est consacré est généralement
très utile. Non seulement cela évite aux développeurs répétitions et travail fastidieux, mais cela réduit la quantité de
documentation et de support.

3.2.1.8.17 Recensement des composants


Avant de pouvoir installer vos composants dans l'EDI, vous devez les recenser. Le recensement indique à Delphi où placer le
composant sur la palette d'outils. Vous pouvez aussi personnaliser la manière dont Delphi stocke les composants dans le fichier
fiche. Le recensement est décrit dans Recensement des composants ( see page 1369).

3.2.1.8.18 Sous-classement de contrôles Windows


En programmation Windows traditionnelle, vous créez des contrôles personnalisés en définissant une nouvelle classe fenêtre et
en l'enregistrant dans Windows. La classe fenêtre (semblable aux objets ou aux classes dans la programmation orientée objet).
Vous pouvez baser une nouvelle classe fenêtre sur une classe existante : cette opération est appelée sous-classement. Vous
pouvez ensuite placer votre contrôle dans une bibliothèque dynamiquement liée (DLL), comme les contrôles Windows standard,
puis lui fournir une interface.

Vous pouvez créer une "enveloppe" de composant autour de n'importe quelle classe fenêtre existante. Ainsi, si vous possédez
déjà une bibliothèque de contrôles personnalisés que vous souhaitez utiliser dans vos applications Delphi, vous pouvez créer
des composants Delphi se comportant comme ces contrôles et dériver de nouveaux contrôles à partir d'eux, comme vous le
feriez avec n'importe quel composant.
3
Pour consulter des exemples de sous-classement des contrôles Windows, reportez-vous aux composants de l'unité StdCtls qui
représentent les contrôles Windows standard, comme TEdit.

3.2.1.8.19 Création d'un composant avec l'expert composant


L'expert composant simplifie les premières étapes de création d'un composant. Lorsque vous utilisez l'expert composant, vous
devez spécifier :

1335
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

• La classe à partir de laquelle le composant est dérivé.


• Le nom de classe du nouveau composant.
• La catégorie de la palette d'outils où vous voulez qu'il apparaisse.
• Le nom de l'unité dans laquelle le composant est créé.
• Le chemin d'accès à cette unité.
• Le nom du package dans lequel vous voulez placer le composant.
L'expert composant exécute les opérations que vous exécuteriez pour créer manuellement un composant :
• Création d'une unité.
• Dérivation du composant.
• Recensement du composant.
L'expert composant ne peut pas ajouter de composant à une unité existante. Cela ne peut se faire que manuellement.

Pour ajouter un nouveau composant avec l'expert composant


1. Pour ouvrir l'expert composant, choisissez l'une de ces deux méthodes :
• Choisissez Composant Nouveau composant VCL.
• Choisissez Fichier Nouveau Autre, allez à la page Projets Delphi Fichiers Delphi et double-cliquez sur Composant.
2. Remplissez les champs de l'expert composant :
• Dans Type ancêtre, spécifiez la classe à partir de laquelle vous dérivez le nouveau composant.
• Dans Nom de classe, spécifiez le nom de classe de votre nouveau composant.
• Dans Page de palette, spécifiez la catégorie de la palette d'outils dans laquelle vous voulez installer le composant.
• Dans Nom de fichier unité, spécifiez le nom de l'unité dans laquelle vous voulez déclarer la classe du composant. Si l'unité
n'est pas dans le chemin de recherche, modifiez ce dernier.
3. Lorsque vous avez rempli les champs de l'expert composant, Cliquez sur Installer. Pour placer le composant dans un
package nouveau ou existant, cliquez sur Composant Installer et spécifiez le package dans la boîte de dialogue qui
apparaît.
4. Cliquez sur OK. L'EDI crée une nouvelle unité.
Avertissement: Si vous dérivez un composant d'une classe dont le nom commence par "custom" (comme TCustomControl),
ne tentez pas de le placer sur une fiche avant d'avoir redéfini toute méthode abstraite du composant initial. Delphi ne peut pas
créer d'instance d'une classe ayant des propriétés ou des méthodes abstraites.
Pour voir le code source de votre unité, cliquez sur Voir Unités... Si l'expert composant est déjà fermé, ouvrez le fichier
unité dans l'éditeur de code en sélectionnant Fichier Ouvrir. Delphi crée une nouvelle unité contenant la déclaration de
classe et la procédure Register, et ajoute une clause uses qui comprend toutes les unités Delphi standard.
L'unité ressemble à cela :
unit MyControl;
interface
uses
Windows, Messages, SysUtils, Types, Classes, Controls;
type
3 TMyControl = class(TCustomControl)
private
{ Déclarations privées }
protected
{ Déclarations protégées }
public
{ Déclarations publiques }
published
{ Déclarations publiées }
end;

1336
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Exemples', [TMyControl]); //Dans CLX, utilisez une autre page que
'Exemples'
end;
end.
// fichier en-tête
#ifndef NewComponentH
#define NewComponentH
//---------------------------------------------------------------------------
#include <SysUtils.hpp>
#include <Controls.hpp>
#include <Classes.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class PACKAGE TNewComponent : public TComponent
{
private:
protected:
public:
__fastcall TNewComponent(TComponent* Owner);
__published:
};
//---------------------------------------------------------------------------
#endif
// fichier d'implémentation
#include <vcl.h>
#pragma hdrstop
#include "NewComponent.h"
#pragma package(smart_init);
//---------------------------------------------------------------------------
// ValidCtrCheck permet de vérifier que les composants créés ne comportent pas
// de fonctions virtuelles pures.
//
static inline void ValidCtrCheck(TNewComponent *)
{
new TNewComponent(NULL);
}
//---------------------------------------------------------------------------
__fastcall TNewComponent::TNewComponent(TComponent* Owner)
: TComponent(Owner)
{
}
//---------------------------------------------------------------------------
namespace Newcomponent
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TNewComponent)};
RegisterComponents("Samples", classes, 0); //Dans CLX, utiliser une autre page que Samples
}
}

3.2.1.8.20 Contenu d'un composant 3


Pour que vos composants s'intègrent de manière sûre à l'environnement de Delphi, vous devez suivre certaines conventions.
Dans cette section, vous allez apprendre :

• Suppression des dépendances ( see page 1335)


• Définition des propriétés ( see page 1333)
• Encapsulation des graphiques ( see page 1332)

1337
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

• Recensement des composants ( see page 1335)

3.2.1.8.21 Emplacement des fichiers du composant


Les concepteurs de composants doivent faire en sorte que tous les fichiers source utilisés par un composant soient placés dans
le même répertoire. Ces fichiers comprennent des fichiers de code source (.pas) et certains fichiers projet (.dfm/.xfm, .res, .rc et
.dcr).

Le processus d'ajout de composants entraîne la création de plusieurs fichiers. Ces fichiers sont automatiquement placés dans
les répertoires spécifiés par les options d'environnement de l'EDI (utilisez la commande de menu Outils Options, naviguez
sur la page Options d'environnement Options Delphi Bibliothèque). Les fichiers .lib sont placés dans le répertoire de
destination DCP. Si l'ajout de composant entraîne la création d'un nouveau package (par opposition à son installation dans un
package existant), le fichier .bpl est placé dans le répertoire de destination BPL.

3.2.1.8.22 Test des composants installés


Vous pouvez tester le comportement d'un composant à la conception après son installation sur la palette d'outils. Cette
technique est particulièrement utile pour le débogage des composants nouvellement créés, mais vous pouvez l'utiliser pour
tester n'importe quel composant, que celui-ci apparaisse ou non sur la palette d'outils. Pour plus d'informations sur le test des
composants qui n'ont pas encore été installés, voir Test des composants non installés ( see page 1338).

Le test de vos composants après l'installation vous permet de déboguer le composant qui génère seulement des exceptions à la
conception lorsqu'il est déposé sur une fiche.

Testez un composant installé en exécutant une seconde instance de l'EDI :


1. Choisissez Projet Options Débogueur et définissez le chemin des sources du débogage sur le fichier source du
composant.
2. Sélectionnez ensuite Outils Options. Sur la page Options du débogueur Débogueurs Borland Exceptions du
langage, activez les exceptions à suivre.
3. Ouvrez le fichier source du composant et définissez des points d'arrêt.
4. Sélectionnez Exécuter Paramètres et affectez au champ Application hôte le nom et l'emplacement du fichier exécutable de
Delphi.
5. Dans la boîte de dialogue Paramètres d'exécution, cliquez sur le bouton Charger pour démarrer une seconde instance de
Delphi.
6. Déposez ensuite les composants à tester sur la fiche, ce qui devrait provoquer l'arrêt sur les points d'arrêt définis dans le
source.

3.2.1.8.23 Test des composants non installés


Vous pouvez tester le comportement d'un composant à l'exécution avant de l'installer sur la palette d'outils. Cette technique est
particulièrement utile pour le débogage des composants nouvellement créés, mais vous pouvez l'utiliser pour tester n'importe
quel composant, que celui-ci apparaisse ou non sur la palette d'outils. Pour plus d'informations sur le test des composants déjà
3 installés, voir Test des composants installés ( see page 1338).

Vous pouvez tester un composant non installé en émulant les actions exécutées par Delphi quand le composant est sélectionné
dans la palette et placé dans une fiche.

Pour tester un composant non installé,


1. Ajoutez le nom de l'unité du composant à la clause uses de l'unité fiche.
2. Ajoutez un champ objet à la fiche pour représenter le composant. Il s'agit là d'une des différences principales entre votre

1338
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

façon d'ajouter des composants et celle utilisée par Delphi. Vous ajoutez le champ objet à la partie publique à la fin de la
déclaration de type de fiche. Delphi l'ajouterait au-dessus, dans la partie de la déclaration de type qu'il gère. Il ne faut jamais
ajouter de champs à la partie gérée par Delphi de la déclaration de type de fiche. Les éléments de cette partie correspondent
à ceux stockés dans le fichier fiche. L'ajout des noms de composants qui n'existent pas sur la fiche peut rendre incorrect le
fichier de la fiche.
3. Attachez un gestionnaire à l'événement OnCreate de la fiche.
4. Construisez le composant dans le gestionnaire OnCreate de la fiche. Lors de l'appel au constructeur du composant, vous
devez transmettre un paramètre spécifiant le propriétaire du composant (le composant chargé de la destruction du composant
au moment opportun). Il faut pratiquement toujours transmettre Self comme propriétaire. Dans une méthode, Self représente
une référence sur l'objet contenant la méthode. Dans ce cas, dans le gestionnaire OnCreate de la fiche, Self représente la
fiche.
5. Initialisez la propriété Parent. L'initialisation de la propriété Parent est toujours la première opération à effectuer après la
construction d'un contrôle. Le parent est le composant qui contient visuellement le contrôle ; le plus souvent c'est sur la fiche
que le contrôle apparaît, mais il peut aussi s'agir d'une boîte groupe ou d'un volet. Normalement, il faut donner à Parent la
valeur Self, c'est-à dire la fiche. Initialisez toujours Parent avant les autres propriétés du contrôle.
Avertissement: Si votre composant n'est pas un contrôle (c'est-à-dire si TControl n'est pas un de ses ancêtres), passez
cette étape. Si vous définissez accidentellement la propriété Parent de la fiche (à la place de celle du composant) à la valeur
Self, vous pouvez provoquer un problème du système d'exploitation.

6. Si vous le souhaitez, initialisez d'autres propriétés du composant.

3.2.1.9 Contrôles orientés données


Rubriques
Nom Description
Ajout du lien de données ( see page 1342) La connexion entre un contrôle et une base de données est gérée par une classe
appelée lien de données. La classe lien de données, qui connecte un contrôle à
un seul champ d'une base de données, est TFieldDataLink. Il existe également
des liens de données vers des tables entières.
Un contrôle orienté données est propriétaire de sa classe lien de données.
Autrement dit, le contrôle est responsable de la construction et de la destruction
du lien de données. Pour des détails sur la gestion des classes ayant un
propriétaire, voir Création d'un contrôle graphique ( see page 1227).
Ajout de la propriété ReadOnly ( see page 1342) En ajoutant une propriété ReadOnly, vous fournissez le moyen de rendre le
contrôle accessible en lecture seulement au moment de la conception. Si la
valeur de cette propriété est True toutes les cellules du contrôle perdront la
capacité à être sélectionnées.
Autorisation des mises à jour nécessaires ( see page 1343) Le calendrier accessible en lecture seulement utilise la méthode SelectCell pour
effectuer toutes sortes de modifications, y compris l'affectation de valeurs aux
propriétés Row et Col. La méthode UpdateCalendar définit Row et Col à chaque
changement de date mais, dans la mesure où SelectCell n'autorise aucune
modification, la position de la sélection reste inchangée, même si la date est
modifiée.
Pour outrepasser cette interdiction de toute modification, vous devez ajouter au
calendrier un indicateur booléen interne et n'autoriser les modifications que si la
valeur de cet indicateur est True :
Modification de la valeur par défaut de FReadOnly ( see page 1345) Comme il s'agit d'un contrôle permettant la modification des données, la
propriété ReadOnly doit être False par défaut. Pour que la propriété ReadOnly
soit à False, modifiez la valeur de FReadOnly dans le constructeur :
Création d'un contrôle pour scruter les données ( see page 1345) La création d'un contrôle calendrier orienté données, que ce soit un contrôle en
3
lecture seulement ou un contrôle grâce auquel l'utilisateur peut changer les
données sous-jacentes, fait intervenir les étapes suivantes :

• Création et recensement du composant ( see page


1346).
• Ajout du lien de données ( see page 1342).
• Réponse aux changements de données ( see page
1350).

1339
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Création d'un contrôle de modification de données ( see page 1345) Lorsque vous créez un contrôle permettant de modifier les données, vous créez
et recensez le composant puis lui ajoutez un lien de données, comme pour les
contrôles permettant de scruter les données. Vous devez également répondre
aux changements de données dans le champ sous-jacent, mais vous devez
prendre en considération quelques points supplémentaires.
Par exemple, vous souhaitez sans doute que votre contrôle réponde aux
événements clavier et souris. Votre contrôle doit répondre lorsque l'utilisateur
change le contenu du contrôle. Lorsque l'utilisateur quitte le contrôle, les
changements effectués dans le contrôle doivent être répercutés dans l'ensemble
de données.
Le contrôle permettant... suite ( see page 1345)
Création et recensement du composant ( see page 1346) La création d'un composant se fait toujours de la même façon : vous créez une
unité et vous recensez le composant avant de l'installer dans la palette d'outils.
Ce processus est décrit dans Création d'un nouveau composant ( see page
1330).
Pour notre exemple, suivez la procédure générale de création d'un composant
en tenant compte des spécificités suivantes :

• Appelez l'unité du composant DBCal.


• Dérivez une nouvelle classe composant appelée
TDBCalendar, descendant du composant
TSampleCalendar. La section Personnalisation d'une
grille ( see page 1275) indique comment créer le
composant TSampleCalendar.
• Recensez TDBCalendar dans la catégorie Exemples de la
palette d'outils.
L'unité résultante dérivée de TCustomGrid... suite ( see
page 1346)
Déclaration des propriétés d'accès d'un contrôle orienté données ( see page Tout contrôle orienté données dispose d'une propriété DataSource indiquant la
1346) classe source de données qui fournit les données au contrôle. En outre, un
contrôle qui accède à un champ unique a besoin d'une propriété DataField pour
spécifier ce champ dans la source de données.
Contrairement aux propriétés d'accès des classes ayant un propriétaire que nous
avons vues avec l'exemple de la section Création d'un contrôle graphique ( see
page 1227), ces propriétés d'accès ne donnent pas accès aux classes ayant un
propriétaire elles-mêmes, mais plutôt aux propriétés correspondantes de la
classe ayant un propriétaire. Autrement dit, vous allez créer des propriétés qui
autorisent... suite ( see page 1346)
Déclaration du champ de classe ( see page 1347) Un composant utilise un champ pour chacune des classes dont il est le
propriétaire, comme cela est expliqué dans Déclaration des champs de classe
( see page 1229). Dans ce cas, le calendrier a besoin d'un champ de type
TFieldDataLink pour son lien de données.
Déclarez un champ pour le lien de données du calendrier :
Gestion des messages liés à la souris ou au clavier ( see page 1347) Lorsque l'utilisateur commence à se servir du contrôle, celui-ci reçoit de Windows
les messages indiquant la manipulation de la souris (WM_LBUTTONDOWN,
WM_MBUTTONDOWN, ou WM_RBUTTONDOWN), ou le message indiquant la
manipulation du clavier (WM_KEYDOWN). Pour permettre à un contrôle de
répondre à ces messages, vous devez écrire les gestionnaires des réponses à
ces messages.

• Réponse aux messages indiquant la manipulation de la


souris ( see page 1351).
• Réponse aux messages indiquant la manipulation du
clavier ( see page 1350).
Initialisation du lien de données ( see page 1347) Un contrôle orienté données doit avoir accès à son lien de données pendant
3 toute sa durée de vie, il doit donc construire l'objet lien de données dans son
propre constructeur et le détruire avant de se détruire lui-même.
Redéfinissez les méthodes Create et Destroy du calendrier pour construire et
détruire l'objet lien de données :

1340
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Contrôles orientés données ( see page 1348) Lorsque vous souhaitez vous connecter avec des bases de données, travaillez
avec les contrôles orientés données. C'est grâce à ces contrôles que l'application
établit un lien avec une partie spécifique d'une base de données. Parmi les
contrôles sensibles aux données Delphi, citons les libellés, les boîtes de saisie,
les boîtes liste, les boîtes à options, les contrôles de référence et les grilles. Vous
avez également la possibilité de construire vos propres contrôles orientés
données. Pour plus d'informations sur l'utilisation des contrôles orientés
données, voir Utilisation de contrôles de données ( see page 1830).
Il existe différents niveaux d'orientation données. Le plus élémentaire... suite (
see page 1348)
Fonctionnement du contrôle en lecture seulement ( see page 1349) Puisque votre calendrier scruteur de données ne fonctionnera qu'en lecture (par
rapport aux données), il est opportun de rendre le contrôle lui-même accessible
en lecture seulement. Ainsi, l'utilisateur ne s'attendra pas à voir répercuter dans
la base de données une modification qu'il aurait apportée au contrôle.
Rendre le calendrier accessible en lecture seulement fait intervenir deux étapes :

• Ajout de la propriété ReadOnly ( see page 1342)


• Autorisation des mises à jour nécessaires ( see page
1343)
Remarque: Si vous démarrez avec le composant
TCalendar de la page Exemples de Delphi au lieu de
TSampleCalendar, le contrôle a déjà une propriété
ReadOnly. Vous pouvez donc ignorer ces... suite ( see
page 1349)
Modification de la méthode Change ( see page 1349) La méthode Change du TDBCalendar est appelée chaque fois qu'est définie une
nouvelle valeur de date. Change appelle le gestionnaire de l'événement
OnChange, s'il existe. L'utilisateur du composant peut écrire du code dans le
gestionnaire de l'événement OnChange afin de répondre aux modifications de la
date.
Lorsque la date du calendrier change, l'ensemble de données sous-jacent doit
être averti de ce changement. Vous pouvez le faire en redéfinissant la méthode
Change et en ajoutant une ligne de code de plus.
Réponse aux changements de données ( see page 1350) Lorsqu'un contrôle a un lien de données et les propriétés précisant la source et le
champ des données, il doit répondre aux changements des données de ce
champ provoqués soit par un déplacement vers un autre enregistrement, soit par
une modification du champ.
Les classes lien de données ont toutes un événement intitulé OnDataChange.
Lorsque la source de données indique un changement dans ses données, l'objet
lien de données appelle le gestionnaire attaché à son événement
OnDataChange.
Pour mettre à jour un contrôle en réponse à une modification des données, vous
devez attacher un gestionnaire à l'événement OnDataChange... suite ( see
page 1350)
Réponse aux messages indiquant la manipulation du clavier ( see page 1350) Une méthode KeyDown est une méthode protégée de l'événement OnKeyDown
d'un contrôle. Le contrôle lui-même appelle KeyDown en réponse au message
Windows indiquant la manipulation du clavier. Lorsque vous redéfinissez la
méthode KeyDown héritée, vous pouvez inclure le code qui apporte d'autres
réponses en plus de l'appel à l'événement OnKeyDown.
Réponse aux messages indiquant la manipulation de la souris ( see page 1351) Une méthode MouseDown est une méthode protégée de l'événement
OnMouseDown d'un contrôle. Le contrôle lui-même appelle MouseDown en
réponse au message Windows indiquant la manipulation de la souris. Lorsque
vous redéfinissez la méthode MouseDown héritée, vous pouvez inclure du code
apportant d'autres réponses en plus de l'appel à l'événement OnMouseDown.
Pour redéfinir MouseDown, ajoutez la méthode MouseDown à la classe
TDBCalendar :
Mise à jour de l'ensemble de données ( see page 1352) A ce point, une modification dans le contrôle orienté données a changé les
valeurs dans la classe du lien de données sur un champ. La dernière étape de la
création d'un contrôle permettant la modification des données consiste à mettre à 3
jour l'ensemble de données avec la nouvelle valeur. Cela doit se produire après
que la personne ayant changé la valeur du contrôle orienté données quitte le
contrôle en cliquant à l'extérieur de celui-ci ou en appuyant sur la touche Tab.
Remarque: Les applications VCL définissent des ID de message pour les
opérations sur les contrôles. Par exemple, le... suite ( see page 1352)

1341
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Mise à jour de la classe lien de données sur un champ ( see page 1354) Il existe deux types de modification des données :

• Le changement de la valeur d'un champ doit se répercuter


dans le contrôle orienté données
• Le changement dans le contrôle orienté données doit se
répercuter dans la valeur du champ
Le composant TDBCalendar a déjà une méthode
DataChange qui gère les modifications de la valeur du
champ dans l'ensemble de données en assignant cette
valeur à la propriété CalendarDate. La méthode
DataChange est le gestionnaire de l'événement
OnDataChange. Ainsi le composant calendrier est
capable de gérer le premier type de modification des
données.
De manière semblable, la classe lien de... suite ( see page
1354)

3.2.1.9.1 Ajout du lien de données


La connexion entre un contrôle et une base de données est gérée par une classe appelée lien de données. La classe lien de
données, qui connecte un contrôle à un seul champ d'une base de données, est TFieldDataLink. Il existe également des liens de
données vers des tables entières.

Un contrôle orienté données est propriétaire de sa classe lien de données. Autrement dit, le contrôle est responsable de la
construction et de la destruction du lien de données. Pour des détails sur la gestion des classes ayant un propriétaire, voir
Création d'un contrôle graphique ( see page 1227).

Pour établir un lien de données en tant que classe ayant un propriétaire, respectez ces étapes :
1. Déclaration du champ de classe ( see page 1347).
2. Déclaration des propriétés d'accès ( see page 1346).
3. Initialisation du lien de données ( see page 1347).

3.2.1.9.2 Ajout de la propriété ReadOnly


En ajoutant une propriété ReadOnly, vous fournissez le moyen de rendre le contrôle accessible en lecture seulement au
moment de la conception. Si la valeur de cette propriété est True toutes les cellules du contrôle perdront la capacité à être
sélectionnées.

Pour ajouter la propriété ReadOnly, suivez ces étapes :


1. Ajoutez la déclaration de la propriété ainsi qu'une donnée membre private pour contenir la valeur :
type
TDBCalendar = class(TSampleCalendar)
private
3 FReadOnly: Boolean; { champ de stockage interne }
public
constructor Create(AOwner: TComponent); override; { doit effectuer une redéfinition
pour définir les valeurs par défaut }
published
property ReadOnly: Boolean read FReadOnly write FReadOnly default True;
end;
.
.
.
constructor TDBCalendar.Create(AOwner: TComponent);

1342
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

begin
inherited Create(AOwner); { appeler toujours le constructeur hérité ! }
FReadOnly := True; { définir la valeur par
défaut }
end;
// fichier en-tête
class PACKAGE TDBCalendar : public TSampleCalendar
{
private:
bool FReadOnly; // champ de stockage interne
protected:
public:
virtual __fastcall TDBCalendar(TComponent* Owner);
__published:
__property ReadOnly = {read=FReadOnly, write=FReadOnly, default=true};
};
// fichier d'implémentation :
virtual __fastcall TDBCalendar::TDBCalendar(TComponent* Owner) :
TSampleCalendar(Owner)
{
FReadOnly = true; // définit la valeur par défaut
}
2. Redéfinissez la méthode SelectCell pour inhiber la sélection si le contrôle est accessible en lecture seulement. L'utilisation de
SelectCell est expliquée dans Exclusion des cellules vides ( see page 1275).
function TDBCalendar.SelectCell(ACol, ARow: Longint): Boolean;
begin
if FReadOnly then Result := False { sélection impossible en cas de
lecture seule }
else Result := inherited SelectCell(ACol, ARow); { sinon, utiliser la méthode héritée }
end;
bool __fastcall TDBCalendar::SelectCell(long ACol, long ARow)
{
if (FReadOnly) return false; // sélection impossible si accès
en lecture seule
return TSampleCalendar::SelectCell(ACol, ARow); // sinon, utilise la méthode héritée
}
N'oubliez pas d'ajouter la déclaration de SelectCell à la déclaration de la classe de TDBCalendar, et ajoutez la directive override.

Si vous ajoutez maintenant le calendrier à une fiche, vous vous rendez compte que le composant ignore les clics de souris et les
frappes de touches. Et il ne met plus à jour la position de la sélection lorsque vous changez la date.

3.2.1.9.3 Autorisation des mises à jour nécessaires


Le calendrier accessible en lecture seulement utilise la méthode SelectCell pour effectuer toutes sortes de modifications, y
compris l'affectation de valeurs aux propriétés Row et Col. La méthode UpdateCalendar définit Row et Col à chaque
changement de date mais, dans la mesure où SelectCell n'autorise aucune modification, la position de la sélection reste
inchangée, même si la date est modifiée.

Pour outrepasser cette interdiction de toute modification, vous devez ajouter au calendrier un indicateur booléen interne et
n'autoriser les modifications que si la valeur de cet indicateur est True :
type 3
TDBCalendar = class(TSampleCalendar)
private
FUpdating: Boolean; { indicateur privé à usage interne }
protected
function SelectCell(ACol, ARow: Longint): Boolean; override;
public
procedure UpdateCalendar; override; { ne pas oublier la directive override }
end;
.

1343
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

.
.
function TDBCalendar.SelectCell(ACol, ARow: Longint): Boolean;
begin
if (not FUpdating) and FReadOnly then Result := False { sélection possible si mise à
jour }
else Result := inherited SelectCell(ACol, ARow); { sinon, utiliser la méthode héritée }
end;
procedure TDBCalendar.UpdateCalendar;
begin
FUpdating := True; { définir l'indicateur pour
permettre les mises à jour }
try
inherited UpdateCalendar; { mise à jour
habituelle }
finally
FUpdating := False; { toujours réinitialiser
l'indicateur }
end;
end;
class PACKAGE TDBCalendar : public TSampleCalendar
{
private:
.
.
.
bool FUpdating; // indicateur privé à usage interne
protected:
virtual bool __fastcall SelectCell(long ACol, long ARow);
public:
.
.
.
virtual void __fastcall UpdateCalendar();
.
.
.
};
bool __fastcall TDBCalendar::SelectCell(long ACol, long ARow)
{
if (!FUpdating && FReadOnly) return false; // sélection impossible si accès
en lecture seule
return TSampleCalendar::SelectCell(ACol, ARow); // sinon, utilise la méthode héritée
}
void __fastcall TDBCalendar::UpdateCalendar()
{
FUpdating=true; // définit l'indicateur pour
permettre les modifications
try
{
TSampleCalendar::UpdateCalendar(); // mise à jour normale
}
catch(...)
{
FUpdating = false;
throw;
3 }
FUpdating = false; // toujours effacer l'indicateur
}
Le calendrier n'autorise toujours pas les modifications directes de l'utilisateur mais les modifications de la date effectuées via les
propriétés de date sont prises en compte. Vous disposez maintenant d'un contrôle en lecture seulement tout à fait opérationnel.
Vous voilà prêt à ajouter les fonctionnalités servant à scruter les données.

1344
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.9.4 Modification de la valeur par défaut de FReadOnly


Comme il s'agit d'un contrôle permettant la modification des données, la propriété ReadOnly doit être False par défaut. Pour que
la propriété ReadOnly soit à False, modifiez la valeur de FReadOnly dans le constructeur :
constructor TDBCalendar.Create(AOwner: TComponent);
begin
.
.
.
FReadOnly := False; { définir la valeur par défaut }
.
.
.
end;
__fastcall TDBCalendar::TDBCalendar (TComponent* Owner) : TSampleCalendar(Owner)
{
FReadOnly = false; // définit la valeur par défaut
.
.
.
}

3.2.1.9.5 Création d'un contrôle pour scruter les données


La création d'un contrôle calendrier orienté données, que ce soit un contrôle en lecture seulement ou un contrôle grâce auquel
l'utilisateur peut changer les données sous-jacentes, fait intervenir les étapes suivantes :

• Création et recensement du composant ( see page 1346).


• Ajout du lien de données ( see page 1342).
• Réponse aux changements de données ( see page 1350).

3.2.1.9.6 Création d'un contrôle de modification de données


Lorsque vous créez un contrôle permettant de modifier les données, vous créez et recensez le composant puis lui ajoutez un
lien de données, comme pour les contrôles permettant de scruter les données. Vous devez également répondre aux
changements de données dans le champ sous-jacent, mais vous devez prendre en considération quelques points
supplémentaires.

Par exemple, vous souhaitez sans doute que votre contrôle réponde aux événements clavier et souris. Votre contrôle doit
répondre lorsque l'utilisateur change le contenu du contrôle. Lorsque l'utilisateur quitte le contrôle, les changements effectués
dans le contrôle doivent être répercutés dans l'ensemble de données.

Le contrôle permettant la modification des données décrit ici est le même que le contrôle calendrier décrit dans Création d'un
contrôle pour scruter les données ( see page 1345). Le contrôle est modifié de telle sorte qu'il permette l'édition en plus de la
consultation des données du champ lié.

Voici les étapes à suivre pour modifier un contrôle existant et en faire un contrôle permettant la modification des données :
3
• Modification de la valeur par défaut de FReadOnly ( see page 1345)
• Gestion des messages liés à la souris ou au clavier. ( see page 1347)
• Mise à jour de la classe lien de données sur un champ. ( see page 1354)
• Modification de la méthode Change. ( see page 1349)
• Mise à jour de l'ensemble de données. ( see page 1352)

1345
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.9.7 Création et recensement du composant


La création d'un composant se fait toujours de la même façon : vous créez une unité et vous recensez le composant avant de
l'installer dans la palette d'outils. Ce processus est décrit dans Création d'un nouveau composant ( see page 1330).

Pour notre exemple, suivez la procédure générale de création d'un composant en tenant compte des spécificités suivantes :

• Appelez l'unité du composant DBCal.


• Dérivez une nouvelle classe composant appelée TDBCalendar, descendant du composant TSampleCalendar. La section
Personnalisation d'une grille ( see page 1275) indique comment créer le composant TSampleCalendar.
• Recensez TDBCalendar dans la catégorie Exemples de la palette d'outils.
L'unité résultante dérivée de TCustomGrid dans une application VCL doit ressembler à ceci :
unit CalSamp;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids;
type
TSampleCalendar = class(TCustomGrid)
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Exemples', [TSampleCalendar]);
end;
end.
Si vous installez le composant calendrier maintenant, vous verrez qu'il apparaît sur la page Exemples. Les seules propriétés
disponibles sont les propriétés de contrôle les plus basiques. L'étape suivante consiste à rendre disponible certaines des
propriétés plus spécialisées aux utilisateurs du calendrier.

Remarque: Bien que vous puissiez installer le composant calendrier exemple que vous venez de compiler, n'essayez pas de le
placer tout de suite sur une fiche. Le composant TCustomGrid contient une méthode DrawCell abstraite qui doit être redéclarée
avant que les objets d'instance puissent être créés. La redéfinition de la méthode DrawCell est décrite dans Remplissage des
cellules ( see page 1275).

3.2.1.9.8 Déclaration des propriétés d'accès d'un contrôle orienté données


Tout contrôle orienté données dispose d'une propriété DataSource indiquant la classe source de données qui fournit les
données au contrôle. En outre, un contrôle qui accède à un champ unique a besoin d'une propriété DataField pour spécifier ce
champ dans la source de données.

Contrairement aux propriétés d'accès des classes ayant un propriétaire que nous avons vues avec l'exemple de la section
Création d'un contrôle graphique ( see page 1227), ces propriétés d'accès ne donnent pas accès aux classes ayant un
propriétaire elles-mêmes, mais plutôt aux propriétés correspondantes de la classe ayant un propriétaire. Autrement dit, vous
allez créer des propriétés qui autorisent le contrôle et son lien de données à partager la même source et le même champ.
3 Déclarez les propriétés DataSource et DataField ainsi que leurs méthodes d'implémentation, puis écrivez ces méthodes en tant
que simples "boîtes à lettres" vers les propriétés correspondantes de la classe lien de données.

Voir aussi
Initialisation du lien de données ( see page 1347)

1346
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.9.9 Déclaration du champ de classe


Un composant utilise un champ pour chacune des classes dont il est le propriétaire, comme cela est expliqué dans Déclaration
des champs de classe ( see page 1229). Dans ce cas, le calendrier a besoin d'un champ de type TFieldDataLink pour son lien
de données.

Déclarez un champ pour le lien de données du calendrier :


type
TDBCalendar = class(TSampleCalendar)
private
FDataLink: TFieldDataLink;
.
.
.
end;
class PACKAGE TDBCalendar : public TSampleCalendar
{
private:
TFieldDataLink *FDataLink;
.
.
.
};
#include <DB.hpp>
#include <DBTables.hpp>
Avant de compiler l'application, vous devez ajouter DB et DBCtrls à la clause uses de l'unité.

3.2.1.9.10 Gestion des messages liés à la souris ou au clavier


Lorsque l'utilisateur commence à se servir du contrôle, celui-ci reçoit de Windows les messages indiquant la manipulation de la
souris (WM_LBUTTONDOWN, WM_MBUTTONDOWN, ou WM_RBUTTONDOWN), ou le message indiquant la manipulation du
clavier (WM_KEYDOWN). Pour permettre à un contrôle de répondre à ces messages, vous devez écrire les gestionnaires des
réponses à ces messages.

• Réponse aux messages indiquant la manipulation de la souris ( see page 1351).


• Réponse aux messages indiquant la manipulation du clavier ( see page 1350).

3.2.1.9.11 Initialisation du lien de données


Un contrôle orienté données doit avoir accès à son lien de données pendant toute sa durée de vie, il doit donc construire l'objet
lien de données dans son propre constructeur et le détruire avant de se détruire lui-même.

Redéfinissez les méthodes Create et Destroy du calendrier pour construire et détruire l'objet lien de données :
type
TDBCalendar = class(TSampleCalendar)
public { les constructeurs et destructeurs sont toujours
publics } 3
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
.
.
.
end;
.
.
.

1347
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

constructor TDBCalendar.Create(AOwner: TComponent);


begin
inherited Create(AOwner); { appeler toujours d'abord le constructeur hérité
}
FDataLink := TFieldDataLink.Create; { construire l'objet lien de données
}
FDataLink.Control := self; {informer le lien de données sur le calendrier }
FReadOnly := True; { existe déjà }
end;
destructor TDBCalendar.Destroy;
begin
FDataLink.Free; { détruire toujours d'abord les objets
ayant un propriétaire... }
inherited Destroy; { ...puis appeler le destructeur hérité
}
end;
class PACKAGE TDBCalendar : public TSampleCalendar
{
public:
virtual __fastcall TDBCalendar(TComponent* Owner);
__fastcall ~TDBCalendar();
};
__fastcall TDBCalendar::TDBCalendar (TComponent* Owner) : TSampleCalendar(Owner)
{
FReadOnly = true;
FDataLink = new TFieldDataLink();
FDataLink->Control = this;
}
__fastcall TDBCalendar::~TDBCalendar()
{
FDataLink->Control = NULL;
FDataLink->OnUpdateData = NULL;
delete FDataLink;
}
Vous avez maintenant un lien de données complet. Il vous reste à indiquer au contrôle les données qu'il doit lire dans le champ
lié. La section suivante ( see page 1350) vous explique comment procéder.

Voir aussi
Déclaration des propriétés d'accès d'un contrôle orienté données ( see page 1346)

3.2.1.9.12 Contrôles orientés données


Lorsque vous souhaitez vous connecter avec des bases de données, travaillez avec les contrôles orientés données. C'est grâce
à ces contrôles que l'application établit un lien avec une partie spécifique d'une base de données. Parmi les contrôles sensibles
aux données Delphi, citons les libellés, les boîtes de saisie, les boîtes liste, les boîtes à options, les contrôles de référence et les
grilles. Vous avez également la possibilité de construire vos propres contrôles orientés données. Pour plus d'informations sur
l'utilisation des contrôles orientés données, voir Utilisation de contrôles de données ( see page 1830).

Il existe différents niveaux d'orientation données. Le plus élémentaire fonctionne en lecture seulement, permet de scruter des
données et reflète l'état d'une base de données. L'orientation données modifiables, permettant de modifier les données, est plus
3 complexe car l'utilisateur peut changer les valeurs stockées dans la base en manipulant le contrôle. Notez également que le
degré d'implication de la base de données peut varier du cas le plus simple, un lien établi avec un seul champ, aux cas plus
complexes faisant intervenir des contrôles à enregistrements multiples.

Cette section illustre d'abord le cas le plus simple, en créant un contrôle en lecture simple qui est lié à un seul champ d'un
ensemble de données. Le contrôle spécifique utilisé sera le calendrier TSampleCalendar créé dans Personnalisation d'une grille
( see page 1275). Vous pouvez aussi utiliser le contrôle calendrier standard de la page Exemples de la palette d'outils,
TCalendar.

Cette section continue ensuite avec une explication sur la manière de faire d'un nouveau contrôle pour scruter les données un

1348
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

contrôle de modification des données.

3.2.1.9.13 Fonctionnement du contrôle en lecture seulement


Puisque votre calendrier scruteur de données ne fonctionnera qu'en lecture (par rapport aux données), il est opportun de rendre
le contrôle lui-même accessible en lecture seulement. Ainsi, l'utilisateur ne s'attendra pas à voir répercuter dans la base de
données une modification qu'il aurait apportée au contrôle.

Rendre le calendrier accessible en lecture seulement fait intervenir deux étapes :

• Ajout de la propriété ReadOnly ( see page 1342)


• Autorisation des mises à jour nécessaires ( see page 1343)
Remarque: Si vous démarrez avec le composant TCalendar de la page Exemples de Delphi au lieu de TSampleCalendar, le
contrôle a déjà une propriété ReadOnly. Vous pouvez donc ignorer ces étapes.

3.2.1.9.14 Modification de la méthode Change


La méthode Change du TDBCalendar est appelée chaque fois qu'est définie une nouvelle valeur de date. Change appelle le
gestionnaire de l'événement OnChange, s'il existe. L'utilisateur du composant peut écrire du code dans le gestionnaire de
l'événement OnChange afin de répondre aux modifications de la date.

Lorsque la date du calendrier change, l'ensemble de données sous-jacent doit être averti de ce changement. Vous pouvez le
faire en redéfinissant la méthode Change et en ajoutant une ligne de code de plus.

Voici les étapes à suivre :


1. Ajoutez une nouvelle méthode Change au composant TDBCalendar :
type
TDBCalendar = class(TSampleCalendar);
private
procedure Change; override;
.
.
.
end;
class PACKAGE TDBCalendar : public TSampleCalendar
{
protected:
virtual void __fastcall Change();
.
.
.
};
2. Ecrivez la méthode Change, appelant la méthode Modified qui informe l'ensemble de données que celles-ci ont changé, puis
appelle la méthode Change héritée :
procedure TDBCalendar.Change;
begin
FDataLink.Modified; { appeler la méthode Modified } 3
inherited Change; { appeler la méthode Change héritée }
end;
void __fastcall TDBCalendar::Change()
{
if (FDataLink != NULL)
FDataLink->Modified(); // Appelle la méthode Modified
TSampleCalendar::Change(); // Appelle la méthode Change héritée
}

1349
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.9.15 Réponse aux changements de données


Lorsqu'un contrôle a un lien de données et les propriétés précisant la source et le champ des données, il doit répondre aux
changements des données de ce champ provoqués soit par un déplacement vers un autre enregistrement, soit par une
modification du champ.

Les classes lien de données ont toutes un événement intitulé OnDataChange. Lorsque la source de données indique un
changement dans ses données, l'objet lien de données appelle le gestionnaire attaché à son événement OnDataChange.

Pour mettre à jour un contrôle en réponse à une modification des données, vous devez attacher un gestionnaire à l'événement
OnDataChange du lien de données.

Dans notre exemple, vous allez ajouter une méthode au calendrier, puis la désigner comme gestionnaire de l'événement
OnDataChange du lien de données.

Déclarez et implémentez la méthode DataChange, puis associez-la à l'événement OnDataChange dans le constructeur. Dans le
destructeur, détachez le gestionnaire OnDataChange avant de détruire l'objet.

3.2.1.9.16 Réponse aux messages indiquant la manipulation du clavier


Une méthode KeyDown est une méthode protégée de l'événement OnKeyDown d'un contrôle. Le contrôle lui-même appelle
KeyDown en réponse au message Windows indiquant la manipulation du clavier. Lorsque vous redéfinissez la méthode
KeyDown héritée, vous pouvez inclure le code qui apporte d'autres réponses en plus de l'appel à l'événement OnKeyDown.

Pour redéfinir KeyDown, suivez ces instructions :


1. Ajoutez une méthode KeyDown à la classe TDBCalendar :
type
TDBCalendar = class(TSampleCalendar);
.
.
.
protected
procedure KeyDown(var Key: Word; Shift: TShiftState; X: Integer; Y: Integer);
override;
.
.
.
end;
class PACKAGE TDBCalendar : public TSampleCalendar
{
.
.
.
protected:
virtual void __fastcall KeyDown(unsigned short &Key, TShiftState Shift);
.
.
.
3 };
2. Implémentez la méthode KeyDown :
procedure KeyDown(var Key: Word; Shift: TShiftState);
var
MyKeyDown: TKeyEvent;
begin
if not ReadOnly and (Key in [VK_UP, VK_DOWN, VK_LEFT, VK_RIGHT, VK_END,
VK_HOME, VK_PRIOR, VK_NEXT]) and FDataLink.Edit then
inherited KeyDown(Key, Shift)

1350
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

else
begin
MyKeyDown := OnKeyDown;
if Assigned(MyKeyDown) then MyKeyDown(Self, Key, Shift);
end;
end;
void __fastcall TDBCalendar::KeyDown(unsigned short &Key, TShiftState Shift)
{
TKeyEvent MyKeyDown; // déclare le type d'événement
Set<unsigned short,0,8> keySet;
keySet = keySet << VK_UP << VK_DOWN << VK_LEFT // affecte les touches virtuelles à
l'ensemble
<< VK_RIGHT << VK_END << VK_HOME << VK_PRIOR << VK_NEXT;
if (!FReadOnly && // si le contrôle n'est pas en lecture
(keySet.Contains(Key)) && // ...seule, si la touche est dans...
FDataLink->Edit() ) // ...l'ensemble et le champ en mode saisie.
{
TCustomGrid::KeyDown(Key, Shift); // Appel de la méthode KeyDown héritée
}
else
{
MyKeyDown = OnKeyDown; // Affecte l'événement OnKeyDown
if (MyKeyDown != NULL) MyKeyDown(this,Key,Shift); // Exécute le code du gestionnaire...
} // ...d'événement OnKeyDown
}
Lorsque KeyDown répond à un message indiquant la manipulation du clavier, la méthode KeyDown héritée est appelée
uniquement si la propriété ReadOnly du contrôle vaut False, si la touche appuyée est une des touches de déplacement du
curseur et si l'objet lien de données est en mode édition, c'est-à-dire si le champ peut être modifié. Si le champ ne peut être
modifié ou si une autre touche a été pressée, le code mis par le programmeur dans le gestionnaire de l'événement OnKeyDown,
s'il en existe un, est exécuté.

3.2.1.9.17 Réponse aux messages indiquant la manipulation de la souris


Une méthode MouseDown est une méthode protégée de l'événement OnMouseDown d'un contrôle. Le contrôle lui-même
appelle MouseDown en réponse au message Windows indiquant la manipulation de la souris. Lorsque vous redéfinissez la
méthode MouseDown héritée, vous pouvez inclure du code apportant d'autres réponses en plus de l'appel à l'événement
OnMouseDown.

Pour redéfinir MouseDown, ajoutez la méthode MouseDown à la classe TDBCalendar :


type
TDBCalendar = class(TSampleCalendar);
.
.
.
protected
procedure MouseDown(Button: TButton, Shift: TShiftState, X: Integer, Y: Integer);
override;
.
.
.
end; 3
procedure TDBCalendar.MouseDown(Button: TButton; Shift: TShiftState; X, Y: Integer);
var
MyMouseDown: TMouseEvent;
begin
if not ReadOnly and FDataLink.Edit then
inherited MouseDown(Button, Shift, X, Y)
else
begin
MyMouseDown := OnMouseDown;
if Assigned(MyMouseDown then MyMouseDown(Self, Button, Shift, X, Y);

1351
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

end;
end;
// fichier en-tête
class PACKAGE TDBCalendar : public TSampleCalendar
{
.
.
.
protected:
virtual void __fastcall MouseDown(TMouseButton Button, TShiftState Shift, int X,
int Y);
.
.
.
};
// fichier d'implémentation
void __fastcall TDBCalendar::MouseDown(TMouseButton Button, TShiftState Shift, int X, int
Y)
{
TMouseEvent MyMouseDown; // déclare le type d'événement
if (!FReadOnly && FDataLink->Edit()) // si le champ peut être modifié
TSampleCalendar::MouseDown(Button, Shift, X, Y); // appelle MouseDown héritée
else
{
MyMouseDown = OnMouseDown; // affecte l'événement OnMouseDown
if (MyMouseDown != NULL) MyMouseDown(this, Button, // exécute le code contenu dans...
Shift, X, Y); // ...le gestionnaire d'événement
OnMouseDown
}
}
Lorsque MouseDown répond à un message indiquant la manipulation de la souris, la méthode MouseDown héritée est appelée
uniquement si la propriété ReadOnly du contrôle est False et si l'objet lien de données est en mode édition, c'est-à-dire si le
champ peut être modifié. Si le champ ne peut être modifié, le code mis par le programmeur dans le gestionnaire de l'événement
OnMouseDown, s'il en existe un, est exécuté.

3.2.1.9.18 Mise à jour de l'ensemble de données


A ce point, une modification dans le contrôle orienté données a changé les valeurs dans la classe du lien de données sur un
champ. La dernière étape de la création d'un contrôle permettant la modification des données consiste à mettre à jour
l'ensemble de données avec la nouvelle valeur. Cela doit se produire après que la personne ayant changé la valeur du contrôle
orienté données quitte le contrôle en cliquant à l'extérieur de celui-ci ou en appuyant sur la touche Tab.

Remarque: Les applications VCL définissent des ID de message pour les opérations sur les contrôles. Par exemple, le
message CM_EXIT est envoyé au contrôle lorsque l'utilisateur quitte celui-ci. Vous pouvez écrire des gestionnaires de
messages qui répondent au message. Et ensuite, lorsque l'utilisateur quitte le contrôle, la méthode CMExit, gestionnaire du
message CM_EXIT, répondra en mettant à jour l'enregistrement dans l'ensemble de données avec les valeurs modifiées dans la
classe lien de données sur un champ. Pour plus d'informations sur les gestionnaires de messages, voir Gestion des messages
et des notifications système ( see page 1320).

3 Pour mettre à jour l'ensemble de données depuis un gestionnaire de message, suivez ces instructions :
1. Ajoutez le gestionnaire de message au composant TDBCalendar :
type
TDBCalendar = class(TSampleCalendar);
private
procedure CMExit(var Message: TWMNoParams); message CM_EXIT;
.
.
.
end;

1352
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

class PACKAGE TDBCalendar : public TSampleCalendar


{
private:
void __fastcall CMExit(TWMNoParams Message);
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(CM_EXIT, TWMNoParams, CMExit)
END_MESSAGE_MAP
};
2. Implémentez la méthode CMExit afin qu'elle ressemble à ceci :
procedure TDBCalendar.CMExit(var Message: TWMNoParams);
begin
try
FDataLink.UpdateRecord; { indiquer à la liaison de données de
mettre à jour la base de données }
except
on Exception do SetFocus; { si échec, ne pas perdre la focalisation }
end;
inherited;
end;
void __fastcall TDBCalendar::CMExit(TWMNoParams &Message)
{
try
{
FDataLink.UpdateRecord(); // Indiquer au lien de données d'actualiser la base de
données
}
catch(...)
{
SetFocus(); // si échec, ne pas perdre la focalisation
throw;
}
}

Pour mettre à jour l'ensemble de données quand l'utilisateur quitte le contrôle, suivez les étapes ci-après :
1. Ajoutez un override à la méthode DoExit du composant TDBCalendar :
type
TDBCalendar = class(TSampleCalendar);
private
procedure DoExit; override;
.
.
.
end;
class PACKAGE TDBCalendar : public TSampleCalendar
{
private:
DYNAMIC void __fastcall DoExit(void);
.
.
.
};
2. Implémentez la méthode DoExit afin qu'elle ressemble à ceci :
procedure TDBCalendar.CMExit(var Message: TWMNoParams);
3
begin
try
FDataLink.UpdateRecord; { indiquer à la liaison de données de
mettre à jour la base de données }
except
on Exception do SetFocus; { si échec, ne pas perdre la focalisation }
end;
inherited; { laisser la méthode héritée générer un événement OnExit }
end;

1353
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

void __fastcall TDBCalendar::DoExit(void)


{
try
{
FDataLink.UpdateRecord(); // Indiquer au lien de données d'actualiser la base de
données
}
catch(...)
{
SetFocus(); // si échec, ne pas perdre la focalisation
throw;
}
TCustomGrid::DoExit(); // laisser la méthode héritée générer un événement OnExit
}

3.2.1.9.19 Mise à jour de la classe lien de données sur un champ


Il existe deux types de modification des données :

• Le changement de la valeur d'un champ doit se répercuter dans le contrôle orienté données
• Le changement dans le contrôle orienté données doit se répercuter dans la valeur du champ
Le composant TDBCalendar a déjà une méthode DataChange qui gère les modifications de la valeur du champ dans l'ensemble
de données en assignant cette valeur à la propriété CalendarDate. La méthode DataChange est le gestionnaire de
l'événement OnDataChange. Ainsi le composant calendrier est capable de gérer le premier type de modification des données.
De manière semblable, la classe lien de données sur un champ a aussi un événement OnUpdateData qui se produit lorsque
l'utilisateur modifie le contenu du contrôle orienté données. Le contrôle calendrier a une méthode UpdateData qui devient le
gestionnaire de l'événement OnUpdateData. UpdateData assigne au champ lien de données la valeur modifiée dans le
contrôle orienté données.

Pour répercuter dans la valeur du champ une modification effectuée sur la valeur du calendrier :
1. Ajoutez une méthode UpdateData à la section private du composant calendrier :
type
TDBCalendar = class(TSampleCalendar);
private
procedure UpdateData(Sender: TObject);
.
.
.
end;
class PACKAGE TDBCalendar : public TSampleCalendar
{
private:
void __fastcall UpdateData(TObject *Sender);
};
2. Implémentez la méthode UpdateData :
procedure UpdateData(Sender: TObject);
begin
FDataLink.Field.AsDateTime := CalendarDate; { définir le champ lien par la date du
calendrier }
3 end;
void __fastcall TDBCalendar::UpdateData( TObject* Sender)
{
FDataLink->Field->AsDateTime = CalendarDate; // définit le champ par la date du
calendrier
}
3. Dans le constructeur de TDBCalendar, affectez la méthode UpdateData à l'événement OnUpdateData :
constructor TDBCalendar.Create(AOwner: TComponent);
begin
inherited Create(AOwner);

1354
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

FReadOnly := True;
FDataLink := TFieldDataLink.Create;
FDataLink.OnDataChange := DataChange;
FDataLink.OnUpdateData := UpdateData;
end;
__fastcall TDBCalendar::TDBCalendar(TComponent* Owner)
: TSampleCalendar(Owner)
{
FDataLink = new TFieldDataLink(); // déjà ici
FDataLink->OnDataChange = DataChange; // également déjà ici
FDataLink->OnUpdateData = UpdateData; // Affecte UpdateData à l'événement OnUpdateData
}

3.2.1.10 Accessibilité des composants au moment de la conception


Rubriques
Nom Description
Ajout de formats de presse-papiers ( see page 1360) Par défaut, lorsque l'utilisateur choisit Copier lorsqu'un composant est
sélectionné dans l'EDI, le composant est copié dans le format interne de Delphi.
Il peut ensuite être collé dans une autre fiche ou module de données. Votre
composant peut copier d'autres formats dans le Presse-papiers en redéfinissant
la méthode Copy.
Par exemple, la méthode Copy suivante permet à un composant TImage de
copier son image dans le Presse-papiers. L'image est ignorée par l'EDI de
Delphi, mais elle peut être collée dans d'autres applications.
Ajout d'éditeurs de composants ( see page 1360) Les éditeurs de composants déterminent ce qui se passe lorsque vous
double-cliquez sur le composant dans le concepteur et ajoutent des commandes
au menu contextuel qui apparaît lorsque vous cliquez sur le composant avec le
bouton droit. Ils peuvent également copier votre composant dans le
Presse-papiers Windows dans des formats personnalisés.
Si vous n'attribuez pas d'éditeur à vos composants, Delphi utilise l'éditeur de
composants par défaut. Ce dernier est implémenté par la classe TDefaultEditor.
TDefaultEditor n'ajoute aucun nouvel élément au menu contextuel d'un
composant. Lorsque vous double-cliquez sur le composant, TDefaultEditor
recherche ses propriétés et génère le premier gestionnaire... suite ( see page
1360)
Ajout d'éléments au menu contextuel ( see page 1361) Lorsque l'utilisateur clique avec le bouton droit sur le composant, les méthodes
GetVerbCount et GetVerb de l'éditeur de composants sont appelées pour
construire un menu contextuel. Vous pouvez redéfinir ces méthodes pour ajouter
des commandes (verbes) au menu contextuel.
L'ajout d'éléments au menu contextuel requiert ces étapes :

• Spécification d'éléments de menu ( see page 1372)


• Implémentation des commandes ( see page 1366)
Ajout d'éditeurs de propriétés ( see page 1361) L'inspecteur d'objets permet par défaut de modifier tous les types de propriétés.
Vous pouvez toutefois créer un éditeur pour des propriétés spécifiques en
l'écrivant et en le recensant. Vous pouvez recenser les éditeurs de propriétés
afin qu'ils s'appliquent uniquement aux propriétés des composants dont vous
êtes l'auteur, ou à toutes les propriétés du type spécifié.
A la base, un éditeur de propriétés peut opérer selon deux modes : affichage
sous la forme d'une chaîne texte permettant à l'utilisateur la modification de la
valeur courante ; affichage d'une boîte de dialogue permettant des modifications
d'une autre sorte. Selon la propriété en cours de... suite ( see page 1361)

1355
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Modification du comportement suite à un double-clic ( see page 1361) Lorsque vous double-cliquez sur le composant, la méthode Edit du composant
est appelée. Par défaut, la méthode Edit exécute la première commande ajoutée
au menu contextuel. Ainsi, dans l'exemple précédent ( see page 1366), le fait
de double-cliquer sur le composant exécute la commande DoThis.
Même si l'exécution de la première commande est généralement une bonne
idée, vous pouvez modifier ce comportement par défaut. Par exemple, vous
pouvez définir un comportement différent si :

• vous n'ajoutez aucune commande au menu contextuel ;


• vous souhaitez afficher une boîte de dialogue qui combine
plusieurs commandes lorsque l'utilisateur double-clique
sur le composant.
Redéfinissez la méthode Edit pour... suite ( see page 1361)
Compilation des composants en packages ( see page 1362) Une fois vos composants recensés, vous devez les compiler en packages avant
de les installer dans l'EDI. Un package peut contenir un ou plusieurs composants
ainsi que des éditeurs de propriétés personnalisés. Pour plus d'informations sur
les packages, voir Utilisation des packages et des composants ( see page
2285).
Pour créer et compiler un package, voir Création et modification de packages (
see page 2287). Placez les unités de code source de vos composants
personnalisés dans la liste Contient du package. Si vos composants dépendent
d'autres packages, incluez ces derniers dans la liste Requiert.
Pour installer vos composants dans l'EDI, voir Installation de packages de
composants ( see page 2291)... suite ( see page 1362)
Création des entrées ( see page 1363) Pour que l'aide associée à votre composant fonctionne de façon transparente
avec celle des autres composants de la bibliothèque, vous devez respecter les
conventions suivantes :
Chaque composant doit avoir une rubrique d'aide :
La rubrique associée au composant doit montrer dans quelle unité est déclaré le
composant et fournir une brève description du composant. La rubrique du
composant doit proposer des liens vers des fenêtres secondaires décrivant la
position du composant dans la hiérarchie des objets et répertorier l'ensemble de
ses propriétés, événements et méthodes. Les développeurs d'applications
accéderont à cette rubrique en sélectionnant le composant dans une fiche et
en... suite ( see page 1363)
Création du fichier d'aide ( see page 1364) Vous pouvez utiliser l'outil de votre choix pour créer les fichiers d'aide Windows
(au format .rtf). Delphi inclut le Microsoft Help Workshop, qui compile les fichiers
d'aide et contient un guide en ligne destiné à l'auteur du système d'aide. Vous y
trouverez toutes les informations nécessaires à la création des systèmes d'aide.
La composition de fichiers d'aide pour les composants s'effectue en plusieurs
étapes :

• Création des entrées ( see page 1363).


• Aide contextuelle des composants ( see page 1366).
Déclaration de la procédure Register ( see page 1364) Le recensement implique l'écriture d'une procédure unique dans l'unité, qui doit
être nommée Register. La procédure Register doit apparaître dans la partie
interface de l'unité et, contrairement au reste du Delphi, son nom tient compte
des différences majuscules/minuscules.
Remarque: Bien que Delphi soit un langage qui ne tient pas compte de la
distinction minuscules/majuscules, la procédure Register en tient compte et doit
être orthographiée avec un R majuscule.
Le code suivant montre la présentation d'une seule unité qui crée et recense des
nouveaux composants :
Dérivation d'une classe éditeur de propriétés ( see page 1364) La bibliothèque de composants définit plusieurs sortes d'éditeurs de propriétés,
tous descendant de TPropertyEditor. Lorsque vous créez un éditeur de
propriétés, votre classe éditeur de propriétés peut descendre directement de
TPropertyEditor ou d'un des types d'éditeurs de propriétés décrits dans le
3 tableau ci-après. Les classes de l'unité DesignEditors peuvent être utilisées dans
les applications VCL.
Remarque: Ce qui est absolument nécessaire pour un éditeur de propriété est
qu'il dérive de TBasePropertyEditor et qu'il prenne en charge l'interface
IProperty. Néanmoins, TPropertyEditor fournit une implémentation par défaut de
l'interface IProperty.
La liste du tableau ci-après n'est pas complète.... suite ( see page 1364)

1356
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Modification globale de la propriété ( see page 1365) Si vous le souhaitez, vous pouvez fournir une boîte de dialogue pour la définition
de la propriété. L'utilisation la plus courante des éditeurs de propriétés concerne
les propriétés qui sont des classes. Un exemple est la propriété Font, qui a une
boîte de dialogue éditeur associée permettant au développeur de choisir tous les
attributs de fonte en même temps.
Pour fournir une boîte de dialogue de définition globale de la propriété,
redéfinissez la méthode Edit de la classe éditeur de propriétés.
Les méthodes Edit utilisent les mêmes méthodes "Get" et "Set" utilisées dans les
méthodes GetValue et SetValue.... suite ( see page 1365)
Implémentation des commandes ( see page 1366) Lorsque la commande fournie par GetVerb est sélectionnée dans le concepteur,
la méthode ExecuteVerb est appelée. Pour chaque commande que vous
spécifiez dans la méthode GetVerb, implémentez une action dans la méthode
ExecuteVerb. Vous pouvez accéder au composant en cours de modification à
l'aide de la propriété Component de l'éditeur.
Par exemple, la méthode ExecuteVerb suivante implémente les commandes de
la méthode GetVerb de l'exemple précédent ( see page 1372).
Aide contextuelle des composants ( see page 1366) Chaque rubrique de composant, de propriété, de méthode et d'événement doit
comporter une note de bas de page A. La note de bas de page A permet
d'afficher la rubrique lorsque l'utilisateur sélectionne un composant et appuie sur
F1, ou lorsqu'il sélectionne une propriété ou un événement dans l'inspecteur
d'objets et appuie sur F1. Les notes de bas de page A doivent suivre certaines
conventions d'appellation :
Si la rubrique d'aide est destinée à un composant, la note de bas de page A
comprend deux entrées séparées par un point-virgule selon la syntaxe suivante :
Accessibilité des composants au moment de la conception : Vue globale ( see Rendre vos composants accessibles à la conception est un processus qui
page 1367) nécessite plusieurs étapes :

• Recensement des composants ( see page 1369)


• Fournir l'aide pour vos composants ( see page 1368)
• Ajout d'éditeurs de propriétés ( see page 1361)
• Ajout d'éditeurs de composants ( see page 1360)
• Compilation des composants en packages ( see page
1362)
Toutes les étapes ne s'appliquent pas à tous les
composants. Par exemple, si vous ne définissez ni
propriété ni événement nouveau, il n'est pas nécessaire
de fournir de l'aide. Le recensement et la compilation sont
les seules étapes obligatoires.
Une fois que vos composants ont été recensés et compilés
en packages, ils peuvent être distribués à d'autres
développeurs et installés dans l'EDI. Pour plus
d'informations... suite ( see page 1367)
Catégories de propriétés ( see page 1367) Dans l'IDE, l'inspecteur d'objets vous permet de masquer et d'afficher
sélectivement des propriétés basées sur les catégories de propriété. Les
propriétés des nouveaux composants personnalisés peuvent rentrer dans ce
schéma en recensant des propriétés par catégories. Faites ceci lors du
recensement du composant en appelant RegisterPropertyInCategory ou
RegisterPropertiesInCategory. Utilisez RegisterPropertyInCategory pour
recenser une seule propriété. Utilisez RegisterPropertiesInCategory pour
recenser plusieurs propriétés dans un seul appel de fonction. Ces fonctions sont
définies dans l'unité DesignIntf.
Notez qu'il n'est pas obligatoire de recenser des propriétés ni que toutes les
propriétés d'un composant personnalisé soient recensées lorsque quelques-unes
le sont.... suite ( see page 1367) 3
Spécification de catégories de propriétés ( see page 1368) Lorsque vous recensez les propriétés dans une catégorie, vous pouvez utiliser la
chaîne de votre choix pour le nom de la catégorie. Si vous utilisez une chaîne qui
n'a pas encore été utilisée, l'inspecteur d'objets génère une nouvelle classe de
catégorie de propriétés avec ce nom. Vous pouvez néanmoins recenser des
propriétés dans des catégories intégrées. Les catégories de propriétés intégrées
sont décrites dans le tableau suivant :
Catégories de propriétés

1357
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Fournir l'aide pour vos composants ( see page 1368) Lorsque vous sélectionnez un composant standard dans une fiche, ou une
propriété ou un événement dans l'inspecteur d'objets, vous pouvez appuyer sur
F1 pour obtenir de l'aide concernant cet élément. Les développeurs pourront
accéder au même type d'information sur vos composants si vous créez les
fichiers d'aide appropriés.
Vous pouvez fournir un fichier d'aide de faible encombrement pour décrire vos
composants et votre fichier d'aide devient partie intégrante du système d'aide
global de Delphi.
Voir la section Création du fichier d'aide ( see page 1364), pour des
informations sur la manière de composer le fichier d'aide à utiliser avec un
composant.
Recensement des composants ( see page 1369) Le recensement fonctionne en ayant l'unité de compilation comme base. Si vous
créez plusieurs composants dans la même unité de compilation, ils seront tous
recensés en même temps.
Pour recenser un composant, ajoutez une procédure Register à l'unité. Dans la
procédure Register, vous recensez les composants et déterminez leur
emplacement sur la palette d'outils.
Remarque: Si vous créez votre composant en choisissant
Composant->Nouveau Composant
dans l'EDI, le code requis pour recenser votre composant est automatiquement
ajouté. Les étapes d'un recensement manuel de composant sont :

• Déclaration de la procédure Register ( see page 1364)


• Ecriture de la procédure Register ( see page 1374)
Recensement de plusieurs propriétés en une seule fois ( see page 1369) Vous pouvez recenser plusieurs propriétés en une seule fois et les associer à
une catégorie de propriété en utilisant la fonction RegisterPropertiesInCategory.
RegisterPropertiesInCategory est fournie dans trois variations surchargées,
chacune proposant un ensemble différent de critères pour l'identification de la
propriété dans le composant personnalisé associé à la catégorie de propriété.
La première variation vous permet d'identifier des propriétés en fonction du nom
ou du type de propriété. La liste est transmise sous la forme d'un tableau de
constantes. Dans l'exemple ci-après, toute propriété ayant pour nom "Text" ou
qui appartient à une classe de type TEdit est recensée... suite ( see page 1369)
Recensement d'une propriété à la fois ( see page 1369) Vous pouvez recenser une propriété à la fois et l'associer à une catégorie de
propriété en utilisant la fonction RegisterPropertyInCategory.
RegisterPropertyInCategory est fournie dans quatre variations surchargées,
chacune proposant un ensemble différent de critères pour l'identification de la
propriété dans le composant personnalisé associé à la catégorie de propriété.
La première variation vous permet d'identifier la propriété selon son nom. La
ligne ci-après recense une propriété associée à l'affichage visuel du composant,
en identifiant la propriété par son nom, "AutoSize".
Recensement d'un éditeur de composants ( see page 1370) Une fois l'éditeur de composants défini, il peut être enregistré pour fonctionner
avec une classe de composants spécifique. Un éditeur de composants enregistré
est créé pour chaque composant de cette classe lorsqu'il est sélectionné dans le
concepteur de fiche.
Pour associer un éditeur de composants à une classe composant, appelez
RegisterComponentEditor. RegisterComponentEditor adopte le nom de la classe
composant qui utilise l'éditeur et le nom de la classe éditeur de composants que
vous avez définie. Par exemple, l'instruction suivante recense une classe éditeur
de composants nommée TMyEditor en vue de son utilisation avec tous les
composants de type TMyComponent... suite ( see page 1370)
Recensement de l'éditeur de propriétés ( see page 1371) Lorsque l'éditeur de propriétés est créé, vous devez le recenser dans Delphi. Le
recensement d'un éditeur de propriétés associe un type de propriété et un
éditeur spécifique. Vous pouvez recenser un éditeur pour toutes les propriétés
d'un type particulier ou juste pour une propriété particulière d'un type de
composant particulier.
Pour recenser un éditeur de propriétés, appelez une procédure
RegisterPropertyEditor.
RegisterPropertyEditor prend quatre paramètres :
3
• Un pointeur de type information décrivant le type de la
propriété à modifier. Il s'agit toujours d'un appel à la
fonction intégrée TypeInfo, telle que
TypeInfo(TMyComponent)__typeinfo(TMyCompone
nt).
• Le type du composant auquel s'applique... suite ( see
page 1371)

1358
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Définition de la valeur de la propriété ( see page 1371) La méthode SetValue de l'éditeur de propriétés accepte la chaîne saisie dans
l'inspecteur d'objets, la convertit dans le type approprié, et définit la propriété. Si
la chaîne n'est pas une valeur convenant à la propriété, SetValue doit déclencher
et ignorer la valeur.
Pour lire des valeurs chaîne dans les propriétés, vous devez redéfinir la méthode
SetValue de l'éditeur de propriétés.
SetValue doit convertir la chaîne et la valider avant d'appeler une des méthodes.
Spécification des attributs de l'éditeur ( see page 1371) L'éditeur de propriétés doit fournir les informations permettant à l'inspecteur
d'objets de déterminer les outils à afficher. Par exemple, l'inspecteur d'objets a
besoin de savoir si la propriété a des sous-propriétés, ou s'il doit afficher la liste
des valeurs possibles de la propriété.
Pour spécifier les attributs de l'éditeur, vous devez redéfinir sa méthode
GetAttributes.
GetAttributes renvoie un ensemble de valeurs de type TPropertyAttributes qui
peut inclure une ou plusieurs des valeurs suivantes :
Indicateurs des attributs des éditeurs de propriétés
Spécification d'éléments de menu ( see page 1372) Redéfinissez la méthode GetVerbCount pour renvoyer le nombre de commandes
que vous ajoutez au menu contextuel. Redéfinissez la méthode GetVerb pour
renvoyer les chaînes qui doivent être ajoutées pour chacune de ces commandes.
Lorsque vous redéfinissez GetVerb, ajoutez un "et" commercial (&) dans une
chaîne afin que le caractère suivant apparaisse souligné dans le menu
contextuel et fasse office de touche de raccourci pour la sélection de l'élément du
menu. Veillez à ajouter des points de suspension (...) à la fin d'une commande si
elle fait apparaître une boîte de dialogue. GetVerb possède un paramètre unique
pour indiquer l'index... suite ( see page 1372)
Spécification des composants ( see page 1372) Dans la procédure Register, transmettez les noms de composant dans un
tableau ouvert, que vous pouvez construire dans l'appel à RegisterComponents.
Spécification de la catégorie de palette ( see page 1373) Le nom de la catégorie de palette est une chaîne. Si le nom que vous donnez
pour la catégorie de palette n'existe pas, Delphi crée une nouvelle catégorie avec
ce nom. Delphi stocke les noms des catégories standard dans des ressources
liste de chaînes afin que les versions internationales du produit puissent nommer
les catégories dans leur langue. Si vous voulez installer un composant dans l'une
des catégories standard, vous obtiendrez la chaîne du nom de cette catégorie en
appelant la fonction LoadStr et en transmettant la constante représentant la
ressource chaîne de cette catégorie (par exemple srSystem pour la... suite (
see page 1373)
Problèmes d'installation de composants personnalisés (C++) ( see page 1373) Un problème courant lors du recensement et de l'installation de composants
personnalisés est l'absence du composant dans la liste des composants après
l'installation correcte du paquet.
Voici les causes les plus courantes de l'absence des composants dans la liste
des composants ou sur la palette :

• Modificateur de macro PACKAGE sur la fonction


Register manquant.
• Modificateur de macro PACKAGE sur la classe manquant
• Absence de #pragma package(smart_init) dans le
fichier source C++.
• Fonction Register non trouvée dans un espace de
nommage de même nom que le module code source.
• Register n'est pas correctement exportée. Utilisez
tdump sur le fichier .BPL pour... suite ( see page 1373)
Utilisation de la fonction IsPropertyInCategory ( see page 1373) Une application peut rechercher les propriétés recensées existantes afin de
déterminer si une propriété donnée est toujours recensée dans une catégorie
indiquée. Ceci peut être particulièrement utile dans des situations telles qu'un
utilitaire de localisation qui vérifie la catégorisation des propriétés afin de
préparer ses opérations de localisation. Deux variations surchargées de la
fonction IsPropertyInCategory sont disponibles, autorisant différents critères afin
3
de déterminer si une propriété se trouve dans une catégorie.
La première variation vous permet de baser le critère de comparaison sur une
combinaison du type de classe du composant propriétaire et du nom de la
propriété. Dans la... suite ( see page 1373)

1359
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Utilisation de la fonction RegisterComponents ( see page 1374) Dans la procédure Register, appelez RegisterComponents pour recenser les
composants dans le tableau des classes. RegisterComponents est une fonction
qui présente deux paramètres : le nom d'une catégorie de la palette d'outils et le
tableau des classes de composants.
Donnez au paramètre Page le nom de la catégorie de la palette d'outils où
doivent se placer les composants. Si la catégorie nommée existe déjà, les
composants y sont ajoutés. Si elle n'existe pas, Delphi crée une nouvelle
catégorie sur la palette ayant ce nom.
Appelez RegisterComponents depuis l'implémentation de la routine Register
dans une des unités définissant les composants personnalisés.... suite ( see
page 1374)
Ecriture de la procédure Register ( see page 1374) Dans la procédure Register d'une unité contenant des composants, vous devez
recenser chaque composant que vous voulez ajouter à la palette d'outils. Si
l'unité contient plusieurs composants, vous pouvez les recenser en une seule
fois.
Pour recenser un composant, appelez la procédure RegisterComponents pour
chacune des catégories de la palette d'outils auxquelles vous souhaitez ajouter
des composants. RegisterComponents nécessite trois informations importantes :

1. Spécification des composants. ( see page 1372)


2. Spécification de la page de palette. ( see page 1373)
3. Utilisation de la fonction RegisterComponents ( see
page 1374).

3.2.1.10.1 Ajout de formats de presse-papiers


Par défaut, lorsque l'utilisateur choisit Copier lorsqu'un composant est sélectionné dans l'EDI, le composant est copié dans le
format interne de Delphi. Il peut ensuite être collé dans une autre fiche ou module de données. Votre composant peut copier
d'autres formats dans le Presse-papiers en redéfinissant la méthode Copy.

Par exemple, la méthode Copy suivante permet à un composant TImage de copier son image dans le Presse-papiers. L'image
est ignorée par l'EDI de Delphi, mais elle peut être collée dans d'autres applications.
procedure TMyComponent.Copy;
var
MyFormat : Word;
AData,APalette : THandle;
begin
TImage(Component).Picture.Bitmap.SaveToClipBoardFormat(MyFormat, AData, APalette);
ClipBoard.SetAsHandle(MyFormat, AData);
end;
void __fastcall TMyComponentEditor::Copy(void)
{
WORD AFormat;
int AData;
HPALETTE APalette;
((TImage *)Component)->Picture->SaveToClipboardFormat(AFormat, AData, APalette);
TClipboard *pClip = Clipboard(); // n'efface pas le presse-papiers!
pClip->SetAsHandle(AFormat, AData);
}

3.2.1.10.2 Ajout d'éditeurs de composants


3
Les éditeurs de composants déterminent ce qui se passe lorsque vous double-cliquez sur le composant dans le concepteur et
ajoutent des commandes au menu contextuel qui apparaît lorsque vous cliquez sur le composant avec le bouton droit. Ils
peuvent également copier votre composant dans le Presse-papiers Windows dans des formats personnalisés.

Si vous n'attribuez pas d'éditeur à vos composants, Delphi utilise l'éditeur de composants par défaut. Ce dernier est implémenté
par la classe TDefaultEditor. TDefaultEditor n'ajoute aucun nouvel élément au menu contextuel d'un composant. Lorsque vous
double-cliquez sur le composant, TDefaultEditor recherche ses propriétés et génère le premier gestionnaire d'événement trouvé
ou s'y rend.

1360
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Pour ajouter des éléments au menu contextuel, modifier le comportement du composant lorsque vous double-cliquez dessus ou
ajouter de nouveaux formats de presse-papiers, dérivez une nouvelle classe à partir de TComponentEditor et recensez-la pour
qu'elle soit utilisée avec votre composant. Dans vos méthodes redéfinies, vous pouvez utiliser la propriété Component de
TComponentEditor pour accéder au composant en cours de modification.

L'ajout d'un éditeur de composants personnalisé comprend plusieurs étapes :

• Ajout d'éléments au menu contextuel ( see page 1361)


• Modification du comportement suite à un double-clic ( see page 1361)
• Ajout de formats de presse-papiers ( see page 1360)
• Recensement d'un éditeur de composants ( see page 1370)

3.2.1.10.3 Ajout d'éléments au menu contextuel


Lorsque l'utilisateur clique avec le bouton droit sur le composant, les méthodes GetVerbCount et GetVerb de l'éditeur de
composants sont appelées pour construire un menu contextuel. Vous pouvez redéfinir ces méthodes pour ajouter des
commandes (verbes) au menu contextuel.

L'ajout d'éléments au menu contextuel requiert ces étapes :

• Spécification d'éléments de menu ( see page 1372)


• Implémentation des commandes ( see page 1366)

3.2.1.10.4 Ajout d'éditeurs de propriétés


L'inspecteur d'objets permet par défaut de modifier tous les types de propriétés. Vous pouvez toutefois créer un éditeur pour des
propriétés spécifiques en l'écrivant et en le recensant. Vous pouvez recenser les éditeurs de propriétés afin qu'ils s'appliquent
uniquement aux propriétés des composants dont vous êtes l'auteur, ou à toutes les propriétés du type spécifié.

A la base, un éditeur de propriétés peut opérer selon deux modes : affichage sous la forme d'une chaîne texte permettant à
l'utilisateur la modification de la valeur courante ; affichage d'une boîte de dialogue permettant des modifications d'une autre
sorte. Selon la propriété en cours de modification, vous pourrez faire appel à l'un ou l'autre mode.

L'écriture d'un éditeur de propriété se déroule en cinq étapes :

1. Dérivation d'une classe éditeur de propriétés ( see page 1364).


2. Modification de la propriété sous une forme textuelle.
3. Modification globale de la propriété ( see page 1365).
4. Spécification des attributs de l'éditeur ( see page 1371).
5. Recensement de l'éditeur de propriétés ( see page 1371).

3.2.1.10.5 Modification du comportement suite à un double-clic


Lorsque vous double-cliquez sur le composant, la méthode Edit du composant est appelée. Par défaut, la méthode Edit exécute 3
la première commande ajoutée au menu contextuel. Ainsi, dans l'exemple précédent ( see page 1366), le fait de double-cliquer
sur le composant exécute la commande DoThis.

Même si l'exécution de la première commande est généralement une bonne idée, vous pouvez modifier ce comportement par
défaut. Par exemple, vous pouvez définir un comportement différent si :

• vous n'ajoutez aucune commande au menu contextuel ;


• vous souhaitez afficher une boîte de dialogue qui combine plusieurs commandes lorsque l'utilisateur double-clique sur le

1361
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

composant.
Redéfinissez la méthode Edit pour spécifier un nouveau comportement lorsque l'utilisateur double-clique sur le composant. Par
exemple, la méthode Edit suivante appelle une boîte de dialogue de fontes lorsque l'utilisateur double-clique sur le
composant :
procedure TMyEditor.Edit;
var
FontDlg: TFontDialog;
begin
FontDlg := TFontDialog.Create(Application);
try
if FontDlg.Execute then
MyComponent.FFont.Assign(FontDlg.Font);
finally
FontDlg.Free
end;
end;
void __fastcall TMyEditor::Edit(void)
{
TFontDialog *pFontDlg = new TFontDialog(NULL);
pFontDlg->Execute();
((TMyComponent *)Component)->Font = pFontDlg->Font;
delete pFontDlg;
}
Remarque: Si vous souhaitez qu'un double-clic sur le composant affiche l'éditeur de code d'un gestionnaire d'événement,
utilisez TDefaultEditor comme classe de base pour votre éditeur de composants au lieu de TComponentEditor. Ainsi, au lieu de
redéfinir la méthode Edit, redéfinissez la méthode protégée TDefaultEditor.EditProperty. EditProperty recherche les
gestionnaires d'événement du composant et affiche le premier qu'il trouve. Vous pouvez modifier ce comportement pour
visualiser un événement particulier. Par exemple :

procedure TMyEditor.EditProperty(PropertyEditor: TPropertyEditor;


Continue, FreeEditor: Boolean)
begin
if (PropertyEditor.ClassName = 'TMethodProperty') and
(PropertyEditor.GetName = 'OnSpecialEvent') then
// DefaultEditor.EditProperty(PropertyEditor, Continue, FreeEditor);
end;
void __fastcall TMyEditor::EditProperty(TPropertyEditor* PropertyEditor,
bool &Continue, bool &FreeEditor)
{
if (PropertyEditor->ClassNameIs("TMethodProperty") &&
CompareText(PropertyEditor->GetName, "OnSpecialEvent") == 0)
{
TDefaultEditor::EditProperty(PropertyEditor, Continue, FreeEditor);
}
}

3.2.1.10.6 Compilation des composants en packages


Une fois vos composants recensés, vous devez les compiler en packages avant de les installer dans l'EDI. Un package peut
3 contenir un ou plusieurs composants ainsi que des éditeurs de propriétés personnalisés. Pour plus d'informations sur les
packages, voir Utilisation des packages et des composants ( see page 2285).

Pour créer et compiler un package, voir Création et modification de packages ( see page 2287). Placez les unités de code
source de vos composants personnalisés dans la liste Contient du package. Si vos composants dépendent d'autres packages,
incluez ces derniers dans la liste Requiert.

Pour installer vos composants dans l'EDI, voir Installation de packages de composants ( see page 2291).

1362
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.10.7 Création des entrées


Pour que l'aide associée à votre composant fonctionne de façon transparente avec celle des autres composants de la
bibliothèque, vous devez respecter les conventions suivantes :

Chaque composant doit avoir une rubrique d'aide :

La rubrique associée au composant doit montrer dans quelle unité est déclaré le composant et fournir une brève description du
composant. La rubrique du composant doit proposer des liens vers des fenêtres secondaires décrivant la position du composant
dans la hiérarchie des objets et répertorier l'ensemble de ses propriétés, événements et méthodes. Les développeurs
d'applications accéderont à cette rubrique en sélectionnant le composant dans une fiche et en appuyant sur F1. Pour avoir un
exemple d'une rubrique associée à un composant, positionnez-vous sur un composant quelconque dans une fiche et appuyez
sur F1.

La rubrique de composant doit avoir une note de bas de page # avec une valeur unique de rubrique. La note de bas de page #
identifie de manière unique chaque rubrique du système d'aide.

La rubrique associée au composant doit avoir une note de bas de page “K” (qui indique les mots clé de recherche) comprenant
le nom de la classe du composant. Par exemple, la note de bas de page des mots clés pour le composant TMemo contient
"TMemo".

La rubrique associée au composant doit également comprendre une note de bas de page $ qui indique le titre de la rubrique. Le
titre apparaît dans la boîte de dialogue des rubriques, la boîte de dialogue Signet et la fenêtre Historique.

Chaque composant doit inclure les rubriques de navigation secondaires suivantes :

• Une rubrique de hiérarchie offrant des liens vers chaque ancêtre du composant appartenant à sa hiérarchie.
• Une liste de toutes les propriétés disponibles dans le composant, avec des liens vers les entrées décrivant ces propriétés.
• Une liste de tous les événements disponibles dans le composant, avec des liens vers les entrées décrivant ces événements.
• Une liste de toutes les méthodes disponibles dans le composant, avec des liens vers les entrées décrivant ces méthodes.
Les liens vers les classes d'objets, les propriétés ou les événements dans le système d'aide de Delphi peuvent être réalisés à
l'aide de Alinks. Alink opère la liaison vers une classe d'objet en utilisant le nom de classe de l'objet suivi d'un caractère de
soulignement et de la chaîne "object". Par exemple, pour réaliser un lien vers l'objet TCustomPanel, utilisez le code suivant :
!AL(TCustomPanel_object,1)
Pour réaliser un lien vers une propriété, une méthode ou un événement, faites précéder son nom par celui de l'objet qui
l'implémente et par un caractère de soulignement. Par exemple, pour réaliser un lien vers la propriété Text implémentée par
TControl, utilisez le code suivant :
!AL(TControl_Text,1)
Pour voir un exemple de rubriques de navigation secondaires, affichez l'aide d'un composant quelconque et cliquez sur les liens
étiquetés hiérarchie, propriétés, méthodes ou événements.

Chaque propriété, événement ou méthode déclaré à l'intérieur du composant doit avoir une rubrique :

Une rubrique décrivant une propriété, un événement ou une méthode doit indiquer la déclaration de l'élément et décrire son rôle.
Les développeurs d'applications accéderont à cette rubrique en sélectionnant l'élément dans l'inspecteur d'objets et en appuyant 3
sur F1, ou en plaçant le curseur dans l'éditeur de code sur le nom de l'élément et en appuyant sur F1. Pour avoir un exemple de
rubrique associée à une propriété, sélectionnez un élément quelconque dans l'inspecteur d'objets et appuyez sur F1.

Les rubriques de propriété, d'événement et de méthode doivent inclure une note de bas de page K qui indique le nom de la
propriété, de l'événement et de la méthode, son nom et celui du composant. Ainsi, la propriété Text de TControl présente la note
de bas de page K suivante :
Text,TControl;TControl,Text;Text,

1363
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Les rubriques de propriété, de méthode ou d'événement doivent également comporter une note de bas de page $ indiquant le
titre de la rubrique, tel que TControl.Text.

Toutes ces rubriques doivent disposer d'un identificateur de rubrique unique à la rubrique, entré sous la forme d'une note de bas
de page #.

3.2.1.10.8 Création du fichier d'aide


Vous pouvez utiliser l'outil de votre choix pour créer les fichiers d'aide Windows (au format .rtf). Delphi inclut le Microsoft Help
Workshop, qui compile les fichiers d'aide et contient un guide en ligne destiné à l'auteur du système d'aide. Vous y trouverez
toutes les informations nécessaires à la création des systèmes d'aide.

La composition de fichiers d'aide pour les composants s'effectue en plusieurs étapes :

• Création des entrées ( see page 1363).


• Aide contextuelle des composants ( see page 1366).

3.2.1.10.9 Déclaration de la procédure Register


Le recensement implique l'écriture d'une procédure unique dans l'unité, qui doit être nommée Register. La procédure Register
doit apparaître dans la partie interface de l'unité et, contrairement au reste du Delphi, son nom tient compte des différences
majuscules/minuscules.

Remarque: Bien que Delphi soit un langage qui ne tient pas compte de la distinction minuscules/majuscules, la procédure
Register en tient compte et doit être orthographiée avec un R majuscule.

Le code suivant montre la présentation d'une seule unité qui crée et recense des nouveaux composants :
unit MyBtns;
interface
type
... { déclarez vos composants ici }
procedure Register; { ceci doit apparaître dans la section interface }
implementation
... { l'implémentation de composant vient ici }
procedure Register;
begin
... { recense les composants }
end;
end.
namespace Newcomp
{
void __fastcall PACKAGE Register()
{
}
}
Dans la procédure Register, appelez RegisterComponents pour chaque composant que vous souhaitez ajouter à la palette
d'outils. Si l'unité contient plusieurs composants, vous pouvez les recenser en une seule fois.

3
3.2.1.10.10 Dérivation d'une classe éditeur de propriétés
La bibliothèque de composants définit plusieurs sortes d'éditeurs de propriétés, tous descendant de TPropertyEditor. Lorsque
vous créez un éditeur de propriétés, votre classe éditeur de propriétés peut descendre directement de TPropertyEditor ou d'un
des types d'éditeurs de propriétés décrits dans le tableau ci-après. Les classes de l'unité DesignEditors peuvent être utilisées
dans les applications VCL.

Remarque: Ce qui est absolument nécessaire pour un éditeur de propriété est qu'il dérive de TBasePropertyEditor et qu'il

1364
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

prenne en charge l'interface IProperty. Néanmoins, TPropertyEditor fournit une implémentation par défaut de l'interface
IProperty.

La liste du tableau ci-après n'est pas complète. L'unité VCLEditors définit également certains éditeurs spécialisés utilisés
exclusivement par certaines propriétés comme le nom du composant. Les éditeurs de propriétés ci-dessous sont les plus utiles
aux concepteurs de propriétés définies par l'utilisateur.

Types d'éditeurs de propriétés prédéfinis

Type Propriétés modifiables


TOrdinalProperty Tous les éditeurs de valeurs ordinales (propriétés de type entier, caractères, énuméré) sont des
descendants de TOrdinalProperty.
TIntegerProperty Tous les types entiers y compris ceux prédéfinis ainsi que les intervalles utilisateur.
TCharProperty Le type Char et les intervalles de valeurs Char tels que ‘A'..'Z'.
TEnumProperty Tous les types énumérés.
TFloatProperty Tous les nombres à virgule flottante.
TStringProperty Chaînes.
TSetElementProperty Les éléments des ensembles comme valeurs booléennes.
TSetProperty Tous les ensembles. Les ensembles ne sont pas directement modifiables mais peuvent être
développés sous la forme d'une liste de propriétés que sont les éléments de l'ensemble.
TClassProperty Classes. Affiche le nom de la classe et se développe pour afficher les propriétés de la classe.
TMethodProperty Pointeurs sur des méthodes, le plus souvent des événements.
TComponentProperty Les composants de la même fiche. Ne permet pas la modification des propriétés des composants, mais
peut pointer sur un composant spécifique de type compatible.
TColorProperty Les couleurs d'un composant. Montre si possible les constantes de couleurs ou à défaut leurs valeurs
en hexadécimal. Une liste déroulante affiche les constantes de couleurs. Un double-clic a pour effet
d'ouvrir la boîte de dialogue de sélection des couleurs.
TFontNameProperty Les noms de fontes. La liste déroulante affiche toutes les fontes actuellement installées.
TFontProperty Les fontes. Autorise le développement des propriétés d'une fonte particulière et offre l'accès à la boîte
de dialogue des fontes.

3.2.1.10.11 Modification globale de la propriété


Si vous le souhaitez, vous pouvez fournir une boîte de dialogue pour la définition de la propriété. L'utilisation la plus courante
des éditeurs de propriétés concerne les propriétés qui sont des classes. Un exemple est la propriété Font, qui a une boîte de
dialogue éditeur associée permettant au développeur de choisir tous les attributs de fonte en même temps.

Pour fournir une boîte de dialogue de définition globale de la propriété, redéfinissez la méthode Edit de la classe éditeur de
propriétés.

Les méthodes Edit utilisent les mêmes méthodes "Get" et "Set" utilisées dans les méthodes GetValue et SetValue. En fait, une
méthode Edit appelle à la fois une méthode "Get" et une méthode "Set". Comme l'éditeur est spécifique du type, il est 3
habituellement inutile de convertir les valeurs des propriétés en chaînes. L'éditeur traite généralement la valeur telle qu'elle a été
récupérée.

Lorsque l'utilisateur clique sur le bouton '...' à côté de la propriété, ou double-clique sur la colonne des valeurs, l'inspecteur
d'objets appelle la méthode Edit de l'éditeur de propriétés.

1365
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Pour votre implémentation de la méthode Edit, suivez ces étapes :


1. Construisez l'éditeur que vous utilisez pour cette propriété.
2. Lisez la valeur en cours et attribuez-la à la propriété en utilisant une méthode "Get".
3. Lorsque l'utilisateur sélectionne une nouvelle valeur, attribuez cette valeur à la propriété en utilisant une méthode "Set".
4. Détruisez l'éditeur.

3.2.1.10.12 Implémentation des commandes


Lorsque la commande fournie par GetVerb est sélectionnée dans le concepteur, la méthode ExecuteVerb est appelée. Pour
chaque commande que vous spécifiez dans la méthode GetVerb, implémentez une action dans la méthode ExecuteVerb. Vous
pouvez accéder au composant en cours de modification à l'aide de la propriété Component de l'éditeur.

Par exemple, la méthode ExecuteVerb suivante implémente les commandes de la méthode GetVerb de l'exemple précédent (
see page 1372).
procedure TMyEditor.ExecuteVerb(Index: Integer);
var
MySpecialDialog: TMyDialog;
begin
case Index of
0: begin
MyDialog := TMySpecialDialog.Create(Application); { instancier l'éditeur }
if MySpecialDialog.Execute then; { si l'utilisateur valide la boîte
de dialogue par OK... }
MyComponent.FThisProperty := MySpecialDialog.ReturnValue; { ...utiliser la valeur
}
MySpecialDialog.Free; { détruire l'éditeur }
end;
1: That; { appeler la méthode That }
end;
end;
void __fastcall TMyEditor::ExecuteVerb(int Index)
{
switch (Index)
{
case 0:
TMyDialog *MySpecialDialog = new TMyDialog();
MySpecialDialog->Execute();
((TMyComponent *)Component)->ThisProperty = MySpecialDialog->ReturnValue;
delete MySpecialDialog;
break;
case 1:
That(); // Appelle la méthode "That"
break;
}
}

3.2.1.10.13 Aide contextuelle des composants


3 Chaque rubrique de composant, de propriété, de méthode et d'événement doit comporter une note de bas de page A. La note
de bas de page A permet d'afficher la rubrique lorsque l'utilisateur sélectionne un composant et appuie sur F1, ou lorsqu'il
sélectionne une propriété ou un événement dans l'inspecteur d'objets et appuie sur F1. Les notes de bas de page A doivent
suivre certaines conventions d'appellation :

Si la rubrique d'aide est destinée à un composant, la note de bas de page A comprend deux entrées séparées par un
point-virgule selon la syntaxe suivante :
ComponentClass_Object;ComponentClass

1366
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

où ComponentClass est le nom de la classe du composant.

Si la rubrique d'aide est destinée à une propriété ou à un événement, la note de bas de page A comprend trois entrées séparées
par des points-virgules selon la syntaxe suivante :
ComponentClass_Element;Element_Type;Element
où ComponentClass est le nom de la classe du composant, Element est le nom de la propriété, de la méthode ou de
l'événement et Type est la propriété, la méthode ou l'événement

Par exemple, en supposant une propriété BackgroundColor d'un composant TMyGrid, la note de bas de page A est
TMyGrid_BackgroundColor;BackgroundColor_Property;BackgroundColor

3.2.1.10.14 Accessibilité des composants au moment de la conception : Vue


globale
Rendre vos composants accessibles à la conception est un processus qui nécessite plusieurs étapes :

• Recensement des composants ( see page 1369)


• Fournir l'aide pour vos composants ( see page 1368)
• Ajout d'éditeurs de propriétés ( see page 1361)
• Ajout d'éditeurs de composants ( see page 1360)
• Compilation des composants en packages ( see page 1362)
Toutes les étapes ne s'appliquent pas à tous les composants. Par exemple, si vous ne définissez ni propriété ni événement
nouveau, il n'est pas nécessaire de fournir de l'aide. Le recensement et la compilation sont les seules étapes obligatoires.
Une fois que vos composants ont été recensés et compilés en packages, ils peuvent être distribués à d'autres développeurs et
installés dans l'EDI. Pour plus d'informations sur l'installation des packages dans l'EDI, voir Installation de packages de
composants ( see page 2291).
Voir aussi
Extensions de l'EDI ( see page 1297)

3.2.1.10.15 Catégories de propriétés


Dans l'IDE, l'inspecteur d'objets vous permet de masquer et d'afficher sélectivement des propriétés basées sur les catégories de
propriété. Les propriétés des nouveaux composants personnalisés peuvent rentrer dans ce schéma en recensant des propriétés
par catégories. Faites ceci lors du recensement du composant en appelant RegisterPropertyInCategory ou
RegisterPropertiesInCategory. Utilisez RegisterPropertyInCategory pour recenser une seule propriété. Utilisez
RegisterPropertiesInCategory pour recenser plusieurs propriétés dans un seul appel de fonction. Ces fonctions sont définies
dans l'unité DesignIntf.

Notez qu'il n'est pas obligatoire de recenser des propriétés ni que toutes les propriétés d'un composant personnalisé soient
recensées lorsque quelques-unes le sont. Toute propriété non explicitement associée à une catégorie est incluse dans la
catégorie TMiscellaneousCategory. De telles propriétés sont affichées ou masquées dans l'inspecteur d'objets selon cette
catégorisation par défaut. 3
En plus de ces deux fonctions de recensement de propriétés, il existe une fonction IsPropertyInCategory. Cette fonction est utile
pour la création d'utilitaires de localisation, dans laquelle vous devez déterminer si une propriété est recensée dans une
catégorie de propriété donnée.

• Recensement d'une propriété à la fois ( see page 1369)


• Recensement de plusieurs propriétés en une seule fois ( see page 1369)
• Spécification de catégories de propriétés ( see page 1368)

1367
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

• Utilisation de la fonction IsPropertyInCategory ( see page 1373)

3.2.1.10.16 Spécification de catégories de propriétés


Lorsque vous recensez les propriétés dans une catégorie, vous pouvez utiliser la chaîne de votre choix pour le nom de la
catégorie. Si vous utilisez une chaîne qui n'a pas encore été utilisée, l'inspecteur d'objets génère une nouvelle classe de
catégorie de propriétés avec ce nom. Vous pouvez néanmoins recenser des propriétés dans des catégories intégrées. Les
catégories de propriétés intégrées sont décrites dans le tableau suivant :

Catégories de propriétés

Catégorie Utilisation
Action Propriétés relatives aux actions d'exécution ; les propriétés Enabled et Hint de TEdit se trouvent dans cette
catégorie.
Base de Propriétés relatives aux opérations de bases de données ; les propriétés DatabaseName et SQL de TQuery se
données trouvent dans cette catégorie.
Glisser, Propriétés relatives aux opérations de glisser-déplacer et d'ancrage ; les propriétés DragCursor et DragKind de
Déplacer TImage se trouvent dans cette catégorie.
et Ancrer
Aide et Propriétés relatives à l'utilisation de l'aide en ligne ou des conseils ; les propriétés HelpContext et Hint de TMemo
conseils se trouvent dans cette catégorie.
Disposition Propriétés relatives à l'affichage visuel d'un contrôle à la conception ; les propriétés Top et Left de TDBEdit se
trouvent dans cette catégorie.
Legs Propriétés relatives aux opérations obsolètes ; les propriétés Ctl3D et ParentCtl3D de TComboBox se trouvent
dans cette catégorie.
Liaison Propriétés relatives à l'association ou à la liaison d'un composant à un autre ; la propriété DataSet de
TDataSource se trouve dans cette catégorie.
Locale Propriétés relatives aux localisations internationales ; les propriétés BiDiMode et ParentBiDiMode de TMainMenu
se trouvent dans cette catégorie.
Localisable Propriétés qui peuvent nécessiter des modifications dans les versions localisées d'une application. De
nombreuses propriétés chaîne (comme Caption) font partie de cette catégorie ainsi que les propriétés qui
déterminent la taille et la position des contrôles.
Visuel Propriétés relatives à l'affichage visuel d'un contrôle à l'exécution ; les propriétés Align et Visible de TScrollBox se
trouvent dans cette catégorie.
Entrée Propriétés relatives à la saisie de données (il n'est pas nécessaire qu'elles soient relatives aux opérations de
bases de données) ; les propriétés Enabled et ReadOnly de TEdit se trouvent dans cette catégorie.
Divers Propriétés qui ne rentrent pas dans une catégorie ou n'ont pas besoin d'être mises dans des catégories (et les
propriétés non explicitement recensées dans une catégorie spécifique) ; les propriétés AllowAllUp et Name de
TSpeedButton se trouvent dans cette catégorie.

3.2.1.10.17 Fournir l'aide pour vos composants


3
Lorsque vous sélectionnez un composant standard dans une fiche, ou une propriété ou un événement dans l'inspecteur d'objets,
vous pouvez appuyer sur F1 pour obtenir de l'aide concernant cet élément. Les développeurs pourront accéder au même type
d'information sur vos composants si vous créez les fichiers d'aide appropriés.

Vous pouvez fournir un fichier d'aide de faible encombrement pour décrire vos composants et votre fichier d'aide devient partie
intégrante du système d'aide global de Delphi.

Voir la section Création du fichier d'aide ( see page 1364), pour des informations sur la manière de composer le fichier d'aide à

1368
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

utiliser avec un composant.

3.2.1.10.18 Recensement des composants


Le recensement fonctionne en ayant l'unité de compilation comme base. Si vous créez plusieurs composants dans la même
unité de compilation, ils seront tous recensés en même temps.

Pour recenser un composant, ajoutez une procédure Register à l'unité. Dans la procédure Register, vous recensez les
composants et déterminez leur emplacement sur la palette d'outils.

Remarque: Si vous créez votre composant en choisissant Composant->Nouveau Composant

dans l'EDI, le code requis pour recenser votre composant est automatiquement ajouté. Les étapes d'un recensement manuel
de composant sont :

• Déclaration de la procédure Register ( see page 1364)


• Ecriture de la procédure Register ( see page 1374)

3.2.1.10.19 Recensement de plusieurs propriétés en une seule fois


Vous pouvez recenser plusieurs propriétés en une seule fois et les associer à une catégorie de propriété en utilisant la fonction
RegisterPropertiesInCategory. RegisterPropertiesInCategory est fournie dans trois variations surchargées, chacune proposant
un ensemble différent de critères pour l'identification de la propriété dans le composant personnalisé associé à la catégorie de
propriété.

La première variation vous permet d'identifier des propriétés en fonction du nom ou du type de propriété. La liste est transmise
sous la forme d'un tableau de constantes. Dans l'exemple ci-après, toute propriété ayant pour nom "Text" ou qui appartient à
une classe de type TEdit est recensée dans la catégorie 'Localisable'.
RegisterPropertiesInCategory('Localisable', ['Text', TEdit]);
RegisterPropertiesInCategory("Localizable", ARRAYOFCONST("Text", __typeinfo(TEdit)));
La deuxième variation vous permet de limiter les propriétés recensées à celles qui appartiennent à un composant spécifique. La
liste des propriétés à recenser comprend seulement les noms, pas les types. Par exemple, le code suivant recense un nombre
de propriétés dans la catégorie 'Aide et conseils' pour tous les composants :
RegisterPropertiesInCategory('Aide et conseils', TComponent, ['HelpContext', 'Hint',
'ParentShowHint', 'ShowHint']);
RegisterPropertyInCategory('Aide et conseils', __classid(TComponent),
ARRAYOFCONST("HelpContext", "Hint", "ParentShowHint"));
La troisième variation vous permet de limiter les propriétés recensées à celles possédant un type spécifique. Comme avec la
seconde variation, la liste des propriétés à recenser peut n'inclure que les noms :
RegisterPropertiesInCategory('Localisable', TypeInfo(String), ['Text', 'Caption']);
RegisterPropertiesInCategory("Localizable", __typeinfo(TStrings), ARRAYOFCONST("Lines",
"Commands"));
Consultez la section Spécification de catégories de propriétés ( see page 1368) pour obtenir une liste des catégories de
propriété disponibles ainsi qu'une brève description de leur utilisation.
3

3.2.1.10.20 Recensement d'une propriété à la fois


Vous pouvez recenser une propriété à la fois et l'associer à une catégorie de propriété en utilisant la fonction
RegisterPropertyInCategory. RegisterPropertyInCategory est fournie dans quatre variations surchargées, chacune proposant un
ensemble différent de critères pour l'identification de la propriété dans le composant personnalisé associé à la catégorie de
propriété.

1369
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

La première variation vous permet d'identifier la propriété selon son nom. La ligne ci-après recense une propriété associée à
l'affichage visuel du composant, en identifiant la propriété par son nom, "AutoSize".
RegisterPropertyInCategory('Visuel', 'AutoSize');
RegisterPropertyInCategory("Visual", "AutoSize");
La deuxième variation identifie la propriété en utilisant le type de classe de composant et le nom de propriété caractéristiques.
L'exemple ci-après recense (dans la catégorie THelpCategory) une propriété appelée "HelpContext" d'un composant de la
classe personnalisée TMyButton.
RegisterPropertyInCategory('Aide et conseils', TMyButton, 'HelpContext');
RegisterPropertyInCategory("Aide et conseils", __classid(TMyButton), "HelpContext");
La troisième variation identifie la propriété en utilisant son type au lieu de son nom. L'exemple ci-dessous recense une propriété
en se basant sur son type, Integer.
RegisterPropertyInCategory('Visuel', TypeInfo(Integer));
RegisterPropertyInCategory("Visuel", typeid(TArrangement));
La dernière variation utilise à la fois le type de la propriété et son nom pour identifier la propriété. L'exemple ci-après recense
une propriété basée sur une combinaison de son type, TBitmap et de son nom, "Pattern".
RegisterPropertyInCategory('Visuel', TypeInfo(TBitmap), 'Pattern');
RegisterPropertyInCategory("Visuel", typeid(TBitmap), "Pattern");
Consultez la section Spécification de catégories de propriétés ( see page 1368) pour obtenir une liste des catégories de
propriété disponibles ainsi qu'une brève description de leur utilisation.

3.2.1.10.21 Recensement d'un éditeur de composants


Une fois l'éditeur de composants défini, il peut être enregistré pour fonctionner avec une classe de composants spécifique. Un
éditeur de composants enregistré est créé pour chaque composant de cette classe lorsqu'il est sélectionné dans le concepteur
de fiche.

Pour associer un éditeur de composants à une classe composant, appelez RegisterComponentEditor. RegisterComponentEditor
adopte le nom de la classe composant qui utilise l'éditeur et le nom de la classe éditeur de composants que vous avez définie.
Par exemple, l'instruction suivante recense une classe éditeur de composants nommée TMyEditor en vue de son utilisation avec
tous les composants de type TMyComponent :
RegisterComponentEditor(TMyComponent, TMyEditor);
RegisterComponentEditor(__classid( TMyComponent), __classid(TMyEditor));
Placez l'appel à RegisterComponentEditor dans la procédure Register où vous recensez votre composant. Par exemple, si un
nouveau composant nommé TMyComponent et son éditeur de composants TMyEditor sont tous les deux implémentés dans la
même unité, le code suivant recense le composant et son association à l'éditeur de composants.
procedure Register;
begin
RegisterComponents('Divers', [TMyComponent);
RegisterComponentEditor(classes[0], TMyEditor);
end;
namespace Newcomp
3 {
void __fastcall PACKAGE Register()
{

RegisterComponents("Divers", classes, 0);


RegisterComponentEditor(classes[0], __classid(TMyEditor));
}
}

1370
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

3.2.1.10.22 Recensement de l'éditeur de propriétés


Lorsque l'éditeur de propriétés est créé, vous devez le recenser dans Delphi. Le recensement d'un éditeur de propriétés associe
un type de propriété et un éditeur spécifique. Vous pouvez recenser un éditeur pour toutes les propriétés d'un type particulier ou
juste pour une propriété particulière d'un type de composant particulier.

Pour recenser un éditeur de propriétés, appelez une procédure RegisterPropertyEditor.

RegisterPropertyEditor prend quatre paramètres :

• Un pointeur de type information décrivant le type de la propriété à modifier. Il s'agit toujours d'un appel à la fonction intégrée
TypeInfo, telle que TypeInfo(TMyComponent)__typeinfo(TMyComponent).
• Le type du composant auquel s'applique cet éditeur. Si ce paramètre est nil, l'éditeur s'applique à toutes les propriétés d'un
type donné.
• Le nom de la propriété. Ce paramètre n'est significatif que si le paramètre qui le précède spécifie un type particulier de
composant. Dans ce cas, vous pouvez spécifier une propriété de ce type auquel s'applique l'éditeur.
• Le type d'éditeur de propriétés à utiliser pour modifier la propriété spécifiée.

3.2.1.10.23 Définition de la valeur de la propriété


La méthode SetValue de l'éditeur de propriétés accepte la chaîne saisie dans l'inspecteur d'objets, la convertit dans le type
approprié, et définit la propriété. Si la chaîne n'est pas une valeur convenant à la propriété, SetValue doit déclencher et ignorer
la valeur.

Pour lire des valeurs chaîne dans les propriétés, vous devez redéfinir la méthode SetValue de l'éditeur de propriétés.

SetValue doit convertir la chaîne et la valider avant d'appeler une des méthodes.

3.2.1.10.24 Spécification des attributs de l'éditeur


L'éditeur de propriétés doit fournir les informations permettant à l'inspecteur d'objets de déterminer les outils à afficher. Par
exemple, l'inspecteur d'objets a besoin de savoir si la propriété a des sous-propriétés, ou s'il doit afficher la liste des valeurs
possibles de la propriété.

Pour spécifier les attributs de l'éditeur, vous devez redéfinir sa méthode GetAttributes.

GetAttributes renvoie un ensemble de valeurs de type TPropertyAttributes qui peut inclure une ou plusieurs des valeurs
suivantes :

Indicateurs des attributs des éditeurs de propriétés

Indicateur Méthode associée Signification si inclus

paValueList GetValues L'éditeur peut fournir une liste de valeurs énumérées.


paSubProperties GetProperties La propriété dispose de sous-propriétés qu'il est possible d'afficher.
3
paDialog Edit L'éditeur peut afficher une boîte de dialogue permettant de modifier
globalement la propriété.
paMultiSelect N/D La propriété doit s'afficher lorsque l'utilisateur sélectionne plusieurs
composants.
paAutoUpdate SetValue Mise à jour du composant après chaque modification au lieu d'attendre
l'approbation de la valeur.
paSortList N/D L'inspecteur d'objets doit trier la liste de valeurs.

1371
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

paReadOnly N/D La valeur de la propriété ne peut être modifiée lors de la conception.


paRevertable N/D Active l'élément de menu Revenir à hérité dans le menu contextuel de
l'inspecteur d'objets. Cet élément de menu demande à l'éditeur d'annuler la
valeur en cours de la propriété et de revenir à une valeur par défaut ou
standard préalablement établie.
paFullWidthName N/D La valeur n'a pas besoin d'être affichée. L'inspecteur d'objets utilise toute sa
largeur pour le nom de propriété.
paVolatileSubProperties GetProperties L'inspecteur d'objets récupère les valeurs de toutes les sous-propriétés à
chaque modification de la valeur de la propriété.
paReference GetComponentValue La valeur est une référence à quelque chose d'autre. Utilisé conjointement
avec paSubProperties, l'objet référencé devrait être affiché comme
sous-propriétés de cette propriété.

3.2.1.10.25 Spécification d'éléments de menu


Redéfinissez la méthode GetVerbCount pour renvoyer le nombre de commandes que vous ajoutez au menu contextuel.
Redéfinissez la méthode GetVerb pour renvoyer les chaînes qui doivent être ajoutées pour chacune de ces commandes.
Lorsque vous redéfinissez GetVerb, ajoutez un "et" commercial (&) dans une chaîne afin que le caractère suivant apparaisse
souligné dans le menu contextuel et fasse office de touche de raccourci pour la sélection de l'élément du menu. Veillez à ajouter
des points de suspension (...) à la fin d'une commande si elle fait apparaître une boîte de dialogue. GetVerb possède un
paramètre unique pour indiquer l'index de la commande.

Le code suivant redéfinit les méthodes GetVerbCount et GetVerb pour ajouter deux commandes au menu contextuel.
function TMyEditor.GetVerbCount: Integer;
begin
Result := 2;
end;
function TMyEditor.GetVerb(Index: Integer): String;
begin
case Index of
0: Result := '&DoThis ...';
1: Result := 'Do&That';
end;
end;
int __fastcall TMyEditor::GetVerbCount(void)
{
return 2;
}
System::AnsiStringBase __fastcall TMyEditor::GetVerb(int Index)
{
switch (Index)
{
case 0: return "&DoThis ..."; break;
case 1: return "Do&That"; break;
}
}
3 Remarque: Veillez à ce que votre méthode GetVerb renvoie une valeur pour chaque index possible indiqué par GetVerbCount.

3.2.1.10.26 Spécification des composants


Dans la procédure Register, transmettez les noms de composant dans un tableau ouvert, que vous pouvez construire dans
l'appel à RegisterComponents.
RegisterComponents('Miscellaneous', [TMyComponent]);

1372
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

TMetaClass classes[1] = {__classid(TNewComponent)};


Vous pouvez aussi recenser plusieurs composants sur la même page ou différents composants sur des pages distinctes,
comme l'illustre le code suivant :
procedure Register;
begin
RegisterComponents('Miscellaneous', [TFirst, TSecond]); { deux sur cette page... }
RegisterComponents('Assorted', [TThird]); { ...un sur une autre... }
RegisterComponents(LoadStr(srStandard), [TFourth]); { ...et un sur la page Standard }
end;
TMetaClass classes[2] =
{__classid(TNewComponent), __classid(TAnotherComponent)};
//Une autre manière d'ajouter un composant au tableau
TMetaClass classes[2];
classes[0] = __classid(TNewComponent);
classes[1] = __classid(TAnotherComponent);

3.2.1.10.27 Spécification de la catégorie de palette


Le nom de la catégorie de palette est une chaîne. Si le nom que vous donnez pour la catégorie de palette n'existe pas, Delphi
crée une nouvelle catégorie avec ce nom. Delphi stocke les noms des catégories standard dans des ressources liste de chaînes
afin que les versions internationales du produit puissent nommer les catégories dans leur langue. Si vous voulez installer un
composant dans l'une des catégories standard, vous obtiendrez la chaîne du nom de cette catégorie en appelant la fonction
LoadStr et en transmettant la constante représentant la ressource chaîne de cette catégorie (par exemple srSystem pour la
catégorie Système).

3.2.1.10.28 Problèmes d'installation de composants personnalisés (C++)


Un problème courant lors du recensement et de l'installation de composants personnalisés est l'absence du composant dans la
liste des composants après l'installation correcte du paquet.

Voici les causes les plus courantes de l'absence des composants dans la liste des composants ou sur la palette :

• Modificateur de macro PACKAGE sur la fonction Register manquant.


• Modificateur de macro PACKAGE sur la classe manquant
• Absence de #pragma package(smart_init) dans le fichier source C++.
• Fonction Register non trouvée dans un espace de nommage de même nom que le module code source.
• Register n'est pas correctement exportée. Utilisez tdump sur le fichier .BPL pour rechercher la fonction exportée :
tdump -ebpl mypack.bpl mypack.dmp
Dans la section exports du dump, vous devriez voir la fonction Register (dans l'espace de nommage) exportée.

3.2.1.10.29 Utilisation de la fonction IsPropertyInCategory


Une application peut rechercher les propriétés recensées existantes afin de déterminer si une propriété donnée est toujours
recensée dans une catégorie indiquée. Ceci peut être particulièrement utile dans des situations telles qu'un utilitaire de 3
localisation qui vérifie la catégorisation des propriétés afin de préparer ses opérations de localisation. Deux variations
surchargées de la fonction IsPropertyInCategory sont disponibles, autorisant différents critères afin de déterminer si une
propriété se trouve dans une catégorie.

La première variation vous permet de baser le critère de comparaison sur une combinaison du type de classe du composant
propriétaire et du nom de la propriété. Dans la ligne de commande ci-après, pour que IsPropertyInCategory renvoie True, la
propriété doit appartenir à un descendant de TCustomEdit, avoir le nom "Text", et se trouver dans la catégorie de propriétés
’Localizable'.

1373
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

IsItThere := IsPropertyInCategory('Localizable', TCustomEdit, 'Text');


IsItThere = IsPropertyInCategory("Localizable", __classid(TCustomEdit), "Text");
La deuxième variation vous permet de baser le critère de comparaison sur une combinaison du nom de classe du composant
propriétaire et du nom de la propriété. Dans la ligne de commande ci-après, pour que IsPropertyInCategory renvoie True, la
propriété doit appartenir à un descendant de TCustomEdit, avoir le nom "Text", et se trouver dans la catégorie de propriétés
’Localizable'.
IsItThere := IsPropertyInCategory('Localizable', 'TCustomEdit', 'Text');
IsItThere = IsPropertyInCategory("Localizable", "TCustomEdit", "Text");

3.2.1.10.30 Utilisation de la fonction RegisterComponents


Dans la procédure Register, appelez RegisterComponents pour recenser les composants dans le tableau des classes.
RegisterComponents est une fonction qui présente deux paramètres : le nom d'une catégorie de la palette d'outils et le tableau
des classes de composants.

Donnez au paramètre Page le nom de la catégorie de la palette d'outils où doivent se placer les composants. Si la catégorie
nommée existe déjà, les composants y sont ajoutés. Si elle n'existe pas, Delphi crée une nouvelle catégorie sur la palette ayant
ce nom.

Appelez RegisterComponents depuis l'implémentation de la routine Register dans une des unités définissant les composants
personnalisés. Les unités définissant les composants doivent alors être compilées en un package et ce dernier doit être installé
avant l'ajout des composants personnalisés à la palette d'outils.
procedure Register;
begin
RegisterComponents('System', [TSystem1, TSystem2]); {ajouter à la
catégorie Système}
RegisterComponents('MyCustomPage',[TCustom1, TCustom2]); { nouvelle
catégorie}
end;
namespace Newcomp
{
void __fastcall PACKAGE Register()
{
TMetaClass classes[1] = {__classid(TMyComponent)};
RegisterComponents("Divers", classes, 0);
}
}
namespace Mycomps
{
void __fastcall PACKAGE Register()
{
// déclare un tableau contenant deux composants
TMetaClass* classes1[2] = {__classid(TFirst), __classid(TSecond)};
// ajoute une nouvelle page à la palette avec les deux composants du tableau classes1
RegisterComponents("Divers", classes1, 1);
// déclare un second tableau
TMetaClass classes2[1];
// Affecte un composant comme premier élément de ce tableau
classes2[0] = __classid(TThird);
// ajoute le composant du tableau classes2 à la page Exemples
3 RegisterComponents("Exemples", classes2, 0);
}
}

3.2.1.10.31 Ecriture de la procédure Register


Dans la procédure Register d'une unité contenant des composants, vous devez recenser chaque composant que vous voulez
ajouter à la palette d'outils. Si l'unité contient plusieurs composants, vous pouvez les recenser en une seule fois.

1374
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Pour recenser un composant, appelez la procédure RegisterComponents pour chacune des catégories de la palette d'outils
auxquelles vous souhaitez ajouter des composants. RegisterComponents nécessite trois informations importantes :

1. Spécification des composants. ( see page 1372)


2. Spécification de la page de palette. ( see page 1373)
3. Utilisation de la fonction RegisterComponents ( see page 1374).

3.2.1.11 Transformation d'une boîte de dialogue en composant


Rubriques
Nom Description
Ajout des propriétés de l'interface ( see page 1376) Avant de poursuivre, vous devez déterminer les propriétés de votre composant
enveloppe nécessaires pour permettre aux développeurs d'utiliser votre boîte de
dialogue en tant que composant dans leurs applications. Puis, ajoutez les
déclarations de ces propriétés à la déclaration de classe du composant.
Les propriétés d'un composant enveloppe sont sensiblement plus simples à
écrire que celles d'un composant standard. Souvenez-vous que vous ne faites
que créer des données permanentes que l'enveloppe et la boîte de dialogue
peuvent échanger. En définissant ces données sous la forme de propriétés, vous
donnez aux développeurs la possibilité de définir des données au moment de...
suite ( see page 1376)
Ajout de la méthode Execute ( see page 1376) Il vous reste à définir dans l'interface du composant les moyens d'ouvrir la boîte
de dialogue et de récupérer un résultat lorsqu'elle se ferme. Comme pour les
composants des boîtes de dialogue standard, vous utiliserez une fonction
booléenne appelée Execute qui renvoie True si l'utilisateur clique sur OK, ou
False s'il annule la boîte de dialogue.
La déclaration de la méthode Execute ressemble toujours à ceci :
Création et recensement du composant ( see page 1377) La création d'un composant débute toujours de la même façon. vous créez une
unité et vous recensez le composant avant de l'installer dans la palette d'outils.
Ce processus est décrit dans Création d'un nouveau composant ( see page
1330).
Pour notre exemple, suivez la procédure générale de création d'un composant
en tenant compte des spécificités suivantes :

• Nommez l'unité du composant AboutDlg.


• Dérivez un nouveau type de composant appelé
TAboutBoxDlg, descendant de TComponent.
• Recensez TAboutBoxDlg dans la catégorie Exemples de
la palette d'outils.
L'unité que vous obtenez doit ressembler à ceci :
Création de l'interface du composant ( see page 1378) Voici les étapes nécessaires à la création de l'interface du composant :

1. Inclusion des fichiers de l'unité de la fiche ( see page


1378).
2. Ajout des propriétés de l'interface ( see page 1376).
3. Ajout de la méthode Execute ( see page 1376).
Définition de l'interface du composant ( see page 1378) Avant de créer le composant pour votre boîte de dialogue, vous devez décider
de la façon dont il sera utilisé par les développeurs. Vous devez créer une
interface entre votre boîte de dialogue et les applications qui l'utilisent. 3
Par exemple, considérons les propriétés des composants associés aux boîtes de
dialogue standard. Elles autorisent le développeur à définir l'état initial de la boîte
de dialogue, tel que le titre ou le paramétrage initial des contrôles, et renvoient
toutes les informations nécessaires lorsque la boîte de dialogue se ferme. Les
seules interactions directes ne se produisent qu'avec les propriétés du
composant enveloppe... suite ( see page 1378)
Inclusion de l'unité de la fiche ( see page 1378) Pour que votre composant enveloppe puisse initialiser et afficher la boîte de
dialogue enveloppée, vous devez ajouter les fichiers de l'unité de la fiche dans la
clause uses de l'unité du composant enveloppe.
Ajoutez About à la clause uses de l'unité AboutDlg.
La clause uses ressemble maintenant à ceci :

1375
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Transformation d'une boîte de dialogue en composant : Vue globale ( see page Il est pratique de transformer une boîte de dialogue fréquemment sollicitée en un
1379) composant que vous pourrez ajouter dans la palette d'outils. Ainsi, vos
composants boîte de dialogue fonctionneront exactement comme ceux des
boîtes de dialogue standard. L'objectif ici est de créer un composant simple qu'un
utilisateur peut ajouter à un projet et dont il peut définir les propriétés lors de la
conception.
La transformation d'une boîte de dialogue en composant nécessite les étapes
suivantes :

1. Définition de l'interface du composant ( see page 1378)


2. Création et recensement du composant ( see page
1377)
3. Création de l'interface du composant ( see page 1378)
4. Test du composant ( see page 1379)
A l'exécution, le composant "enveloppe" de Delphi,... suite (
see page 1379)
Test du composant ( see page 1379) Une fois le composant boîte de dialogue installé, vous pouvez l'utiliser comme
n'importe quelle autre boîte de dialogue commune, en le plaçant sur une fiche et
en l'exécutant. Un moyen rapide de vérifier le fonctionnement de la boîte A
propos de consiste à ajouter un bouton de commande dans une fiche et à
exécuter la boîte de dialogue lorsque l'utilisateur clique sur ce bouton.

3.2.1.11.1 Ajout des propriétés de l'interface


Avant de poursuivre, vous devez déterminer les propriétés de votre composant enveloppe nécessaires pour permettre aux
développeurs d'utiliser votre boîte de dialogue en tant que composant dans leurs applications. Puis, ajoutez les déclarations de
ces propriétés à la déclaration de classe du composant.

Les propriétés d'un composant enveloppe sont sensiblement plus simples à écrire que celles d'un composant standard.
Souvenez-vous que vous ne faites que créer des données permanentes que l'enveloppe et la boîte de dialogue peuvent
échanger. En définissant ces données sous la forme de propriétés, vous donnez aux développeurs la possibilité de définir des
données au moment de la conception qui, lors de l'exécution, seront transmises par l'enveloppe à la boîte de dialogue.

La déclaration d'une propriété d'interface nécessite deux ajouts à la déclaration de classe du composant :

• Un champ de classe privé qui est une variable utilisée par l'enveloppe pour stocker la valeur de la propriété.
• La déclaration published de la propriété elle-même qui indique son nom et le champ à utiliser pour le stockage.
De telles propriétés d'interface n'ont pas besoin de méthodes d'accès. Elles accèdent directement aux données stockées. Par
convention, le champ qui stocke la valeur de la propriété porte le même nom que la propriété, mais précédé de la lettre F. Le
champ et la propriété doivent avoir le même type.

3.2.1.11.2 Ajout de la méthode Execute


Il vous reste à définir dans l'interface du composant les moyens d'ouvrir la boîte de dialogue et de récupérer un résultat
lorsqu'elle se ferme. Comme pour les composants des boîtes de dialogue standard, vous utiliserez une fonction booléenne
appelée Execute qui renvoie True si l'utilisateur clique sur OK, ou False s'il annule la boîte de dialogue.

3 La déclaration de la méthode Execute ressemble toujours à ceci :


type
TMyWrapper = class(TComponent)
public
function Execute: Boolean;
end;
class PACKAGE TMyWrapper : public TComponent
{
.
.

1376
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

.
public:
bool __fastcall Execute();
.
.
.
};
L'implémentation minimale de la méthode Execute doit construire la fiche de la boîte de dialogue, puis afficher celle-ci en tant
que boîte de dialogue modale avant de renvoyer True ou False, selon la valeur renvoyée par ShowModal.

3.2.1.11.3 Création et recensement du composant


La création d'un composant débute toujours de la même façon. vous créez une unité et vous recensez le composant avant de
l'installer dans la palette d'outils. Ce processus est décrit dans Création d'un nouveau composant ( see page 1330).

Pour notre exemple, suivez la procédure générale de création d'un composant en tenant compte des spécificités suivantes :

• Nommez l'unité du composant AboutDlg.


• Dérivez un nouveau type de composant appelé TAboutBoxDlg, descendant de TComponent.
• Recensez TAboutBoxDlg dans la catégorie Exemples de la palette d'outils.
L'unité que vous obtenez doit ressembler à ceci :
unit AboutDlg;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms;
type
TAboutBoxDlg = class(TComponent)
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Exemples', [TAboutBoxDlg]);
end;
end.
#include <vcl\vcl.h>
#pragma hdrstop
#include "AboutDlg.h"
//---------------------------------------------------------------------------
#pragma package(smart_init);
//---------------------------------------------------------------------------
static inline TAboutBoxDlg *ValidCtrCheck()
{
return new TAboutBoxDlg(NULL);
}
//---------------------------------------------------------------------------
namespace AboutDlg {
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TAboutBoxDlg)}; 3
RegisterComponents("Exemples", classes, 0);
}
}
#ifndef AboutDlgH
#define AboutDlgH
//---------------------------------------------------------------------------
#include <vcl\sysutils.hpp>
#include <vcl\controls.hpp>
#include <vcl\classes.hpp>
#include <vcl\forms.hpp>

1377
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

//---------------------------------------------------------------------------
class PACKAGE TAboutBoxDlg : public TComponent
{
private:
protected:
public:
__published:
};
//---------------------------------------------------------------------------
#endif
Pour l'instant, le nouveau composant possède uniquement les fonctionnalités intégrées à TComponent. C'est le composant non
visuel le plus simple. Dans la section suivante ( see page 1378), vous allez créer l'interface entre le composant et la boîte de
dialogue.

3.2.1.11.4 Création de l'interface du composant


Voici les étapes nécessaires à la création de l'interface du composant :

1. Inclusion des fichiers de l'unité de la fiche ( see page 1378).


2. Ajout des propriétés de l'interface ( see page 1376).
3. Ajout de la méthode Execute ( see page 1376).

3.2.1.11.5 Définition de l'interface du composant


Avant de créer le composant pour votre boîte de dialogue, vous devez décider de la façon dont il sera utilisé par les
développeurs. Vous devez créer une interface entre votre boîte de dialogue et les applications qui l'utilisent.

Par exemple, considérons les propriétés des composants associés aux boîtes de dialogue standard. Elles autorisent le
développeur à définir l'état initial de la boîte de dialogue, tel que le titre ou le paramétrage initial des contrôles, et renvoient
toutes les informations nécessaires lorsque la boîte de dialogue se ferme. Les seules interactions directes ne se produisent
qu'avec les propriétés du composant enveloppe et pas avec les contrôles individuels de la boîte de dialogue.

L'interface doit donc contenir suffisamment d'informations pour que la fiche boîte de dialogue s'affiche selon les indications du
développeur et qu'elle renvoie les informations nécessaires à l'application. Les propriétés du composant enveloppe peuvent être
vues comme les données permanentes d'une boîte de dialogue transitoire.

Dans le cas de votre boîte A propos de, aucune information n'est renvoyée. Les propriétés de l'enveloppe contiennent donc
uniquement les informations nécessaires pour afficher correctement la boîte A propos de. Puisqu'il y a quatre champs distincts
dans cette boîte sur lesquels l'application peut agir, il vous faut fournir quatre propriétés de type chaîne pour les paramétrer.

3.2.1.11.6 Inclusion de l'unité de la fiche


Pour que votre composant enveloppe puisse initialiser et afficher la boîte de dialogue enveloppée, vous devez ajouter les
fichiers de l'unité de la fiche dans la clause uses de l'unité du composant enveloppe.

3 Ajoutez About à la clause uses de l'unité AboutDlg.

La clause uses ressemble maintenant à ceci :


uses
Windows, SysUtils, Messages, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms,
About;
// pour C++
#include "About.h"
#pragma link "About.obj"

1378
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

L'unité fiche déclare toujours une instance de la classe de la fiche. Dans le cas de la boîte A propos de, la classe de la fiche est
TAboutBox, et l'unité About doit inclure la déclaration suivante :
var
AboutBox: TAboutBox;
extern TAboutBox *AboutBox;
Ainsi en ajoutant About à la clause uses, vous rendez disponible AboutBox au composant enveloppe.

3.2.1.11.7 Transformation d'une boîte de dialogue en composant : Vue globale


Il est pratique de transformer une boîte de dialogue fréquemment sollicitée en un composant que vous pourrez ajouter dans la
palette d'outils. Ainsi, vos composants boîte de dialogue fonctionneront exactement comme ceux des boîtes de dialogue
standard. L'objectif ici est de créer un composant simple qu'un utilisateur peut ajouter à un projet et dont il peut définir les
propriétés lors de la conception.

La transformation d'une boîte de dialogue en composant nécessite les étapes suivantes :

1. Définition de l'interface du composant ( see page 1378)


2. Création et recensement du composant ( see page 1377)
3. Création de l'interface du composant ( see page 1378)
4. Test du composant ( see page 1379)
A l'exécution, le composant "enveloppe" de Delphi, associé à la boîte de dialogue crée et exécute celle-ci en lui transmettant les
données spécifiées par l'utilisateur. Le composant boîte de dialogue est donc à la fois réutilisable et personnalisable.
Dans cette section, vous allez voir comment créer un composant enveloppe autour de la fiche générique A propos de...
disponible dans le référentiel d'objets de Delphi.
Remarque: Copiez les fichiers ABOUT.PAS et ABOUT.DFM dans votre répertoire de travail.
Il n'y a pas grand chose à dire concernant la conception de la boîte de dialogue enveloppée par un composant. Dans un tel
contexte, n'importe quelle fiche peut fonctionner comme une boîte de dialogue.

3.2.1.11.8 Test du composant


Une fois le composant boîte de dialogue installé, vous pouvez l'utiliser comme n'importe quelle autre boîte de dialogue
commune, en le plaçant sur une fiche et en l'exécutant. Un moyen rapide de vérifier le fonctionnement de la boîte A propos de
consiste à ajouter un bouton de commande dans une fiche et à exécuter la boîte de dialogue lorsque l'utilisateur clique sur ce
bouton.

Par exemple, si vous avez créé une boîte de dialogue A propos de, et si vous l'avez ajouté à la palette d'outils, vous
pouvez tester son fonctionnement en suivant les étapes ci-dessous :
1. Créez un nouveau projet.
2. Placez un composant A propos de dans la fiche principale.
3. Placez un bouton de commande dans la fiche.
4. Double-cliquez sur le bouton de commande pour créer un gestionnaire d'événements vide. 3
5. Dans le gestionnaire d'événements, entrez la ligne de code suivante :
AboutBoxDlg1.Execute;
AboutBoxDlg1->Execute();
6. Exécutez l'application.
Lorsque la fiche principale apparaît, cliquez sur le bouton de commande. La boîte A propos de s'affiche avec l'icône projet par
défaut et Project1 comme titre. Choisissez OK pour fermer la boîte de dialogue.

1379
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Vous pouvez pousser plus loin le test du fonctionnement du composant en définissant les différentes propriétés du composant A
propos de et en exécutant une nouvelle fois l'application.

3.2.1.12 Modification d'un composant existant


Rubriques
Nom Description
Création et recensement du composant ( see page 1381) La création d'un composant se fait toujours de la même façon : vous créez une
unité, puis dérivez et recensez une classe composant avant de l'installer dans la
palette d'outils. Ce processus est décrit dans Création d'un nouveau composant
( see page 1330).
Pour notre exemple, suivez la procédure générale de création d'un composant
en tenant compte des spécificités suivantes :

• Nommez l'unité du composant Memos.


• Dérivez un nouveau type de composant appelé
TWrapMemo, descendant de TMemo.
• Recensez TWrapMemo dans la catégorie Exemples de la
palette d'outils.
• L'unité que vous obtenez doit ressembler à ceci :
Modification d'un composant existant : Vue globale ( see page 1382) Le moyen le plus simple de créer un composant consiste à le dériver d'un
composant qui réalise la presque totalité des fonctions souhaitées et lui apporter
ensuite quelques modifications. L'exemple de ce chapitre modifie le composant
mémo standard pour créer un mémo qui ne fait pas de saut de ligne par défaut.
La valeur de la propriété WordWrap du composant mémo est initialisée à True.
Si vous utilisez fréquemment des mémos n'effectuant pas de saut de ligne, vous
pouvez créer un nouveau composant mémo qui ne fait pas de saut de ligne par
défaut.
Remarque: Pour modifier les propriétés... suite ( see page 1382)
Modification de l'objet composant ( see page 1382) Une fois la nouvelle classe composant créée, vous pouvez lui apporter presque
toutes les modifications que vous voulez. Dans notre exemple, vous allez
changer la valeur par défaut d'une propriété du composant mémo. Cela implique
deux changements mineurs dans la classe composant :

• Redéfinition du constructeur
• Spécification de la nouvelle valeur par défaut de la
propriété
Le constructeur définit la valeur de la propriété. La valeur par
défaut indique à Delphi quelles valeurs stocker dans le
fichier fiche (.dfm pour les applications VCL). Delphi ne
stocke que les valeurs qui diffèrent de la valeur par
défaut, c'est pourquoi il est important... suite ( see page
1382)
Redéfinition du constructeur ( see page 1382) Lorsque vous placez un composant dans une fiche au moment de la conception
ou lorsqu'une application en cours d'exécution construit un composant, le
constructeur du composant définit les valeurs des propriétés. Quand un
composant est chargé depuis un fichier fiche, l'application définit toutes les
propriétés qui ont été modifiées lors de la conception.
Remarque: Lorsque vous redéfinissez un constructeur, le nouveau constructeur
doit appeler le constructeur reçu en héritage avant toute autre action. Pour plus
3 d'informations, voir Redéfinition des méthodes ( see page 1393).
Dans notre exemple, votre nouveau composant doit redéfinir le constructeur
transmis en héritage par TMemo en attribuant la valeur... suite ( see page
1382)

1380
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Spécification de la nouvelle valeur par défaut de la propriété ( see page 1383) Lorsque Delphi stocke la description d'une fiche dans un fichier fiche, il ne stocke
que les valeurs des propriétés différentes des valeurs par défaut. La taille du
fichier fiche reste minime et le chargement est plus rapide. Si vous créez une
propriété ou si vous changez la valeur par défaut d'une propriété existante, c'est
une bonne idée de mettre à jour la déclaration de la propriété en y incluant la
nouvelle valeur par défaut. Les fichiers fiche ainsi que le chargement et les
valeurs par défaut sont expliqués en détail dans Accessibilité des composants au
moment de la conception ( see page 1367).... suite ( see page 1383)

3.2.1.12.1 Création et recensement du composant


La création d'un composant se fait toujours de la même façon : vous créez une unité, puis dérivez et recensez une classe
composant avant de l'installer dans la palette d'outils. Ce processus est décrit dans Création d'un nouveau composant ( see
page 1330).

Pour notre exemple, suivez la procédure générale de création d'un composant en tenant compte des spécificités suivantes :

• Nommez l'unité du composant Memos.


• Dérivez un nouveau type de composant appelé TWrapMemo, descendant de TMemo.
• Recensez TWrapMemo dans la catégorie Exemples de la palette d'outils.
• L'unité que vous obtenez doit ressembler à ceci :
unit Memos;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, StdCtrls;
type
TWrapMemo = class(TMemo)
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Exemples', [TWrapMemo]);
end;
end.
#include <vcl.h>
#pragma hdrstop
#include "Yelmemo.h"
//---------------------------------------------------------------------------
#pragma package(smart_init);
//---------------------------------------------------------------------------
// ValidCtrCheck permet de vérifier que les composants créés ne comportent pas
// de fonctions virtuelles pures.
//
static inline void ValidCtrCheck(TYellowMemo *)
{
new TYellowMemo(NULL);
}
//---------------------------------------------------------------------------
__fastcall TYellowMemo::TYellowMemo(TComponent* Owner)
: TMemo(Owner)
{ 3
}
//---------------------------------------------------------------------------
namespace Yelmemo
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TYellowMemo)};
RegisterComponents("Samples", classes, 0); //"Contrôles courants" dans les applications CLX
}

1381
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

}
#ifndef YelMemoH
#define YelmemoH
//---------------------------------------------------------------------------
#include <sysutils.hpp>
#include <controls.hpp>
#include <classes.hpp>
#include <forms.hpp>
#include <StdCtrls.hpp>
//---------------------------------------------------------------------------
class PACKAGE TYellowMemo : public TMemo
{
private:
protected:
public:
__published:
};
//---------------------------------------------------------------------------
#endif
Si vous compilez et installez maintenant le nouveau composant, il se comportera exactement comme son ancêtre, TMemo.
Dans la section suivante, vous effectuerez une simple modification à votre composant.

3.2.1.12.2 Modification d'un composant existant : Vue globale


Le moyen le plus simple de créer un composant consiste à le dériver d'un composant qui réalise la presque totalité des fonctions
souhaitées et lui apporter ensuite quelques modifications. L'exemple de ce chapitre modifie le composant mémo standard pour
créer un mémo qui ne fait pas de saut de ligne par défaut.

La valeur de la propriété WordWrap du composant mémo est initialisée à True. Si vous utilisez fréquemment des mémos
n'effectuant pas de saut de ligne, vous pouvez créer un nouveau composant mémo qui ne fait pas de saut de ligne par défaut.

Remarque: Pour modifier les propriétés publiées ou enregistrer des gestionnaires d'événements spécifiques pour un
composant existant, il est souvent plus simple d'utiliser un modèle de composant plutôt que de créer une classe.

La modification d'un composant existant se fait en deux étapes :

• Création et recensement du composant ( see page 1381).


• Modification de la classe composant ( see page 1382).

3.2.1.12.3 Modification de l'objet composant


Une fois la nouvelle classe composant créée, vous pouvez lui apporter presque toutes les modifications que vous voulez. Dans
notre exemple, vous allez changer la valeur par défaut d'une propriété du composant mémo. Cela implique deux changements
mineurs dans la classe composant :

• Redéfinition du constructeur
• Spécification de la nouvelle valeur par défaut de la propriété
Le constructeur définit la valeur de la propriété. La valeur par défaut indique à Delphi quelles valeurs stocker dans le fichier fiche
3 (.dfm pour les applications VCL). Delphi ne stocke que les valeurs qui diffèrent de la valeur par défaut, c'est pourquoi il est
important d'effectuer les deux étapes.

3.2.1.12.4 Redéfinition du constructeur


Lorsque vous placez un composant dans une fiche au moment de la conception ou lorsqu'une application en cours d'exécution
construit un composant, le constructeur du composant définit les valeurs des propriétés. Quand un composant est chargé depuis
un fichier fiche, l'application définit toutes les propriétés qui ont été modifiées lors de la conception.

1382
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Remarque: Lorsque vous redéfinissez un constructeur, le nouveau constructeur doit appeler le constructeur reçu en héritage
avant toute autre action. Pour plus d'informations, voir Redéfinition des méthodes ( see page 1393).

Dans notre exemple, votre nouveau composant doit redéfinir le constructeur transmis en héritage par TMemo en attribuant la
valeur False à la propriété WordWrap. Pour ce faire, ajoutez le constructeur redéfini à la prédéclaration, puis écrivez le nouveau
constructeur dans la partie implementation de l'unité :
type
TWrapMemo = class(TMemo)
public { constructeurs toujours publics }
constructor Create(AOwner: TComponent); override; { cette syntaxe est toujours identique }
end;
.
.
.
constructor TWrapMemo.Create(AOwner: TComponent); { ceci va après l'implémentation }
begin
inherited Create(AOwner); { Faire TOUJOURS ceci en premier ! }
WordWrap := False; { définir la nouvelle valeur désirée }
end;
class PACKAGE TYellowMemo : public TMemo
{
public:
virtual __fastcall TYellowMemo(TComponent* Owner); // déclaration du constructeur
__published:
__property Color ;
};
__fastcall TYellowMemo::TYellowMemo(TComponent* Owner)
: TMemo(Owner) // l'implémentation du
constructeur... // ...commence par appeler le
constructeur pour TMemo
{
Color = clYellow; // colore le composant en jaune
}
Vous pouvez maintenant installer le nouveau composant dans la palette d'outils puis l'ajouter dans une fiche. Remarquez que la
propriété WordWrap est dorénavant initialisée à False.

Si vous changez une valeur de propriété initiale, vous devez aussi désigner cette valeur comme étant celle par défaut. Si vous
échouez à faire correspondre la valeur définie par le constructeur à celle spécifiée par défaut, Delphi ne peut pas stocker, ni
restaurer la valeur correcte.

3.2.1.12.5 Spécification de la nouvelle valeur par défaut de la propriété


Lorsque Delphi stocke la description d'une fiche dans un fichier fiche, il ne stocke que les valeurs des propriétés différentes des
valeurs par défaut. La taille du fichier fiche reste minime et le chargement est plus rapide. Si vous créez une propriété ou si vous
changez la valeur par défaut d'une propriété existante, c'est une bonne idée de mettre à jour la déclaration de la propriété en y
incluant la nouvelle valeur par défaut. Les fichiers fiche ainsi que le chargement et les valeurs par défaut sont expliqués en détail
dans Accessibilité des composants au moment de la conception ( see page 1367).

Pour changer la valeur par défaut d'une propriété, redéclarez le nom de la propriété, suivi de la directive default et de la
nouvelle valeur par défaut. Il n'est pas nécessaire de redéclarer la propriété entière mais uniquement le nom et la valeur par 3
défaut.

Pour le composant mémo de saut à la ligne automatique, redéclarez la propriété WordWrap dans la partie published de la
déclaration d'objet, avec la valeur False par défaut :
type
TWrapMemo = class(TMemo)
.
.

1383
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

.
published
property WordWrap default False;
end;
// fichier en-tête
class PACKAGE TYellowMemo : public TMemo
{
public:
virtual __fastcall TYellowMemo(TComponent* Owner);
__published:
__property Color = {default=clYellow};
};
// fichier d'implémentation
__fastcall TYellowMemo::TYellowMemo(TComponent* AOwner) : TMemo(AOwner)
{
Color = clYellow;
WordWrap = false;
}
//fichier en-tête avec WordWrap ayant false comme valeur par défaut :
class PACKAGE TYellowMemo : public TMemo
{
public:
virtual __fastcall TYellowMemo(TComponent* Owner);
__published:
__property Color = {default=clYellow};
__property WordWrap = {default=false};
};
Spécifier la valeur par défaut de la propriété n'affecte en rien le fonctionnement du composant. Vous devez toujours initialiser la
valeur dans le constructeur du composant. La redéclaration de la valeur par défaut assure que Delphi connaît quand WordWrap
doit être écrit dans le fichier fiche.

3.2.1.13 Programmation orientée objet et écriture des composants


Rubriques
Nom Description
Programmation orientée objet et écriture des composants : Vue globale ( see Si vous avez écrit des applications avec Delphi, vous savez déjà qu'une classe
page 1387) contient à la fois du texte et du code, et que les classes sont manipulables aussi
bien au moment de la conception qu'à l'exécution. C'est ainsi que vous êtes
devenu utilisateur de composants.
Lorsque vous créez de nouveaux composants, votre approche des classes n'est
pas celle du développeur d'applications standard. Vous essayez de cacher les
travaux internes du composant aux développeurs qui vont les utiliser. En
choisissant les ancêtres appropriés à vos composants, en concevant des
interfaces qui exposent seulement les propriétés et les méthodes dont les... suite
( see page 1387)
Définition de nouvelles classes ( see page 1388) La différence entre un concepteur de composants et un développeur
d'applications est la suivante : le concepteur de composants crée de nouvelles
classes et le développeur d'applications manipule les instances de ces classes.
Une classe est d'abord un type. Comme programmeur, vous travaillez sans arrêt
avec les types et les instances, même si vous ne parlez pas en ces termes. Par
exemple, vous créez des variables d'un certain type, par exemple Integer. Les
classes sont habituellement plus complexes que de simples types de données,
mais elles fonctionnent de la même façon. En affectant différentes valeurs aux
3 instances d'un même type,... suite ( see page 1388)

1384
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Dérivation de nouvelles classes ( see page 1388) Deux raisons peuvent vous amener à dériver une nouvelle classe :

• Modification des valeurs par défaut d'une classe pour


éviter les répétitions ( see page 1389)
• Ajout de nouvelles capacités à une classe ( see page
1388)
L'objectif est le même dans ces deux cas : créer des objets
réutilisables. Si vous concevez vos objets en ayant en tête
leur réutilisation, vous gagnerez un temps considérable.
Attribuez à vos classes des valeurs par défaut
exploitables mais rendez-les personnalisables.
Membres abstraits d'une classe ( see page 1388) Lorsqu'une méthode est déclarée abstract dans une classe ancêtre, vous devez
la surfacer (c'est-à-dire la redéclarer et l'implémenter) dans tout composant
descendant avant d'utiliser le nouveau composant dans les applications. Sur la
plate-forme Win32, Delphi peut créer des instances d'une classe contenant des
membres abstraits. Cela n'est toutefois pas recommandé, et n'est pas autorisé
sur la plate-forme .NET. Pour plus d'informations sur le surfaçage des
constituants hérités des classes, voir Création des propriétés ( see page 1258)
et Création de méthodes ( see page 1252).
Ajout de nouvelles capacités à une classe ( see page 1388) Une raison classique de créer de nouveaux composants est l'ajout de
fonctionnalités qui ne se trouvent pas dans les composants existants. Pour cela,
vous dérivez le nouveau composant à partir d'un composant existant ou à partir
d'une classe de base abstraite, comme TComponent ou TControl.
Dérivez votre nouveau composant à partir de la classe contenant le
sous-ensemble le plus proche des caractéristiques recherchées. Vous pouvez
ajouter des fonctionnalités à une classe, mais vous ne pouvez pas en soustraire.
Par conséquent, si une classe de composant contient des propriétés que vous
ne souhaitez pas inclure dans la vôtre, effectuez la... suite ( see page 1388)
Ancêtres, descendants et hiérarchies des classes ( see page 1389) Les développeurs d'applications peuvent se servir du fait que chaque contrôle a
des propriétés Top et Left qui déterminent son emplacement sur la fiche. Pour
eux, il importe peu que tous les contrôles aient hérité ces propriétés d'un ancêtre
commun, TControl. Mais, lorsque vous écrivez un composant, vous devez savoir
à partir de quelle classe vous le dérivez de façon à ce qu'il reçoive en héritage
les éléments que vous souhaitez. Vous devez également connaître toutes les
fonctionnalités dont hérite votre composant de manière à les exploiter sans avoir
à les recréer vous-même.
La classe à partir de laquelle... suite ( see page 1389)
Modification des valeurs par défaut d'une classe pour éviter les répétitions ( Dans tout programme, les répétitions superflues sont à proscrire. Si vous vous
see page 1389) surprenez à répéter les mêmes lignes de code, vous serez sans doute amené à
les placer à part dans une sous-routine ou fonction, ou encore à construire une
bibliothèque de routines utilisables par un autre programme. Le même
raisonnement s'applique aux composants. Si vous modifiez fréquemment les
mêmes propriétés ou si vous appelez les mêmes méthodes, vous créerez sans
doute un nouveau composant qui effectue ces tâches par défaut.
Par exemple, supposons qu'à chaque création d'une nouvelle application, vous
ajoutez une boîte de dialogue accomplissant une fonction déterminée.... suite (
see page 1389)
Contrôle des accès ( see page 1390) Il existe cinq niveaux de contrôle d'accès, également appelé visibilité, aux
propriétés, méthodes et champs. La visibilité détermine quel code peut accéder à
quelles parties de la classe. En spécifiant la visibilité, vous définissez l'interface
de vos composants.
Le tableau ci-dessous montre les niveaux de visibilité, en allant du plus restrictif
au plus accessible :
Niveaux de visibilité d'un objet
Déclaration d'une nouvelle classe de composant ( see page 1390) En plus des composants standard, Delphi fournit de nombreuses classes
abstraites conçues comme bases pour dériver de nouveaux composants. La
rubrique Comment créer un composant ( see page 1329) montre les classes
dont vous pouvez partir pour créer vos propres composants. 3
Pour déclarer une nouvelle classe de composant, ajoutez une déclaration de
classe au fichier unité du composant.

1385
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Définir l'interface de conception ( see page 1390) Déclarer published une partie d'une classe rend publique cette partie et génère
également les informations de types à l'exécution. Entre autres rôles, les
informations de types à l'exécution permettent à l'inspecteur d'objets d'accéder
aux propriétés et aux événements.
Parce qu'elles apparaissent dans l'inspecteur d'objets, les parties published
d'une classe définissent l'interface de conception de cette classe. L'interface de
conception doit inclure toutes les caractéristiques d'une classe qu'un
développeur d'applications peut vouloir personnaliser au moment de la
conception, tout en excluant toutes les propriétés qui dépendent d'une
information spécifique issue de l'environnement d'exécution.
Les propriétés accessibles en lecture uniquement ne peuvent... suite ( see
page 1390)
Définir l'interface avec le concepteur des composants ( see page 1391) Déclarer protected une partie d'une classe rend cette partie uniquement visible
par cette classe et par ses descendants (et par les autres classes qui partagent
leurs fichiers unité).
Vous pouvez utiliser les déclarations protected pour définir l'interface de
conception des composants d'une classe. Les unités de l'application ne peuvent
pas accéder aux parties protected, mais les classes dérivées le peuvent. Cela
signifie que les concepteurs des composants peuvent modifier la façon dont
fonctionne une classe sans rendre apparents ces détails aux développeurs
d'applications.
Remarque: Une erreur commune consiste à essayer d'accéder aux méthodes
protégées d'un gestionnaire d'événement. Les gestionnaires... suite ( see page
1391)
Définir l'interface d'exécution ( see page 1391) Déclarer public une partie d'une classe rend cette partie visible par tout code qui
dispose d'un accès global à cette classe.
Les parties publiques sont disponibles à l'ensemble du code lors de l'exécution,
et constituent par là même l'interface d'exécution. L'interface d'exécution sert aux
éléments qui sont sans signification ou inappropriés au moment de la
conception ; comme les propriétés contenant des informations uniquement
disponibles à l'exécution ou accessibles uniquement en lecture. Les méthodes
destinées à être appelées par les développeurs d'applications doivent également
être publiques.
Répartition des méthodes ( see page 1392) Le terme de Dispatch fait référence à la façon dont un programme détermine où
il doit rechercher une méthode de classe lorsqu'il rencontre un appel à cette
méthode. Le code qui appelle une méthode de classe ressemble à tout autre
appel de fonction. Mais les classes ont des façons différentes de répartir les
méthodes.
Les trois types de répartition de méthodes sont

• Statique
• Virtuel
• Dynamique
Méthodes dynamiques ( see page 1392) Les méthodes dynamiques sont des méthodes virtuelles avec un mécanisme de
répartition légèrement différent. Comme les méthodes dynamiques n'ont pas
d'entrées dans le tableau de méthode virtuelle de l'objet, elles peuvent réduire la
taille de la mémoire consommée par les objets. Cependant les méthodes de
répartition dynamiques sont quelque peu plus lentes que les méthodes de
répartition virtuelles normales. Si une méthode est fréquemment appelée, ou si
son exécution nécessite un temps court, vous devrez probablement la déclarer
virtuelle plutôt que dynamique.
Les objets doivent stocker les adresses de leurs méthodes dynamiques. Mais
plutôt que de recevoir les entrées dans... suite ( see page 1392)
Masquer les détails d'implémentation ( see page 1392) Déclarer private une partie d'une classe rend cette partie invisible au code situé
hors du fichier unité de la classe. Dans l'unité qui contient la déclaration, le code
peut accéder à cette partie comme si elle était publique.
Méthodes virtuelles ( see page 1392) Les méthodes virtuelles emploient un mécanisme de répartition plus compliqué
et plus souple que les méthodes statiques. Une méthode virtuelle peut être
3 redéfinie dans des classes descendantes, mais est toujours appelée dans la
classe ancêtre. L'adresse d'une méthode virtuelle n'est pas déterminée lors de la
compilation ; à la place, l'objet où la méthode est définie donne l'adresse lors de
l'exécution.
Pour qu'une méthode soit virtuelle, ajoutez la directive virtual après la
déclaration de la méthode. La directive virtual crée une entrée dans le tableau
de méthode virtuelle, de l'objet, ou VMT, qui contient les adresses de toutes les
méthodes... suite ( see page 1392)

1386
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Classes et pointeurs ( see page 1393) Chaque classe (et par conséquent chaque composant) est en fait un pointeur. Le
compilateur déréférence automatiquement les pointeurs de classe à votre place,
aussi n'avez-vous généralement pas besoin de vous poser ces questions. Le
statut des classes en tant que pointeurs devient important lorsque vous passez
une classe comme paramètre. En général, vous transmettrez les classes par
valeur plutôt que par référence. Car les classes sont déjà des pointeurs,
c'est-à-dire des références ; transmettre une classe par référence serait
transmettre une référence à une référence.
Redéfinition des méthodes ( see page 1393) Redéfinir une méthode signifie l'étendre ou la redéfinir plutôt que la remplacer.
Une classe descendante peut redéfinir toutes ses méthodes virtuelles héritées.
Pour redéfinir une méthode dans une classe descendante, ajoutez la directive
override à la fin de la déclaration de méthode.
La redéfinition d'une méthode provoque une erreur de compilation si

• La méthode n'existe pas dans la classe ancêtre.


• La méthode de l'ancêtre du même nom est statique.
• Les déclarations ne sont pas identiques (le numéro et le
type des paramètres arguments diffèrent).
Méthodes standard (C++) ( see page 1393) Les méthodes d'une classe sont considérées comme standard (non virtuelles),
sauf si vous les déclarez virtual ou si elles redéfinissent une méthode virtual
d'une classe de base. Le compilateur peut déterminer l'adresse exacte d'un
membre de classe standard au moment de la compilation. Il s'agit de la liaison au
moment de la compilation.
Une méthode standard de classe de base est héritée par des classes dérivées.
Dans l'exemple ci-dessous, un objet de type Derived peut appeler la méthode
Regular() comme si c'était sa propre méthode. Déclarer dans une classe
dérivée une méthode ayant le même nom et les mêmes paramètres... suite (
see page 1393)
Méthodes statiques ( see page 1394) Toutes les méthodes sont statiques à moins que vous ne les déclariez
spécifiquement autrement. Les méthodes statiques fonctionnent comme des
procédures ou des fonctions normales. Le compilateur détermine l'adresse
exacte de la méthode et la lie au moment de la compilation.
Le premier avantage des méthodes statiques est qu'elles sont réparties très
rapidement. Comme le compilateur peut déterminer l'adresse exacte de la
méthode, il la lie directement. Les méthodes virtuelles et dynamiques, au
contraire, utilisent des moyens indirects pour donner l'adresse de leurs méthodes
lors de l'exécution, ce qui prend davantage de temps.
Une méthode statique ne change pas lorsqu'elle... suite ( see page 1394)

3.2.1.13.1 Programmation orientée objet et écriture des composants : Vue


globale
Si vous avez écrit des applications avec Delphi, vous savez déjà qu'une classe contient à la fois du texte et du code, et que les
classes sont manipulables aussi bien au moment de la conception qu'à l'exécution. C'est ainsi que vous êtes devenu utilisateur
de composants.

Lorsque vous créez de nouveaux composants, votre approche des classes n'est pas celle du développeur d'applications
standard. Vous essayez de cacher les travaux internes du composant aux développeurs qui vont les utiliser. En choisissant les
ancêtres appropriés à vos composants, en concevant des interfaces qui exposent seulement les propriétés et les méthodes dont
les développeurs ont besoin, en suivant les autres conseils des rubriques suivantes, vous pourrez créer des composants
réutilisables parfaitement maniables.

Avant de commencer à créer des composants, vous devez comprendre les sujets suivants qui se rapportent à la programmation
3
orientée objet (OOP) :

• Définition de nouvelles classes ( see page 1388)


• Ancêtres ( see page 1389)
• Contrôle des accès ( see page 1390)
• Répartition des méthodes ( see page 1392)
• Membres abstraits d'une classe ( see page 1388)

1387
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

• Classes et pointeurs ( see page 1393)

3.2.1.13.2 Définition de nouvelles classes


La différence entre un concepteur de composants et un développeur d'applications est la suivante : le concepteur de
composants crée de nouvelles classes et le développeur d'applications manipule les instances de ces classes.

Une classe est d'abord un type. Comme programmeur, vous travaillez sans arrêt avec les types et les instances, même si vous
ne parlez pas en ces termes. Par exemple, vous créez des variables d'un certain type, par exemple Integer. Les classes sont
habituellement plus complexes que de simples types de données, mais elles fonctionnent de la même façon. En affectant
différentes valeurs aux instances d'un même type, vous effectuez différentes tâches.

Par exemple, il est courant de créer une fiche contenant deux boutons appelés OK et Annuler. Chacun correspond à une
instance de la classe TButton, mais, en attribuant une valeur différente à leurs propriétés Caption et différents gestionnaires à
leurs événements OnClick, vous faites se comporter différemment les deux instances.

Voir aussi
Dérivation de nouveaux types ( see page 1388)

Déclaration d'un nouveau type de composant ( see page 1390)

3.2.1.13.3 Dérivation de nouvelles classes


Deux raisons peuvent vous amener à dériver une nouvelle classe :

• Modification des valeurs par défaut d'une classe pour éviter les répétitions ( see page 1389)
• Ajout de nouvelles capacités à une classe ( see page 1388)
L'objectif est le même dans ces deux cas : créer des objets réutilisables. Si vous concevez vos objets en ayant en tête leur
réutilisation, vous gagnerez un temps considérable. Attribuez à vos classes des valeurs par défaut exploitables mais
rendez-les personnalisables.

3.2.1.13.4 Membres abstraits d'une classe


Lorsqu'une méthode est déclarée abstract dans une classe ancêtre, vous devez la surfacer (c'est-à-dire la redéclarer et
l'implémenter) dans tout composant descendant avant d'utiliser le nouveau composant dans les applications. Sur la plate-forme
Win32, Delphi peut créer des instances d'une classe contenant des membres abstraits. Cela n'est toutefois pas recommandé, et
n'est pas autorisé sur la plate-forme .NET. Pour plus d'informations sur le surfaçage des constituants hérités des classes, voir
Création des propriétés ( see page 1258) et Création de méthodes ( see page 1252).

3.2.1.13.5 Ajout de nouvelles capacités à une classe


Une raison classique de créer de nouveaux composants est l'ajout de fonctionnalités qui ne se trouvent pas dans les
composants existants. Pour cela, vous dérivez le nouveau composant à partir d'un composant existant ou à partir d'une classe
3 de base abstraite, comme TComponent ou TControl.

Dérivez votre nouveau composant à partir de la classe contenant le sous-ensemble le plus proche des caractéristiques
recherchées. Vous pouvez ajouter des fonctionnalités à une classe, mais vous ne pouvez pas en soustraire. Par conséquent, si
une classe de composant contient des propriétés que vous ne souhaitez pas inclure dans la vôtre, effectuez la dérivation à partir
de l'ancêtre de ce composant.

Par exemple, pour ajouter des fonctionnalités à une boîte liste, vous devez dériver un nouveau composant à partir de TListBox.
Mais, si vous souhaitez ajouter de nouvelles fonctionnalités et exclure certaines de celles des boîtes liste standard, il vous faut

1388
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

dériver votre boîte liste de l'ancêtre de TListBox, TCustomListBox. Recréez (ou rendez visibles) les fonctionnalités de la boîte
liste que vous voulez, puis ajoutez vos propres fonctionnalités.

Personnalisation d'une grille ( see page 1275) montre un exemple qui personnalise une classe abstraite de composant.

3.2.1.13.6 Ancêtres, descendants et hiérarchies des classes


Les développeurs d'applications peuvent se servir du fait que chaque contrôle a des propriétés Top et Left qui déterminent son
emplacement sur la fiche. Pour eux, il importe peu que tous les contrôles aient hérité ces propriétés d'un ancêtre commun,
TControl. Mais, lorsque vous écrivez un composant, vous devez savoir à partir de quelle classe vous le dérivez de façon à ce
qu'il reçoive en héritage les éléments que vous souhaitez. Vous devez également connaître toutes les fonctionnalités dont hérite
votre composant de manière à les exploiter sans avoir à les recréer vous-même.

La classe à partir de laquelle vous effectuez la dérivation est l'ancêtre immédiat. Chaque composant hérite de son ancêtre
immédiat, et lui-même de son ancêtre immédiat. Toutes les classes dont hérite un composant sont les ancêtres de ce
composant ; le composant est un descendant de ses ancêtres.

L'ensemble des relations ancêtre-descendant de l'application constitue les hiérarchies des classes. Dans cette hiérarchie,
chaque génération contient plus que ses ancêtres puisqu'une classe hérite de tout ce que contiennent ses ancêtres et ajoute de
nouvelles propriétés et de nouvelles méthodes, ou redéfinit celles qui existent.

Si vous ne spécifiez aucun ancêtre immédiat, Delphi dérive votre composant à partir de l'ancêtre par défaut, TObject. TObject
est le dernier ancêtre de toutes les classes de la hiérarchie d'objets.

La règle générale du choix de l'objet de départ de la dérivation est simple : Prenez l'objet qui contient le plus possible ce que
vous voulez inclure dans votre nouvel objet, mais qui ne comprend rien de ce que vous ne voulez pas dans le nouvel objet. Vous
pouvez toujours ajouter des choses à vos objets, mais vous ne pouvez pas en retirer.

3.2.1.13.7 Modification des valeurs par défaut d'une classe pour éviter les
répétitions
Dans tout programme, les répétitions superflues sont à proscrire. Si vous vous surprenez à répéter les mêmes lignes de code,
vous serez sans doute amené à les placer à part dans une sous-routine ou fonction, ou encore à construire une bibliothèque de
routines utilisables par un autre programme. Le même raisonnement s'applique aux composants. Si vous modifiez fréquemment
les mêmes propriétés ou si vous appelez les mêmes méthodes, vous créerez sans doute un nouveau composant qui effectue
ces tâches par défaut.

Par exemple, supposons qu'à chaque création d'une nouvelle application, vous ajoutez une boîte de dialogue accomplissant une
fonction déterminée. Bien qu'il soit simple de recréer à chaque fois cette boîte de dialogue, c'est superflu. Vous pouvez
concevoir la boîte de dialogue une fois pour toute, définir ses propriétés puis installer le composant enveloppe associé dans la
palette d'outils. En faisant du dialogue un composant réutilisable, non seulement vous éliminez une tâche répétitive mais
renforcez la standardisation et minimisez les erreurs qui peuvent être occasionnées par chaque nouvelle création de la boîte de
dialogue.

Modification d'un composant existant ( see page 1382) montre un exemple qui modifie les propriétés par défaut d'un
composant. 3
Remarque: Si vous voulez ne modifier que les propriétés publiées d'un composant existant ou enregistrer des gestionnaires
d'événement spécifiques à un composant ou à un groupe de composants, vous pourrez accomplir ceci plus facilement en créant
un modèle de composant.

1389
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.13.8 Contrôle des accès


Il existe cinq niveaux de contrôle d'accès, également appelé visibilité, aux propriétés, méthodes et champs. La visibilité
détermine quel code peut accéder à quelles parties de la classe. En spécifiant la visibilité, vous définissez l'interface de vos
composants.

Le tableau ci-dessous montre les niveaux de visibilité, en allant du plus restrictif au plus accessible :

Niveaux de visibilité d'un objet

Visibilité Signification Utilisation


private Accessible uniquement au code de l'unité où est définie Masquer les détails d'implémentation ( see page
la classe. 1392)
protected Accessible au code de ou des unités où sont définis la Définir l'interface avec le concepteur des composants
classe et ses descendants. ( see page 1391)
public Accessible à tout le code. Définir l'interface d'exécution ( see page 1391)
automated Accessible à tout le code. Les informations Automatisation OLE seulement.
d'automatisation sont générées.
published Accessible à tout le code et accessible depuis Définir l'interface de conception ( see page 1390)
l'inspecteur d'objets. Enregistré dans un fichier fiche.

Déclarez les membres en private si vous voulez qu'ils ne soient disponibles que dans la classe où ils ont été définis.
Déclarez-les en protected si vous voulez qu'ils ne soient disponibles que dans cette classe et ses descendants. Souvenez-vous
que si un membre est disponible n'importe où dans un fichier unité, il est disponible partout dans ce fichier. Ainsi, si vous
définissez deux classes dans la même unité, elles pourront accéder à l'une ou l'autre des méthodes privées. Et si vous dérivez
une classe dans une unité différente de son ancêtre, toutes les classes de la nouvelle unité pourront accéder aux méthodes
protégées de l'ancêtre.

Voir aussi
Masquer les détails d'implémentation ( see page 1392)

Définir l'interface avec le concepteur des composants ( see page 1391)

Définir l'interface d'exécution ( see page 1391)

Définir l'interface de conception ( see page 1390)

3.2.1.13.9 Déclaration d'une nouvelle classe de composant


En plus des composants standard, Delphi fournit de nombreuses classes abstraites conçues comme bases pour dériver de
nouveaux composants. La rubrique Comment créer un composant ( see page 1329) montre les classes dont vous pouvez
partir pour créer vos propres composants.

Pour déclarer une nouvelle classe de composant, ajoutez une déclaration de classe au fichier unité du composant.
3
Voir aussi
Dérivation de nouveaux types ( see page 1388)

3.2.1.13.10 Définir l'interface de conception


Déclarer published une partie d'une classe rend publique cette partie et génère également les informations de types à
l'exécution. Entre autres rôles, les informations de types à l'exécution permettent à l'inspecteur d'objets d'accéder aux propriétés

1390
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

et aux événements.

Parce qu'elles apparaissent dans l'inspecteur d'objets, les parties published d'une classe définissent l'interface de conception de
cette classe. L'interface de conception doit inclure toutes les caractéristiques d'une classe qu'un développeur d'applications peut
vouloir personnaliser au moment de la conception, tout en excluant toutes les propriétés qui dépendent d'une information
spécifique issue de l'environnement d'exécution.

Les propriétés accessibles en lecture uniquement ne peuvent pas faire partie de l'interface de conception car le développeur
d'applications ne peut pas leur affecter des valeurs directement. Les propriétés accessibles en lecture uniquement doivent donc
être déclarées public plutôt que published.

Voir aussi
Masquer les détails d'implémentation ( see page 1392)

Définir l'interface avec le concepteur des composants ( see page 1391)

Définir l'interface d'exécution ( see page 1391)

3.2.1.13.11 Définir l'interface avec le concepteur des composants


Déclarer protected une partie d'une classe rend cette partie uniquement visible par cette classe et par ses descendants (et par
les autres classes qui partagent leurs fichiers unité).

Vous pouvez utiliser les déclarations protected pour définir l'interface de conception des composants d'une classe. Les unités
de l'application ne peuvent pas accéder aux parties protected, mais les classes dérivées le peuvent. Cela signifie que les
concepteurs des composants peuvent modifier la façon dont fonctionne une classe sans rendre apparents ces détails aux
développeurs d'applications.

Remarque: Une erreur commune consiste à essayer d'accéder aux méthodes protégées d'un gestionnaire d'événement. Les
gestionnaires d'événements sont généralement des méthodes de la fiche, et non du composant qui reçoit l'événement. Par
conséquent, ils n'accèdent pas aux méthodes protégées du composant (à moins que le composant ne soit déclaré dans la
même unité que la fiche).

Voir aussi
Masquer les détails d'implémentation ( see page 1392)

Définir l'interface d'exécution ( see page 1391)

Définir l'interface de conception ( see page 1390)

3.2.1.13.12 Définir l'interface d'exécution


Déclarer public une partie d'une classe rend cette partie visible par tout code qui dispose d'un accès global à cette classe.

Les parties publiques sont disponibles à l'ensemble du code lors de l'exécution, et constituent par là même l'interface
d'exécution. L'interface d'exécution sert aux éléments qui sont sans signification ou inappropriés au moment de la conception ;
comme les propriétés contenant des informations uniquement disponibles à l'exécution ou accessibles uniquement en lecture.
Les méthodes destinées à être appelées par les développeurs d'applications doivent également être publiques. 3
Voir aussi
Masquer les détails d'implémentation ( see page 1392)

Définir l'interface avec le concepteur des composants ( see page 1391)

Définir l'interface de conception ( see page 1390)

1391
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

3.2.1.13.13 Répartition des méthodes


Le terme de Dispatch fait référence à la façon dont un programme détermine où il doit rechercher une méthode de classe
lorsqu'il rencontre un appel à cette méthode. Le code qui appelle une méthode de classe ressemble à tout autre appel de
fonction. Mais les classes ont des façons différentes de répartir les méthodes.

Les trois types de répartition de méthodes sont

• Statique
• Virtuel
• Dynamique

3.2.1.13.14 Méthodes dynamiques


Les méthodes dynamiques sont des méthodes virtuelles avec un mécanisme de répartition légèrement différent. Comme les
méthodes dynamiques n'ont pas d'entrées dans le tableau de méthode virtuelle de l'objet, elles peuvent réduire la taille de la
mémoire consommée par les objets. Cependant les méthodes de répartition dynamiques sont quelque peu plus lentes que les
méthodes de répartition virtuelles normales. Si une méthode est fréquemment appelée, ou si son exécution nécessite un temps
court, vous devrez probablement la déclarer virtuelle plutôt que dynamique.

Les objets doivent stocker les adresses de leurs méthodes dynamiques. Mais plutôt que de recevoir les entrées dans le tableau
de méthode virtuelle, les méthodes dynamiques sont indiquées séparément. La liste des méthodes dynamiques contient des
entrées uniquement pour les méthodes introduites ou redéfinies par une classe particulière. Le tableau de méthode virtuelle, à
l'inverse, comprend toutes les méthodes virtuelles de l'objet, à la fois héritées et introduites. Les méthodes dynamiques héritées
sont réparties en cherchant chaque liste de méthode dynamique de l'ancêtre, en allant en arrière dans l'arborescence de
l'héritage.

Pour rendre une méthode dynamique, ajoutez la directive dynamic après la déclaration de méthode.

3.2.1.13.15 Masquer les détails d'implémentation


Déclarer private une partie d'une classe rend cette partie invisible au code situé hors du fichier unité de la classe. Dans l'unité
qui contient la déclaration, le code peut accéder à cette partie comme si elle était publique.

Voir aussi
Définir l'interface avec le concepteur des composants ( see page 1391)

Définir l'interface d'exécution ( see page 1391)

Définir l'interface de conception ( see page 1390)

3.2.1.13.16 Méthodes virtuelles


3 Les méthodes virtuelles emploient un mécanisme de répartition plus compliqué et plus souple que les méthodes statiques. Une
méthode virtuelle peut être redéfinie dans des classes descendantes, mais est toujours appelée dans la classe ancêtre.
L'adresse d'une méthode virtuelle n'est pas déterminée lors de la compilation ; à la place, l'objet où la méthode est définie donne
l'adresse lors de l'exécution.

Pour qu'une méthode soit virtuelle, ajoutez la directive virtual après la déclaration de la méthode. La directive virtual crée une
entrée dans le tableau de méthode virtuelle, de l'objet, ou VMT, qui contient les adresses de toutes les méthodes virtuelles d'un
type objet.

1392
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Lorsque vous dérivez une nouvelle classe d'une classe existante, la nouvelle classe a son propre VMT, qui comprend toutes les
entrées provenant du VMT de l'ancêtre plus toutes les méthodes virtuelles supplémentaires déclarées dans la nouvelle classe.

Voir aussi
Méthodes standard ( see page 1393)

Redéfinition des méthodes ( see page 1393)

3.2.1.13.17 Classes et pointeurs


Chaque classe (et par conséquent chaque composant) est en fait un pointeur. Le compilateur déréférence automatiquement les
pointeurs de classe à votre place, aussi n'avez-vous généralement pas besoin de vous poser ces questions. Le statut des
classes en tant que pointeurs devient important lorsque vous passez une classe comme paramètre. En général, vous
transmettrez les classes par valeur plutôt que par référence. Car les classes sont déjà des pointeurs, c'est-à-dire des
références ; transmettre une classe par référence serait transmettre une référence à une référence.

3.2.1.13.18 Redéfinition des méthodes


Redéfinir une méthode signifie l'étendre ou la redéfinir plutôt que la remplacer. Une classe descendante peut redéfinir toutes ses
méthodes virtuelles héritées.

Pour redéfinir une méthode dans une classe descendante, ajoutez la directive override à la fin de la déclaration de méthode.

La redéfinition d'une méthode provoque une erreur de compilation si

• La méthode n'existe pas dans la classe ancêtre.


• La méthode de l'ancêtre du même nom est statique.
• Les déclarations ne sont pas identiques (le numéro et le type des paramètres arguments diffèrent).
Voir aussi
Rendre virtuelles des méthodes ( see page 1254)

3.2.1.13.19 Méthodes standard (C++)


Les méthodes d'une classe sont considérées comme standard (non virtuelles), sauf si vous les déclarez virtual ou si elles
redéfinissent une méthode virtual d'une classe de base. Le compilateur peut déterminer l'adresse exacte d'un membre de
classe standard au moment de la compilation. Il s'agit de la liaison au moment de la compilation.

Une méthode standard de classe de base est héritée par des classes dérivées. Dans l'exemple ci-dessous, un objet de type
Derived peut appeler la méthode Regular() comme si c'était sa propre méthode. Déclarer dans une classe dérivée une
méthode ayant le même nom et les mêmes paramètres qu'une méthode standard de l'ancêtre de la classe remplace la méthode
de l'ancêtre. Dans notre exemple, lorsque d->AnotherRegular() est appelée, c'est la méthode qui remplace
AnotherRegular() dans la classe Derived qui est appelée.
class Base
{ 3
public:
void Regular();
void AnotherRegular();
virtual void Virtual();
};
class Derived : public Base
{
public:
void AnotherRegular(); // remplace Base::AnotherRegular()

1393
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

void Virtual(); // surcharge Base::Virtual()


};
void FunctionOne()
{
Derived *d;
d = new Derived;
d->Regular(); // appel de Regular() comme si c'était un membre de Derived
// identique à l'appel de d->Base::Regular()
d->AnotherRegular(); // appel de AnotherRegular() redéfini, ...
// ... en remplacement de Base::AnotherRegular()
delete d;
}
void FunctionTwo(Base *b)
{
b->Virtual();
b->AnotherRegular();
}

3.2.1.13.20 Méthodes statiques


Toutes les méthodes sont statiques à moins que vous ne les déclariez spécifiquement autrement. Les méthodes statiques
fonctionnent comme des procédures ou des fonctions normales. Le compilateur détermine l'adresse exacte de la méthode et la
lie au moment de la compilation.

Le premier avantage des méthodes statiques est qu'elles sont réparties très rapidement. Comme le compilateur peut déterminer
l'adresse exacte de la méthode, il la lie directement. Les méthodes virtuelles et dynamiques, au contraire, utilisent des moyens
indirects pour donner l'adresse de leurs méthodes lors de l'exécution, ce qui prend davantage de temps.

Une méthode statique ne change pas lorsqu'elle est héritée d'une classe descendante. Si vous déclarez une classe comprenant
une méthode statique, puis dérivez une nouvelle classe à partir de celle-ci, la classe dérivée partage exactement la même
méthode à la même adresse. Cela signifie que vous ne pouvez pas redéfinir des méthodes statiques. Une méthode statique
réalise toujours la même chose quelle que soit la classe qui y est appelée. Si vous déclarez une méthode dans une classe
dérivée ayant le même nom qu'une méthode statique dans la classe ancêtre, la nouvelle méthode remplace simplement celle
héritée dans la classe dérivée.

3.2.1.14 Graphiques et composants


Rubriques
Nom Description
Création et gestion des bitmaps hors écran ( see page 1396) Lorsque vous créez des images graphiques complexes, vous devez
généralement éviter de les dessiner directement sur le canevas qui apparaît à
l'écran. Au lieu de les dessiner sur le canevas d'un formulaire ou d'un contrôle,
vous devez plutôt construire un objet bitmap puis dessiner sur son canevas avant
de copier la totalité de l'image sur le canevas affiché.
La méthode Paint d'un contrôle graphique est un exemple d'utilisation typique
d'un bitmap hors écran. Comme avec tout objet temporaire, l'objet bitmap doit
être protégé par un bloc try..finally :
Chargement et stockage des graphiques ( see page 1397) Toutes les images et tous les graphiques de Delphi peuvent charger leurs
images à partir d'un fichier et les stocker en retour dans ce même fichier (ou
dans un autre). Ceci peut s'effectuer à tout moment.
3
Pour charger une image dans un objet image à partir d'un fichier, appelez la
méthode LoadFromFile de l'objet image. Pour enregistrer une image dans un
fichier à partir d'un objet image, appelez la méthode SaveToFile de l'objet image.
LoadFromFile et SaveToFile acceptent le nom d'un fichier comme seul
paramètre. LoadFromFile utilise l'extension du fichier pour déterminer le type
d'objet graphique créé ou chargé. SaveToFile... suite ( see page 1397)

1394
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Gestion des palettes ( see page 1397) Pour les composants VCL, lorsque l'exécution fait intervenir un périphérique
supportant les palettes (typiquement un mode vidéo 256 couleurs), Delphi assure
automatiquement la réalisation des palettes. Si un contrôle dispose d'une palette,
vous pouvez utiliser deux méthodes héritées de TControl pour contrôler la façon
dont Windows prend en compte la palette.
Les points suivants sont à prendre en compte lorsque vous travaillez avec des
palettes :

• Spécification d'une palette pour un contrôle ( see page


1399)
• Réponse aux changements de palette ( see page 1399)
Toutefois, dans le cas des contrôles contenant des images
graphiques riches en couleurs (tels que le contrôle image)
une interaction entre Windows et le... suite ( see page
1397)
Bitmaps hors écran ( see page 1397) Lorsque vous dessinez des images graphiques complexes, une technique de
programmation graphique habituelle consiste à créer d'abord un bitmap hors
écran, puis à dessiner l'image dans ce bitmap et à copier ensuite la totalité de
l'image du bitmap vers sa destination finale à l'écran. L'utilisation d'une image
hors-écran réduit le scintillement causé par un tracé répétitif à l'écran.
Dans Delphi, la classe bitmap qui représente les images point par point stockées
dans les ressources et les fichiers, peut également fonctionner en tant qu'image
hors écran.
Les points suivants sont à prendre en compte lorsque vous travaillez avec des
bitmaps hors... suite ( see page 1397)
Présentation des graphiques ( see page 1398) Delphi encapsule à différents niveaux les fonctions GDI de Windows. Le
programmeur qui écrit des composants doit comprendre comment ceux-ci
affichent leurs images à l'écran. Lorsque vous appelez directement les fonctions
GDI, vous devez disposer d'un handle sur un contexte de périphérique dans
lequel vous avez sélectionné des outils de dessin comme les crayons, les
pinceaux et les fontes. Après avoir tracé vos images, vous devez remettre le
contexte de périphérique dans son état initial avant de le restituer.
Au lieu de vous contraindre à gérer les graphiques au niveau détaillé, Delphi met
à votre disposition une interface simple mais... suite ( see page 1398)
Utilisation d'une image, d'un graphique ou d'un canevas ( see page 1398) Il existe trois sortes de classes dans Delphi intervenant sur les graphiques :

• Un canevas représente une surface de dessin point par


point dans une fiche, un contrôle graphique, une
imprimante ou un bitmap. Un canevas est toujours une
propriété de quelque chose d'autre, jamais une classe
autonome.
• Un graphique représente une image graphique telle
qu'elle se trouve dans un fichier ou une ressource,
comme un bitmap, une icône ou un métafichier. Delphi
définit les classes TBitmap, TIcon et TMetafile, toutes
descendants de l'objet générique TGraphic. Vous pouvez
aussi définir vos propres classes graphiques. En
définissant une interface... suite ( see page 1398)
Réponse aux changements ( see page 1398) Tous les objets graphiques, y compris les canevas et les objets dont ils sont
propriétaires (crayons, pinceaux et fontes), disposent d'événements intégrés
pour répondre aux changements. Grâce à ces événements, vous pouvez faire en
sorte que vos composants (ou les applications qui les utilisent) répondent aux
changements en redessinant leurs images.
S'agissant d'objets graphiques, la réponse aux changements est particulièrement
importante si ces objets sont publiés comme éléments accessibles de l'interface 3
de conception de vos composants. La seule façon d'être certain que l'aspect d'un
composant au moment de la conception corresponde aux propriétés définies
dans l'inspecteur d'objets consiste à répondre... suite ( see page 1398)

1395
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

Réponse aux changements de palette ( see page 1399) Si votre contrôle VCL spécifie une palette en surchargeant GetPalette, Delphi se
chargera de répondre automatiquement aux messages de palette en provenance
de Windows. La méthode qui gère les messages de palette est PaletteChanged.
Le rôle primaire de PaletteChanged est de déterminer s'il est nécessaire de
réaliser les palettes des contrôles en avant et arrière-plan. Windows gère la
réalisation des palettes en faisant en sorte que la fenêtre la plus en avant
dispose de la palette d'avant-plan, la résolution des couleurs des autres fenêtres
se faisant à l'aide des palettes d'arrière-plan. Delphi va même plus loin car il
réalise... suite ( see page 1399)
Spécification d'une palette pour un contrôle ( see page 1399) Pour spécifier la palette d'un contrôle, vous devez redéfinir la méthode
GetPalette du contrôle pour qu'elle renvoie le handle de la palette.
Le fait de spécifier la palette d'un contrôle a deux conséquences pour votre
application :

• Cela informe l'application que la palette de votre contrôle


doit être réalisée.
• Cela désigne la palette à utiliser pour cette réalisation.
Utilisation des graphiques et des composants Vue globale ( see page 1399) Windows fournit une puissante interface GDI (Graphics Device Interface) servant
à dessiner des graphiques indépendamment des périphériques.
Malheureusement, GDI impose au programmeur des contraintes
supplémentaires telles que la gestion des ressources graphiques. Delphi prend
en charge toutes ces tâches GDI ingrates, vous laisse vous concentrer sur le
travail productif, vous épargnant les recherches de handles perdus ou de
ressources non restituées.
De même que toute partie de l'API Windows, vous pouvez appeler les fonctions
GDI directement depuis votre application Delphi Toutefois, vous vous rendrez
vite compte que l'utilisation de l'encapsulation Delphi des fonctions graphiques
est un moyen plus... suite ( see page 1399)
Utilisation du canevas ( see page 1400) La classe canevas encapsule les contrôles graphiques à plusieurs niveaux, allant
des fonctions de haut niveau (pour dessiner des lignes, des formes et du texte)
aux propriétés de niveau intermédiaire pour manipuler les fonctionnalités de
dessin du canevas ; et dans la bibliothèque de composants, offre un accès de
bas niveau au GDI Windows.
Le tableau suivant résume les possibilités du canevas.
Résumé des possibilités du canevas
Travail sur les images ( see page 1400) Dans Delphi, la part la plus importante de votre travail sur les graphiques se
limitera au dessin direct sur le canevas des composants et des fiches. Mais
Delphi fournit également les moyens de gérer les images graphiques
indépendantes, comme les bitmaps, les métafichiers et les icônes, en assurant
dans le même temps la gestion automatique des palettes.
Les trois sujets suivants sont nécessaires à la compréhension du travail sur les
images dans Delphi :

• Utilisation d'une image ( see page 1398)


• Chargement et stockage des graphiques ( see page
1397)
• Gestion des palettes ( see page 1397)

3.2.1.14.1 Création et gestion des bitmaps hors écran


Lorsque vous créez des images graphiques complexes, vous devez généralement éviter de les dessiner directement sur le
canevas qui apparaît à l'écran. Au lieu de les dessiner sur le canevas d'un formulaire ou d'un contrôle, vous devez plutôt
construire un objet bitmap puis dessiner sur son canevas avant de copier la totalité de l'image sur le canevas affiché.
3 La méthode Paint d'un contrôle graphique est un exemple d'utilisation typique d'un bitmap hors écran. Comme avec tout objet
temporaire, l'objet bitmap doit être protégé par un bloc try..finally :
type
TFancyControl = class(TGraphicControl)
protected
procedure Paint; override; { redéfinir la méthode Paint }
end;
procedure TFancyControl.Paint;
var

1396
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

Bitmap: TBitmap; { variable temporaire pour le bitmap hors écran }


begin
Bitmap := TBitmap.Create;{ construire l'objet bitmap }
try
{ dessiner sur le bitmap }
{ copier le résultat dans le canevas du contrôle }
finally
Bitmap.Free; { détruire l'objet bitmap }
end;
end;

3.2.1.14.2 Chargement et stockage des graphiques


Toutes les images et tous les graphiques de Delphi peuvent charger leurs images à partir d'un fichier et les stocker en retour
dans ce même fichier (ou dans un autre). Ceci peut s'effectuer à tout moment.

Pour charger une image dans un objet image à partir d'un fichier, appelez la méthode LoadFromFile de l'objet image. Pour
enregistrer une image dans un fichier à partir d'un objet image, appelez la méthode SaveToFile de l'objet image.

LoadFromFile et SaveToFile acceptent le nom d'un fichier comme seul paramètre. LoadFromFile utilise l'extension du fichier
pour déterminer le type d'objet graphique créé ou chargé. SaveToFile utilise le type de fichier approprié au type d'objet
graphique enregistré.

3.2.1.14.3 Gestion des palettes


Pour les composants VCL, lorsque l'exécution fait intervenir un périphérique supportant les palettes (typiquement un mode vidéo
256 couleurs), Delphi assure automatiquement la réalisation des palettes. Si un contrôle dispose d'une palette, vous pouvez
utiliser deux méthodes héritées de TControl pour contrôler la façon dont Windows prend en compte la palette.

Les points suivants sont à prendre en compte lorsque vous travaillez avec des palettes :

• Spécification d'une palette pour un contrôle ( see page 1399)


• Réponse aux changements de palette ( see page 1399)
Toutefois, dans le cas des contrôles contenant des images graphiques riches en couleurs (tels que le contrôle image) une
interaction entre Windows et le pilote de périphérique écran peut être nécessaire pour afficher correctement le contrôle. Dans
Windows, ce processus est appelé réalisation de palettes.
La réalisation de palettes est le processus mis en œuvre pour que la fenêtre en avant-plan utilise la totalité de la palette qui lui
est associée. Quant aux fenêtres en arrière-plan, elles exploitent autant que possible les couleurs de leurs palettes propres,
l'approximation des couleurs manquantes se faisant en prenant la couleur disponible la plus proche dans la palette “réelle”.
Windows effectue un travail permanent de réalisation des palettes au fur et à mesure que les fenêtres sont déplacées d'avant
en arrière-plan.
Remarque: Delphi n'assure ni la création, ni la maintenance des palettes autres que celles des bitmaps. Toutefois, si vous
disposez d'un handle de palette, les contrôles Delphi peuvent se charger de sa gestion.

3.2.1.14.4 Bitmaps hors écran


Lorsque vous dessinez des images graphiques complexes, une technique de programmation graphique habituelle consiste à 3
créer d'abord un bitmap hors écran, puis à dessiner l'image dans ce bitmap et à copier ensuite la totalité de l'image du bitmap
vers sa destination finale à l'écran. L'utilisation d'une image hors-écran réduit le scintillement causé par un tracé répétitif à l'écran.

Dans Delphi, la classe bitmap qui représente les images point par point stockées dans les ressources et les fichiers, peut
également fonctionner en tant qu'image hors écran.

Les points suivants sont à prendre en compte lorsque vous travaillez avec des bitmaps hors écran :

• Création et gestion des bitmaps hors écran. ( see page 1396)

1397
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32

• Copie des images bitmap.

3.2.1.14.5 Présentation des graphiques


Delphi encapsule à différents niveaux les fonctions GDI de Windows. Le programmeur qui écrit des composants doit
comprendre comment ceux-ci affichent leurs images à l'écran. Lorsque vous appelez directement les fonctions GDI, vous devez
disposer d'un handle sur un contexte de périphérique dans lequel vous avez sélectionné des outils de dessin comme les
crayons, les pinceaux et les fontes. Après avoir tracé vos images, vous devez remettre le contexte de périphérique dans son état
initial avant de le restituer.

Au lieu de vous contraindre à gérer les graphiques au niveau détaillé, Delphi met à votre disposition une interface simple mais
complète : il s'agit de la propriété Canvas des composants. Le canevas garantit qu'un contexte de périphérique valide est
disponible et restitue le contexte lorsqu'il est inutilisé. Il dispose également de propriétés spécifiques pour représenter la fonte, le
crayon et le pinceau en cours.

Le canevas gère toutes ces ressources à votre place et vous n'avez donc pas le souci de créer, de sélectionner ou de restituer
les éléments comme le handle d'un crayon. Vous n'avez qu'à indiquer au canevas le crayon à utiliser et il se charge du reste.

Un des avantage à laisser Delphi gérer les ressources graphiques est que Delphi peut les mettre en cache pour les utiliser
ultérieurement, ce qui peut accélérer les opérations répétitives. Par exemple, supposons qu'un programme crée, utilise puis
restitue un outil crayon d'un certain type plusieurs fois de suite, vous devez répéter ces étapes chaque fois que vous l'utilisez.
Comme Delphi met en cache les ressources graphiques, il est probable que l'outil que vous utilisez souvent est encore dans le
cache et, au lieu d'avoir à recréer un outil, Delphi utilise celui qui existe.

Par exemple, vous pouvez imaginer une application avec des dizaines de fiches ouvertes et des centaines de contrôles. Chacun
de ces contrôles peut présenter une ou plusieurs propriétés TFont. Comme cela peut générer des centaines ou des milliers
d'instances d'objets TFont, la plupart des applications n'utiliseront que deux ou trois handles de fontes grâce à un cache de
fontes.

3.2.1.14.6 Utilisation d'une image, d'un graphique ou d'un canevas


Il existe trois sortes de classes dans Delphi intervenant sur les graphiques :

• Un canevas représente une surface de dessin point par point dans une fiche, un contrôle graphique, une imprimante ou un
bitmap. Un canevas est toujours une propriété de quelque chose d'autre, jamais une classe autonome.
• Un graphique représente une image graphique telle qu'elle se trouve dans un fichier ou une ressource, comme un bitmap,
une icône ou un métafichier. Delphi définit les classes TBitmap, TIcon et TMetafile, toutes descendants de l'objet générique
TGraphic. Vous pouvez aussi définir vos propres classes graphiques. En définissant une interface standard minimale pour
tous les graphiques, TGraphic fournit un mécanisme simple destiné aux applications pour qu'elles puissent exploiter
facilement les différentes sortes de graphiques disponibles.
• Une image est le conteneur d'un graphique, elle peut donc contenir n'importe quelle classe graphique. Autrement dit, un
élément de type TPicture peut contenir un bitmap, une icône, un métafichier, un type de graphique défini par l'utilisateur, et
l'application y accède d'une seule façon par l'intermédiaire de la classe image. Par exemple, un contrôle image dispose d'une
propriété Picture, de type TPicture, qui le rend capable d'afficher les images de plusieurs sortes de graphiques.
Souvenez-vous qu'une classe image a toujours un graphique et qu'un graphique peut avoir un canevas. Le seul graphique
3 standard ayant un canevas est TBitmap. Normalement, lorsque vous avez affaire à une image, vous travaillez uniquement
avec les constituants de la classe graphique exposés via TPicture. Si vous voulez accéder aux constituants spécifiques de la
classe graphique elle-même, vous pouvez faire référence à la propriété Graphic de l'image.

3.2.1.14.7 Réponse aux changements


Tous les objets graphiques, y compris les canevas et les objets dont ils sont propriétaires (crayons, pinceaux et fontes),
disposent d'événements intégrés pour répondre aux changements. Grâce à ces événements, vous pouvez faire en sorte que

1398
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants

vos composants (ou les applications qui les utilisent) répondent aux changements en redessinant leurs images.

S'agissant d'objets graphiques, la réponse aux changements est particulièrement importante si ces objets sont publiés comme
éléments accessibles de l'interface de conception de vos composants. La seule façon d'être certain que l'aspect d'un composant
au moment de la conception corresponde aux propriétés définies dans l'inspecteur d'objets consiste à répondre aux
changements apportés aux objets.

Pour répondre aux modifications d'un objet graphique, vous devez associer une méthode à l'événement OnChange de sa classe.

3.2.1.14.8 Réponse aux changements de palette


Si votre contrôle VCL spécifie une palette en surchargeant GetPalette, Delphi se chargera de répondre automatiquement aux
messages de palette en provenance de Windows. La méthode qui gère les messages de palette est PaletteChanged.

Le rôle primaire de PaletteChanged est de déterminer s'il est nécessaire de réaliser les palettes des contrôles en avant et
arrière-plan. Windows gère la réalisation des palettes en faisant en sorte que la fenêtre la plus en avant dispose de la palette
d'avant-plan, la résolution des couleurs des autres fenêtres se faisant à l'aide des palettes d'arrière-plan. Delphi va même plus
loin car il réalise les palettes des contrôles d'une fenêtre en respectant l'ordre de tabulation. Seul cas où vous voudrez peut-être
redéfinir ce comportement : lorsqu'un contrôle, autre que le premier dans l'ordre de tabulation, doit récupérer la palette
d'avant-plan.

3.2.1.14.9 Spécification d'une palette pour un contrôle


Pour spécifier la palette d'un contrôle, vous devez redéfinir la méthode GetPalette du contrôle pour qu'elle renvoie le handle de
la palette.

Le fait de spécifier la palette d'un contrôle a deux conséquences pour votre application :

• Cela informe l'application que la palette de votre contrôle doit être réalisée.
• Cela désigne la palette à utiliser pour cette réalisation.

3.2.1.14.10 Utilisation des graphiques et des composants Vue globale


Windows fournit une puissante interface GDI (Graphics Device Interface) servant à dessiner des graphiques indépendamment
des périphériques. Malheureusement, GDI impose au programmeur des contraintes supplémentaires telles que la gestion des
ressources graphiques. Delphi prend en charge toutes ces tâches GDI ingrates, vous laisse vous concentrer sur le travail
productif, vous épargnant les recherches de handles perdus ou de ressources non restituées.

De même que toute partie de l'API Windows, vous pouvez appeler les fonctions GDI directement depuis votre application Delphi
Toutefois, vous vous rendrez vite compte que l'utilisation de l'encapsulation Delphi des fonctions graphiques est un moyen plus
efficace et plus rapide de créer des graphiques.

Les rubriques de cette section comprennent :

• Présentation des graphiques ( see page 1398)


• Utilisation du canevas ( see page 1400) 3
• Travail sur les images ( see page 1400)
• Bitmaps hors écran ( see page 1397)
• Réponse aux changements ( see page 1398)

1399
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

3.2.1.14.11 Utilisation du canevas


La classe canevas encapsule les contrôles graphiques à plusieurs niveaux, allant des fonctions de haut niveau (pour dessiner
des lignes, des formes et du texte) aux propriétés de niveau intermédiaire pour manipuler les fonctionnalités de dessin du
canevas ; et dans la bibliothèque de composants, offre un accès de bas niveau au GDI Windows.

Le tableau suivant résume les possibilités du canevas.

Résumé des possibilités du canevas

Niveau Opération Outils


Elevé Dessin de lignes et de formes Méthodes comme MoveTo, LineTo, Rectangle et Ellipse
Affichage et mesure de texte Méthodes TextOut, TextHeight, TextWidth et TextRect
Remplissage de zones Méthodes FillRect et FloodFill
Intermédiaire Personnalisation de texte et des Propriétés Pen, Brush et Font
graphiques
Manipulation de pixels Propriété Pixels.
Copie et fusion d'images Méthodes Draw, StretchDraw, BrushCopy et CopyRect ; propriété
CopyMode
Bas Appel des fonctions GDI de Windows Propriété Handle

3.2.1.14.12 Travail sur les images


Dans Delphi, la part la plus importante de votre travail sur les graphiques se limitera au dessin direct sur le canevas des
composants et des fiches. Mais Delphi fournit également les moyens de gérer les images graphiques indépendantes, comme les
bitmaps, les métafichiers et les icônes, en assurant dans le même temps la gestion automatique des palettes.

Les trois sujets suivants sont nécessaires à la compréhension du travail sur les images dans Delphi :

• Utilisation d'une image ( see page 1398)


• Chargement et stockage des graphiques ( see page 1397)
• Gestion des palettes ( see page 1397)

3.2.2 Développement d'applications COM


Contient les rubriques du Guide du développeur relatives à la création d'applications COM dans Delphi.

Rubriques
Nom Description
3 Principes de COM ( see page 1401)
Création d'une page Active Server ( see page 1419)
Utilisation des contrôles ActiveX ( see page 1426)
Création de clients COM ( see page 1438)
Création de serveurs COM simples ( see page 1453)
Utilisation des bibliothèques de types ( see page 1468)

1400
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

3.2.2.1 Principes de COM


Rubriques
Nom Description
Présentation des technologies COM ( see page 1404) Delphi fournit des experts et des classes qui facilitent l'implémentation
d'applications basées sur COM (Component Object Model) de Microsoft. Grâce à
ces experts, vous pouvez créer des classes et des composants basés sur COM
que vous utiliserez dans des applications, ou vous pouvez créer des clients ou
des serveurs COM complètement fonctionnels qui implémentent des objets COM
sophistiqués, des serveurs Automation (y compris, des objets Active Server), des
contrôles ActiveX ou des fiches ActiveForms.
COM est un modèle de composant logiciel indépendant du langage qui permet
l'interaction entre des composants logiciels et des applications s'exécutant sous
Windows. L'aspect fondamental de... suite ( see page 1404)
Composantes d'une application COM ( see page 1405) Quand vous implémentez une application COM, vous fournissez ceci :
Interfaces COM ( see page 1405) Les clients COM communiquent avec des objets par le biais d'interfaces COM.
Les interfaces sont des groupes de routines, liées par la logique ou par la
sémantique, qui assurent la communication entre le fournisseur d'un service
(objet serveur) et ses clients. Voici la représentation standard d'une interface
COM :

Par exemple, tout objet COM doit implémenter l'interface de base, IUnknown (
see page 1406). Via une routine appelée QueryInterface de IUnknown, les
clients peut demander les autres interfaces implémentées par le serveur.
Les objets peuvent avoir plusieurs interfaces, où chacune implémente une
fonctionnalité. L'interface est le moyen de mettre à... suite ( see page 1405)
L'interface COM de base, IUnknown ( see page 1406) Les objets COM doivent tous supporter l'interface fondamentale, appelée
IUnknown, un typedef du type d'interface de base IInterface. IUnknown contient
les routines suivantes :
Pointeurs d'interface COM ( see page 1406) Un pointeur d'interface est un pointeur vers une instance d'objet qui pointe, à son
tour, vers l'implémentation de chaque méthode de l'interface. L'implémentation
est accédée via un tableau de pointeurs vers ces méthodes, appelé vtable. Les
vtables sont similaires au mécanisme utilisé pour gérer les fonctions virtuelles
sous Delphi. A cause de cette similitude, le compilateur peut résoudre les appels
de méthode de l'interface de la même manière qu'il résout les appels des
méthodes de classes Delphi.
La vtable est partagée par toutes les instances d'une classe objet, et pour
chaque instance de l'objet, le code de l'objet alloue... suite ( see page 1406)
Serveurs COM ( see page 1407) Un serveur COM est une application ou une bibliothèque qui fournit des services
à une application ou bibliothèque client. Un serveur COM est constitué d'un ou
de plusieurs objets COM, un objet COM étant un ensemble de propriétés
(données membre ou contenu) et de méthodes (fonctions membre).
Les clients ne savent pas comment l'objet COM effectue son service ;
l'implémentation de l'objet est encapsulée. Un objet met ses services à
disposition par le biais de ses interfaces ( see page 1405).
En outre, les clients n'ont pas besoin de savoir où réside l'objet COM. COM
fournit un accès transparent quel que soit l'emplacement ( see page 1408)...
suite ( see page 1407)
CoClasses et factories de classes ( see page 1407) Un objet COM est une instance d'une CoClass, qui est une classe implémentant
une ou plusieurs interfaces COM. L'objet COM fournit les services définis par ses
interfaces.
Les CoClasses sont instanciées par un type d'objet spécial, appelé une factory
de classe. Chaque fois que des services d'un objet sont demandés par un client,
une factory de classe crée une instance de cet objet pour ce client particulier.
Généralement, si un autre client demande les services de l'objet, la factory de 3
classe crée une autre instance de l'objet pour ce deuxième client. Les clients
peuvent également se lier à... suite ( see page 1407)
Serveurs en processus, hors processus et distants ( see page 1408) Avec COM, un client n'a pas besoin de savoir où réside un objet, il suffit de faire
un appel à une interface de l'objet. COM accomplit les étapes nécessaires à cet
appel. Ces étapes sont différentes selon que l'objet réside dans le même
processus que le client, dans un autre processus sur la machine du client ou sur
une autre machine du réseau. Ces différents types de serveurs sont décrits ici :

1401
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Le mécanisme du marshaling ( see page 1409) Le marshaling est le mécanisme qui permet à un client de faire des appels aux
fonctions de l'interface d'objets distants qui se trouvent dans un autre processus
ou sur une autre machine. Le marshaling

• Prend un pointeur d'interface dans le processus du


serveur et rend un pointeur de proxy disponible au code
dans le processus du client.
• Prend les arguments d'un appel à l'interface passés
depuis le client et les place dans l'espace processus de
l'objet distant.
Pour tout appel à l'interface, le client met les arguments sur
une pile et émet un appel à une fonction via le pointeur...
suite ( see page 1409)
Serveurs Automation ( see page 1410) Dans certains cas, un objet serveur peut utiliser un autre objet COM pour
effectuer certaines de ces fonctions. Par exemple, un objet de gestion de stock
peut utiliser un objet commande séparé pour gérer les commandes des clients.
Si l'objet de gestion de stock veut présenter une interface de commande au
client, il y a un problème. Même si le client ayant une interface stock peut appeler
QueryInterface pour obtenir l'interface commande, quand l'objet commande a été
créé, il ne connaît pas l'objet gestion de stock et ne peut lui renvoyer une
interface stock en réponse à un appel de... suite ( see page 1410)
Clients COM ( see page 1410) Les clients peuvent toujours interroger les interfaces d'un objet COM pour
déterminer ce qu'il est capable de faire. Tous les objets COM permettent aux
clients de demander les interfaces connues. De plus, si le serveur gère l'interface
IDispatch, les clients peuvent demander au serveur des informations sur les
méthodes gérées par le serveur. Les objets serveurs n'ont pas d'attentes
concernant l'utilisation de ses objets par le client. De même, les clients n'ont pas
besoin de savoir comment (ou même si) un objet fournit les services ; ils s'en
remettent simplement sur les objets serveurs pour fournir les services qu'ils
annoncent... suite ( see page 1410)
Extensions de COM ( see page 1411) COM a été initialement conçu pour fournir une fonctionnalité de communication
de base et permettre l'enrichissement de cette fonctionnalité via des extensions.
COM lui-même a étendu sa fonctionnalité première en définissant des
ensembles spécialisés d'interfaces couvrant des besoins spécifiques.
Le tableau suivant est un résumé de certaines des extensions de services que
COM fournit actuellement.
Serveurs Automation ( see page 1412) L'Automation désigne la capacité d'une application à contrôler par programme
les objets d'une autre application, comme une macro qui peut manipuler
plusieurs applications à la fois. Le client d'un objet Automation est appelé
contrôleur Automation, et l'objet serveur manipulé est appelé objet Automation.
L'Automation peut être utilisée sur des serveurs en processus, locaux ou distants.
L'Automation présente deux caractéristiques :

• L'objet Automation définit un ensemble de propriétés et de


commandes, et décrit ses capacités via les descriptions
de type. Pour ce faire, il doit disposer d'un moyen de
fournir des informations sur les interfaces de l'objet, les
méthodes des interfaces et... suite ( see page 1412)
Pages Active Server ( see page 1412) La technologie ASP (pages Active Server) vous permet d'écrire des scripts
simples, appelés pages Active Server qui peuvent être exécutées par les clients
via un serveur Web. A la différence des contrôles ActiveX qui s'exécutent sur le
client, les pages Active Server s'exécutent sur le serveur et renvoient les pages
HTML résultantes aux clients.
Les pages Active Server sont écrites en JScript ou en VBscript. Le script est
exécuté à chaque fois que le serveur charge la page Web. Ce script peut alors
lancer un serveur Automation incorporé (ou un Bean Java Entreprise). Vous
3 pouvez, par exemple, écrire un... suite ( see page 1412)
Contrôles ActiveX ( see page 1413) ActiveX est une technologie qui permet aux composants COM, particulièrement
aux contrôles, d'être plus compacts et efficaces. Cela est particulièrement
important pour les contrôles conçus pour des applications Intranet qui
nécessitent leur téléchargement par le client avant de les utiliser.
Les contrôles ActiveX sont des contrôles visuels qui s'exécutent uniquement
comme des serveurs en processus et qui peuvent s'intégrer dans une application
conteneur ActiveX. Ce ne sont pas des applications complètes par eux-mêmes,
vous pouvez les voir comme des contrôles OLE préfabriqués qui sont
réutilisables dans diverses applications. Les contrôles ActiveX ont une interface
utilisateur apparente et reposent sur l'utilisation... suite ( see page 1413)

1402
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Documents Active ( see page 1413) Les Documents Active (préalablement appelés documents OLE) constituent un
ensemble de services COM prenant en charge la liaison et l'incorporation, le
glisser-déplacer, ainsi que l'édition visuelle. Les documents Active intègrent de
façon transparente des données ou des objets de différents formats, par
exemple des clips sonores, des feuilles de calcul, du texte et des images.
Au contraire des contrôles ActiveX, les Documents Active ne sont pas limités aux
serveurs en processus; ils peuvent être utilisés dans des applications
inter-processus.
Au contraire des objets Automation, qui ne sont presque jamais visuels, les
objets Document Active peuvent être visuellement actifs dans une... suite ( see
page 1413)
Bibliothèques de types ( see page 1414) Les bibliothèques de types offrent un moyen d'obtenir davantage d'informations
de type sur un objet que les interfaces de l'objet. Les bibliothèques de types
contiennent les informations nécessaires sur les objets et leurs interfaces,
comme les interfaces associées à tels objets (étant donné le CLSID), les
fonctions membre de chaque interface et les arguments requis par ces fonctions.
Vous pouvez obtenir les informations de type en interrogeant une instance d'un
objet pendant qu'elle s'exécute ou, en chargeant et en lisant les bibliothèques de
types. Grâce à ces informations, vous pouvez implémenter un client qui utilise un
objet souhaité, en sachant... suite ( see page 1414)
Implémentation des objets COM à l'aide d'experts ( see page 1416) Delphi facilite l'écriture de serveurs COM en fournissant des experts qui gèrent
nombre des problèmes posés. Delphi propose des experts distincts permettant
de créer :

• Un simple objet COM


• Un objet Automation
• Un objet événement COM+
• Une bibliothèque de types
• Une bibliothèque ActiveX
Les experts gèrent beaucoup des problèmes intervenant
dans la création de chaque type d'objet. Ils fournissent les
interfaces COM requises pour chaque type d'objet. Avec
un simple objet COM, l'expert implémente la seule
interface COM obligatoire, IUnknown, qui fournit un
pointeur d'interface vers l'objet.

L'expert objet COM propose également une implémentation


de... suite ( see page 1416)
Code généré par les experts ( see page 1417) Les experts Delphi des classes qui dérivent du modèle ActiveX Delphi (DAX). En
dépit de son nom, DAX gère tous les types d'objet COM et pas uniquement les
contrôles ActiveX. Les classes de ce modèle fournissent l'implémentation
sous-jacente des interfaces COM aux objets que vous créez en utilisant un
expert. La figure suivante illustre les objets de l'infrastructure ActiveX de Delphi :

3
Chaque expert génère une unité d'implémentation qui implémente votre objet
serveur COM. L'objet serveur COM (l'objet implémentation) descend de l'une des
classes DAX :
Classes de base DAX utilisées par les classes d'implémentation
générées... suite ( see page 1417)

1403
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Objets Abonnement d'événement et Evénement COM+ ( see page 1418) Le système d'événements COM+ présente une couche logicielle intermédiaire
qui sépare les applications générant des événements (appelées éditeurs de
logiciels) des applications répondant aux événements (appelées abonnés). Au
lieu d'être étroitement liés les uns aux autres, les éditeurs de logiciels et les
abonnés peuvent être développés, déployés et activés indépendamment.
Dans le modèle d'événements COM+, une interface événement est d'abord
créée en employant l'expert Objet Evénement COM+. L'interface événement n'a
pas d'implémentation ; elle définit simplement les méthodes des événements que
les éditeurs de logiciels généreront et auxquels les abonnés répondront. L'objet
événement COM+ est ensuite installé dans une application COM+,... suite (
see page 1418)

3.2.2.1.1 Présentation des technologies COM


Delphi fournit des experts et des classes qui facilitent l'implémentation d'applications basées sur COM (Component Object
Model) de Microsoft. Grâce à ces experts, vous pouvez créer des classes et des composants basés sur COM que vous utiliserez
dans des applications, ou vous pouvez créer des clients ou des serveurs COM complètement fonctionnels qui implémentent des
objets COM sophistiqués, des serveurs Automation (y compris, des objets Active Server), des contrôles ActiveX ou des fiches
ActiveForms.

COM est un modèle de composant logiciel indépendant du langage qui permet l'interaction entre des composants logiciels et
des applications s'exécutant sous Windows. L'aspect fondamental de COM est de permettre la communication entre
composants, entre applications et entre clients et serveurs, par le biais d'interfaces clairement définies. Les interfaces offrent aux
clients un moyen de demander à un composant COM quelles fonctionnalités il supporte à l'exécution. Pour fournir d'autres
fonctionnalités à votre composant, il suffit d'ajouter une autre interface pour ces fonctionnalités.

Les applications peuvent accéder aux interfaces des composants COM se trouvant sur le même ordinateur que l'application ou
sur un autre ordinateur du réseau, en utilisant un mécanisme nommé DCOM (Distributed COM). Pour plus d'informations sur les
clients, les serveurs et les interfaces, voir Composantes d'une application COM ( see page 1405).

COM, spécification et implémentation


COM est à la fois une spécification et une implémentation. La spécification COM définit comment des objets sont créés et
comment ils communiquent entre eux. Selon cette spécification, les objets COM peuvent être écrits dans différents langages,
exécutés dans différents espaces de processus et sur différentes plates-formes. Tant que les objets adhèrent à la spécification,
ils peuvent communiquer. Cela vous permet d'intégrer le code de composants existants à de nouveaux composants
implémentés dans des langages orientés objet.

L'implémentation COM est construite dans le sous-système Win32, qui fournit de nombreux services intégrés supportant la
spécification écrite. La bibliothèque COM contient un ensemble d'interfaces standard définissant la fonctionnalité interne d'un
objet COM et un petit ensemble de fonctions API pour la création et la gestion des objets COM.

Lorsque vous utilisez dans votre application les experts de Delphi et les objets de la VCL, vous utilisez l'implémentation Delphi
de la spécification COM. En outre, Delphi fournit quelques enveloppes pour les services COM dont les fonctionnalités ne sont
pas implémentées directement. Ces enveloppes sont définies dans l'unité ComObj, et les définitions d'API se trouvent dans
l'unité AxCtrls.

Remarque: Les objets et les langages des interfaces Delphi sont conformes à la spécification COM. L'implémentation Delphi de
la spécification COM utilise un ensemble de classes appelé cadre de travail Delphi ActiveX (DAX). Ces classes se trouvent dans
3 les unités AxCtrls, OleCtrls et OleServer. En outre, l'interface Delphi avec l'API COM se trouve dans ActiveX.pas

et ComSvcs.pas.

extensions de COM
COM a évolué et a été étendu au-delà des services COM de base. COM sert de fondement à d'autres technologies, comme
l'Automation, les contrôles ActiveX et les annuaires Active. Pour plus de détails, voir Extensions de COM ( see page 1411).

Delphi fournit des experts permettant d'implémenter facilement des applications qui incorporent toutes ces technologies dans
l'environnement Delphi. Pour plus de détails, voir Implémentation des objets COM à l'aide d'experts ( see page 1416).

1404
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Voir aussi
Création de serveurs COM simples : Vue globale ( see page 1456)

Création de pages Active Server : Vue globale ( see page 1420)

Création d'objets MTS ou COM+ : Vue globale

3.2.2.1.2 Composantes d'une application COM


Quand vous implémentez une application COM, vous fournissez ceci :

Interface Le moyen par lequel un objet expose ses services aux clients. Un objet COM fournit une interface pour chaque
COM ( ensemble de méthodes. Attention : les propriétés COM ne sont pas identiques aux propriétés des objets VCL. Les
see page propriétés COM utilisent toujours des méthodes d'accès en lecture/écriture.
1405)
Serveur Un module, EXE, DLL ou OCX, contenant le code d'un objet COM. Les implémentations d'objets résident sur les
COM ( serveurs. Un objet COM implémente une ou plusieurs interfaces.
see page
1407)
Client Le code appelant les interfaces afin d'obtenir du serveur les services demandés. Les clients savent ce qu'ils
COM ( veulent obtenir du serveur (via l'interface) ; les clients ne savent pas comment en interne le serveur fournit les
see page services. Delphi facilite le processus de création de client en vous permettant d'installer des serveurs COM (tel
1410) qu'un document Word ou une diapositive PowerPoint) en tant que composants sur la palette d'outils. Cela vous
permet de vous connecter au serveur et de vous lier à ses événements en utilisant l'inspecteur d'objets.

3.2.2.1.3 Interfaces COM


Les clients COM communiquent avec des objets par le biais d'interfaces COM. Les interfaces sont des groupes de routines,
liées par la logique ou par la sémantique, qui assurent la communication entre le fournisseur d'un service (objet serveur) et ses
clients. Voici la représentation standard d'une interface COM :

Par exemple, tout objet COM doit implémenter l'interface de base, IUnknown ( see page 1406). Via une routine appelée
QueryInterface de IUnknown, les clients peut demander les autres interfaces implémentées par le serveur.

Les objets peuvent avoir plusieurs interfaces, où chacune implémente une fonctionnalité. L'interface est le moyen de mettre à
disposition du client le service fourni par l'objet, sans lui donner les détails de l'implémentation sur la façon dont ce service est
fourni.

Les aspects majeurs des interfaces COM sont les suivants :

• Une fois publiées, les interfaces sont immuables ; c'est-à-dire qu'elles ne changent plus. Une interface permet d'accéder à un
ensemble précis de fonctions. Les fonctionnalités supplémentaires sont fournies par le biais d'interfaces supplémentaires.
• Par convention, les identificateurs d'interfaces COM commencent par un I majuscule suivi d'un nom symbolique définissant 3
l'interface, comme IMalloc ou IPersist.
• L'identification unique des interfaces est garantie par un GUID (Globally Unique Identifier), qui est un nombre aléatoire de
128 bits. Les GUID utilisés pour identifier les interfaces sont appelés IID (Identificateurs d'interfaces). Ils permettent
d'éliminer les conflits de noms entre différentes versions d'un produit ou différents produits.
• Les interfaces sont indépendantes du langage. Vous pouvez utiliser n'importe quel langage pour implémenter une interface
COM, à condition que ce langage supporte les structures de pointeurs et puisse appeler une fonction via un pointeur, de
façon explicite ou implicite.

1405
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

• Les interfaces ne sont pas elles-mêmes des objets ; elles fournissent l'accès à un objet. Donc, les clients n'ont pas accès
directement aux données ; ils accèdent aux données par le biais d'un pointeur d'interface ( see page 1406). Windows 2000
ajoute une couche supplémentaire d'indirection connue en tant qu'intercepteur à partir duquel il fournit des fonctionnalités
COM+ telles que l'activation just-in-time et le regroupement d'objets.
• Les interfaces sont toujours dérivées de l'interface de base, IUnknown ( see page 1406).
• Les interfaces peuvent être redirigées par COM via des proxy pour permettre aux appels de méthodes de l'interface de
s'effectuer entre différents threads, processus et machines en réseau, sans que les objets client ou serveur ne soient jamais
informés de la redirection. Pour plus d'informations, voir Serveurs en processus ( see page 1408).
Voir aussi
L'interface COM de base ( see page 1406)

Pointeurs d'interface COM ( see page 1406)

3.2.2.1.4 L'interface COM de base, IUnknown


Les objets COM doivent tous supporter l'interface fondamentale, appelée IUnknown, un typedef du type d'interface de base
IInterface. IUnknown contient les routines suivantes :

QueryInterface Fournit des pointeurs sur d'autres interfaces supportées par l'objet.
AddRef et Méthodes simples de décompte de références qui permettent à un objet de contrôler sa durée de vie et de se
Release supprimer lui-même lorsque le client n'a plus besoin de son service.

Les clients obtiennent des pointeurs sur d'autres interfaces via la méthode QueryInterface de IUnknown. QueryInterface connaît
chaque interface de l'objet serveur et peut donner au client un pointeur vers l'interface demandée. Lorsqu'il reçoit un pointeur
vers une interface, le client est assuré de pouvoir appeler n'importe quelle méthode de l'interface.

Les objets contrôlent leur propre durée de vie grâce aux méthodes AddRef et Release de IUnknown, qui sont de simples
méthodes de décompte de références. Tant que le décompte de références est différent de zéro, l'objet reste en mémoire. Dès
qu'il atteint zéro, l'implémentation de l'interface peut en toute sécurité disposer du ou des objets sous-jacents.

Voir aussi
Interfaces COM ( see page 1405)

Pointeurs d'interface COM ( see page 1406)

3.2.2.1.5 Pointeurs d'interface COM


Un pointeur d'interface est un pointeur vers une instance d'objet qui pointe, à son tour, vers l'implémentation de chaque méthode
de l'interface. L'implémentation est accédée via un tableau de pointeurs vers ces méthodes, appelé vtable. Les vtables sont
similaires au mécanisme utilisé pour gérer les fonctions virtuelles sous Delphi. A cause de cette similitude, le compilateur peut
résoudre les appels de méthode de l'interface de la même manière qu'il résout les appels des méthodes de classes Delphi.

La vtable est partagée par toutes les instances d'une classe objet, et pour chaque instance de l'objet, le code de l'objet alloue
une deuxième structure contenant ses données privées. Le pointeur d'interface du client, est alors un pointeur vers le pointeur
3 vers la vtable, comme le montre le diagramme suivant.

1406
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Dans Windows 2000 et toutes les versions ultérieures de Windows, quand un objet s'exécute sous COM+, un niveau
supplémentaire d'indirection est fourni entre le pointeur d'interface et le pointeur vtable. Le pointeur d'interface disponible sur le
client pointe sur un intercepteur, qui à son tour pointe sur la vtable. Cela permet à COM+ de fournir des services comme
l'activation just-in-time, par lequel le serveur peut être désactivé et réactivé dynamiquement d'une façon opaque pour le client.
COM+ garantit que l'intercepteur se comporte comme s'il était un pointeur vtable ordinaire.

Voir aussi
L'interface COM de base ( see page 1406)

Interfaces COM ( see page 1405)

3.2.2.1.6 Serveurs COM


Un serveur COM est une application ou une bibliothèque qui fournit des services à une application ou bibliothèque client. Un
serveur COM est constitué d'un ou de plusieurs objets COM, un objet COM étant un ensemble de propriétés (données membre
ou contenu) et de méthodes (fonctions membre).

Les clients ne savent pas comment l'objet COM effectue son service ; l'implémentation de l'objet est encapsulée. Un objet met
ses services à disposition par le biais de ses interfaces ( see page 1405).

En outre, les clients n'ont pas besoin de savoir où réside l'objet COM. COM fournit un accès transparent quel que soit
l'emplacement ( see page 1408) de l'objet.

Quand il demande un service à un objet COM, le client transmet un identificateur de classe (CLSID) à COM. Un CLSID est juste
un GUID qui référence un objet COM. COM utilise ce CLSID, recensé dans le registre système, pour localiser l'implémentation
appropriée du serveur. Une fois le serveur localisé, COM amène le code en mémoire, et fait instancier par le serveur une
instance de l'objet pour le client. Ce processus est géré indirectement par un objet spécial appelé une factory (basé sur les
interfaces) qui crée sur demande des instances d'objet.

Au minimum, un serveur COM doit effectuer ceci :

• Recenser des entrées dans le registre système pour associer le module serveur à l'identificateur de classe (CLSID).
• Implémenter un objet factory de classe ( see page 1407), qui fabrique un autre objet à partir d'un CLSID particulier.
• Exposer la factory d'objet à COM.
• Fournir un mécanisme de déchargement grâce auquel un serveur qui ne sert pas de client pourra être supprimé de la
mémoire.
Remarque: Les experts de Delphi automatisent la création des objets et des serveurs COM ( see page 1416).
Voir aussi
Interfaces COM ( see page 1405)

CoClasses et factories de classes ( see page 1407)

Serveurs en processus ( see page 1408)

3.2.2.1.7 CoClasses et factories de classes 3


Un objet COM est une instance d'une CoClass, qui est une classe implémentant une ou plusieurs interfaces COM. L'objet COM
fournit les services définis par ses interfaces.

Les CoClasses sont instanciées par un type d'objet spécial, appelé une factory de classe. Chaque fois que des services d'un
objet sont demandés par un client, une factory de classe crée une instance de cet objet pour ce client particulier. Généralement,
si un autre client demande les services de l'objet, la factory de classe crée une autre instance de l'objet pour ce deuxième client.
Les clients peuvent également se lier à des objets COM en cours d'exécution qui se recensent eux-mêmes pour le gérer.

1407
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Une CoClasse doit posséder une factory de classe et un identificateur de classe (CLSID) de sorte qu'elle puisse être instancié
en externe, c'est-à-dire pour un autre module. L'utilisation de ces identificateurs uniques pour les CoClasses implique qu'elles
peuvent être mises à jour chaque fois que de nouvelles interfaces sont implémentées dans leur classe. Une nouvelle interface
peut modifier ou ajouter des méthodes sans affecter les versions antérieures, ce qui est un problème courant lorsqu'on utilise
des DLL.

Les experts de Delphi prennent en compte l'attribution d'identificateurs de classe, l'implémentation et l'instanciation des factory
de classe.

Voir aussi
Serveurs COM ( see page 1407)

Serveurs en processus ( see page 1408)

Agrégation ( see page 1410)

3.2.2.1.8 Serveurs en processus, hors processus et distants


Avec COM, un client n'a pas besoin de savoir où réside un objet, il suffit de faire un appel à une interface de l'objet. COM
accomplit les étapes nécessaires à cet appel. Ces étapes sont différentes selon que l'objet réside dans le même processus que
le client, dans un autre processus sur la machine du client ou sur une autre machine du réseau. Ces différents types de serveurs
sont décrits ici :

Serveur Une bibliothèque (DLL) s'exécutant dans le même espace processus que le client, par exemple, un contrôle
en ActiveX incorporé dans une page Web visualisée sous Internet Explorer ou Netscape. Le contrôle ActiveX est alors
processus téléchargé sur la machine du client et appelé dans le même processus que le navigateur Web.
Le client communique avec le serveur en processus grâce à des appels directs à l'interface COM.
Serveur Une autre application (EXE) s'exécutant dans un espace processus différent mais sur la même machine que le
hors client. Par exemple, une feuille de calcul Excel incorporée dans un document Word constitue deux applications
processus distinctes tournant sur la même machine.
(ou Le serveur local utilise COM pour communiquer avec le client.
serveur
local)
Serveur Une DLL ou une autre application s'exécutant sur une machine différente de celle du client. Par exemple, une
distant application Delphi de base de données connectée à un serveur d'application sur une autre machine du réseau.
Le serveur distant utilise des interfaces COM distribuées (DCOM) pour accéder aux interfaces et communiquer
avec le serveur d'application.

Comme illustré dans la figure suivante, pour les serveurs en processus, les pointeurs sur les interfaces de l'objet sont dans le
même espace processus que le client, et COM fait des appels directs dans l'implémentation de l'objet.

3
Remarque: Cela n'est pas toujours vrai avec COM+. Quand le client appelle un objet dans un contexte différent, COM+
intercepte l'appel afin qu'il se comporte comme l'appel d'un serveur hors processus (voir plus bas) même si le serveur est en
processus.

Comme illustré dans la figure suivante, quand le processus est soit différent, soit sur une autre machine, COM utilise un proxy
pour initier les appels de procédure distants. Le proxy réside dans le même processus que le client, de sorte que vu du client,
tous les appels à des interfaces semblent pareils. Le proxy intercepte l'appel du client et le transmet là où l'objet réel s'exécute.

1408
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Le mécanisme qui permet aux clients d'accéder aux objets d'un espace processus différent, ou même d'une machine différente,
comme s'ils se trouvaient dans leur propre processus, est appelé le marshaling ( see page 1409).

La différence entre les serveurs hors processus et serveurs distants est le type de communication inter-processus utilisé. Le
proxy utilise COM pour communiquer avec un serveur hors processus et COM distribué (DCOM) pour communiquer avec une
machine distante. DCOM transfère de manière transparente une demande d'objet local dans l'objet distant s'exécutant sur une
autre machine.

Remarque: Pour les appels de procédure à distance, DCOM utilise le protocole RPC fourni par le DCE (Distributed Computing
Environment) d'Open Group. Pour la sécurité distribuée, DCOM utilise le protocole de sécurité NTLM (NT LAN Manager). Pour
les services de répertoires, DCOM utilise le DNS (Domain Name System).

Voir aussi
CoClasses et factories de classes ( see page 1407)

Serveurs COM ( see page 1407)

Le mécanisme du marshaling ( see page 1409)

Agrégation ( see page 1410)

3.2.2.1.9 Le mécanisme du marshaling


Le marshaling est le mécanisme qui permet à un client de faire des appels aux fonctions de l'interface d'objets distants qui se
trouvent dans un autre processus ou sur une autre machine. Le marshaling

• Prend un pointeur d'interface dans le processus du serveur et rend un pointeur de proxy disponible au code dans le
processus du client.
• Prend les arguments d'un appel à l'interface passés depuis le client et les place dans l'espace processus de l'objet distant.
Pour tout appel à l'interface, le client met les arguments sur une pile et émet un appel à une fonction via le pointeur d'interface.
Si l'appel à l'objet n'est pas en processus, il est passé au proxy. Celui-ci compresse les arguments dans un paquet de
marshaling et transmet la structure à l'objet distant. Le stub de l'objet décompresse le paquet, place les arguments sur la pile
et appelle l'implémentation de l'objet. L'objet recrée l'appel du client dans son propre espace d'adressage.
Le type de marshaling dépend de l'interface implémentée par l'objet COM. Les objets peuvent utiliser le mécanisme de
marshaling standard fourni par l'interface IDispatch. C'est un mécanisme de marshaling générique qui permet la
communication via un appel standard à une procédure distante (RPC). Pour plus de détails sur l'interface IDispatch, voir 3
Interfaces d'Automation ( see page 1464). Quand l'objet n'implémente pas IDispatch, s'il se limite lui-même aux types
compatibles Automation et s'il a une bibliothèque de types recensée, COM fournit automatiquement la gestion du marshaling.
Les applications qui ne se limitent pas eux-mêmes aux types compatibles automation ou recensent une bibliothèque de types
doivent fournir leur propre marshaling. Le marshaling est fourni par le biais d'une implémentation de l'interface IMarshal, ou
en utilisant une DLL proxy/stub générée séparément. Delphi ne prend pas en charge la génération automatique des DLL
proxy/stub.

1409
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Voir aussi
Serveurs en processus ( see page 1408)

Automation ( see page 1412)

Agrégation ( see page 1410)

3.2.2.1.10 Serveurs Automation


Dans certains cas, un objet serveur peut utiliser un autre objet COM pour effectuer certaines de ces fonctions. Par exemple, un
objet de gestion de stock peut utiliser un objet commande séparé pour gérer les commandes des clients. Si l'objet de gestion de
stock veut présenter une interface de commande au client, il y a un problème. Même si le client ayant une interface stock peut
appeler QueryInterface pour obtenir l'interface commande, quand l'objet commande a été créé, il ne connaît pas l'objet gestion
de stock et ne peut lui renvoyer une interface stock en réponse à un appel de QueryInterface. Un client qui a l'interface
commande ne peut revenir dans l'interface stock.

Pour éviter ce problème, certains objets COM gèrent l'agrégation. Quand l'objet gestion de stock crée une instance de l'objet
commande, il lui transmet une copie de sa propre interface IUnknown. L'objet commande peut ensuite utiliser cette interface
IUnknown et gérer les appels de any QueryInterface qui demandent une interface, comme l'interface stock, qu'il ne gère pas.
Quand cela se produit, les deux objets pris ensemble s'appellent un agrégat. L'objet commande est appelé l'objet interne (ou
objet contenu) de l'agrégat et l'objet stock est appelé l'objet externe.

Remarque: Pour pouvoir se comporter comme objet externe d'un agrégat, un objet COM doit créer l'objet interne en utilisant
l'API Windows CoCreateInstance ou CoCreateInstanceEx, en lui transmettant comme paramètre un IUnknown que l'objet
interne peut utiliser pour les appels de QueryInterface.

Pour créer un objet qui puisse se comporter comme objet interne d'un agrégat, il doit descendre de TContainedObject. Quand
l'objet est créé, l'interface IUnknown de l'objet externe est transmise au constructeur afin qu'elle puisse être utilisée par la
méthode QueryInterface pour les appels que l'objet interne ne peut pas traiter.

Voir aussi
Serveurs en processus ( see page 1408)

Automation ( see page 1412)

Le mécanisme du marshaling ( see page 1409)

3.2.2.1.11 Clients COM


Les clients peuvent toujours interroger les interfaces d'un objet COM pour déterminer ce qu'il est capable de faire. Tous les
objets COM permettent aux clients de demander les interfaces connues. De plus, si le serveur gère l'interface IDispatch, les
clients peuvent demander au serveur des informations sur les méthodes gérées par le serveur. Les objets serveurs n'ont pas
d'attentes concernant l'utilisation de ses objets par le client. De même, les clients n'ont pas besoin de savoir comment (ou même
si) un objet fournit les services ; ils s'en remettent simplement sur les objets serveurs pour fournir les services qu'ils annoncent
via leurs interfaces.
3
Il y a deux types de clients COM : les contrôleurs et les conteneurs. Un contrôleur lance le serveur et interagit avec lui via son
interface. Il demande des services de l'objet COM ou il le pilote comme processus distinct. Les conteneurs accueillent des
contrôles visuels ou des objets qui apparaissent dans l'interface utilisateur du conteneur. Ils utilisent des interfaces prédéfinies
pour négocier les problèmes d'affichage avec les objets serveur. Il est impossible d'avoir une relation conteneur sur DCOM ; par
exemple, les contrôles visuels qui apparaissent dans l'interface utilisateur du conteneur doivent être localisés localement. En
effet, les contrôles sont supposés se dessiner eux-mêmes, ce qui nécessite qu'ils puissent accéder aux ressources GDI locales.

Delphi facilite le développement d'un contrôleur Automation en permettant d'importer la bibliothèque de types ou un contrôle

1410
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

ActiveX dans un composant enveloppe de telle manière que les objets serveur apparaissent comme les autres composants
VCL. Pour des détails sur ce processus, voir Création de clients COM ( see page 1440)

3.2.2.1.12 Extensions de COM


COM a été initialement conçu pour fournir une fonctionnalité de communication de base et permettre l'enrichissement de cette
fonctionnalité via des extensions. COM lui-même a étendu sa fonctionnalité première en définissant des ensembles spécialisés
d'interfaces couvrant des besoins spécifiques.

Le tableau suivant est un résumé de certaines des extensions de services que COM fournit actuellement.

serveurs L'Automation désigne la capacité d'une application à contrôler par programme les objets d'une autre
Automation ( see application. Les serveurs Automation sont les objets qui peuvent être contrôlés par d'autres exécutables
page 1412) à l'exécution.
contrôles ActiveX Les contrôles ActiveX sont des serveurs en processus COM spécialisés, généralement conçus pour être
( see page 1413) incorporés dans une application client. Les contrôles proposent des comportements et des événements à
la conception et à l'exécution.
Pages Active Les pages Active Server sont des scripts qui génèrent des pages HTML. Le langage de script contient
Server ( see page des structures permettant la création et l'exécution d'objets Automation. C'est-à-dire qu'une page Active
1412) Server se comporte comme un contrôleur Automation
Documents Active Objets supportant la liaison et l'incorporation, le glisser-déplacer, l'édition visuelle et l'activation in-situ.
( see page 1413) Les documents Word et les feuilles de calcul Excel sont des exemples de documents Active.
Objets abonnement Objets prenant en charge le modèle événementiel COM+ faiblement lié. A l'inverse du modèle
d'événement et étroitement lié utilisé par les contrôles ActiveX, le modèle événementiel COM+ vous permet de
événement COM+ développer des éditeurs d'événements indépendamment des abonnés d'événements.
Bibliothèques de Collection de structures de données statiques, souvent enregistrées en tant que ressource, fournissant
types ( see page des informations de type détaillées sur un objet et ses interfaces. Les clients des serveurs Automation,
1414) les contrôles ActiveX et les objets transactionnels ont besoin des informations de type.

Le diagramme page suivante montre les relations entre les extensions de COM et la façon dont elles dérivent de COM.

Les objets COM peuvent être visuels ou non visuels. Certains s'exécutent dans le même espace processus que leurs clients ;
d'autres peuvent s'exécuter dans des processus différents ou sur des machines distantes si les objets assurent le marshaling.
Le tableau suivant récapitule les types d'objets COM que vous pouvez créer, s'ils sont visuels, les espaces processus dans
lesquels ils peuvent s'exécuter, le marshaling ( see page 1409) qu'ils fournissent et s'ils ont besoin d'une bibliothèque de types.

Exigences des objets COM

1411
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Objet Objet visuel ? Espace processus Communication Bibliothèque


de types
Document Habituellement En processus ou hors Verbes OLE Non
Active processus
Serveur Parfois En processus, hors Marshaling automatique via l'interface IDispatch Requis pour
Automation processus ou distant (pour les serveurs hors processus ou distants) le marshaling
automatique
Contrôle Habituellement En processus Marshaling automatique via l'interface IDispatch Requise
ActiveX
COM+ Parfois En processus pour Marshaling automatique via une bibliothèque de Requise
MTS, tous pour COM+ types
Objet interface Facultativement En processus Pas de marshaling requis pour les serveurs en Recommandé
personnalisé processus
Autre objet Facultativement En processus, hors Marshaling automatique via une bibliothèque de Recommandé
interface processus ou distant types ; sinon, marshaling manuel via des
personnalisé interfaces personnalisées

3.2.2.1.13 Serveurs Automation


L'Automation désigne la capacité d'une application à contrôler par programme les objets d'une autre application, comme une
macro qui peut manipuler plusieurs applications à la fois. Le client d'un objet Automation est appelé contrôleur Automation, et
l'objet serveur manipulé est appelé objet Automation.

L'Automation peut être utilisée sur des serveurs en processus, locaux ou distants.

L'Automation présente deux caractéristiques :

• L'objet Automation définit un ensemble de propriétés et de commandes, et décrit ses capacités via les descriptions de type.
Pour ce faire, il doit disposer d'un moyen de fournir des informations sur les interfaces de l'objet, les méthodes des interfaces
et les arguments de ces méthodes. Généralement, ces informations se trouvent dans des bibliothèques de types ( see page
1414). Le serveur Automation peut aussi générer des informations dynamiquement quand elles lui sont demandées via son
interface IDispatch (voir plus bas).
• Les objets Automation rendent ces méthodes accessibles pour que d'autres applications puissent les utiliser. Pour cela, ils
implémentent l'interface IDispatch. C'est par le biais de cette interface qu'un objet peut exposer toutes ses méthodes et
propriétés. Et c'est par le biais de la méthode primaire de cette interface que les méthodes de l'objet peuvent être appelées,
une fois qu'elles ont été identifiées grâce aux informations de type.
Les développeurs utilisent souvent l'Automation pour créer et utiliser des objets OLE non visuels qui s'exécutent dans n'importe
quel espace processus, car l'interface Automation IDispatch automatise le processus de marshaling. En revanche,
l'Automation limite les types que vous pouvez utiliser.
Pour obtenir une liste de types compatibles avec les bibliothèques de types en général, et d'interfaces Automation en particulier,
voir Types autorisés ( see page 1481).
Voir aussi

3 Création de serveurs COM simples : Vue globale ( see page 1456)

Utilisation des bibliothèques de types : Vue globale ( see page 1472)

Création de pages Active Server ( see page 1420)

3.2.2.1.14 Pages Active Server


La technologie ASP (pages Active Server) vous permet d'écrire des scripts simples, appelés pages Active Server qui peuvent

1412
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

être exécutées par les clients via un serveur Web. A la différence des contrôles ActiveX qui s'exécutent sur le client, les pages
Active Server s'exécutent sur le serveur et renvoient les pages HTML résultantes aux clients.

Les pages Active Server sont écrites en JScript ou en VBscript. Le script est exécuté à chaque fois que le serveur charge la
page Web. Ce script peut alors lancer un serveur Automation incorporé (ou un Bean Java Entreprise). Vous pouvez, par
exemple, écrire un serveur Automation pour se connecter à une base de données, ce serveur accédant à des données qui sont
actualisées à chaque fois que le client charge la page Web.

Les pages Active Server s'appuient sur l'environnement IIS (Internet Information Server) de Microsoft pour traiter vos pages Web.

Les experts Delphi facilitent la création de pages Active Server ( see page 1420) qui est un objet Automation spécialement
conçu pour travailler avec une page Active Server.

Voir aussi
Création de pages Active Server ( see page 1420)

Utilisation des bibliothèques de types : Vue globale ( see page 1472)

3.2.2.1.15 Contrôles ActiveX


ActiveX est une technologie qui permet aux composants COM, particulièrement aux contrôles, d'être plus compacts et efficaces.
Cela est particulièrement important pour les contrôles conçus pour des applications Intranet qui nécessitent leur téléchargement
par le client avant de les utiliser.

Les contrôles ActiveX sont des contrôles visuels qui s'exécutent uniquement comme des serveurs en processus et qui peuvent
s'intégrer dans une application conteneur ActiveX. Ce ne sont pas des applications complètes par eux-mêmes, vous pouvez les
voir comme des contrôles OLE préfabriqués qui sont réutilisables dans diverses applications. Les contrôles ActiveX ont une
interface utilisateur apparente et reposent sur l'utilisation d'interfaces prédéfinies pour négocier les entrées/sorties et les
questions d'affichage avec le conteneur hôte.

Les contrôles ActiveX utilisent l'Automation pour exposer leurs propriétés, méthodes et événements. Leurs fonctionnalités
incluent la capacité à déclencher des événements, la liaison aux sources de données et la gestion de licence.

Les contrôles ActiveX s'utilisent parfois dans un site Web comme objets interactifs placés dans une page Web. Ainsi, ActiveX est
devenu un standard particulièrement destiné à des contenus interactifs pour le Web, y compris l'utilisation de documents ActiveX
employés pour visualiser des documents non HTML via un navigateur Web. Pour plus d'informations sur la technologie ActiveX,
voir le site Web de Microsoft.

Voir aussi
Utilisation des contrôles ActiveX ( see page 1426)

3.2.2.1.16 Documents Active


Les Documents Active (préalablement appelés documents OLE) constituent un ensemble de services COM prenant en charge la
liaison et l'incorporation, le glisser-déplacer, ainsi que l'édition visuelle. Les documents Active intègrent de façon transparente
des données ou des objets de différents formats, par exemple des clips sonores, des feuilles de calcul, du texte et des images.
3
Au contraire des contrôles ActiveX, les Documents Active ne sont pas limités aux serveurs en processus; ils peuvent être utilisés
dans des applications inter-processus.

Au contraire des objets Automation, qui ne sont presque jamais visuels, les objets Document Active peuvent être visuellement
actifs dans une autre application. De ce fait, les objets Document Active sont associés à deux types de données : les données
de présentation, utilisées pour afficher visuellement l'objet sur un écran ou un autre périphérique de sortie, et les données
natives, utilisées pour modifier un objet.

Les objets document Active peuvent être des conteneurs ou des serveurs de documents. Bien que Delphi ne fournisse pas

1413
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

d'expert pour créer automatiquement des documents Active, vous pouvez utiliser la classe TOleContainer de la VCL pour
supporter la liaison et l'incorporation dans les documents Active existants.

Vous pouvez aussi utiliser TOleContainer comme base d'un conteneur de document Active. Pour créer des objets pour les
serveurs de documents Active, utilisez une des classes de base COM de la VCL et implémentez les interfaces appropriées à ce
type d'objet, en fonction des services que l'objet doit gérer. Pour plus d'informations sur la création et l'utilisation de serveurs de
documents Active, voir le site Web Microsoft.

Remarque: Bien que la spécification des documents Active contienne une gestion intégrée du marshaling des applications à
processus croisé, les documents Active ne s'exécutent pas sur des serveurs distants car les types qu'ils utilisent (handles de
fenêtre, de menu, etc.) sont spécifiques à un système sur une machine donnée.

3.2.2.1.17 Bibliothèques de types


Les bibliothèques de types offrent un moyen d'obtenir davantage d'informations de type sur un objet que les interfaces de l'objet.
Les bibliothèques de types contiennent les informations nécessaires sur les objets et leurs interfaces, comme les interfaces
associées à tels objets (étant donné le CLSID), les fonctions membre de chaque interface et les arguments requis par ces
fonctions.

Vous pouvez obtenir les informations de type en interrogeant une instance d'un objet pendant qu'elle s'exécute ou, en chargeant
et en lisant les bibliothèques de types. Grâce à ces informations, vous pouvez implémenter un client qui utilise un objet souhaité,
en sachant exactement les fonctions membre dont vous avez besoin, et ce qu'il faut passer à ces fonctions.

Les clients des serveurs Automation, les contrôles ActiveX et les objets transactionnels ont besoin des informations de type.
Tous les experts Delphi génèrent automatiquement une bibliothèque de types (même si c'est facultatif avec l'expert objet COM).
Vous pouvez visualiser et modifier ces informations de type en utilisant l'éditeur de bibliothèques de types ( see page 1472).

Contenu d'une bibliothèque de types


Les bibliothèques de types contiennent des informations de type qui indiquent quelles interfaces existent et dans quels objets
COM, ainsi que le type et le nombre d'arguments des méthodes d'interface. Ces descriptions incluent les identificateurs uniques
de CoClasses (CLSID) et d'interfaces (IID), pour que l'utilisateur y accède de façon correcte, ainsi que les identificateurs de
répartition (dispID) pour les méthodes et propriétés d'interface Automation.

Les bibliothèques de types peuvent aussi contenir les informations suivantes :

• Une description des informations personnalisées de type associées aux interfaces personnalisées
• Des routines exportées par le serveur Automation ou ActiveX mais qui ne sont pas des méthodes d'interface
• Des informations concernant l'énumération, les enregistrements (structures), les unions, les alias et les types des données
des modules
• Des références aux descriptions de types issues d'autres bibliothèques de types
Création de bibliothèques de types
Avec les outils de développement traditionnels, vous créez des bibliothèques de types en écrivant des scripts en IDL (Interface
Definition Language) ou en ODL (Object Description Language), puis en compilant ces scripts. Delphi génère automatiquement
une bibliothèque de types lorsque vous créez un objet COM (contrôles ActiveX, objets Automation, modules de données
3 distants, etc.) en utilisant l'un des experts de la page ActiveX de la boîte de dialogue Nouveaux Eléments. Vous pouvez décider
de ne pas générer de bibliothèque de types si vous utilisez l'expert objet COM. Vous pouvez également créer une bibliothèque
de types en choisissant dans le menu principal Fichier Nouveau Autre, en sélectionnant le dossier ActiveX sous Projets
Delphi, puis en choisissant Bibliothèque de types dans le volet droit .

Vous pouvez ensuite voir la bibliothèque de types en utilisant l'éditeur de bibliothèques de types de Delphi. Il est facile de
modifier la bibliothèque de types à l'aide de l'éditeur de bibliothèques de types Delphi met automatiquement à jour le fichier TLB
correspondant quand la bibliothèque de types est enregistrée. Si vous modifiez les interfaces et les CoClasses créées en
utilisant un expert, l'éditeur de bibliothèques de types actualise également les fichiers d'implémentation.

1414
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Quand utiliser les bibliothèques de types


Il est important de créer une bibliothèque de types pour chaque ensemble d'objets qui est présenté aux utilisateurs finaux, par
exemple,

• Les contrôles ActiveX nécessitent une bibliothèque de types, qui doit être incluse en tant que ressource dans la DLL qui
contient les contrôles ActiveX.
• Les objets exposés qui gèrent la liaison de vtable des interfaces personnalisées doivent être décrits dans une bibliothèque de
types car les références à la vtable sont liées à la compilation. Les clients importent depuis la bibliothèque de types les
informations sur les interfaces et utilisent ces informations pour compiler. Pour plus de détails sur les vtables et les liaisons
effectuées lors de la compilation, voir Interfaces d'Automation ( see page 1464).
• Les applications qui implémentent des serveurs Automation doivent fournir une bibliothèque de types pour que les clients
puissent faire une liaison immédiate.
• Les objets instanciés depuis des classes qui gèrent l'interface IProvideClassInfo tels que tous les descendants de la classe
VCL TTypedComObject, doivent posséder une bibliothèque de types.
• Les bibliothèques de types ne sont pas nécessaires mais utiles pour identifier les objets OLE utilisables par glisser-déplacer.
Si vous définissez des interfaces à usage exclusivement interne (au sein d'une application), il n'est pas nécessaire de créer une
bibliothèque de types. .
Accès aux bibliothèques de types
En règle générale, une bibliothèque de types fait partie d'un fichier de ressource (.res) ou d'un fichier autonome à l'extension .tlb.
Quand elle est placée dans un fichier ressource, la bibliothèque de types peut être liée à un serveur (.dll, .ocx ou .exe).

Lorsqu'une bibliothèque de types a été créée, les scruteurs d'objets, les compilateurs et les outils similaires peuvent y accéder
par des interfaces spéciales :

Interfaces spéciales

Interface Description
ITypeLib Fournit des méthodes pour accéder à la description d'une bibliothèque de types.
ITypeLib2 Augmente ITypeLib pour inclure la gestion des chaînes de documentation, les données personnalisées et des
statistiques sur la bibliothèque de types.
ITypeInfo Fournit la description de chaque objet d'une bibliothèque de types. Par exemple, un navigateur utilise cette
interface pour extraire des informations sur les objets de la bibliothèque de types.
ITypeInfo2 Augmente ITypeInfo pour accéder à des informations supplémentaires de la bibliothèque de types, comme les
méthodes d'accès aux éléments de données personnalisés.
ITypeComp Fournit un moyen rapide d'accéder aux informations dont le compilateur a besoin lors de la liaison avec une
interface.

Delphi peut importer et utiliser des bibliothèques de types venant d'autres applications en choisissant Projet|Importer une
bibliothèque de types. La plupart des classes de la VCL employées pour les applications COM supportent les interfaces
essentielles utilisées pour stocker et récupérer les informations de types à partir des bibliothèques de types et des instances
actives d'un objet. La classe TTypedComObject de la VCL supporte les interfaces qui fournissent des informations de type et
s'utilise comme une fondation pour l'environnement objet ActiveX.
3
Avantages des bibliothèques de types
Même si votre application ne nécessite pas de bibliothèque de types, considérez les avantages suivants :

• La vérification des types peut se faire lors de la compilation.


• Vous pouvez utiliser la liaison immédiate avec l'automation (ce qui remplace les appels par le biais de variants) et les
contrôleurs qui ne gèrent pas les vtables ou les interfaces doubles peuvent coder les dispID lors de la compilation pour
améliorer les performances de l'application.
• Les scruteurs de types peuvent parcourir la bibliothèque.

1415
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

• La fonction RegisterTypeLib peut être utilisée pour recenser vos objets présentés dans la base de données de recensement.
• La fonction UnRegisterTypeLib peut être utilisée pour désinstaller complètement la bibliothèque de types d'une application du
registre.
• L'accès local au serveur est accéléré car l'automation utilise les informations de la bibliothèque de types pour regrouper les
paramètres qui sont passés à un objet d'un autre processus.
Utilisation des outils de bibliothèques de types
Les outils permettant de manipuler des bibliothèques de types sont indiqués

• L'outil TLIBIMP (importation de bibliothèque de types), qui crée des fichiers d'interface Delphi (fichiers _TLB.pas) à partir de
bibliothèques de types est intégré dans l'éditeur de bibliothèques de types. TLIBIMP offre des options de configuration
supplémentaires non disponibles dans l'éditeur de bibliothèques de types.
• TRegSvr est un outil pour recenser et dérecenser les serveurs et les bibliothèques de types, fourni avec Delphi. Le source de
TRegSvr est disponible sous la forme d'un exemple dans le répertoire Demos.
• Le compilateur Microsoft IDL (MIDL) compile les scripts IDL pour créer une bibliothèque de types.
• RegSvr32.exe est un utilitaire standard de Windows pour recenser et dérecenser les serveurs et les bibliothèques de types.
• OLEView est un outil de visualisation de bibliothèque de types disponible sur le site Web de Microsoft.
Voir aussi
Utilisation des bibliothèques de types ( see page 1472)

3.2.2.1.18 Implémentation des objets COM à l'aide d'experts


Delphi facilite l'écriture de serveurs COM en fournissant des experts qui gèrent nombre des problèmes posés. Delphi propose
des experts distincts permettant de créer :

• Un simple objet COM


• Un objet Automation
• Un objet événement COM+
• Une bibliothèque de types
• Une bibliothèque ActiveX
Les experts gèrent beaucoup des problèmes intervenant dans la création de chaque type d'objet. Ils fournissent les interfaces
COM requises pour chaque type d'objet. Avec un simple objet COM, l'expert implémente la seule interface COM obligatoire,
IUnknown, qui fournit un pointeur d'interface vers l'objet.

L'expert objet COM propose également une implémentation de IDispatch si vous spécifiez que vous créez un objet gérant un
descendant de IDispatch.
Pour les objets Automation et Active Server, l'expert implémente IUnknown et IDispatch, qui fournissent le marshaling
automatique.

Pour les objets contrôles ActiveX et fiches ActiveX, l'expert implémente toutes les interfaces requises par les contrôles ActiveX :
IUnknown, IDispatch, IOleObject, IOleControl, etc. Pour obtenir la liste complète des interfaces, reportez-vous à la page de
référence de TActiveXControl.

1416
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Le tableau suivant énumère les divers experts et les interfaces qu'ils implémentent :
Experts Delphi qui implémentent des objets COM, Automation et ActiveX

Expert Interfaces Ce que fait l'expert


implémentées
Serveur IUnknown (et Exporte les routines nécessaires pour gérer le recensement du serveur, le recensement des
COM ( see IDispatch si classes, le chargement et le déchargement du serveur et l'instanciation des objets.
page 1456) vous Crée et gère les factories de classes pour les objets implémentés sur le serveur.
sélectionnez
Fournit les entrées de registre pour l'objet spécifiant le modèle de thread sélectionné.
une interface
par défaut qui Déclare les méthodes qui implémentent l'interface sélectionnée et fournit un squelette
descend de d'implémentation que vous devez compléter.
IDispatch) Fournit une bibliothèque de types, si elle est demandée.
Vous permet de sélectionner une interface arbitraire qui est recensée dans la bibliothèque de
types et de l'implémenter. Pour cela, vous devez utiliser une bibliothèque de types.
Serveur IUnknown, Effectue les actions d'un expert serveur COM (décrit plus haut) plus :
Automation IDispatch Implémente l'interface spécifiée (dual ou dispatch).
( see page
Fournit une prise en charge côté serveur de la génération des événements, le cas échéant.
1458)
Fournit automatiquement une bibliothèque de types.
Objet Aucune par Crée un objet événement COM+ que vous pouvez définir en utilisant l'éditeur de bibliothèque
événement défaut de types. A la différence des autres experts, l'expert objet événement COM+ ne crée pas
COM+ d'unité d'implémentation car les objets événement n'ont pas d'implémentation (elle est fournie
par les souscripteurs d'événements des clients).
Bibliothèque Aucune par Crée une nouvelle bibliothèque de types et l'associe au projet actif.
de types ( défaut
see page
1472)
Bibliothèque Aucune par Crée une nouvelle DLL ActiveX ou serveur COM et expose les fonctions d'exportation
ActiveX défaut nécessaires.

Si vous voulez, vous pouvez ajouter d'autres objets COM (ou refaire une implémentation existante). Pour ajouter un nouvel
objet, il est plus simple d'utiliser l'expert une seconde fois. En effet, l'expert met en place l'association entre la bibliothèque de
types et une classe d'implémentation, ainsi les modifications effectuées dans l'éditeur de bibliothèques de types sont
automatiquement appliquées à l'unité d'implémentation.
3
3.2.2.1.19 Code généré par les experts
Les experts Delphi des classes qui dérivent du modèle ActiveX Delphi (DAX). En dépit de son nom, DAX gère tous les types
d'objet COM et pas uniquement les contrôles ActiveX. Les classes de ce modèle fournissent l'implémentation sous-jacente des
interfaces COM aux objets que vous créez en utilisant un expert. La figure suivante illustre les objets de l'infrastructure ActiveX
de Delphi :

1417
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Chaque expert génère une unité d'implémentation qui implémente votre objet serveur COM. L'objet serveur COM (l'objet
implémentation) descend de l'une des classes DAX :

Classes de base DAX utilisées par les classes d'implémentation générées

Expert Classe de base Gestion héritée


DAX

Serveur COM ( see page 1456) TTypedComObject Gestion des interfaces IUnknown et ISupportErrorInfo.
Gestion de l'agrégation, des exceptions OLE, de la convention
d'appel safecall et des conventions sur les interfaces doubles.
Gestion de la lecture des informations des bibliothèques de types.
Serveur Automation ( see page TAutoObject Tout ce qui est fourni par TTypedComObject, plus :
1458) ou Création de pages Active Gestion de l'interface IDispatch.
Server ( see page 1420)
Gestion de l'auto-marshaling.

Une hiérarchie d'objets fabricant de classe correspond aux classes de DAX et gère la création de ces objets COM. L'expert
ajoute du code à la section initialisation de votre unité d'implémentation pour instancier le fabricant de classe approprié à votre
classe d'implémentation.

Les experts génèrent également une bibliothèque de types et son unité associée, qui porte un nom de la forme Project1_TLB.
L'unité Project1_TLB contient les définitions dont votre application a besoin pour utiliser les types et les interfaces définis dans
la bibliothèque de types. Pour plus d'informations sur le contenu de ce fichier, voir Code généré par l'importation des
informations d'une bibliothèque de types ( see page 1442).

Vous pouvez modifier l'interface générée par l'expert en utilisant l'éditeur de bibliothèques de types. Si vous le faites, la classe
d'implémentation est automatiquement actualisée pour refléter vos modifications. Il vous suffit juste de remplir le corps des
méthodes générées pour compléter l'implémentation.

3.2.2.1.20 Objets Abonnement d'événement et Evénement COM+


Le système d'événements COM+ présente une couche logicielle intermédiaire qui sépare les applications générant des
événements (appelées éditeurs de logiciels) des applications répondant aux événements (appelées abonnés). Au lieu d'être
étroitement liés les uns aux autres, les éditeurs de logiciels et les abonnés peuvent être développés, déployés et activés
indépendamment.
3 Dans le modèle d'événements COM+, une interface événement est d'abord créée en employant l'expert Objet Evénement
COM+. L'interface événement n'a pas d'implémentation ; elle définit simplement les méthodes des événements que les éditeurs
de logiciels généreront et auxquels les abonnés répondront. L'objet événement COM+ est ensuite installé dans une application
COM+, dans le catalogue COM+. Cela peut s'effectuer par programmation à l'aide de l'objet TComAdminCatalog, ou par un
administrateur système utilisant l'outil Component Services.

Les abonnés d'événements ont la responsabilité de fournir une implémentation pour l'interface événement. Vous pouvez créer
les composants abonnés d'événements à l'aide de l'expert Abonnement Evénement COM+. En utilisant l'expert, vous pouvez

1418
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

sélectionner l'objet événement à implémenter et l'EDI écrasera chaque méthode de l'interface. Vous pouvez également
sélectionner une bibliothèque de types si l'objet événement n'a pas encore été installé dans le catalogue COM+.

Enfin, une fois le composant abonné implémenté, il doit également être installé dans le catalogue COM+. Ceci peut se faire par
programme avec un objet TComAdminCatalog ou à l'aide de l'outil d'administration des services de composants.

Lorsqu'un éditeur de logiciels souhaite générer un événement, il crée simplement une instance de l'objet événement (pas du
composant abonné), et appelle les méthodes appropriées sur l'interface événement. COM+ intervient ensuite et avertit toutes les
applications abonnées à cet objet événement, en les appelant de façon synchrone, une à la fois. De cette façon, les éditeurs de
logiciels n'ont pas besoin de connaître quoi que ce soit des applications abonnées à l'événement. Les abonnés n'ont pas besoin
d'autre chose que d'une implémentation de l'interface événement, et de sélectionner les éditeurs de logiciels auxquels ils
souhaitent s'abonner. COM+ gère le reste.

Pour plus d'informations sur le système d'événements COM+, voir Génération d'événements dans COM+.

3.2.2.2 Création d'une page Active Server


Rubriques
Nom Description
Création de pages Active Server : Vue globale ( see page 1420) Si vous utilisez l'environnement Microsoft Internet Information Server (IIS) pour
proposer vos pages Web, vous pouvez utiliser ASP (Active Server Pages) pour
créer des applications client/serveur Web dynamiques. ASP vous permet d'écrire
un script qui est appelé à chaque fois que le serveur charge la page Web. Ce
script peut, à son tour, appeler des objets Automation ( see page 1456) pour
obtenir des informations qu'il peut inclure dans une page HTML générée. Vous
pouvez, par exemple, écrire un serveur Automation Delphi pour se connecter à
une base de données et utiliser ce contrôle pour accéder aux données qui sont
ainsi actualisées à chaque... suite ( see page 1420)
Création d'un objet Active Server ( see page 1420) Un objet Active Server est un objet Automation qui accède à toutes les
informations de l'application ASP et aux messages HTTP qu'elle utilise pour
communiquer avec les navigateurs. Il descend de TASPObject ou de
TASPMTSObject (qui à son tour descend de TAutoObject), et il gère les
protocoles d'Automation, en s'exposant pour être utilisé par d'autres applications
ou par le script dans la page Active Server. Pour créer un objet Active Server,
utilisez l'expert Objet Active Server.
Votre projet d'objet Active Server peut prendre, selon vos besoins, la forme d'un
exécutable (exe) ou d'une bibliothèque (dll). Cependant vous devez tenir
compte... suite ( see page 1420)
Utilisation des éléments intrinsèques ASP ( see page 1421) Les objets intrinsèques ASP sont un ensemble d'objets COM fournis par ASP
aux objets qui s'exécutent dans une page Active Server. Ils permettent à votre
objet Active Server d'accéder aux informations reflétant les messages échangés
entre votre application et le navigateur Web ainsi qu'un moyen de stocker des
informations partagées par tous les objets Active Server appartenant à une
même application ASP.
Pour simplifier l'accès à ces objets, la classe de base de votre objet Active
Server les présente sous la forme de propriétés. Pour une description complète
de ces objets, reportez-vous à la documentation Microsoft. Les rubriques
suivantes vous... suite ( see page 1421)
Création d'ASP pour des serveurs en et hors processus ( see page 1425) Vous pouvez utiliser Server.CreateObject dans une page ASP pour démarrer un
serveur en ou hors processus ( see page 1408) en fonction de vos besoins.
Généralement les serveurs en processus sont plus couramment utilisés.
A la différence de la plupart des serveurs en processus, un objet Active Server
ne s'exécute pas dans l'espace de processus du client. A la place, il s'exécute
dans l'espace du processus IIS. Cela signifie que le client n'a pas besoin de
télécharger votre application (comme c'est, par exemple, le cas avec des objets
3
ActiveX). Les composants DLL en processus sont plus rapides et plus fiables
que des serveurs hors... suite ( see page 1425)
Recensement d'un objet Active Server ( see page 1425) Vous pouvez recenser l'objet ASP comme serveur en ou hors processus ( see
page 1425). Généralement les serveurs en processus sont plus couramment
utilisés.
Remarque: Si vous voulez retirer l'objet ASP de votre système, vous devez
commencer par annuler son recensement, puis retirer ses entrées dans le
registre Windows.

1419
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Test et débogage d'une application ASP (Active Server Page) ( see page 1425) Le débogage d'un serveur en processus comme un objet Active Server se fait
comme celui d'une DLL. Vous choisissez une application hôte qui charge la DLL
et débogez de manière habituelle.

3.2.2.2.1 Création de pages Active Server : Vue globale


Si vous utilisez l'environnement Microsoft Internet Information Server (IIS) pour proposer vos pages Web, vous pouvez utiliser
ASP (Active Server Pages) pour créer des applications client/serveur Web dynamiques. ASP vous permet d'écrire un script qui
est appelé à chaque fois que le serveur charge la page Web. Ce script peut, à son tour, appeler des objets Automation ( see
page 1456) pour obtenir des informations qu'il peut inclure dans une page HTML générée. Vous pouvez, par exemple, écrire un
serveur Automation Delphi pour se connecter à une base de données et utiliser ce contrôle pour accéder aux données qui sont
ainsi actualisées à chaque fois que le serveur charge la page Web.

Pour le client, ASP apparaît comme un document standard HTML qui peut être visualisé par les utilisateurs de toute plate-forme
disposant d'un navigateur Web.

Les applications ASP sont similaires aux applications écrites en utilisant la technologie courtier Web Delphi. Pour davantage
d'informations sur la technologie Web Broker, voir Création d'applications serveur Internet ( see page 2327). Cependant ASP
est différent car il sépare la conception de l'interface utilisateur de l'implémentation des règles de gestion et de la logique
complexe d'une application.

• La conception de l'interface utilisateur est gérée par la page Active Server. C'est essentiellement un document HTML, mais
elle peut contenir des scripts incorporés qui appellent des objets ASP pour fournir au document le contenu qui reflète les
règles de gestion ou la logique de l'application.
• La logique de l'application est encapsulée par des objets Active Server qui exposent des méthodes simples à la page Active
Server en lui fournissant le contenu dont elle a besoin.
Remarque: Même si ASP présente l'avantage de séparer la conception de l'interface utilisateur de la logique de l'application,
à grande échelle ses performances sont limitées. Pour des sites Web devant satisfaire un très grand nombre de clients, il est
recommandé d'utiliser à la place une approche exploitant la technologie courtier Web.
Les scripts des pages Active Server et les objets Automation incorporés dans une page peuvent utiliser les éléments
intrinsèques ASP ( see page 1421) (des objets prédéfinis qui fournissent des informations sur l'application en cours, les
messages HTTP du navigateur, etc).
Les rubriques suivantes décrivent comment créer un objet Active Server en utilisant l'expert objet Active Server Delphi. Ce
contrôle Automation spécial peut ensuite être appelé par une page Active Server et lui fournir son contenu.
Voici les étapes de la création d'un objet Active Server :
• Création d'un objet Active Server ( see page 1420) pour l'application.
• Définition de l'interface de l'objet Active Server. ( see page 1461)
• Recensement ( see page 1425) de l'objet Active Server.
• Test et débogage ( see page 1425) de l'application.
Voir aussi
Présentation des technologies COM ( see page 1404)

Création de serveurs COM simples : Vue globale ( see page 1456)


3
3.2.2.2.2 Création d'un objet Active Server
Un objet Active Server est un objet Automation qui accède à toutes les informations de l'application ASP et aux messages HTTP
qu'elle utilise pour communiquer avec les navigateurs. Il descend de TASPObject ou de TASPMTSObject (qui à son tour
descend de TAutoObject), et il gère les protocoles d'Automation, en s'exposant pour être utilisé par d'autres applications ou par
le script dans la page Active Server. Pour créer un objet Active Server, utilisez l'expert Objet Active Server.

1420
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Votre projet d'objet Active Server peut prendre, selon vos besoins, la forme d'un exécutable (exe) ou d'une bibliothèque (dll).
Cependant vous devez tenir compte des inconvénients liés à l'utilisation d'un serveur hors processus ( see page 1425).

Pour afficher l'expert d'objet Active Server :


1. Choisissez Fichier Nouveau Autre.
2. Sélectionnez le dossier nommé ActiveX sous Projets Delphi.
3. Double-cliquez sur l'icône Objet Active Server. Dans l'expert, spécifiez le nom du nouvel objet Active Server et spécifiez les
modèles d'instanciation ( see page 1459) et de thread ( see page 1459) qu'il faut gérer. Ces paramètres déterminent
comment l'objet peut être appelé. Vous devez écrire l'implémentation de telle manière qu'elle soit conforme au modèle (par
exemple, en évitant les conflits de thread). Ce qui rend unique l'objet Active Server est sa capacité à accéder aux
informations relatives à l'application ASP et aux messages HTTP échangés entre la page Active Server et les navigateurs
client Web. L'accès à ces informations se fait via les éléments intrinsèques ASP ( see page 1421). Vous pouvez, dans
l'expert, spécifier comment votre objet y accède en spécifiant l'option Type d'Active Server :
• Si vous utilisez IIS 3 ou IIS 4, vous pouvez utiliser Méthodes d'événement de niveau page. Avec ce modèle, votre objet
implémente les méthodes OnStartPage et OnEndPage appelées au chargement/déchargement de la page Active Server.
Quand l'objet est chargé, il obtient automatiquement une interface IScriptingContext qu'il utilise pour accéder aux éléments
intrinsèques ASP. Ces interfaces sont à leur tour reflétées sous la forme de propriétés héritées de la classe de base
(TASPObject).
• Si vous utilisez IIS5 ou plus, utilisez le type Contexte d'objet. Avec ce modèle, votre objet obtient une interface IObjectContext
qu'il utilise pour accéder aux éléments intrinsèques ASP. Là encore, ces interfaces sont à leur tour reflétées sous la forme de
propriétés héritées de la classe de base (TASPMTSObject). L'avantage de cette approche tient à ce que l'objet accède à tous
les autres services proposés par IObjectContext. Pour accéder à l'interface IObjectContext, appelez simplement
GetObjectContext (définie dans l'unité mtx) de la manière suivante : ObjectContext := GetObjectContext; Pour
davantage d'informations sur les services accessibles via IObjectContext, voir Création d'objets MTS ou COM+.
Vous pouvez demander à l'expert de générer une page .ASP simple pour accueillir le nouvel objet Active Server. La page
générée contient un script minimaliste (écrit en VBScript) qui crée votre objet Active Server à partir de son ProgID et indique
où vous pouvez appeler ses méthodes. Ce script appelle Server.CreateObject pour démarrer votre objet Active Server.
Remarque: Même si le script de test généré utilise VBScript, une page Active Server peut également contenir du code
Jscript.
Lorsque vous sortez de l'expert, une nouvelle unité est ajoutée au projet en cours ; elle contient la définition de l'objet Active
Server. De plus, l'expert ajoute un projet de bibliothèque de types et ouvre l'éditeur de bibliothèque de types. Vous pouvez
alors exposer les propriétés et méthodes de l'interface via la bibliothèque de type comme indiqué dans Définition de l'interface
d'un objet COM ( see page 1461). Quand vous écrivez l'implémentation des propriétés et méthodes de votre objet, vous
pouvez tirer profit des éléments intrinsèques ASP ( see page 1421) pour obtenir des informations sur l'application ASP et
les messages HTTP qu'elle utilise pour communiquer avec les navigateurs.
Comme tout autre objet Automation, l'objet Active Server implémente une interface double ( see page 1464), qui gère aussi
bien la liaison précoce (à la compilation) via la VTable et la liaison tardive (à l'exécution) via l'interface IDispatch.
Voir aussi
Implémentation des objets COM à l'aide d'experts ( see page 1416)

Utilisation de l'expert Objet Automation ( see page 1458)

Code généré par les experts ( see page 1417)

Création de serveurs COM simples : Vue globale ( see page 1456)


3

3.2.2.2.3 Utilisation des éléments intrinsèques ASP


Les objets intrinsèques ASP sont un ensemble d'objets COM fournis par ASP aux objets qui s'exécutent dans une page Active
Server. Ils permettent à votre objet Active Server d'accéder aux informations reflétant les messages échangés entre votre
application et le navigateur Web ainsi qu'un moyen de stocker des informations partagées par tous les objets Active Server
appartenant à une même application ASP.

1421
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Pour simplifier l'accès à ces objets, la classe de base de votre objet Active Server les présente sous la forme de propriétés. Pour
une description complète de ces objets, reportez-vous à la documentation Microsoft. Les rubriques suivantes vous en donnent
une présentation rapide.

Application
On accède à l'objet Application via une interface IApplicationObject. Il représente toute l'application ASP, définie comme étant
l'ensemble de tous les fichiers .asp d'un même répertoire virtuel et de ses sous-répertoires. L'objet Application peut être partagé
par plusieurs clients, il propose donc une gestion du verrouillage que vous devez utiliser pour empêcher des conflits de threads.

IApplicationObject propose les membres suivants :

Membres de l'interface IApplicationObject

Propriété, Signification
méthode ou
événement
Contents (propriété) Enumère tous les objets ajoutés à l'application en utilisant les commandes de script. Cette interface a
deux méthodes Remove et RemoveAll que vous pouvez utiliser pour supprimer un objet de la liste ou
bien tous les objets.
StaticObjects Enumère tous les objets ajoutés à l'application avec la balise <OBJECT>.
(propriété)
Lock (méthode) Empêche d'autres clients de verrouiller l'objet Application jusqu'à l'appel de Unlock. Tous les clients
doivent appeler Lock avant d'accéder à la mémoire partagée (par exemple, les propriétés).
Unlock (méthode) Libère le verrou placé en utilisant la méthode Lock.

Application_OnEnd Se produit à la sortie de l'application, après l'événement Session_OnEnd. Les seuls éléments
(événement) intrinsèques alors disponibles sont Application et Server. Ce gestionnaire d'événement doit être écrit en
VBScript ou en JScript.
Application_OnStart Se produit avant la création d'une nouvelle session (avant Session_OnStart). Les seuls éléments
(événement) intrinsèques alors disponibles sont Application et Server. Ce gestionnaire d'événement doit être écrit en
VBScript ou en JScript.

Request
On accède à l'objet Request via une interface IRequest. Il donne des informations sur le message de requête HTTP qui a
entraîné l'ouverture de la page Active Server.

IRequest propose les membres suivants :

Membres de l'interface IRequest

Propriété, méthode Signification


ou événement
ClientCertificate Indique la valeur de tous les champs du certificat client qui a été envoyé avec le message HTTP.
(propriété)
Cookies (propriété) Indique la valeur de tous les en-têtes de cookie du message HTTP.
3
Form (propriété) Indique la valeur des éléments de fiche dans le corps HTTP. Il est possible d'y accéder par nom.
QueryString Indique la valeur de toutes les variables de la chaîne de requête de l'en-tête HTTP.
(propriété)
ServerVariables Indique la valeur de diverses variables d'environnement. Ces variables représentent la plupart des
(propriété) variables courantes d'un en-tête HTTP.
TotalBytes (propriété) Indique le nombre d'octets dans le corps de la requête. C'est la limite supérieure du nombre d'octets
renvoyés par la méthode BinaryRead.

1422
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

BinaryRead Récupère le contenu d'un message Post. Appelez la méthode en spécifiant le nombre maximum
(méthode) d'octets à lire. Le contenu résultant est renvoyé dans un tableau Variant d'octets. Après avoir appelé
BinaryRead vous ne pouvez plus utiliser la propriété Form.

Response
On accède à l'objet Request via une interface IResponse. Il vous permet de spécifier des informations sur le message de
réponse HTTP renvoyé au navigateur client.

IResponse propose les membres suivants :

Membres de l'interface IResponse

Propriété, méthode ou Signification


événement
Cookies (propriété) Détermine la valeur des tous les en-têtes de cookie du message HTTP.
Buffer (propriété) Indique si la sortie de la page est placée dans un tampon. Si c'est le cas, le serveur n'envoie la
réponse au client qu'après avoir traité tous les scripts serveur de la page en cours.
CacheControl (propriété) Détermine si des serveurs proxy peuvent placer dans un cache la sortie de la réponse.
Charset (propriété) Ajoute le nom du jeu de caractères à l'en-tête de type de contenu.
ContentType (propriété) Spécifie le type de contenu HTTP du corps du message de réponse.
Expires (propriété) Spécifie combien de temps la réponse peut rester dans le cache d'un navigateur avant d'expirer.
ExpiresAbsolute (propriété) Spécifie l'heure et la date d'expiration de la réponse.
IsClientConnected Indique si le client n'est plus connecté au serveur.
(propriété)
Pics (propriété) Définit la valeur du champ pics-label de l'en-tête de réponse.
Status (propriété) Indique l'état de la réponse. C'est la valeur d'un en-tête de status HTTP.
AddHeader (méthode) Ajoute un en-tête HTTP de nom et de valeur spécifiés.
AppendToLog (méthode) Ajoute une chaîne à la fin de l'entrée de l'historique du serveur Web pour cette requête.
BinaryWrite (méthode) Ecrit des informations brutes (non interprétées) dans le corps du message de réponse.
Clear (méthode) Efface tout le HTML placé dans le tampon.
End (méthode) Arrête le traitement du fichier .asp et renvoie le résultat en cours.
Flush (méthode) Envoie immédiatement tout ce que contient le tampon de sortie.
Redirect (méthode) Envoie un message de réponse de redirection qui renvoie le navigateur client sur une autre
URL.
Write (méthode) Ecrit, sous forme de chaîne, une variable dans la sortie HTTP en cours.

Session
On accède à l'objet Session via une interface ISessionObject. Il vous permet de stocker des variables qui subsistent durant toute
l'interaction d'un client avec l'application ASP. Ces variables ne sont donc pas libérées quand le client passe d'une page à une 3
autre dans l'application ASP mais uniquement quand le client sort de l'application.

ISessionObject propose les membres suivants :

Membres de l'interface ISessionObject

1423
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Propriété, Signification
méthode ou
événement
Contents Enumère tous les objets ajoutés à la session avec la balise <OBJECT>. Vous pouvez accéder à toute
(propriété) variable de la liste par son nom ou appeler les méthodes Remove ou RemoveAll de l'objet Contents pour
supprimer des valeurs.
StaticObjects Enumère tous les objets ajoutés à la session avec la balise <OBJECT>.
(propriété)
CodePage Spécifie le code de page à utiliser pour mettre en correspondance les symboles. Différentes localisations
(propriété) peuvent utiliser des pages de code différentes.
LCID (propriété) Spécifie l'identificateur de localisation à utiliser pour interpréter des contenus chaîne.
SessionID Indique l'identificateur de session du client en cours.
(propriété)
TimeOut Spécifie la durée (en minutes) durant laquelle la session subsiste sans une requête (ou une
(propriété) réactualisation) du client avant la fin de l'application.
Abandon Détruit la session et libère ses ressources.
(méthode)
Session_OnEnd Se produit lors de l'abandon ou du dépassement de délai d'une session. Les seuls éléments intrinsèques
(événement) alors disponibles sont Application, Server et Session. Ce gestionnaire d'événement doit être écrit en
VBScript ou en JScript.
Session_OnStart Se produit lors de la création par le serveur d'une nouvelle session (après Application_OnStart mais avant
(événement) l'exécution du script de la page Active Server). Tous les éléments intrinsèques sont alors disponibles. Ce
gestionnaire d'événement doit être écrit en VBScript ou en JScript.

Server
On accède à l'objet Server via une interface IServer. Il propose divers utilitaires pour écrire votre application ASP.

IServer propose les membres suivants :

Membres de l'interface IServer

Propriété, méthode ou Signification


événement
ScriptTimeout (propriété) Identique à la propriété Timeout de l'objet Session.
CreateObject (méthode) Instancie l'objet Active Server spécifié.
Execute (méthode) Exécute le script d'un fichier .asp spécifié.
GetLastError (méthode) Renvoie un objet ASPError qui décrit la condition d'erreur.
HTMLEncode (méthode) Code une chaîne en vue de son utilisation dans un en-tête HTML, en remplaçant les caractères
réservés par les constantes symboliques appropriées.
MapPath (méthode) Associe un répertoire virtuel spécifié (un répertoire absolu dans le serveur en cours ou un chemin
relatif à la page en cours) à un chemin d'accès physique.
3 Transfer (méthode) Envoie toutes les informations d'état en cours à une autre page Active Server pour traitement.
URLEncode (méthode) Applique les règles de codage d'une URL, y compris les caractères d'échappement, à la chaîne
spécifiée.

Voir aussi
Création d'ASP pour des serveurs en et hors processus ( see page 1425)

Définition de l'interface d'un objet COM ( see page 1461)

1424
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

3.2.2.2.4 Création d'ASP pour des serveurs en et hors processus


Vous pouvez utiliser Server.CreateObject dans une page ASP pour démarrer un serveur en ou hors processus ( see page
1408) en fonction de vos besoins. Généralement les serveurs en processus sont plus couramment utilisés.

A la différence de la plupart des serveurs en processus, un objet Active Server ne s'exécute pas dans l'espace de processus du
client. A la place, il s'exécute dans l'espace du processus IIS. Cela signifie que le client n'a pas besoin de télécharger votre
application (comme c'est, par exemple, le cas avec des objets ActiveX). Les composants DLL en processus sont plus rapides et
plus fiables que des serveurs hors processus, il est donc préférable de les utiliser du côté serveur.

Comme les serveurs hors processus sont moins fiables, IIS est fréquemment configuré pour ne pas autoriser l'utilisation
d'exécutables hors processus. Dans ce cas, la création d'un serveur hors processus par votre objet Active Server produit une
erreur de la forme suivante :
Server object error ’ASP 0196’
Cannot launch out of process component
/path/outofprocess_exe.asp, line 11
De plus, comme les composants hors processus créent souvent des processus de serveur individuels pour chaque instance
d'objet, ils sont plus lents que les applications CGI. Ils ne supportent pas aussi bien les redéploiements que les composants DLL.

Si les performances et le redéploiement sont des priorités, il est fortement conseillé d'utiliser des composants en processus.
Cependant les sites Intranet qui ont un trafic faible ou modéré peuvent utiliser un composant hors processus sans affecter les
performances globales du site.

Voir aussi
Implémentation des objets COM à l'aide d'experts ( see page 1416)

Création de serveurs COM simples : Vue globale ( see page 1456)

3.2.2.2.5 Recensement d'un objet Active Server


Vous pouvez recenser l'objet ASP comme serveur en ou hors processus ( see page 1425). Généralement les serveurs en
processus sont plus couramment utilisés.

Remarque: Si vous voulez retirer l'objet ASP de votre système, vous devez commencer par annuler son recensement, puis
retirer ses entrées dans le registre Windows.

Recensement d'un serveur en processus


Pour recenser un serveur en processus (DLL ou OCX), choisissez Exécuter Recenser le serveur ActiveX.

Pour annuler le recensement d'un serveur en processus, choisissez Exécuter Dé-recenser le serveur ActiveX.

Recensement d'un serveur hors processus


Pour recenser un serveur hors processus, exécutez le serveur avec l'option en ligne de commande /regserver. Vous pouvez
également recenser le serveur en l'exécutant.

Pour annuler le recensement d'un serveur hors processus, exécutez le serveur avec l'option en ligne de commande /unregserver. 3

3.2.2.2.6 Test et débogage d'une application ASP (Active Server Page)


Le débogage d'un serveur en processus comme un objet Active Server se fait comme celui d'une DLL. Vous choisissez une
application hôte qui charge la DLL et débogez de manière habituelle.

1425
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Pour tester et déboguer un objet Active Server,


1. Si nécessaire, activez les informations de débogage en utilisant la page Compilateur de la boîte de dialogue
Projet Options. Activez aussi Débogage intégré dans la boîte de dialogue Outils Options Options du débogueur.
2. Choisissez Exécuter Paramètres, entrez le nom de votre serveur Web dans la zone Application hôte et choisissez OK.
3. Choisissez Exécuter Exécuter.
4. Définissez des points d'arrêt dans l'implémentation de l'objet Active Server.
5. Utilisez le navigateur Web pour interagir avec l'objet ASP.
Le débogueur s'arrête quand les points d'arrêt sont atteints.

3.2.2.3 Utilisation des contrôles ActiveX


Rubriques
Nom Description
Eléments d'un contrôle ActiveX ( see page 1428) Un contrôle ActiveX implique plusieurs éléments qui ont chacun une fonction
spécifique. Ces éléments sont un contrôle VCL, un objet enveloppe COM
correspondant qui expose des propriétés, des méthodes, des événements, et
une ou plusieurs bibliothèques de types associées.
Conception d'un contrôle ActiveX ( see page 1429) Lors de la conception d'un contrôle ActiveX, vous commencez par créer un
contrôle VCL personnalisé. Il sert de base à votre contrôle ActiveX. Pour des
informations sur la création de contrôles personnalisés, voir la partie Création de
composants personnalisés ( see page 1327).
Quand vous concevez le contrôle VCL, n'oubliez pas qu'il va être incorporé dans
une autre application : ce contrôle n'est pas une application en lui-même. De ce
fait, vous devez éviter de concevoir des boîte de dialogue trop sophistiquées.
Généralement, votre but est de concevoir un contrôle simple qui travaille à
l'intérieur d'une application principale et en respecte les règles.
De... suite ( see page 1429)
Génération d'un contrôle ActiveX basé sur une fiche VCL ( see page 1429) A la différence des autres contrôles ActiveX, les fiches actives ne sont pas
d'abord conçues puis encapsulées dans une classe enveloppe ActiveX. A la
place, l'expert ActiveForm génère une fiche vide que vous concevez après coup
quand l'expert vous laisse dans le concepteur de fiche.
Lorsqu'une fiche ActiveForm est déployée sur le Web, Delphi crée une page
HTML pour contenir la référence à la fiche ActiveForm et spécifier son
emplacement dans la page. La fiche ActiveForm peut ensuite être affichée et
exécutée depuis un navigateur Web. Dans le navigateur Web, la fiche se
comporte comme une fiche autonome Delphi. Elle... suite ( see page 1429)
Licences des contrôles ActiveX ( see page 1430) Attribuer une licence à un contrôle ActiveX consiste à fournir une clé de licence à
la conception et à gérer la création dynamique de licences pour les contrôles
créés à l'exécution.
Pour fournir des licences de conception, une clé est créée pour le contrôle et elle
est stockée dans un fichier d'extension LIC portant le même nom que le projet.
Ce fichier .LIC est ajouté au projet. L'utilisateur du contrôle doit avoir un copie
du fichier .LIC pour ouvrir le contrôle dans un environnement de
développement. Chaque contrôle d'un projet pour lequel la case Licence de
conception est cochée dispose... suite ( see page 1430)
Personnalisation de l'interface du contrôle ActiveX ( see page 1431) Vous pouvez ajouter, modifier ou supprimer les propriétés, méthodes et
événements d'un contrôle ActiveX en modifiant la bibliothèque de types. Vous
pouvez utiliser l'éditeur de bibliothèques de types comme décrit dans Utilisation
de l'éditeur de bibliothèques de types ( see page 1480). N'oubliez pas que si
vous ajoutez des événements, ils doivent être ajoutés à l'interface Events et non
3 à l'interface par défaut du contrôle ActiveX.
Remarque: Vous pouvez ajouter des propriétés non publiées à l'interface de
votre contrôle ActiveX. De telles propriétés peuvent être définies à l'exécution et
apparaissent dans l'environnement de développement, mais les modifications
effectuées ne sont pas persistantes. Donc,... suite ( see page 1431)

1426
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Ajout de propriétés, méthodes et événements supplémentaires ( see page Vous pouvez ajouter au contrôle des propriétés, méthodes et événements
1431) supplémentaires par le biais de l'éditeur de bibliothèques de types. La
déclaration est automatiquement ajoutée à l'unité d'implémentation, au fichier de
bibliothèque de types (TLB) et à l'unité de bibliothèque de types du contrôle. Ce
que Delphi ajoute réellement dépend de ce que vous avez ajouté : propriété ou
méthode ( see page 1431) ou si vous avez ajouté un événement ( see page
1433).
Comment Delphi ajoute-t-il des propriétés ( see page 1431) La classe enveloppe ActiveX implémente les propriétés dans son interface en
utilisant des méthodes d'accès en lecture et en écriture. C'est-à-dire que la
classe enveloppe a des propriétés COM qui apparaissent dans une interface
comme des méthodes get et/ou set. A la différence des propriétés VCL, vous ne
voyez pas une déclaration de propriété dans l'interface des propriétés COM.
Vous ne voyez que les méthodes qui sont indiquées comme méthodes d'accès à
la propriété. Quand vous ajoutez une propriété à l'interface par défaut du contrôle
ActiveX, la définition de la classe enveloppe (qui apparaît dans le fichier unité
_TLB actualisé... suite ( see page 1431)
Comment Delphi ajoute-t-il des événements ( see page 1433) Le contrôle ActiveX peut déclencher des événements dans son conteneur de la
même manière qu'un objet automation déclenche des événements dans ses
clients. Ce mécanisme est décrit dans Gestion des événements dans un objet
Automation ( see page 1464).
Si le contrôle VCL que vous utilisez comme base pour votre contrôle ActiveX a
des événements publiés, l'expert ajoute automatiquement le traitement de la liste
d'événements client à la classe enveloppe ActiveX et définit la dispinterface de
sortie que les clients doivent implémenter pour répondre aux événements.
Vous ajoutez des événements à cette dispinterface de sortie. Pour ajouter un
événement dans l'éditeur de bibliothèques... suite ( see page 1433)
Activation de la liaison de données simple avec la bibliothèque de types ( see Avec la liaison de données simple, vous pouvez lier une propriété de votre
page 1434) contrôle ActiveX à un champ d'une base de données. Pour ce faire, le contrôle
ActiveX doit communiquer à son application hôte la valeur que représente le
champ de données et quand elle est modifiée. Vous activez cette communication
en définissant les indicateurs de liaison de la propriété avec l'éditeur de
bibliothèques de types.
Si vous spécifiez qu'une propriété est liée, quand un utilisateur modifie la
propriété (par exemple, un champ d'une base de données), le contrôle notifie son
conteneur (l'application client hôte) que la valeur a été... suite ( see page 1434)
Création d'une page de propriétés pour un contrôle ActiveX ( see page 1435) Une page de propriétés est une boîte de dialogue similaire à l'inspecteur
d'objets Delphi qui permet aux utilisateurs de modifier les propriétés d'un
contrôle ActiveX. Un dialogue de page de propriétés sert à regrouper plusieurs
propriétés d'un contrôle afin de les modifier ensemble ou à gérer des propriétés
complexes. Vous pouvez aussi fournir une boîte de dialogue pour des propriétés
plus complexes.
En général, les utilisateurs accèdent à la page des propriétés en cliquant sur le
contrôle ActiveX avec le bouton droit de la souris et en choisissant Propriétés.
Création d'une nouvelle page de propriétés ( see page 1435) Pour créer une nouvelle page de propriétés, utilisez l'expert Page propriétés.
Ajout de contrôles à une page de propriétés ( see page 1436) Vous devez ajouter à la page de propriétés un contrôle pour chaque propriété du
contrôle ActiveX à laquelle l'utilisateur doit avoir accès.
Par exemple, la figure suivante illustre la configuration de la page de propriétés
pour un contrôle ActiveX MaskEdit.

La boîte liste permet à l'utilisateur de sélectionner parmi une liste de modèles


3
exemple. Les contrôles de saisie permettent à l'utilisateur de tester le masque
avant de l'appliquer au contrôle ActiveX. Pour ajouter des contrôles à la page de
propriétés, procédez comme avec une fiche.
Association des contrôles de la page de propriétés aux propriétés du contrôle Une fois tous les contrôles nécessaires ajoutés à la page de propriétés, il faut
ActiveX ( see page 1436) associer chaque contrôle à la propriété correspondante. Cette association
s'effectue en ajoutant du code à l'unité implémentant la page de propriétés.
Précisément, il faut ajouter du code aux méthodes UpdatePropertyPage ( see
page 1436) et UpdateObject ( see page 1437).

1427
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Mise à jour de la page de propriétés ( see page 1436) Ajoutez du code à la méthode UpdatePropertyPage pour mettre à jour le contrôle
de la page de propriétés quand les propriétés du contrôle ActiveX changent.
Vous devez ajouter du code à la méthode UpdatePropertyPage pour actualiser la
page de propriétés avec les valeurs en cours des propriétés du contrôle ActiveX.
Vous pouvez accéder au contrôle ActiveX en utilisant la propriété OleObject de la
page de propriétés, qui est un OleVariant contenant l'interface du contrôle
ActiveX.
Par exemple, le code suivant actualise le contrôle boîte de saisie (InputMask) de
la page de propriétés avec la valeur en cours de la propriété... suite ( see page
1436)
Mise à jour de l'objet ( see page 1437) Ajoutez du code à la méthode UpdateObject pour mettre à jour la propriété
quand l'utilisateur modifie les contrôles de la page de propriétés. Vous devez
ajouter du code à la méthode UpdateObject afin de définir la nouvelle valeur des
propriétés du contrôle ActiveX.
Pour accéder à d'autres contrôles ActiveX, utilisez la propriété OleObject.
Par exemple, le code suivant affecte la propriété EditMask d'un contrôle ActiveX
en utilisant la valeur du contrôle boîte de saisie (InputMask) de la page de
propriétés :
Connexion d'une page de propriétés à un contrôle ActiveX ( see page 1437)

3.2.2.3.1 Eléments d'un contrôle ActiveX


Un contrôle ActiveX implique plusieurs éléments qui ont chacun une fonction spécifique. Ces éléments sont un contrôle VCL, un
objet enveloppe COM correspondant qui expose des propriétés, des méthodes, des événements, et une ou plusieurs
bibliothèques de types associées.

Contrôle VCL
Dans Delphi, l'implémentation sous-jacente à un contrôle ActiveX est un contrôle VCL. Quand vous créez un contrôle ActiveX,
vous devez commencer par concevoir ou choisir le contrôle VCL à partir duquel vous aller construire votre contrôle ActiveX.

Le contrôle VCL sous-jacent doit être un descendant de TWinControl car il doit disposer d'une fenêtre qui peut être accueillie par
l'application hôte. Quand vous créez une fiche active, cet objet est un descendant de TActiveForm.

Remarque: L'expert contrôle ActiveX énumère les descendants TWinControl dans lesquels vous pouvez choisir pour créer un
contrôle ActiveX. Néanmoins, cette liste ne propose pas tous les descendants TWinControl. Certains contrôles, comme
THeaderControl, sont répertoriés comme incompatibles avec ActiveX (en utilisant la procédure RegisterNonActiveXprocedure)
et n'apparaissent pas dans cette liste.

Enveloppe ActiveX
Le véritable objet COM est un objet ActiveX qui encaspule le contrôle VCL. Pour les fiches actives, cette classe est toujours
TActiveFormControl. Pour les autres contrôles ActiveX, elle a un nom de la forme TVCLClassX, où TVCLClass est le nom de la
classe du contrôle VCL. Ainsi, par exemple, l'enveloppe ActiveX de TButton se nommerait TButtonX.

La classe enveloppe est un descendant de TActiveXControl, qui gère les interfaces ActiveX. L'enveloppe ActiveX en hérite, ce
qui lui permet de retransmettre les messages Windows au contrôle VCL et d'accueillir sa fenêtre dans l'application hôte.

L'enveloppe ActiveX expose les propriétés et méthodes du contrôle VCL aux clients en utilisant son interface par défaut. Vous
devez implémenter les propriétés et les méthodes de classe enveloppe en déléguant les appels de méthode au contrôle VCL
sous-jacent. Vous devez également fournir à la classe enveloppe les méthodes qui déclenchent les événements du contrôle
VCL dans les clients et affecter ces méthodes aux gestionnaires d'événements du contrôle VCL.
3
Bibliothèque de types
Vous devez générer pour votre contrôle ActiveX une bibliothèque de types contenant les définitions de types pour la classe
enveloppe, son interface par défaut et toutes les définitions de types nécessaires. Ces informations de type permettent au
contrôle d'informer les applications hôtes de ses services. Vous pouvez visualiser et modifier ces informations en utilisant
l'éditeur de bibliothèques de types. Même si ces informations sont stockées dans un fichier de bibliothèque de types binaire
séparé (d'extension .TLB), vous pouvez également le compiler sous forme de ressource dans la DLL du contrôle ActiveX.

1428
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Page de propriétés
Vous pouvez éventuellement attribuer à votre contrôle ActiveX une page de propriétés. La page de propriétés permet à
l'utilisateur de l'application hôte (le client) de visualiser et de modifier les propriétés du contrôle. Vous pouvez regrouper
plusieurs propriétés dans une page ou utiliser une page pour proposer une interface de type boîte de dialogue à une propriété.
Pour de plus amples informations sur la manière de créer des pages de propriétés, voir Création d'une page de propriétés pour
un contrôle ActiveX ( see page 1435).

3.2.2.3.2 Conception d'un contrôle ActiveX


Lors de la conception d'un contrôle ActiveX, vous commencez par créer un contrôle VCL personnalisé. Il sert de base à votre
contrôle ActiveX. Pour des informations sur la création de contrôles personnalisés, voir la partie Création de composants
personnalisés ( see page 1327).

Quand vous concevez le contrôle VCL, n'oubliez pas qu'il va être incorporé dans une autre application : ce contrôle n'est pas
une application en lui-même. De ce fait, vous devez éviter de concevoir des boîte de dialogue trop sophistiquées. Généralement,
votre but est de concevoir un contrôle simple qui travaille à l'intérieur d'une application principale et en respecte les règles.

De plus, vous devez vous assurer que les types de toutes les propriétés et méthodes que votre contrôle expose aux clients sont
compatibles avec l'Automation ( see page 1481), car l'interface du contrôle ActiveX doit gérer IDispatch. L'expert n'ajoute à
l'interface de la classe enveloppe que les méthodes ayant des paramètres dont le type est compatible avec l'Automation.

Les experts implémentent toutes les interfaces ActiveX nécessaires en utilisant la classe enveloppe COM. Ils représentent
également toutes les propriétés, méthodes et événements compatibles avec l'Automation via l'interface par défaut de la classe
enveloppe. Quand l'expert a généré la classe COM enveloppe et son interface, vous pouvez utiliser l'éditeur de bibliothèques de
types ( see page 1473) pour modifier l'interface par défaut ou augmenter la classe enveloppe en implémentant d'autres
interfaces.

Voir aussi
Vue globale de la création d'un composant ( see page 1327)

Eléments d'un contrôle ActiveX ( see page 1428)

3.2.2.3.3 Génération d'un contrôle ActiveX basé sur une fiche VCL
A la différence des autres contrôles ActiveX, les fiches actives ne sont pas d'abord conçues puis encapsulées dans une classe
enveloppe ActiveX. A la place, l'expert ActiveForm génère une fiche vide que vous concevez après coup quand l'expert vous
laisse dans le concepteur de fiche.

Lorsqu'une fiche ActiveForm est déployée sur le Web, Delphi crée une page HTML pour contenir la référence à la fiche
ActiveForm et spécifier son emplacement dans la page. La fiche ActiveForm peut ensuite être affichée et exécutée depuis un
navigateur Web. Dans le navigateur Web, la fiche se comporte comme une fiche autonome Delphi. Elle peut contenir n'importe
quel composant VCL ou ActiveX, y compris des contrôles VCL personnalisés.

Pour démarrer l'expert ActiveForm :


3
1. Choisissez Fichier Nouveau Autre pour ouvrir la boîte de dialogue Nouveaux éléments.
2. Sélectionnez l'onglet intitulé ActiveX.
3. Double-cliquez sur l'icône ActiveForm.
Dans l'expert Active Form, vous ne pouvez pas spécifier le nom de la classe VCL à envelopper. En effet, les fiches actives sont
toujours basées sur TActiveForm.
Vous pouvez changer les noms par défaut de la CoClasse, de l'unité d'implémentation et du projet de bibliothèque ActiveX. De
même l'expert vous permet d'indiquer si vous voulez que votre fiche active nécessite une licence, si elle doit contenir des

1429
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

informations de version et si vous voulez une fiche A propos.


Quand vous sortez de l'expert, il génère :
• Un fichier projet de bibliothèque ActiveX qui contient le code nécessaire pour démarrer un contrôle ActiveX. Généralement,
vous ne modifierez pas ce fichier.
• Une bibliothèque de types qui définit une CoClasse pour le contrôle, l'interface qu'elle expose aux clients et les définitions de
types qui leurs sont nécessaires. Pour plus d'informations sur la bibliothèque de types, voir Utilisation des bibliothèques de
types ( see page 1472).
• Une fiche qui dérive de TActiveForm. Cette fiche apparaît dans le concepteur de fiche, ce qui vous permet de concevoir
visuellement comment la fiche active apparaîtra aux clients. Son implémentation apparaît dans l'unité d'implémentation
générée. Dans la section initialisation de l'unité d'implémentation, un fabricant de classe est créé, et il configure
TActiveFormControl comme l'enveloppe ActiveX de cette fiche.
• Une unité et une fiche de boîte de dialogue A propos, si vous l'avez demandé.
• Un fichier .LIC, si vous avez demandé une licence.
Arrivé là, vous pouvez ajouter des contrôles à la fiche et la concevoir à votre guise.
Une fois le projet ActiveForm conçu et compilé dans une bibliothèque ActiveX (d'extension OCX), vous pouvez déployer le projet
sur votre serveur Web, et Delphi crée une page HTML de test contenant une référence à la fiche active.
Voir aussi
Eléments d'un contrôle ActiveX ( see page 1428)

Implémentation des objets COM à l'aide d'experts ( see page 1416)

Code généré par les experts ( see page 1417)

3.2.2.3.4 Licences des contrôles ActiveX


Attribuer une licence à un contrôle ActiveX consiste à fournir une clé de licence à la conception et à gérer la création dynamique
de licences pour les contrôles créés à l'exécution.

Pour fournir des licences de conception, une clé est créée pour le contrôle et elle est stockée dans un fichier d'extension LIC
portant le même nom que le projet. Ce fichier .LIC est ajouté au projet. L'utilisateur du contrôle doit avoir un copie du fichier
.LIC pour ouvrir le contrôle dans un environnement de développement. Chaque contrôle d'un projet pour lequel la case Licence
de conception est cochée dispose d'une entrée distincte dans le fichier .LIC.

Pour gérer les licences à l'exécution, la classe enveloppe implémente deux méthodes, GetLicenseString et GetLicenseFilename.
Elles renvoient, respectivement, la chaîne de licence du contrôle et le nom du fichier .LIC. Quand une application hôte tente de
créer un contrôle ActiveX, le fabricant de classe du contrôle appelle ces méthodes et compare la chaîne renvoyée par
GetLicenseString à la chaîne stockée dans le fichier .LIC.

Les licences d'exécution pour Internet Explorer nécessitent un niveau supplémentaire d'indirection, car l'utilisateur peut visualiser
le code source HTML de toutes les pages Web et un contrôle ActiveX est copié sur son ordinateur avant qu'il ne soit affiché.
Pour créer des licences d'exécution pour les contrôles utilisés sous Internet Explorer, vous devez d'abord générer un fichier
package de licence (fichier LPK) et l'incorporer dans la page HTML qui contient le contrôle. Le fichier LPK est essentiellement un
tableau de CLSID et de clés de licence.
3
Remarque: Pour générer le fichier LPK, utilisez l'utilitaire LPK_TOOL.EXE, que vous pouvez télécharger à partir du site Web de
Microsoft (www.microsoft.com).

Pour incorporer le fichier LPK dans une page Web, utilisez les objets HTML, <OBJECT> et <PARAM>, comme suit :
<OBJECT CLASSID="clsid:6980CB99-f75D-84cf-B254-55CA55A69452">
<PARAM NAME="LPKPath" VALUE="ctrllic.lpk">
</OBJECT>
Le CLSID identifie l'objet en tant que package de licence et PARAM spécifie l'emplacement relatif du fichier package de licence

1430
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

par rapport à la page HTML.

Lorsque Internet Explorer essaie d'afficher la page Web contenant le contrôle, il analyse le fichier LPK, extrait la clé de licence
et, si celle-ci correspond à la licence du contrôle (renvoyée par GetLicenseString), il restitue le contrôle dans la page. Si
plusieurs fichiers LPK sont inclus dans une page Web, Internet Explorer ne prend en compte que le premier.

Pour plus d'informations, effectuez des recherches sur la définition de licences de contrôles ActiveX sur le site Web de Microsoft.

3.2.2.3.5 Personnalisation de l'interface du contrôle ActiveX


Vous pouvez ajouter, modifier ou supprimer les propriétés, méthodes et événements d'un contrôle ActiveX en modifiant la
bibliothèque de types. Vous pouvez utiliser l'éditeur de bibliothèques de types comme décrit dans Utilisation de l'éditeur de
bibliothèques de types ( see page 1480). N'oubliez pas que si vous ajoutez des événements, ils doivent être ajoutés à
l'interface Events et non à l'interface par défaut du contrôle ActiveX.

Remarque: Vous pouvez ajouter des propriétés non publiées à l'interface de votre contrôle ActiveX. De telles propriétés
peuvent être définies à l'exécution et apparaissent dans l'environnement de développement, mais les modifications effectuées
ne sont pas persistantes. Donc, si l'utilisateur du contrôle modifie la valeur de la propriété à la conception, les modifications ne
sont pas prises en compte dans le contrôle à l'exécution. Si la source est un objet VCL alors que la propriété n'est pas déjà
publiée, vous pouvez rendre la propriété persistente en créant un descendant de l'objet VCL et en publiant la propriété dans le
descendant.

Vous n'êtes pas obligé d'exposer toutes les propriétés, méthodes et événements du contrôle VCL aux applications hôtes. Vous
pouvez utiliser l'éditeur de bibliothèques de types pour les retirer des interfaces que l'expert a généré. Quand vous retirez des
propriétés et méthodes d'une interface en utilisant l'éditeur de bibliothèques de types, l'éditeur ne les retire pas de la classe
d'implémentation correspondante. Editez la classe enveloppe ActiveX dans l'unité d'implémentation pour les en retirer une fois
que vous avez modifié l'interface dans l'éditeur de bibliothèques de types.

Avertissement: Toutes les modifications effectuées dans la bibliothèque de types sont perdues si vous régénérez le contrôle
ActiveX depuis le contrôle ou la fiche VCL d'origine.

Conseil: Il est judicieux de tester les méthodes que l'expert ajoute à votre classe enveloppe ActiveX. Cela vous donne
l'opportunité de vérifier où l'expert a omis des propriétés orientées données ou des méthodes incompatibles avec l'Automation ;
mais cela vous donne également l'occasion de détecter les méthodes pour lesquelles l'expert n'a pas pu générer une
implémentation. Ces méthodes apparaissent dans l'implémentation avec un commentaire indiquant le problème.

Voir aussi
Génération d'un contrôle ActiveX basé sur une fiche VCL ( see page 1429)

3.2.2.3.6 Ajout de propriétés, méthodes et événements supplémentaires


Vous pouvez ajouter au contrôle des propriétés, méthodes et événements supplémentaires par le biais de l'éditeur de
bibliothèques de types. La déclaration est automatiquement ajoutée à l'unité d'implémentation, au fichier de bibliothèque de
types (TLB) et à l'unité de bibliothèque de types du contrôle. Ce que Delphi ajoute réellement dépend de ce que vous avez
ajouté : propriété ou méthode ( see page 1431) ou si vous avez ajouté un événement ( see page 1433).
3
Voir aussi
Personnalisation de l'interface du contrôle ActiveX ( see page 1431)

3.2.2.3.7 Comment Delphi ajoute-t-il des propriétés


La classe enveloppe ActiveX implémente les propriétés dans son interface en utilisant des méthodes d'accès en lecture et en
écriture. C'est-à-dire que la classe enveloppe a des propriétés COM qui apparaissent dans une interface comme des méthodes

1431
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

get et/ou set. A la différence des propriétés VCL, vous ne voyez pas une déclaration de propriété dans l'interface des propriétés
COM. Vous ne voyez que les méthodes qui sont indiquées comme méthodes d'accès à la propriété. Quand vous ajoutez une
propriété à l'interface par défaut du contrôle ActiveX, la définition de la classe enveloppe (qui apparaît dans le fichier unité _TLB
actualisé par l'éditeur de bibliothèques de types) est augmentée d'une ou deux nouvelles méthodes (une méthode get et/ou une
méthode set). Vous devez implémenter comme si vous aviez ajouté une méthode à l'interface, la classe enveloppe est
augmentée d'une méthode correspondante que vous devez implémenter. L'ajout de propriétés à l'interface de la classe
enveloppe revient donc à ajouter des méthodes : le squelette de nouvelles implémentations de méthodes à compléter est ajouté
à la définition de la classe enveloppe.

Remarque: Pour davantage d'informations sur ce qui apparaît dans l'unité _TLB générée, voir Code généré par l'importation
des informations d'une bibliothèque de types ( see page 1442).

Par exemple, soit une propriété Caption de type TCaption dans l'objet VCL sous-jacent. Pour ajouter cette propriété à l'interface
de l'objet, entrez ce qui suit quand vous ajoutez une propriété à l'interface via l'éditeur de bibliothèques de types :
property Caption: TCaption read Get_Caption write Set_Caption;
Delphi ajoute les déclarations suivantes à la classe enveloppe :
function Get_Caption: WideString; safecall;
procedure Set_Caption(const Value: WideString); safecall;
STDMETHOD(get_Caption(BSTR* Value));
STDMETHOD(set_Caption(BSTR Value));
De plus, il ajoute les squelettes de méthodes d'implémentation suivants que vous devez compléter :
function TButtonX.Get_Caption: WideString;
begin
end;
procedure TButtonX.Set_Caption(Value: WideString);
begin
end;
STDMETHODIMP TButtonXImpl::get_Caption(BSTR* Value)
{
try
{
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IButtonX);
}
return S_OK;
};
STDMETHODIMP TButtonXImpl::set_Caption(BSTR Value)
{
try
{
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IButtonX);
}
return S_OK;
};
3
Généralement, vous pouvez implémenter ces méthodes par simple délégation au contrôle VCL associé auquel vous avez accès
en utilisant le membre FDelphiControl de la classe enveloppe :
function TButtonX.Get_Caption: WideString;
begin
Result := WideString(FDelphiControl.Caption);
end;

procedure TButtonX.Set_Caption(const Value: WideString);


begin

1432
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

FDelphiControl.Caption := TCaption(Value);
end;
STDMETHODIMP TButtonXImpl::get_Caption(BSTR* Value)
{
try
{
*Value = WideString(m_VclCtl->Caption).Copy();
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IButtonX);
}
return S_OK;
};
STDMETHODIMP TButtonXImpl::set_Caption(BSTR Value)
{
try
{
m_VclCtl->Caption = AnsiString(Value);
}
catch(Exception &e)
{
return Error(e.Message.c_str(), IID_IButtonX);
}
return S_OK;
};
Dans certains cas, vous avez besoin d'ajouter du code pour convertir les types de données COM en types natifs Delphi.
L'exemple précédent le fait en utilisant le transtypage.

Remarque: Comme les méthodes d'une interface Automation sont déclarées safecall, vous n'avez pas besoin
d'implémenter le code d'exception COM pour ces méthodes. Le compilateur Delphi gère cela pour vous en générant
autour du corps des méthodes safecall le code permettant de capturer les exceptions Delphi et de les convertir en
structures d'information et en codes de retour des erreurs COM.

Voir aussi
Code généré par l'importation des informations d'une bibliothèque de types ( see page 1442)

3.2.2.3.8 Comment Delphi ajoute-t-il des événements


Le contrôle ActiveX peut déclencher des événements dans son conteneur de la même manière qu'un objet automation
déclenche des événements dans ses clients. Ce mécanisme est décrit dans Gestion des événements dans un objet Automation
( see page 1464).

Si le contrôle VCL que vous utilisez comme base pour votre contrôle ActiveX a des événements publiés, l'expert ajoute
automatiquement le traitement de la liste d'événements client à la classe enveloppe ActiveX et définit la dispinterface de sortie
que les clients doivent implémenter pour répondre aux événements.

Vous ajoutez des événements à cette dispinterface de sortie. Pour ajouter un événement dans l'éditeur de bibliothèques de
types, sélectionnez l'interface d'événement et cliquez sur l'icône de méthode. Ajoutez ensuite manuellement la liste de
paramètres que vous voulez inclure par le biais de la page des paramètres.
3
Déclarez ensuite une méthode dans la classe d'implémentation qui soit de même type que le gestionnaire de l'événement dans
le contrôle VCL sous-jacent. Cela n'est pas généré automatiquement car Delphi ne sait pas quel gestionnaire d'événement vous
utilisez :
procedure KeyPressEvent(Sender: TObject; var Key: Char);
Implémentez cette méthode pour utiliser le récepteur d'événements de l'application hôte stocké dans le membre FEvents de la
classe enveloppe :

1433
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

procedure TButtonX.KeyPressEvent(Sender: TObject; var Key: Char);


var
TempKey: Smallint;
begin
TempKey := Smallint(Key); {transtypage dans un type compatible OleAutomation }
if FEvents <> nil then
FEvents.OnKeyPress(TempKey)
Key := Char(TempKey);
end;
void __fastcall TButtonXImpl::KeyPressEvent(TObject *Sender, char &Key)
{
short TempKey;
TempKey = (short)Key;
Fire_OnKeyPress(&TempKey);
Key = (short)TempKey;
};
Remarque: Si vous déclenchez des événements dans un contrôle ActiveX, vous n'avez pas besoin de parcourir une liste de
récepteurs d'événements car le contrôle n'a qu'une seule application hôte. Le processus est plus simple qu'avec la plupart des
serveurs Automation.

Enfin, vous devez attribuer ce gestionnaire d'événement au contrôle VCL sous-jacent afin qu'il soit appelé quand l'événement
se produit. Vous effectuez cette affectation dans la méthode InitializeControl :
procedure TButtonX.InitializeControl;
begin
FDelphiControl := Control as TButton;
FDelphiControl.OnClick := ClickEvent;
FDelphiControl.OnKeyPress := KeyPressEvent;
end;
void InitializeControl()
{
m_VclCtl->OnClick = ClickEvent;
m_VclCtl->OnKeyPress = KeyPressEvent;
}
Voir aussi
Code généré par l'importation des informations d'une bibliothèque de types ( see page 1442)

3.2.2.3.9 Activation de la liaison de données simple avec la bibliothèque de


types
Avec la liaison de données simple, vous pouvez lier une propriété de votre contrôle ActiveX à un champ d'une base de données.
Pour ce faire, le contrôle ActiveX doit communiquer à son application hôte la valeur que représente le champ de données et
quand elle est modifiée. Vous activez cette communication en définissant les indicateurs de liaison de la propriété avec l'éditeur
de bibliothèques de types.

Si vous spécifiez qu'une propriété est liée, quand un utilisateur modifie la propriété (par exemple, un champ d'une base de
données), le contrôle notifie son conteneur (l'application client hôte) que la valeur a été modifiée et demande que
l'enregistrement de la base de données soit actualisé. Le conteneur interagit avec la base de données, puis notifie le contrôle de
la réussite ou de l'échec de l'actualisation de l'enregistrement.
3
Remarque: C'est l'application conteneur accueillant votre contrôle ActiveX qui est responsable de la connexion avec la base de
données des propriétés spécifiées comme orientés données dans la bibliothèque de types.

Utilisez la bibliothèque de types pour activer la liaison de données simple,


1. Dans la barre d'outils, cliquez sur la propriété à lier.
2. Choisissez la page Indicateurs.

1434
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

3. Sélectionnez les attributs de liaison suivants :

Attribut Description
de liaison

Bindable Indique que la propriété supporte la liaison de données. Si elle est marquée “bindable”, la propriété notifie à son
conteneur quand sa valeur a été modifiée.
Request Indique que la propriété supporte la notification OnRequestEdit. Cela permet au contrôle de demander au
Edit conteneur si sa valeur peut être modifiée par l'utilisateur.
Display Indique que le conteneur peut montrer aux utilisateurs que cette propriété est "bindable".
Bindable
Default Indique la propriété "bindable" qui représente le mieux l'objet. Les propriétés qui ont cet attribut de liaison par
Bindable défaut doivent avoir aussi l'attribut bindable. On ne peut pas spécifier plusieurs propriétés de ce type dans une
dispinterface.
Immediate Chacune des propriétés "bindable" d'une fiche peut bénéficier de ce comportement. Quand ce bit est défini, toutes
Bindable les modifications sont notifiées. Les bits Bindable et Request Edit doivent être définis pour que cet attribut prenne
effet.

4. Cliquez sur le bouton Actualiser de la barre d'outils pour actualiser la bibliothèque de types. Pour pouvoir tester un contrôle
dont la liaison de données est activée, vous devez d'abord le recenser. Par exemple, pour lier un contrôle TEdit aux données
d'un contrôle ActiveX, créez le contrôle ActiveX à partir d'un TEdit, puis modifiez les indicateurs de la propriété Text en
Bindable, Display Bindable, Default Bindable et Immediate Bindable. Une fois le contrôle recensé et importé, il peut être utilisé
pour afficher les données.
Voir aussi
Utilisation des bibliothèques de types : Vue globale ( see page 1472)

3.2.2.3.10 Création d'une page de propriétés pour un contrôle ActiveX


Une page de propriétés est une boîte de dialogue similaire à l'inspecteur d'objets Delphi qui permet aux utilisateurs de modifier
les propriétés d'un contrôle ActiveX. Un dialogue de page de propriétés sert à regrouper plusieurs propriétés d'un contrôle afin
de les modifier ensemble ou à gérer des propriétés complexes. Vous pouvez aussi fournir une boîte de dialogue pour des
propriétés plus complexes.

En général, les utilisateurs accèdent à la page des propriétés en cliquant sur le contrôle ActiveX avec le bouton droit de la souris
et en choisissant Propriétés.

Le processus de création d'une page de propriétés est similaire à celui d'une fiche :
1. Création d'une nouvelle page de propriétés ( see page 1435).
2. Ajout de contrôles à la page de propriétés ( see page 1436).
3. Association des contrôles de la page de propriétés aux propriétés d'un contrôle ActiveX ( see page 1436).
4. Connexion de la page de propriétés au contrôle ActiveX ( see page 1437).
Remarque: Quand des propriétés sont ajoutées à un contrôle ActiveX ou à une fiche ActiveForm, vous devez publier les
propriétés dont vous voulez qu'elles persistent. Si ces propriétés ne sont pas publiées dans le contrôle VCL sous-jacent, vous 3
devez créer un descendant personnalisé du contrôle VCL qui redéclare les propriétés comme publiées, puis un contrôle
ActiveX à partir de la classe dérivée.

3.2.2.3.11 Création d'une nouvelle page de propriétés


Pour créer une nouvelle page de propriétés, utilisez l'expert Page propriétés.

1435
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Pour créer une nouvelle page de propriétés,


1. Choisissez Fichier Nouveau Autre.
2. Sélectionnez le dossier ActiveX sous Projets Delphi.
3. Double-cliquez sur l'icône Page propriétés dans le volet droit.
L'expert crée une nouvelle fiche et l'unité d'implémentation de la page de propriétés. La fiche est un descendant de
TPropertyPage qui vous permet d'associer la fiche avec le contrôle ActiveX dont il modifie les propriétés.
Voir aussi
Création d'une page de propriétés pour un contrôle ActiveX ( see page 1435)

3.2.2.3.12 Ajout de contrôles à une page de propriétés


Vous devez ajouter à la page de propriétés un contrôle pour chaque propriété du contrôle ActiveX à laquelle l'utilisateur doit
avoir accès.

Par exemple, la figure suivante illustre la configuration de la page de propriétés pour un contrôle ActiveX MaskEdit.

La boîte liste permet à l'utilisateur de sélectionner parmi une liste de modèles exemple. Les contrôles de saisie permettent à
l'utilisateur de tester le masque avant de l'appliquer au contrôle ActiveX. Pour ajouter des contrôles à la page de propriétés,
procédez comme avec une fiche.

Voir aussi
Création d'une page de propriétés pour un contrôle ActiveX ( see page 1435)

3.2.2.3.13 Association des contrôles de la page de propriétés aux propriétés


du contrôle ActiveX
Une fois tous les contrôles nécessaires ajoutés à la page de propriétés, il faut associer chaque contrôle à la propriété
correspondante. Cette association s'effectue en ajoutant du code à l'unité implémentant la page de propriétés. Précisément, il
faut ajouter du code aux méthodes UpdatePropertyPage ( see page 1436) et UpdateObject ( see page 1437).

Voir aussi
3 Création d'une page de propriétés pour un contrôle ActiveX ( see page 1435)

3.2.2.3.14 Mise à jour de la page de propriétés


Ajoutez du code à la méthode UpdatePropertyPage pour mettre à jour le contrôle de la page de propriétés quand les propriétés
du contrôle ActiveX changent. Vous devez ajouter du code à la méthode UpdatePropertyPage pour actualiser la page de
propriétés avec les valeurs en cours des propriétés du contrôle ActiveX.

1436
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Vous pouvez accéder au contrôle ActiveX en utilisant la propriété OleObject de la page de propriétés, qui est un OleVariant
contenant l'interface du contrôle ActiveX.

Par exemple, le code suivant actualise le contrôle boîte de saisie (InputMask) de la page de propriétés avec la valeur en cours
de la propriété EditMask du contrôle ActiveX :
procedure TPropertyPage1.UpdatePropertyPage;
begin
{ Met vos contrôles à jour à partir de OleObject }
InputMask.Text := OleObject.EditMask;
end;
Par exemple, le code suivant actualise le contrôle de modification (InputMask) de la page de propriétés avec la valeur en cours
de la propriété EditMask du contrôle ActiveX :
void __fastcall TPropertyPage1::UpdatePropertyPage(void)
{
InputMask->Text = OleObject.OlePropertyGet("EditMask");
}
Remarque: Il est également possible d'écrire une page de propriétés qui représente plusieurs contrôles ActiveX. Dans ce cas,
n'utilisez pas la propriété OleObject. Vous devez, à la place, parcourir la liste des interfaces qui est gérée par la propriété
OleObjects.

Voir aussi
Création d'une page de propriétés pour un contrôle ActiveX ( see page 1435)

3.2.2.3.15 Mise à jour de l'objet


Ajoutez du code à la méthode UpdateObject pour mettre à jour la propriété quand l'utilisateur modifie les contrôles de la page de
propriétés. Vous devez ajouter du code à la méthode UpdateObject afin de définir la nouvelle valeur des propriétés du contrôle
ActiveX.

Pour accéder à d'autres contrôles ActiveX, utilisez la propriété OleObject.

Par exemple, le code suivant affecte la propriété EditMask d'un contrôle ActiveX en utilisant la valeur du contrôle boîte de saisie
(InputMask) de la page de propriétés :
procedure TPropertyPage1.UpdateObject;
begin
{Met à jour OleObject à partir de votre contrôle }
OleObject.EditMask := InputMask.Text;
end;
void __fastcall TPropertyPage1::UpdateObject(void)
{
// Met à jour OleObject à partir de votre contrôle
OleObject.OlePropertySet<WideString>("EditMask", WideString(InputMast->Text).Copy());
}
Voir aussi
Création d'une page de propriétés pour un contrôle ActiveX ( see page 1435)
3
3.2.2.3.16 Connexion d'une page de propriétés à un contrôle ActiveX
Pour connecter une page de propriétés à un contrôle ActiveX,
1. Ajoutez DefinePropertyPage, avec la constante GUID de la page de propriétés comme paramètre, à l'implémentation de la
méthode DefinePropertyPages dans l'implémentation des contrôles de l'unité. Par exemple,
procedure TButtonX.DefinePropertyPages(DefinePropertyPage: TDefinePropertyPage);
begin

1437
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

DefinePropertyPage(Class_PropertyPage1);
end;
BEGIN_PROPERTY_MAP(TActiveFormXImpl)
// Définir ici les pages de propriétés. Les pages de propriétés sont définies en utilisant
// la macro PROP_PAGE avec l'id de classe de la page. Par exemple,
// PROP_PAGE(CLSID_ActiveFormXPage)
PROP_PAGE(CLSID_PropertyPage1)
END_PROPERTY_MAP()
La constante GUID, Class_PropertyPage1, de la page de propriétés peut être trouvée dans l'unité des pages de propriétés. Le
GUID est défini dans l'unité d'implémentation de la page de propriétés.

2. Ajoutez l'unité de la page de propriétés à la clause uses de l'unité d'implémentation des contrôles.
Voir aussi
Création d'une page de propriétés pour un contrôle ActiveX ( see page 1435)

3.2.2.4 Création de clients COM


Rubriques
Nom Description
Création de clients COM ( see page 1440) Les clients COM sont des applications qui utilisent un objet COM implémenté par
une autre application ou bibliothèque. Les types les plus courants sont les
applications qui contrôlent un serveur Automation ( see page 1456)
(contrôleurs Automation) et les applications qui accueillent un contrôle ActiveX
(conteneurs ActiveX).
Au premier abord, ces deux types de clients COM semblent très différents : un
contrôleur Automation standard lance un serveur EXE externe et émet des
commandes que le serveur traite pour lui. Le serveur Automation est
généralement non visuel et hors processus. D'un autre côté, le client ActiveX
standard accueille un contrôle visuel en l'utilisant comme vous pouvez... suite (
see page 1440)
Importation des informations d'une bibliothèque de types ( see page 1441) Pour que votre application client dispose des informations sur le serveur COM,
vous devez importer les informations décrivant le serveur qui sont stockées dans
la bibliothèque de types ( see page 1414). Votre application peut ensuite
utiliser les classes générées pour contrôler l'objet serveur.
Il y a deux manières d'importer les informations d'une bibliothèque de types :

• Vous pouvez utiliser la boîte de dialogue Importer un


composant pour importer toutes les informations
disponibles sur le type de serveur, les objets et les
interfaces. C'est la méthode la plus générale, car elle
vous permet d'importer des informations de toute
bibliothèque de types et peut, facultativement,... suite (
see page 1441)
Code généré par l'importation des informations d'une bibliothèque de types ( Une fois une bibliothèque de types importée, vous pouvez visualiser generated
see page 1442) NomBibTypes_TLB générée. En haut, vous trouverez les éléments suivants :
Tout d'abord, les déclarations des constantes donnant des noms symboliques
aux GUIDS de la bibliothèque de types, ses interfaces et ses CoClasses. Le nom
de ces constantes est généré comme suit :

• le GUID de la bibliothèque de types de la forme


LBID_NomBibTypes, où NomBibTypes est le nom de la
3 bibliothèque de types.
• Le GUID d'une interface a la forme IID_NomInterface, où
NomInterface est le nom de l'interface.
• Le GUID d'une dispinterface a la forme DIID_... suite (
see page 1442)

1438
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Contrôle d'un objet importé ( see page 1443) Après avoir importé les informations de la bibliothèque de types ( see page
1441), vous êtes prêts à commencer à programmer avec les objets importés. La
manière de procéder dépend pour partie des objets, et d'autre part du choix de
créer des composants enveloppe. Il existe deux approches :

• Utilisation des composants enveloppe ( see page 1443).


• Ecriture de code client basé sur les définitions de la
bibliothèque de types ( see page 1444).
Utilisation des composants enveloppe ( see page 1443) Si vous avez généré un composant enveloppe pour l'objet serveur, l'écriture de
l'application COM n'est pas très différente de celle d'une application contenant
des composants VCL. Les événements de l'objet serveur sont déjà encapsulés
dans le composant VCL. Il vous suffit juste d'affecter des gestionnaires
d'événements, de définir des valeurs de propriétés et d'appeler des méthodes.
Pour utiliser les propriétés, méthodes et événements de l'objet, voir la
documentation de l'objet serveur. Le composant enveloppe fournit
automatiquement une interface double ( see page 1464) quand c'est possible.
Delphi détermine la forme de la VTable à partir des informations de la
bibliothèque de types.
De plus,... suite ( see page 1443)
Ecriture de code client basé sur les définitions de la bibliothèque de types ( see Si vous êtes obligé d'utiliser un composant enveloppe pour accueillir un contrôle
page 1444) ActiveX, vous pouvez par contre écrire un contrôleur Automation en utilisant
uniquement les définitions de la bibliothèque de types qui apparaissent dans
l'unité NomBibTypes_TLB. Ce processus est un tout petit peu plus compliqué
que si vous laissez un composant enveloppe faire le travail, en particulier si vous
avez besoin de répondre aux événements.
Les rubriques suivantes décrivent comment implémenter les diverses actions que
votre contrôleur Automation doit effectuer.

• Connexion au serveur ( see page 1445).


• Contrôle d'un serveur Automation en utilisant une
interface double ( see page 1445).
• Contrôle d'un serveur Automation en ( see page 1446)...
suite ( see page 1444)
Connexion à un serveur ( see page 1445) Avant de pouvoir piloter un serveur Automation depuis votre application
contrôleur, vous devez obtenir une référence sur une interface qu'il gère.
Généralement, vous vous connectez au serveur via son interface principale.
Si l'interface principale est une interface double ( see page 1464), vous pouvez
utiliser les objets créateur du fichier NomBibTypes_TLB.pas. Les classes de
créateur portent le même nom que la CoClasse sans le préfixe "Co". Vous
pouvez vous connecter à un serveur situé sur la même machine en appelant la
méthode Create ou à un serveur situé sur une autre machine en utilisant la
méthode CreateRemote. Comme Create et CreateRemote... suite ( see page
1445)
Contrôle d'un serveur Automation en utilisant une interface double ( see page Après avoir utilisé la classe créateur générée automatiquement pour vous
1445) connecter au serveur ( see page 1445), appelez les méthodes de l'interface.
Par exemple,
Contrôle d'un serveur Automation en utilisant une interface de répartition ( see Généralement, vous utilisez l'interface double ( see page 1445) pour contrôler
page 1446) le serveur Automation. Toutefois, il se peut que vous deviez contrôler un serveur
Automation avec une interface de répartition ( see page 1465) s'il n'y a pas
d'interface double disponible.
Gestion des événements dans un contrôleur Automation ( see page 1446) Lorsque vous générez un composant enveloppe pour un objet dont vous
importez la bibliothèque de types, vous pouvez répondre aux événements en
utilisant simplement les événements ajoutés au composant généré. Néanmoins,
si vous n'utilisez pas un composant enveloppe (ou si le serveur utilise des
événements COM+), vous devez écrire vous-même le code du collecteur
d'événements.
Création de clients pour les serveurs n'ayant pas une bibliothèque de types (
see page 1448)
Certaines anciennes technologies COM comme OLE ne proposent pas les
informations de type dans une bibliothèque de types. Elles reposent à la place
3
sur un ensemble standard d'interfaces prédéfinies. Pour écrire des clients
accueillant de tels objets, vous pouvez utiliser les composants TOleContainer.
Ce composant apparaît dans la catégorie Système de la palette d'outils.
TOleContainer se comporte comme le site d'accueil d'un objet Ole2. Il
implémente l'interface IOleClientSite et, de manière facultative,
IOleDocumentSite. La communication est gérée en utilisant des verbes OLE.

1439
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Utilisation d'assemblages .NET avec Delphi ( see page 1448) L'environnement .NET Framework et le CLR (Common Language Runtime) de
Microsoft fournissent un environnement d'exécution dans lequel les composants
écrits en langages .NET peuvent interagir de façon transparente. Un compilateur
destiné à un langage .NET n'émet pas de code machine natif. A la place, le
langage est compilé vers une fiche intermédiaire indépendante de la plate-forme
appelée Microsoft Intermediate Language (MSIL ou IL). Les modules contenant
le code IL sont liés pour former un assemblage. Un assemblage peut se
composer de plusieurs modules, ou il peut s'agir d'un seul fichier. Dans les deux
cas, un assemblage est une entité qui... suite ( see page 1448)
Exigences de l'interopérabilité COM ( see page 1449) Si vous développez de nouveaux composants avec l'environnement .NET
Framework, vous devez installer le kit SDK .NET Framework complet, disponible
sur le site Web MSDN de Microsoft à l'adresse msdn.microsoft.com. Si vous
n'utilisez que des types .NET directement à partir des assemblages principaux
de .NET Framework, vous ne devez installer que .NET Framework
Redistributable, également disponible sur le site Web MSDN. Bien entendu, pour
toutes les applications non gérées qui s'appuient sur des services fournis par
l'environnement .NET Framework, vous devrez déployer .NET Framework
Redistributable sur la machine de l'utilisateur final.
Les composants .NET sont exposés au code non... suite ( see page 1449)
Composants .NET et bibliothèques de types ( see page 1449) Les environnements COM et .NET Framework contiennent tous deux des
mécanismes permettant d'exposer les informations de type. Dans
l'environnement COM, ce mécanisme est la bibliothèque de types. Les
bibliothèques de types constituent pour un objet COM une façon binaire neutre
par rapport au langage de programmation d'exposer les métadonnées de type à
l'exécution. Comme les bibliothèques de types sont ouvertes et analysées par les
API système, les langages comme Delphi peuvent les importer et profiter des
avantages de la liaison vtable, même si le composant a été écrit dans un autre
langage de programmation.
Dans l'environnement de développement .NET, l'assemblage... suite ( see
page 1449)
Accès aux composants .NET définis par l'utilisateur ( see page 1450) Quand vous examinez une bibliothèque de types pour un composant .NET, vous
pouvez, selon la façon dont le composant a été conçu et construit, ne trouver
qu'une interface de classe vide. L'interface de classe ne contient alors aucune
information sur les paramètres attendus par les méthodes implémentées par la
classe. Les dispid (identificateurs dispatch) des méthodes de la classe sont
également absents. Cela permet d'éviter les éventuels problèmes rencontrés lors
de la création d'une nouvelle version du composant.
Dans l'environnement COM, l'héritage ne peut s'effectuer que via une interface.
Dans .NET Framework, le mode d'héritage (via une interface ou par... suite (
see page 1450)

3.2.2.4.1 Création de clients COM


Les clients COM sont des applications qui utilisent un objet COM implémenté par une autre application ou bibliothèque. Les
types les plus courants sont les applications qui contrôlent un serveur Automation ( see page 1456) (contrôleurs Automation) et
les applications qui accueillent un contrôle ActiveX (conteneurs ActiveX).

Au premier abord, ces deux types de clients COM semblent très différents : un contrôleur Automation standard lance un serveur
EXE externe et émet des commandes que le serveur traite pour lui. Le serveur Automation est généralement non visuel et hors
processus. D'un autre côté, le client ActiveX standard accueille un contrôle visuel en l'utilisant comme vous pouvez utiliser les
contrôles de la palette des composants. Les serveurs ActiveX sont toujours des serveurs en processus.

Cependant, la réalisation de ces deux types de clients COM est étonnamment similaire : L'application client obtient une interface
pour l'objet serveur et utilise ses propriétés et méthodes. RAD Studio simplifie beaucoup cela en vous permettant d'envelopper
la CoClasse serveur dans un composant du client que vous pouvez même installer dans la palette des composants.

3 Quand vous écrivez un client COM, vous devez comprendre l'interface que le serveur expose aux clients, exactement comme
vous devez comprendre les propriétés et méthodes d'un composant de la palette des composants pour pouvoir l'utiliser dans
votre application. Cette interface (ou cet ensemble d'interfaces) est déterminée par l'application serveur et se trouve
généralement publiée dans une bibliothèque de types ( see page 1472). Pour des informations spécifiques sur les interfaces
publiées par une application serveur spécifique, vous devez consulter la documentation de cette application.

Même si vous ne choisissez pas d'envelopper un objet serveur et de l'installer dans la palette des composants, vous devez
rendre sa définition d'interface accessible à votre application. Pour ce faire, vous pouvez importer les informations de la
bibliothèque de types du serveur ( see page 1441).

1440
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Une fois que vous avez importé les informations de type, vous pouvez écrire du code pour contrôler l'objet importé ( see page
1443).

Remarque: Vous pouvez également interroger directement les informations de type en utilisant l'API COM, mais RAD Studio ne
propose pas de gestion particulière de ce processus.

Certaines anciennes technologies COM comme OLE ne proposent pas les informations de type dans une bibliothèque de types.
Elles reposent à la place sur un ensemble standard d'interfaces prédéfinies. Elles sont présentées dans Création de clients pour
les serveurs n'ayant pas une bibliothèque de types ( see page 1448).

Voir aussi
Création de pages Active Server ( see page 1420)

Utilisation des bibliothèques de types : Vue globale ( see page 1472)

Présentation des technologies COM ( see page 1404)

3.2.2.4.2 Importation des informations d'une bibliothèque de types


Pour que votre application client dispose des informations sur le serveur COM, vous devez importer les informations décrivant le
serveur qui sont stockées dans la bibliothèque de types ( see page 1414). Votre application peut ensuite utiliser les classes
générées pour contrôler l'objet serveur.

Il y a deux manières d'importer les informations d'une bibliothèque de types :

• Vous pouvez utiliser la boîte de dialogue Importer un composant pour importer toutes les informations disponibles sur le
type de serveur, les objets et les interfaces. C'est la méthode la plus générale, car elle vous permet d'importer des
informations de toute bibliothèque de types et peut, facultativement, créer des composants enveloppe pour toutes les
CoClasses de la bibliothèque de types pouvant être créées et qui n'ont pas les indicateurs Hidden, Restricted ou PreDeclID.
• Vous pouvez utiliser la boîte de dialogue Importer un composant si vous importez la bibliothèque de types d'un contrôle
ActiveX. Cela importe les mêmes informations de type, mais ne crée des composants enveloppe que pour les CoClasses qui
représentent des contrôles ActiveX.
• Vous pouvez utiliser l'utilitaire en ligne de commande tlibimp.exe qui fournit des options de configuration supplémentaires non
disponibles à partir de l'EDI.
• Une bibliothèque de types générée à l'aide d'un expert est automatiquement importée en utilisant le mécanisme de l'élément
de menu Importer une bibliothèque de types.
Indépendamment de la méthode utilisée pour importer les informations de la bibliothèque de types, la boîte de dialogue crée une
unité de nom NomBibTypes_TLB, où NomBibTypes est le nom de la bibliothèque de types. Ce fichier contient des
déclarations pour les classes, types et interfaces définis dans la bibliothèque de types. En l'incluant dans votre projet, ces
définitions deviennent accessibles à votre application afin de pouvoir créer des objets et appeler leurs interfaces. Ce fichier
peut être recréé par l'EDI de temps en temps ; de ce fait, des modifications manuelles apportées au fichier ne sont pas
recommandées.
Outre l'ajout des définitions de types à l'unité NomBibTypes_TLB, la boîte de dialogue peut également créer des classes
enveloppe VCL pour toutes les CoClasses définies dans la bibliothèque de types. Quand vous utilisez la boîte de dialogue
Importation de bibliothèque de types, ces classes enveloppe sont facultatives. Quand vous utilisez la boîte de dialogue
Importation d'ActiveX, elles sont toujours générées pour toutes les CoClasses représentant des contrôles.
Les classes enveloppe générées représentent les CoClasses de votre application et exposent les propriétés et méthodes de ses 3
interfaces. Si une CoClasse gère les interfaces de création d'événements (IConnectionPointContainer et IConnectionPoint), la
classe enveloppe VCL crée un collecteur d'événements afin que vous puissiez affecter des gestionnaires d'événements aux
événements aussi facilement que pour les autres composants. Si vous demandez dans la boîte de dialogue d'installer les
classes VCL générées dans la palette d'outils, vous pouvez utiliser l'inspecteur d'objets pour affecter des valeurs aux
propriétés et aux gestionnaires d'événements.
Remarque: La boîte de dialogue Importer un composant
ne crée par de classe enveloppe pour les objets événement COM+. Pour écrire un client répondant aux événements générés
par un objet événement COM+, vous devez créer le collecteur d'événements par code. Ce processus est décrit dans la

1441
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

section Gestion des événements COM+ ( see page 1446). Pour davantage de détails sur le code généré quand vous
importez une bibliothèque de types, voir Code généré par l'importation des informations d'une bibliothèque de types ( see
page 1442).
Voir aussi
Utilisation des bibliothèques de types ( see page 1472)

Contrôle d'un objet importé ( see page 1443)

3.2.2.4.3 Code généré par l'importation des informations d'une bibliothèque de


types
Une fois une bibliothèque de types importée, vous pouvez visualiser generated NomBibTypes_TLB générée. En haut, vous
trouverez les éléments suivants :

Tout d'abord, les déclarations des constantes donnant des noms symboliques aux GUIDS de la bibliothèque de types, ses
interfaces et ses CoClasses. Le nom de ces constantes est généré comme suit :

• le GUID de la bibliothèque de types de la forme LBID_NomBibTypes, où NomBibTypes est le nom de la bibliothèque de


types.
• Le GUID d'une interface a la forme IID_NomInterface, où NomInterface est le nom de l'interface.
• Le GUID d'une dispinterface a la forme DIID_NomInterface, où NomInterface est le nom de la dispinterface.
• Le GUID d'une CoClasse a la forme CLASS_NomClasse, où NomClasse est le nom de la CoClasse.
• La directive de compilation VARPROPSETTER est activée. Ce qui vous permet d'utiliser le mot clé var dans la liste de
paramètres des méthodes setter des propriétés. Cela désactive l'optimisation de la compilation qui entraînerait la
transmission des paramètres par valeur plutôt que par référence. La directive VARPROPSETTER doit être activée lors de la
création d'unités TLB pour des composants écrits dans un langage autre que Delphi.
Deuxièmement, des déclarations des CoClasses de la bibliothèque de types. Elles correspondent à chaque CoClasse de son
interface par défaut.
Troisièmement, des déclarations pour les interfaces et dispinterfaces de la bibliothèque de types.
Quatrièmement, des déclarations pour une classe créateur pour chaque CoClasse dont l'interface par défaut gère les liaisons
par VTable. La classe créateur a deux méthodes de classe, Create et CreateRemote, qui peuvent s'utiliser pour instancier la
CoClasse localement (Create) ou à distance (CreateRemote). Ces méthodes renvoient l'interface par défaut de la CoClasse.
Ces déclarations fournissent ce qu'il faut pour créer des instances de la CoClasse et accéder à son interface. Il vous faut ajouter
le fichier NomBibTypes_TLB.pas généré à la clause uses de l'unité dans laquelle vous voulez effectuer le lien avec une
CoClasse et appeler ses interfaces.
Remarque: Cette portion de l'unitéNomBibTypes_TLB est également générée quand vous utilisez l'éditeur de bibliothèques
de types ou l'utilitaire en ligne de commande TLIBIMP.
Si vous voulez utiliser un contrôle ActiveX, vous avez également besoin de la classe enveloppe VCL générée en plus des
déclarations décrites ci-dessus. L'enveloppe VCL gère les problèmes de gestion de fenêtre du contrôle. Vous pouvez
également avoir d'autres classes enveloppe VCL générées pour d'autres CoClasses avec la boîte de dialogue Importation de
bibliothèque de types. Ces enveloppes VCL simplifient la création d'objets serveur et l'appel de leurs méthodes. Elles sont
particulièrement recommandées si vous voulez que votre application client réponde aux événements.
3 Les déclarations pour les enveloppes VCL générées apparaissent en bas de la section interface. Les composants enveloppe
des contrôles ActiveX sont des descendants de TOleControl. Les composants enveloppe pour les objets Automation
descendent de TOleServer. Le composant enveloppe généré ajoute les propriétés, méthodes et événements exposés par
l'interface de la CoClasse. Vous pouvez utiliser ce composant comme vous utilisez tous les autres composants VCL.
Avertissement: Vous ne devez pas modifier l'unité générée NomBibTypes_TLB. Elle est régénérée à chaque fois que la
bibliothèque de types est rafraîchie, ce qui écrase toutes les modifications.
Remarque: Pour des informations les plus à jour, voir les commentaires placés dans l'unité générée automatiquement
NomBibTypes_TLB.

1442
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

3.2.2.4.4 Contrôle d'un objet importé


Après avoir importé les informations de la bibliothèque de types ( see page 1441), vous êtes prêts à commencer à programmer
avec les objets importés. La manière de procéder dépend pour partie des objets, et d'autre part du choix de créer des
composants enveloppe. Il existe deux approches :

• Utilisation des composants enveloppe ( see page 1443).


• Ecriture de code client basé sur les définitions de la bibliothèque de types ( see page 1444).
Voir aussi
Importation des informations d'une bibliothèque de types ( see page 1441)

3.2.2.4.5 Utilisation des composants enveloppe


Si vous avez généré un composant enveloppe pour l'objet serveur, l'écriture de l'application COM n'est pas très différente de
celle d'une application contenant des composants VCL. Les événements de l'objet serveur sont déjà encapsulés dans le
composant VCL. Il vous suffit juste d'affecter des gestionnaires d'événements, de définir des valeurs de propriétés et d'appeler
des méthodes.

Pour utiliser les propriétés, méthodes et événements de l'objet, voir la documentation de l'objet serveur. Le composant
enveloppe fournit automatiquement une interface double ( see page 1464) quand c'est possible. Delphi détermine la forme de
la VTable à partir des informations de la bibliothèque de types.

De plus, le nouveau composant hérite de sa classe de base des propriétés et méthodes importantes.

Enveloppes ActiveX
Vous devez toujours utiliser un composant enveloppe pour accueillir des contrôles ActiveX car le composant enveloppe intègre
la fenêtre du contrôle dans le modèle VCL.

Le contrôle ActiveX hérite de TOleControl des propriétés et méthodes qui vous permettent d'accéder à l'interface sous-jacente
ou d'obtenir des informations sur le contrôle. Cependant, la plupart des applications n'en n'ont pas besoin. Vous utilisez à la
place le contrôle importé comme vous utiliseriez tout autre contrôle VCL.

Généralement, les contrôles ActiveX proposent une page de propriétés qui vous permet de définir leurs propriétés. Les pages de
propriétés sont similaires aux éditeurs que certains composants affichent quand vous double-cliquez dessus dans le concepteur
de fiche. Pour afficher la page de propriétés d'un contrôle ActiveX, cliquez dessus avec le bouton droit de la souris et choisissez
Propriétés.

La manière dont vous utilisez les contrôles ActiveX importés est déterminée par l'application serveur. Cependant, les contrôles
ActiveX utilisent un ensemble standard de notifications quand ils représentent les données d'un champ de base de données.
Pour davantage d'informations sur la manière d'accueillir des contrôles ActiveX orientés données, voir TOleControl.

Enveloppes des objets Automation


Les enveloppes des objets Automation vous permettent de contrôler comment vous voulez constituer la connexion avec l'objet
serveur :
3
La propriété ConnectKind indique si le serveur est local ou distant et si vous voulez vous connecter avec un serveur en cours
d'exécution ou si une nouvelle instance doit être lancée. Pour se connecter avec un serveur distant, vous devez spécifier le nom
de la machine en utilisant la propriété RemoteMachineName.

Deuxièmement, une fois la valeur de ConnectKind spécifiée, il y a trois manières de connecter le composant au serveur :

• Une connexion explicite au serveur en appelant la méthode Connect du composant.


• Vous pouvez indiquer au composant de se connecter automatiquement avec le serveur au démarrage de votre application en
initialisant la propriété AutoConnect à true.

1443
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

• Vous n'avez pas besoin de vous connecter explicitement au serveur. Le composant crée automatiquement une connexion
quand vous utilisez l'une des propriétés et méthodes du serveur par le biais du composant.
Vous appelez les méthodes ou utilisez les propriétés comme pour tout autre composant :
TServerComponent1.DoSomething;
TServerComponent1->DoSomething();
Il est facile de gérer les événements car vous pouvez utiliser l'inspecteur d'objets pour écrire des gestionnaires d'événements.
Toutefois, vous devez faire attention car les gestionnaires d'événements de votre composant ont des paramètres légèrement
différents de ceux définis pour les événements de la bibliothèque de types. Plus précisément, les types pointeurs (paramètres
var et pointeur d'interface) sont changés en Variants. Vous devez explicitement transtyper les paramètres var dans le type
sous-jacent avant de leur affecter une valeur. Les pointeurs d'interface peuvent être convertis au type d'interface approprié en
utilisant l'opérateur as.

Par exemple, l'exemple de code suivant est un gestionnaire d'événement pour l'événement OnNewWorkBook de
ExcelApplication. Le gestionnaire d'événement a un paramètre qui fournit l'interface d'une autre CoClasse (ExcelWorkbook).
Cependant, l'interface n'est pas transmise comme un pointeur d'interface ExcelWorkBook, mais comme un OleVariant.
procedure TForm1.XLappNewWorkbook(Sender: TObject; var Wb:OleVariant);
begin
{ Remarque : le OleVariant de l'interface est transtypé dans le type adéquat }
ExcelWorkbook1.ConnectTo((iUnknown(wb) as ExcelWorkbook));
end;
void _fastcall TForm1::XLappNewWorkbook(TObject *Sender, ExcelWorkbookPtr Wb)
{
ExcelWorkbook1->ConnectTo(Wb);
}
Dans cet exemple, le gestionnaire d'événement affecte le classeur à un composant ExcelWorkbook (ExcelWorkbook1). Cela
illustre la manière de connecter un composant enveloppe à une interface existante en utilisant la méthode ConnectTo. La
méthode ConnectTo est ajoutée au code généré du composant enveloppe.

Les serveurs qui ont un objet application exposent une méthode Quit pour cet objet afin de permettre aux clients de terminer la
connexion. Généralement Quit expose des fonctionnalités équivalentes à l'utilisation du menu Fichier pour la sortie de
l'application. Du code pour l'appel de la méthode Quit est généré dans la méthode Disconnect de votre composant. Il est
possible d'appeler la méthode Quit sans paramètre. Le composant enveloppe a également une propriété AutoQuit. AutoQuit
oblige le contrôleur à appeler Quit quand le composant est libéré. Si vous voulez déconnecter à un autre moment, ou si la
méthode Quit nécessite des paramètres, vous devez l'appeler explicitement. Quit apparaît comme méthode publique du
composant généré.

Voir aussi
Ecriture de code client basé sur les définitions de la bibliothèque de types ( see page 1444)

Création de clients pour les serveurs n'ayant pas une bibliothèque de types ( see page 1448)

3.2.2.4.6 Ecriture de code client basé sur les définitions de la bibliothèque de


types
3 Si vous êtes obligé d'utiliser un composant enveloppe pour accueillir un contrôle ActiveX, vous pouvez par contre écrire un
contrôleur Automation en utilisant uniquement les définitions de la bibliothèque de types qui apparaissent dans l'unité
NomBibTypes_TLB. Ce processus est un tout petit peu plus compliqué que si vous laissez un composant enveloppe faire le
travail, en particulier si vous avez besoin de répondre aux événements.

Les rubriques suivantes décrivent comment implémenter les diverses actions que votre contrôleur Automation doit effectuer.

• Connexion au serveur ( see page 1445).


• Contrôle d'un serveur Automation en utilisant une interface double ( see page 1445).

1444
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

• Contrôle d'un serveur Automation en utilisant une dispinterface ( see page 1446).
• Réponse aux événements générés par le serveur Automation ( see page 1446).
Voir aussi
Utilisation des composants enveloppe ( see page 1443)

Création de clients pour les serveurs n'ayant pas une bibliothèque de types ( see page 1448)

3.2.2.4.7 Connexion à un serveur


Avant de pouvoir piloter un serveur Automation depuis votre application contrôleur, vous devez obtenir une référence sur une
interface qu'il gère. Généralement, vous vous connectez au serveur via son interface principale.

Si l'interface principale est une interface double ( see page 1464), vous pouvez utiliser les objets créateur du fichier
NomBibTypes_TLB.pas. Les classes de créateur portent le même nom que la CoClasse sans le préfixe "Co". Vous pouvez vous
connecter à un serveur situé sur la même machine en appelant la méthode Create ou à un serveur situé sur une autre machine
en utilisant la méthode CreateRemote. Comme Create et CreateRemote sont des méthodes de classe, vous n'avez pas besoin
d'une instance de la classe de créateur pour les appeler.
MyInterface := CoServerClassName.Create;
MyInterface := CoServerClassName.CreateRemote('Machine1');
pInterface = CoServerClassName.Create();
pInterface = CoServerClassName.CreateRemote("Machine1");
Create et CreateRemote renvoient l'interface par défaut de la CoClasse.

Si l'interface par défaut est une interface de répartition, il n'y a pas de classe créateur générée pour la CoClasse. Vous devez à
la place, appeler la fonction globale CreateOleObject, en lui transmettant le GUID de la CoClasse (il y a une constante pour ce
GUID définie en haut de l'unité _TLB). CreateOleObject renvoie un pointeur IDispatch pour l'interface par défaut.

Voir aussi
Contrôle d'un serveur Automation en utilisant une interface de répartition ( see page 1446)

Contrôle d'un serveur Automation en utilisant une interface double ( see page 1445)

Gestion des événements dans un contrôleur Automation ( see page 1446)

3.2.2.4.8 Contrôle d'un serveur Automation en utilisant une interface double


Après avoir utilisé la classe créateur générée automatiquement pour vous connecter au serveur ( see page 1445), appelez les
méthodes de l'interface. Par exemple,
var
MyInterface : _Application;
begin
MyInterface := CoWordApplication.Create;
MyInterface.DoSomething;
TComApplication AppPtr = CoWordApplication_.Create();
AppPtr->DoSomething;
3
L'interface et la classe créateur sont définies dans l'unité NomBibTypes_TLB générée automatiquement quand vous importez
une bibliothèque de types.

Voir aussi
Contrôle d'un serveur Automation en utilisant une interface de répartition ( see page 1446)

1445
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

3.2.2.4.9 Contrôle d'un serveur Automation en utilisant une interface de


répartition
Généralement, vous utilisez l'interface double ( see page 1445) pour contrôler le serveur Automation. Toutefois, il se peut que
vous deviez contrôler un serveur Automation avec une interface de répartition ( see page 1465) s'il n'y a pas d'interface double
disponible.

Pour appeler les méthodes d'une interface de répartition,


1. Connectez-vous au serveur ( see page 1445), en utilisant la fonction globale CreateOleObject.
2. Utilisez l'opérateur as pour transtyper l'interface IDispatch renvoyée par CreateOleObject en une interface de répartition pour
la CoClasse. Ce type dispinterface est déclaré dans l'unité NomBibTypes_TLB.
3. Contrôlez le serveur Automation en appelant les méthodes de la dispinterface. Vous pouvez utiliser autrement les interfaces
de répartition en les affectant à un Variant. En affectant l'interface renvoyée par CreateOleObject à un Variant, vous pouvez
tirer profit de la gestion intégrée des interfaces que propose le type Variant. Appelez simplement les méthodes de l'interface
et c'est le Variant qui gère automatiquement les appels IDispatch, la récupération de l'identificateur de répartition et les appels
de méthode appropriés. Le type Variant possède une gestion intégrée permettant l'appel des interfaces de répartition, via ses
méthodes var.
V: Variant;
begin
V:= CreateOleObject("TheServerObject");
V.MethodName; { appelle la méthode spécifiée }
...
Un avantage de l'utilisation de Variants est qu'il n'est pas nécessaire d'importer la bibliothèque de types car les Variants utilisent
uniquement les méthodes standard de IDispatch pour appeler le serveur. La contrepartie, c'est que les Variants sont plus lents
car ils utilisent une liaison dynamique à l'exécution.

Voir aussi
Contrôle d'un serveur Automation en utilisant une interface double ( see page 1445)

3.2.2.4.10 Gestion des événements dans un contrôleur Automation


Lorsque vous générez un composant enveloppe pour un objet dont vous importez la bibliothèque de types, vous pouvez
répondre aux événements en utilisant simplement les événements ajoutés au composant généré. Néanmoins, si vous n'utilisez
pas un composant enveloppe (ou si le serveur utilise des événements COM+), vous devez écrire vous-même le code du
collecteur d'événements.

Gestion des événements Automation par code


Avant de pouvoir gérer les événements, vous devez définir un collecteur d'événements. C'est une classe qui implémente
l'interface de répartition des événements qui est définie dans la bibliothèque de types du serveur.

Pour écrire le collecteur d'événements, créez un objet qui implémente l'interface de répartition des événements :
TServerEventsSink = class(TObject, _TheServerEvents)
3 ...{ déclarez ici les méthodes de _TheServerEvents }
end;
class MyEventSinkClass: TEventDispatcher<MyEventSinkClass, DIID_TheServerEvents>
{
...// déclarez ici les méthodes de DIID_TheServerEvents
}
Quand vous disposez d'une instance de votre collecteur d'événements, vous devez informer l'objet serveur de son existence afin
que le serveur puisse l'appeler. Pour ce faire, appelez la procédure globale InterfaceConnect en lui transmettant :

• L'interface du serveur qui génère les événements.

1446
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

• Le GUID de l'interface événement que gère votre collecteur d'événements.


• Une interface IUnknown pour votre collecteur d'événements.
• Une variable qui reçoit un Longint représentant la connexion entre le serveur et votre collecteur d'événements.
{MyInterface est l'interface serveur que vous obtenez quand vous vous connectez au serveur }
InterfaceConnect(MyInterface, DIID_TheServerEvents,
MyEventSinkObject as IUnknown, cookievar);
pInterface = CoServerClassName.CreateRemote("Machine1");
MyEventSinkClass ES;
ES.ConnectEvents(pInterface);
Après avoir appelé InterfaceConnect, votre collecteur d'événements est connecté et reçoit les appels du serveur quand des
événements se produisent.

Vous devez terminer la connexion avant de libérer le collecteur d'événements. Pour ce faire, appelez la procédure globale
InterfaceDisconnect en lui transmettant les mêmes paramètres, sauf l'interface de votre collecteur d'événements (le paramètre
final étant en entrée et non plus en sortie) :
InterfaceDisconnect(MyInterface, DIID_TheServerEvents, cookievar);
ES.DisconnectEvents(pInterface);
Remarque: Vous devez être certain que le serveur a libéré sa connexion avec votre collecteur d'événements avant de libérer le
collecteur. Comme vous ne savez pas comment le serveur répond à la notification de déconnexion initiée par
InterfaceDisconnect, cela peut entraîner une condition si vous libérez votre collecteur d'événements immédiatement après
l'appel. Le moyen le plus simple de vous prémunir contre cela est que votre collecteur d'événements gère son propre compteur
de références qui n'est pas décrémenté tant que le serveur n'a pas libéré l'interface du collecteur d'événements.

Gestion des événements COM+


Avec COM+, les serveurs utilisent un objet utilitaire spécial pour générer des événements à la place d'un groupe d'interfaces
spéciales (IConnectionPointContainer et IConnectionPoint). Donc, vous ne pouvez pas utiliser un collecteur d'événements qui
descend de TEventDispatcher. TEventDispatcher est conçue pour fonctionner avec des interfaces, pas avec des objets
événement COM+.

Au lieu de définir un collecteur d'événements, votre application client définit un objet abonné. Comme les collecteurs
d'événements, les objets abonné fournissent l'implémentation de l'interface événement. Ils sont différents des collecteurs
d'événements car ils décrivent un objet événement particulier et non une connexion avec un point de connexion d'un serveur.

Pour définir un objet abonné, utilisez l'expert objet COM ( see page 1457) en sélectionnant l'interface de l'objet événement que
vous voulez implémenter. L'expert génère une unité d'implémentation avec des squelettes de méthodes que vous pouvez
renseigner pour créer vos gestionnaires d'événements.

Remarque: Vous pouvez avoir à ajouter l'interface de l'objet événement dans le registre en utilisant l'expert si elle n'apparaît
pas dans la liste des interfaces que vous pouvez implémenter.

Une fois l'objet abonné créé, vous devez vous abonner à l'interface de l'objet événement ou individuellement aux méthodes
(événements) de cette interface. Vous pouvez souscrire à trois types d'abonnements :

• Abonnements temporaires. Comme les collecteurs d'événements habituels, les abonnements temporaires sont liés à la
durée de vie de l'instance d'objet. Quand l'objet abonné est libéré, l'abonnement s'arrête et COM+ ne lui transmet plus les
événements.
3
• Abonnements permanents. Ils sont liés à la classe de l'objet et non à une instance d'objet spécifique. Quand l'événement se
produit, COM recherche ou démarre un processus de l'objet abonné et appelle son gestionnaire d'événement. Les objets en
processus (DLL) utilisent ce type d'abonnement.
• Abonnements par utilisateur. Ces abonnements offrent une version plus sécurisée des abonnements temporaires. L'objet
abonné et l'objet serveur qui déclenchent les événements doivent être exécutés avec le même compte utilisateur sur la même
machine.
Remarque: Les objets qui s'abonnent à des événements COM+ doivent être installés dans une application COM+.

1447
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Voir aussi
Contrôle d'un serveur Automation en utilisant une interface de répartition ( see page 1446)

Contrôle d'un serveur Automation en utilisant une interface double ( see page 1445)

3.2.2.4.11 Création de clients pour les serveurs n'ayant pas une bibliothèque
de types
Certaines anciennes technologies COM comme OLE ne proposent pas les informations de type dans une bibliothèque de types.
Elles reposent à la place sur un ensemble standard d'interfaces prédéfinies. Pour écrire des clients accueillant de tels objets,
vous pouvez utiliser les composants TOleContainer. Ce composant apparaît dans la catégorie Système de la palette d'outils.

TOleContainer se comporte comme le site d'accueil d'un objet Ole2. Il implémente l'interface IOleClientSite et, de manière
facultative, IOleDocumentSite. La communication est gérée en utilisant des verbes OLE.

Pour utiliser TOleContainer


1. Placez un composant TOleContainer dans votre fiche.
2. Initialisez la propriété AllowActiveDoc à true si vous voulez pouvoir accueillir un document actif.
3. Initialisez la propriété AllowInPlace pour indiquer si l'objet accueilli doit apparaître dans le TOleContainer ou dans une fenêtre
séparée.
4. Ecrivez des gestionnaires d'événements pour répondre quand l'objet est activé, désactivé, déplacé ou redimensionné.
5. Pour lier l'objet TOleContainer à la conception, cliquez avec le bouton droit de la souris et choisissez Insérer un objet. Dans la
boîte de dialogue Insertion d'objet, choisissez l'objet serveur à accueillir.
6. Vous avez plusieurs moyens de lier l'objet TOleContainer à l'exécution, selon la manière dont vous voulez identifier l'objet
serveur. La méthode CreateObject attend un identificateur de programme, CreateObjectFromFile attend le nom d'un fichier
dans lequel l'objet a été enregistré, CreateObjectFromInfo attend un enregistrement contenant des informations sur la
manière de créer l'objet ou CreateLinkToFile qui attend le nom d'un fichier dans lequel l'objet a été enregistré et effectue une
liaison et non une incorporation.
7. Une fois l'objet lié, vous pouvez accéder à son interface en utilisant la propriété OleObjectInterface. Cependant, comme la
communication avec les objets Ole2 était basée sur les verbes OLE, vous préférerez probablement envoyer des commandes
au serveur en utilisant la méthode DoVerb.
8. Quand vous voulez libérer l'objet serveur, appelez la méthode DestroyObject.
Voir aussi
Utilisation des composants enveloppe ( see page 1443)

Ecriture de code client basé sur les définitions de la bibliothèque de types ( see page 1444)

3.2.2.4.12 Utilisation d'assemblages .NET avec Delphi


L'environnement .NET Framework et le CLR (Common Language Runtime) de Microsoft fournissent un environnement
d'exécution dans lequel les composants écrits en langages .NET peuvent interagir de façon transparente. Un compilateur
3
destiné à un langage .NET n'émet pas de code machine natif. A la place, le langage est compilé vers une fiche intermédiaire
indépendante de la plate-forme appelée Microsoft Intermediate Language (MSIL ou IL). Les modules contenant le code IL sont
liés pour former un assemblage. Un assemblage peut se composer de plusieurs modules, ou il peut s'agir d'un seul fichier. Dans
les deux cas, un assemblage est une entité qui se décrit elle-même ; c'est-à-dire qu'il détient les informations sur les types qu'il
contient, les modules qui le composent et les dépendances par rapport à d'autres assemblages. Un assemblage représente
l'unité de base pour un déploiement dans l'environnement de déploiement .NET, et le CLR gère le chargement, la compilation en
code machine natif et l'exécution ultérieure de ce code. Les applications entièrement exécutées dans le contexte du CLR sont
appelées code managé.

1448
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

L'un des services fournis par le CLR consiste à permettre au code managé d'appeler le code non managé, c'est-à-dire le code
qui a été compilé en langage machine natif et qui ne s'exécute pas dans l'environnement du CLR. Par exemple, grâce au service
Platform Invoke (PInvoke), le code managé peut appeler des API Win32 natives. Cette fonctionnalité s'étend à l'utilisation
d'objets COM existants à partir d'une application .NET managée. L'interopérabilité entre le code managé et les objets COM
fonctionne également dans l'autre sens, ce qui autorise l'exposition des composants .NET aux applications non managées. Pour
ces dernières, le chargement et l'accès aux composants .NET s'apparentent presque en tous points à l'accès aux autres objets
COM.

Voir aussi
Utilisation des bibliothèques de types : Vue globale ( see page 1472)

3.2.2.4.13 Exigences de l'interopérabilité COM


Si vous développez de nouveaux composants avec l'environnement .NET Framework, vous devez installer le kit SDK .NET
Framework complet, disponible sur le site Web MSDN de Microsoft à l'adresse msdn.microsoft.com. Si vous n'utilisez que des
types .NET directement à partir des assemblages principaux de .NET Framework, vous ne devez installer que .NET Framework
Redistributable, également disponible sur le site Web MSDN. Bien entendu, pour toutes les applications non gérées qui
s'appuient sur des services fournis par l'environnement .NET Framework, vous devrez déployer .NET Framework Redistributable
sur la machine de l'utilisateur final.

Les composants .NET sont exposés au code non géré par l'intermédiaire de l'utilisation d'objets proxy appelés COM Callable
Wrappers (CCW). Dans la mesure où les mécanismes COM permettent d'établir le lien entre le code géré et le code non géré,
vous devez recenser les assemblages .NET qui contiennent les composants que vous souhaitez utiliser. Employez l'utilitaire
.NET Framework appelé regasm pour créer les entrées de registre nécessaires. La procédure à suivre est identique au
recensement des autres objets COM ; elle fera l'objet d'une description détaillée dans cette section.

L'assemblage .NET mscorlib.dll contient les types de l'environnement .NET Framework. Tous les assemblages .NET doivent
faire référence à l'assemblage mscorlib, tout simplement parce qu'il fournit la fonctionnalité de base de l'environnement .NET
Framework sur la plate-forme Microsoft Windows. Si vous prévoyez d'utiliser les types directement contenus dans l'assemblage
mscorlib, vous devez exécuter l'utilitaire regasm sur mscorlib.dll. Si ce n'est pas déjà fait, le programme d'installation Delphi
recense l'assemblage mscorlib.

Les composants .NET peuvent être déployés de deux façons : Dans un emplacement global partagé appelé Global Assembly
Cache (GAC) ou tous dans le même répertoire (par exemple, l'exécutable). Les composants partagés par plusieurs applications
doivent être déployés dans le GAC. Comme ils sont partagés et en raison des capacités de déploiement côte à côte de
l'environnement .NET Framework, les assemblages déployés dans le GAC doivent recevoir un nom fort (c'est-à-dire qu'ils
doivent avoir une signature numérique). L'environnement .NET Framework contient un utilitaire appelé sn, qui permet de générer
les clés de cryptage. Une fois les clés générées et le composant créé, l'assemblage est installé dans le GAC à l'aide d'un autre
utilitaire .NET appelé gacutil.

Un composant .NET peut également être déployé dans le même répertoire que l'exécutable non géré. Dans ce scénario de
déploiement, la clé forte et l'utilitaire d'installation GAC ne sont pas requis. En revanche, le composant doit toujours être recensé
à l'aide de l'utilitaire regasm. Contrairement à un objet COM ordinaire, le recensement d'un composant .NET ne le rend pas
accessible à une application qui ne se trouve pas dans le répertoire de déploiement du composant.
3
3.2.2.4.14 Composants .NET et bibliothèques de types
Les environnements COM et .NET Framework contiennent tous deux des mécanismes permettant d'exposer les informations de
type. Dans l'environnement COM, ce mécanisme est la bibliothèque de types. Les bibliothèques de types constituent pour un
objet COM une façon binaire neutre par rapport au langage de programmation d'exposer les métadonnées de type à l'exécution.
Comme les bibliothèques de types sont ouvertes et analysées par les API système, les langages comme Delphi peuvent les
importer et profiter des avantages de la liaison vtable, même si le composant a été écrit dans un autre langage de

1449
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

programmation.

Dans l'environnement de développement .NET, l'assemblage sert de conteneur pour l'IL et les informations de type. Cet
environnement contient des classes qui permettent d'examiner (ou "refléter") les types d'un assemblage. Quand vous accédez à
un composant .NET à partir du code non géré, vous utilisez en fait un proxy (le CCW COM mentionné plus haut), et non pas le
composant .NET lui-même. Le mécanisme CCW et la nature auto-descriptrice des assemblages suffisent pour vous permettre
d'accéder à un composant .NET entièrement par liaison différée.

Comme vous pouvez accéder à un composant .NET par liaison différée, vous n'êtes pas obligé de créer une bibliothèque de
types pour le composant. Il vous suffit de recenser l'assemblage. En fait, les clients non gérés sont limités à la liaison différée
par défaut. Selon la façon dont le composant .NET a été conçu et construit, vous ne trouverez peut-être qu'une interface de
classe "vide" si vous inspectez sa bibliothèque de types. Une telle bibliothèque de types est inutile pour permettre aux clients
d'utiliser la liaison vtable au lieu de la liaison différée via IDispatch.

L'exemple suivant montre comment réaliser une liaison différée à la classe de la collection ArrayList contenue dans mscorlib.dll.
L'assemblage mscorlib doit être recensé avant d'utiliser un type quelconque de la façon décrite ici. Le programme d'installation
Delphi recense automatique mscorlib, mais vous pouvez réexécuter l'utilitaire regasm si cela s'avère nécessaire (par exemple, si
vous avez annulé le recensement de mscorlib avec l'option /u de regasm). Exécutez la commande suivante
regasm mscorlib.dll
dans le répertoire .NET Framework pour recenser l'assemblage mscorlib.

Remarque: N'utilisez pas l'option /tlb pour recenser mscorlib.dll. En effet, .NET Framework comporte déjà une bibliothèque de
types pour l'assemblage mscorlib ; vous ne devez donc pas en créer une nouvelle.

Le code suivant est attaché à un événement clic de bouton d'une fiche Delphi :
procedure TForm1.Button1Click(Sender: TObject);
var
capacity: Integer;
item:Variant;
dotNetArrayList:Variant;
begin
{ Créer l'objet }
dotNetArrayList := CreateOleObject('System.Collections.ArrayList');

{ Obtenir la capacité d'ArrayList }


capacity := dotNetArrayList.Capacity;

{ Ajouter un élément }
dotNetArrayList.Add('Un élément chaîne');

{ Récupérer l'élément à l'aide de la méthode Item() de l'interface Array. }


item := dotNetArrayList.Item(0);

{Supprimer tous les éléments }


dotNetArrayList.Clear;
end;

3.2.2.4.15 Accès aux composants .NET définis par l'utilisateur


3 Quand vous examinez une bibliothèque de types pour un composant .NET, vous pouvez, selon la façon dont le composant a été
conçu et construit, ne trouver qu'une interface de classe vide. L'interface de classe ne contient alors aucune information sur les
paramètres attendus par les méthodes implémentées par la classe. Les dispid (identificateurs dispatch) des méthodes de la
classe sont également absents. Cela permet d'éviter les éventuels problèmes rencontrés lors de la création d'une nouvelle
version du composant.

Dans l'environnement COM, l'héritage ne peut s'effectuer que via une interface. Dans .NET Framework, le mode d'héritage (via
une interface ou par implémentation) est décidé à la conception. Les concepteurs de composants .NET peuvent choisir d'ajouter
une nouvelle méthode ou propriété à tout moment. Si des modifications sont apportées au composant .NET, tous les clients

1450
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

COM qui dépendent de la disposition de l'interface (par exemple en plaçant les dispid en mémoire cache) s'arrêtent.

Un concepteur de composants .NET doit choisir d'exposer les informations de type dans une bibliothèque de types exportée,
mais cette action ne s'effectue pas par défaut. Pour cela, il faut utiliser l'attribut personnalisé ClassInterfaceAttribute.
ClassInterfaceAttribute se trouve dans l'espace de nommage System.Runtime.InteropServices. Il peut prendre les valeurs de
l'énumération ClassInterfaceType, c'est-à-dire AutoDispatch (valeur par défaut), AutoDual et None.

La valeur AutoDispatch entraîne la création de l'interface de classe vide. Lorsqu'ils accèdent à une telle classe, les clients sont
limités à la liaison différée. Lorsqu'une classe a la valeur AutoDual, toutes les informations de type (y compris les dispid) sont
incluses. Avec la valeur AutoDual, les informations de type sont également incluses pour toutes les classes héritées. Il s'agit de
l'approche la plus pratique, qui fonctionne bien quand les composants .NET sont développés dans un environnement contrôlé.
Sachez toutefois que cette approche est également liée aux problèmes de version mentionnés plus haut.

Si vous attribuez la valeur None à ClassInterfaceType, la génération d'une interface de classe est interdite. Dans ce cas, seules
les méthodes implémentées dans les interfaces héritées peuvent être appelées. Pour les composants .NET destinés à être
utilisés par un client COM non géré, l'héritage via l'interface est la méthode préférée pour l'interopérabilité entre le code géré et
le code non géré. Le client COM est ainsi moins enclin aux changements dans la classe .NET. Il renforce aussi un principe de
conception éprouvé : l'immuabilité des interfaces.

L'exemple suivant illustre cette approche. Nous débutons avec une interface C# appelée MyInterface et une classe appelée
MyClass.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;

[assembly:AssemblyKeyFile("KeyFile.snk")]
namespace InteropTest1 {
public interface MyInterface {
void myMethod1();
void myMethod2(string msg);
}

// Les clients sont limités à l'utilisation d'interfaces implémentées.


[ClassInterface(ClassInterfaceType.None)]
public class MyClass : MyInterface {

// La classe doit avoir un constructeur sans paramètre pour l'interopérabilité COM


public MyClass() {
}

// Implémenter les méthodes MyInterface


public void myMethod1() {
MessageBox.Show("Dans la méthode C# !");
}

public void myMethod2(string msg) {


MessageBox.Show(msg);
}
}
}
L'assemblage est marqué avec l'attribut AssemblyKeyFile. C'est nécessaire si le composant doit être déployé dans le GAC. Si
3
vous déployez votre composant dans le même répertoire que le client exécutable non géré, la clé forte n'est pas nécessaire.
Dans l'exemple suivant, le composant sera déployé dans le GAC, donc nous commençons par générer le fichier des clés à l'aide
de l'utilitaire Strong Name du kit SDK de .NET Framework :
sn -k KeyFile.snk
Exécutez cette commande à partir du répertoire dans lequel se trouve le fichier source C#.

L'étape suivante consiste à compiler ce code à l'aide du compilateur C#. Si l'on considère que le code C# se trouve dans le

1451
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

fichier interoptest1.cs :
csc /t:library interoptest1.cs
Le résultat de cette commande est la création d'un assemblage appelé interoptest1.dll. Il faut à présent recenser le composant à
l'aide de l'utilitaire regasm. Cet utilitaire est identique à tregsvr ; il crée dans le registre Windows des entrées qui permettent
l'exposition du composant aux clients COM non gérés.
regasm /tlb interoptest1.dll
Quand vous utilisez l'option /tlb, regasm fait deux choses : Il commence par créer les entrées du registre. Il exporte ensuite les
types de l'assemblage vers une bibliothèque de types (la bibliothèque est également recensée).

Enfin, le composant est déployé dans le GAC à l'aide de la commande gacutil :


gacutil -i interoptest1.dll
L'option -i indique que l'assemblage est installé dans le GAC. Vous devez exécuter la commande gacutil chaque fois que vous
construisez une nouvelle version du composant .NET. Plus tard, si vous souhaitez retirer le composant du GAC, exécutez à
nouveau la commande gacutil, cette fois avec l'option -u :
gacutil -u interoptest1
Remarque: Lorsque vous désinstallez un composant, n'ajoutez pas l'extension .dll au nom de l'assemblage.

Une fois le composant .NET créé, recensé et installé dans le GAC (ou copié dans le répertoire de l'exécutable non géré), vous
pouvez y accéder dans Delphi comme pour tout autre objet COM. Ouvrez ou créez votre projet, puis sélectionnez
Composant Importer bibliothèque de types. Dans la liste des bibliothèques de types recensées, recherchez celle de votre
composant. Vous pouvez créer un package pour le composant et l'installer sur la palette d'outils en cochant la case Intaller.
L'importateur de bibliothèques de types crée un fichier _TLB pour envelopper le composant, le rendant accessible au code
Delphi non géré via la liaison vtable.

Le bouton Ajouter de la boîte de dialogue d'importation de la bibliothèque de types ne permet pas de recenser correctement une
bibliothèque de types exportée pour un assemblage .NET. A la place, vous devez toujours inclure l'utilitaire regasm sur la ligne
de commande.

L'importateur de bibliothèques de types crée automatiquement des fichiers _TLB (et leurs fichiers .dcr et .dcu correspondants)
pour tous les assemblages .NET qui sont référencés dans la bibliothèque de types importée. Si vous importez la bibliothèque de
types pour l'exemple ci-dessus, cela crée les fichiers _TLB, .dcr et .dcu pour les assemblages mscorlib et
System.Windows.Forms.

L'exemple suivant illustre l'appel de méthodes sur le composant .NET, après l'importation de sa bibliothèque de types dans
Delphi. Les noms de classe et de méthode viennent de l'exemple C# précédent, et l'on considère que la variable MyClass1 a
déjà été déclarée (par exemple comme une variable membre d'une classe ou une variable locale d'une procédure ou fonction).
MyClass1 := TMyClass.Create(self);
MyClass1.myMethod1;
MyClass1.myMethod2('Afficher ce message');
MyClass1.Free;

1452
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

3.2.2.5 Création de serveurs COM simples


Rubriques
Nom Description
Création de serveurs COM simples : Vue globale ( see page 1456) Delphi dispose d'experts pour vous aider à créer divers objets COM. Les objets
COM les plus simples sont des serveurs qui exposent des propriétés et des
méthodes (et éventuellement des événements) via une interface par défaut que
leurs clients peuvent appeler.
Deux experts, en particulier, simplifient le processus de création d'objets COM
simples :

• L’ expert objet COM ( see page 1457) construit un objet


COM léger dont l'interface par défaut descend de
IUnknown ( see page 1406) ou qui implémente une
interface déjà recensée dans votre système. Cet expert
offre la plus grande flexibilité dans les types d'objets COM
qu'il est possible de créer.
• L’ expert objet Automation ( see page 1458)... suite (
see page 1456)
Conception d'un objet COM ( see page 1456) Quand vous concevez un objet COM, vous devez choisir les interfaces COM que
vous voulez implémenter. Vous pouvez écrire des objets COM pour implémenter
une interface qui a déjà été définie ou vous pouvez définir une nouvelle interface
que votre objet doit implémenter. De plus, votre objet peut gérer plusieurs
interfaces. Pour des informations sur les interfaces COM standard que vous
pouvez gérer, voir la documentation MSDN.

• Pour créer un objet COM qui implémente une interface


existante, utilisez l'expert objet COM ( see page 1457).
• Pour créer un objet COM qui implémente une nouvelle
interface que vous définissez, utilisez l'expert Objet COM
( see page 1457) ou... suite ( see page 1456)
Utilisation de l'expert Objet COM ( see page 1457) L'expert Objet COM effectue les opérations suivantes :

• Création d'une nouvelle unité.


• Définition d'une nouvelle classe qui descend de
TCOMObject et configure le constructeur de la factory de
classe. Pour plus d'informations sur la classe de base,
voir Code généré par des experts ( see page 1417).
• Facultativement, ajout au projet d'une bibliothèque de
types et ajout de l'objet et de son interface à la
bibliothèque de types.
Avant de créer un objet COM, créez ou ouvrez le projet de
l'application contenant les fonctionnalités à implémenter.
Le projet peut être une application ou une bibliothèque
ActiveX, selon vos besoins.

1453
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Utilisation de l'expert Objet Automation ( see page 1458) L'expert objet Automation effectue les opérations suivantes :

• Création d'une nouvelle unité.


• Définition d'une nouvelle classe qui descend de
TAutoObject et configure le constructeur du fabricant de
classe. Pour plus d'informations sur la classe de base,
voir Code généré par des experts ( see page 1417).
• Ajout au projet d'une bibliothèque de types et ajout de
l'objet et de son interface à la bibliothèque de types.
Avant de créer un objet Automation, créez ou ouvrez le
projet de l'application contenant les fonctionnalités à
implémenter. Le projet peut être une application ou une
bibliothèque ActiveX, selon vos besoins.
Types d'instanciation des objets COM ( see page 1459) La plupart des experts COM attendent que vous spécifiez le mode d'instanciation
de l'objet. L'instanciation détermine le nombre d'instances de votre objet que les
clients peuvent créer dans un seul exécutable. Par exemple, si vous spécifiez le
modèle Instance unique, une fois qu'un client a instancié votre objet, COM rend
l'application invisible ; ainsi d'autres clients doivent lancer leurs propres instances
de l'application. Comme cela affecte la visibilité globale de votre application, le
mode d'instanciation doit être le même pour tous les objets de votre application
qui peuvent être instanciés par les clients. Cela signifie que vous ne pouvez pas
créer... suite ( see page 1459)
Choix d'un modèle de thread ( see page 1459) Lors de la création d'un objet à l'aide de l'expert, sélectionnez le modèle de
thread que votre objet peut gérer. En ajoutant la gestion des threads à votre
objet COM, vous pouvez augmenter ses performances, car plusieurs clients
peuvent accéder simultanément à votre application.
Le tableau suivant énumère les différents modèles de thread que vous pouvez
spécifier.
Modèles de thread pour les objets COM
Définition de l'interface d'un objet COM ( see page 1461) Quand vous utilisez un expert pour créer un objet COM, l'expert crée
automatiquement une bibliothèque de types (sauf si vous avez demandé le
contraire dans l'expert objet COM). La bibliothèque de types permet aux
applications hôte de déterminer ce que l'objet peut faire. Elle vous permet
également de définir l'interface de l'objet en utilisant l'éditeur de bibliothèques de
types ( see page 1473). Les interfaces que vous définissez dans l'éditeur de
bibliothèques de types définissent les propriétés, méthodes et événements que
votre objet expose aux clients.
Remarque: Si vous sélectionnez une interface existante dans l'expert objet
COM, vous n'avez pas besoin d'ajouter des... suite ( see page 1461)
Gestion des événements dans un objet Automation ( see page 1464) L'expert Automation génère automatiquement le code d'événement si vous
activez l'option Générer le code de support dans la boîte de dialogue de l'expert
objet Automation.
Pour qu'un serveur gère les événements COM classiques, il doit proposer une
définition d'une interface de sortie implémentée par un client. Cette interface en
sortie contient tous les gestionnaires d'événements que le client doit implémenter
pour répondre aux événements du serveur.
Quand un client a implémenté l'interface événement en sortie, il informe de son
souhait d'être notifié des événements en interrogeant l'interface
IConnectionPointContainer du serveur. L'interface IConnectionPointContainer
renvoie l'interface IConnectionPoint du serveur qui est utilisée... suite ( see
page 1464)

1454
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

Interfaces d'Automation ( see page 1464) L'expert Objet Automation implémente par défaut une interface double ( see
page 1464) ce qui signifie que l'objet Automation gère :

• La liaison tardive à l'exécution, via son interface


IDispatch. Elle est implémentée comme une interface de
répartition ou dispinterface ( see page 1465).
• La liaison précoce à la compilation, ce qui s'effectue
directement en appelant l'une des fonctions membre de la
table de fonction virtuelle (VTable). C'est ce que l'on
appelle une interface personnalisée ( see page 1465).
Remarque: Les interfaces générées par l'expert Objet
COM
qui ne descendent pas de IDispatch ne gèrent que les
appels de la VTable.
Interfaces doubles ( see page 1464) Une interface double est à la fois une interface personnalisée et une
dispinterface. Elle est implémentée en tant qu'interface VTable COM qui dérive
de IDispatch. Pour les contrôleurs qui accèdent à l'objet uniquement à
l'exécution, la dispinterface est disponible. Pour les objets qui peuvent tirer profit
de la liaison à la compilation, c'est l'interface VTable, la plus efficace, qui est
utilisée.
Les interfaces doubles offrent les avantages combinés des interfaces VTable et
des dispinterfaces :

• Pour les interfaces VTable, le compilateur fait une


vérification de type et fournit des messages d'erreurs plus
informatifs.
• Pour les contrôleurs Automation qui ne peuvent pas...
suite ( see page 1464)
Interfaces de répartition ( see page 1465) Les contrôleurs Automation sont des clients qui utilisent l'interface COM
IDispatch pour accéder aux objets du serveur COM. Le contrôleur doit d'abord
créer l'objet, puis demander à l'interface IUnknown de l'objet un pointeur sur son
interface IDispatch. IDispatch garde en interne la trace des méthodes et des
propriétés par le biais d'un identificateur de répartition (dispID), qui est un
numéro d'identification propre à chaque membre interface. Grâce à IDispatch, un
contrôleur récupère les informations de type de l'objet pour l'interface de
répartition, puis associe les noms des membres interface aux dispID spécifiques.
Ces dispID sont accessibles à l'exécution... suite ( see page 1465)
Interfaces personnalisées ( see page 1465) Les interfaces personnalisées sont des interfaces définies par l'utilisateur qui
permettent aux clients d'appeler les méthodes de l'interface en fonction de leur
ordre dans la VTable et du type des arguments. La VTable contient les adresses
de toutes les propriétés et méthodes qui sont membres de l'objet, y compris les
fonctions membre des interfaces qu'il supporte. Si l'objet ne supporte pas
IDispatch, les entrées correspondant aux membres des interfaces
personnalisées de l'objet suivent immédiatement celles des membres de
IUnknown.
Si l'objet possède une bibliothèque de types, vous pouvez accéder à l'interface
personnalisée via sa disposition VTable, que vous... suite ( see page 1465)
Marshaling des données ( see page 1465) Pour les serveurs hors processus et distants, vous devez prendre en compte la
façon dont COM effectue le marshaling des données hors du processus en
cours. Vous pouvez effectuer le marshaling :

• Automatiquement, en utilisant l'interface IDispatch.


• Automatiquement, en créant une bibliothèque de types
avec votre serveur et en marquant l'interface avec le
drapeau d'Automation OLE. COM sait comment réaliser le
3
marshaling de tous les types compatibles Automation
de la bibliothèque de types et peut implémenter les proxys
et les stubs pour vous. Certaines restrictions de types
sont nécessaires pour permettre le marshaling
automatique.
• Manuellement, en implémentant toutes les méthodes...
suite ( see page 1465)

1455
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32

Recensement d'un objet COM ( see page 1467) Un objet serveur peut être recensé comme serveur en ou hors processus. Pour
des informations générales sur les serveurs en et hors processus, voir Serveurs
en processus ( see page 1408).
Remarque: Pour retirer l'objet COM de votre système, vous devez commencer
par annuler son recensement.
Test et débogage de l'application ( see page 1467) Lorsque vous avez créé une application serveur COM, vous souhaitez la tester
avant de la déployer.

3.2.2.5.1 Création de serveurs COM simples : Vue globale


Delphi dispose d'experts pour vous aider à créer divers objets COM. Les objets COM les plus simples sont des serveurs qui
exposent des propriétés et des méthodes (et éventuellement des événements) via une interface par défaut que leurs clients
peuvent appeler.

Deux experts, en particulier, simplifient le processus de création d'objets COM simples :

• L’ expert objet COM ( see page 1457) construit un objet COM léger dont l'interface par défaut descend de IUnknown ( see
page 1406) ou qui implémente une interface déjà recensée dans votre système. Cet expert offre la plus grande flexibilité dans
les types d'objets COM qu'il est possible de créer.
• L’ expert objet Automation ( see page 1458) crée un objet Automation simple dont l'interface par défaut descend de
IDispatch ( see page 1465). IDispatch introduit un mécanisme de marshaling standard et gère la liaison tardive des appels
d'interfaces.
Remarque: COM définit de nombreuses interfaces standard et des mécanismes pour gérer des situations spécifiques. Les
experts Delphi automatisent les opérations les plus courantes. Cependant, certaines tâches, comme le marshaling
personnalisé ne sont gérées par aucun expert Delphi. Pour des informations à ce propos et sur d'autres technologies qui ne
sont pas explicitement gérées par Delphi, reportez-vous à la documentation Microsoft Developer's Network (MSDN). Le site
Web Microsoft propose également des informations à jour sur la gestion COM.
Présentation de la création d'un objet COM
Que vous utilisiez l'expert objet Automation pour créer un nouveau serveur Automation ou l'expert objet COM pour créer
d'autres types d'objets COM, le processus à suivre est le même.

Il implique les étapes suivantes :


1. Conception ( see page 1456) de l'objet COM.
2. Utilisation de l'expert objet COM ( see page 1457) ou de l'expert objet Automation ( see page 1458) pour créer l'objet
serveur.
3. Définition de l'interface ( see page 1461) que l'objet expose aux clients.
4. Recensement de l'objet COM ( see page 1467).
5. Test et débogage ( see page 1467) de l'application.
Voir aussi
Présentation des technologies COM ( see page 1404)

Création de pages Active Server ( see page 1420)

3 3.2.2.5.2 Conception d'un objet COM


Quand vous concevez un objet COM, vous devez choisir les interfaces COM que vous voulez implémenter. Vous pouvez écrire
des objets COM pour implémenter une interface qui a déjà été définie ou vous pouvez définir une nouvelle interface que votre
objet doit implémenter. De plus, votre objet peut gérer plusieurs interfaces. Pour des informations sur les interfaces COM
standard que vous pouvez gérer, voir la documentation MSDN.

• Pour créer un objet COM qui implémente une interface existante, utilisez l'expert objet COM ( see page 1457).
• Pour créer un objet COM qui implémente une nouvelle interface que vous définissez, utilisez l'expert Objet COM ( see page

1456
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM

1457) ou l'expert Objet Automation ( see page 1458). L'expert objet COM peut générer une nouvelle interface par défaut qui
descend de IUnknown ( see page 1406), l'expert objet Automation attribue à l'objet une interface par défaut qui descend de
IDispatch ( see page 1465). Indépendamment de l'expert utilisé, vous pouvez toujours employer ultérieurement l'éditeur de
bibliothèques de types pour modifier l'interface parent de l'interface par défaut que l'expert a généré.
Outre le choix des interfaces à gérer, vous devez décider si l'objet COM est un serveur en ou hors processus ou un serveur
distant ( see page 1408). Pour les serveurs en processus, les serveurs hors processus et les serveurs distants qui utilisent
une bibliothèque de types, COM vous délègue les données. Sinon, vous devez choisir comment transmettre les données aux
serveurs hors processus.

3.2.2.5.3 Utilisation de l'expert Objet COM


L'expert Objet COM effectue les opérations suivantes :

• Création d'une nouvelle unité.


• Définition d'une nouvelle classe qui descend de TCOMObject et configure le constructeur de la factory de classe. Pour plus
d'informations sur la classe de base, voir Code généré par des experts ( see page 1417).
• Facultativement, ajout au projet d'une bibliothèque de types et ajout de l'objet et de son interface à la bibliothèque de types.
Avant de créer un objet COM, créez ou ouvrez le projet de l'application contenant les fonctionnalités à implémenter. Le projet
peut être une application ou une bibliothèque ActiveX, selon vos besoins.

Pour afficher l'expert objet COM


1. Choisissez Fichier Nouveau Autre pour ouvrir la boîte de dialogue Nouveaux éléments.
2. Sélectionnez le dossier nommé ActiveX sous Projets Delphi
3. Double-cliquez sur l'icône Objet COM dans le volet droit.
Dans l'expert, vous devez spécifier :
• Nom de CoClasse : C'est le nom de l'objet tel qu'il apparaît aux clients. La classe créée pour implémenter votre objet porte
ce nom préfixé par un 'T'. Si vous choisissez de ne pas implémenter une interface existante, l'expert attribue à votre
CoClasse une interface par défaut portant ce nom préfixé par un 'I'.
• Interface implémentée : Par défaut, l'expert attribue à votre objet une interface par défaut qui descend de IUnknown ( see
page 1406). Après être sorti de l'expert, vous devez utiliser l'éditeur de bibliothèques de types pour ajouter des propriétés et
méthodes à cette interface. Cependant, vous pouvez aussi sélectionner une interface prédéfinie que votre objet va

Vous aimerez peut-être aussi