Devwin 32
Devwin 32
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
iii
RAD Studio
Procédures 57
Procédures CodeGuard 58
Utilisation de CodeGuard 58
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
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
vii
RAD Studio
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
xi
RAD Studio
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
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
xvii
RAD Studio
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
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
xxiii
RAD Studio
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
xxv
RAD Studio
xxvi
RAD Studio
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
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 :
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 :
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
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é.
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
Les exceptions suivantes illustrent la façon dont CodeGuard signale les exceptions :
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)
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
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
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.
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)
9
Avertissements CodeGuard RAD Studio 1.1 Débogage d'applications C++ avec les
Voir aussi
Erreurs signalées par CodeGuard ( see page 3)
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. 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. 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.
• 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
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 :
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.
Voir aussi
Utilisation des composants dbGo ( see page 1522)
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.
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)
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 de l'explorateur de données pour obtenir des informations de connexion ( see page 84)
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.
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.
18
1.2 Développement d'applications de RAD Studio Introduction à InterBase Express
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 :
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 :
20
1.2 Développement d'applications de RAD Studio Introduction à InterBase Express
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 :
TIBConfigService
TIBBackupService
TIBRestoreService
TIBValidationService
TIBStatisticalService
TIBLogService
TIBSecurityService
TIBLicensingService
TIBServerProperties
TIBInstall
TIBUnInstall
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
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
Le pilote DbxClient traite à distance l'interface de framework dbExpress 4 sur un transport réseau.
• 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
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.
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.
23
Présentation des nouvelles fonctionnalités RAD Studio 1.2 Développement d'applications de
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
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.
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
26
1.2 Développement d'applications de RAD Studio Présentation de la migration 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.
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
Le tableau suivant présente la correspondance entre les classes ADO.NET, BDP et AdoDbx Client :
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.
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.
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 :
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.
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
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.
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
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.
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.
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.
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.
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
33
Déploiement d'applications de bases de RAD Studio 1.2 Développement d'applications de
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 :
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 :
34
1.2 Développement d'applications de RAD Studio Framework dbExpress
Remarque: * Le pilote n'est pas totalement certifié pour cette version de la base de données.
Voir aussi
Présentation Borland du déploiement d'applications
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.
• 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)
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.
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.
• 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
38
1.3 Développement des applications RAD Studio Développement d'applications COM
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 :
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.
• 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.
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.
• 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'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
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.
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
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)
• 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.
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.
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)
48
1.5 Développement d'applications avec RAD Studio Utilisation de TEncoding pour les fichiers
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).
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.
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
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 :
• 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.
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.
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.
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.
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)
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)
53
Présentation des services Web RAD Studio 1.7 Développement de services Web avec
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)
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
• Applications GUI
• Applications console
• Applications de service
• Packages et DLL
• 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.
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.
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
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++.
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.
58
2.1 Procédures CodeGuard RAD Studio Utilisation de CodeGuard
59
RAD Studio 2.2 Procédures de bases de données
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 :
61
Configuration d'une connexion TSQL RAD Studio 2.2 Procédures de bases de données
Voir aussi
Composants dbExpress ( see page 16)
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.
63
Débogage d'applications dbExpress à RAD Studio 2.2 Procédures de bases de données
64
2.2 Procédures de bases de données RAD Studio Exécution des commandes à l'aide de
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.
66
2.2 Procédures de bases de données RAD Studio Spécification des données à afficher à
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)
67
Spécification des données à afficher à RAD Studio 2.2 Procédures de bases de données
68
2.2 Procédures de bases de données RAD Studio Utilisation du BDE
Voir aussi
Composants dbExpress ( see page 16)
69
Utilisation de DataSnap RAD Studio 2.2 Procédures de bases de données
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.
70
2.2 Procédures de bases de données RAD Studio Utilisation de TBatchMove
71
Connexion aux bases de données avec RAD Studio 2.2 Procédures de bases de données
Utilisation d'objets mise à jour pour mettre à jour un ensemble de données ( see page 1735)
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.
73
Utilisation de TQuery RAD Studio 2.2 Procédures de bases de données
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é.
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.
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)
76
2.2 Procédures de bases de données RAD Studio Gestion des sessions de bases de
77
Utilisation de TSimpleDataSet RAD Studio 2.2 Procédures de bases de données
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)
79
Utilisation de TStoredProc RAD Studio 2.2 Procédures de bases de données
Voir aussi
Utilisation de DataSnap ( see page 70)
80
2.2 Procédures de bases de données RAD Studio Utilisation de TTable
Voir aussi
Vue globale BDE ( see page 15)
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.
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.
82
2.2 Procédures de bases de données RAD Studio Utilisation de dbExpress
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)
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)
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.
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
85
Utilisation des experts COM RAD Studio 2.3 Procédures d'applications
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
• 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
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
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.
88
2.5 Procédures VCL RAD Studio
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 :
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 :
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 :
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 :
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.
93
RAD Studio 2.5 Procédures VCL
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 :
95
Développement d'une application Windows RAD Studio 2.5 Procédures VCL
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.
96
2.5 Procédures VCL RAD Studio Construction des menus d'applications
97
Construction des menus d'applications RAD Studio 2.5 Procédures VCL
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.
98
2.5 Procédures VCL RAD Studio Construction d'une application Fiches VCL
TActionMainMenuBar
TActionManager
TActionToolBar
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
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.
100
2.5 Procédures VCL RAD Studio Construction d'une application MDI Fiches
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)
101
Construction d'une application MDI Fiches RAD Studio 2.5 Procédures VCL
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 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
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)
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 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)
La construction d'une application VCL ADO comprend les étapes principales suivantes :
106
2.5 Procédures VCL RAD Studio Conception d'une application Fiches VCL
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)
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)
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.
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.
109
Utilisation de ActionManager pour créer RAD Studio 2.5 Procédures VCL
La construction d'une application VCL avec ActionManager comprend les étapes principales suivantes :
110
2.5 Procédures VCL RAD Studio Conception d'une application Fiches VCL
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.
Construction d'une application MDI Fiches VCL sans utiliser d'expert ( see page 102)
La construction d'une application Fiches VCL dbExpress comprend les étapes principales suivantes :
111
Conception d'une application Fiches VCL RAD Studio 2.5 Procédures VCL
112
2.5 Procédures VCL RAD Studio Construction d'une application avec des
<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.
114
2.5 Procédures VCL RAD Studio Copie de données d'un flux vers un autre
115
Copie de la totalité d'une liste de chaînes RAD Studio 2.5 Procédures VCL
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
117
Création de chaînes RAD Studio 2.5 Procédures VCL
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)
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.
118
2.5 Procédures VCL RAD Studio Création d'une instance de fiche VCL en
Add('Animaux');
Add('Chats');
Add('Fleurs');
end;
119
Création d'une instance de fiche VCL en RAD Studio 2.5 Procédures VCL
120
2.5 Procédures VCL RAD Studio Suppression de chaînes
Création dynamique d'une fiche VCL non modale ( see page 131)
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.
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();
}
122
2.5 Procédures VCL RAD Studio Affichage d'une image bitmap dans une
123
Affichage d'une image bitmap dans une RAD Studio 2.5 Procédures VCL
Conseil: Vous pouvez modifier la taille du rectangle à afficher en ajustant les valeurs du paramètre Rect.
124
2.5 Procédures VCL RAD Studio Affichage d'une image bitmap plein écran
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)
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.
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)
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 );
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)
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)
Dessin de rectangles et d'ellipses dans une application Fiches VCL ( see page 127)
128
2.5 Procédures VCL RAD Studio Création dynamique d'une fiche VCL
Voir aussi
Présentation de la VCL ( see page 46)
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)
129
Création dynamique d'une fiche VCL RAD Studio 2.5 Procédures VCL
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)
Création dynamique d'une fiche VCL non modale ( see page 131)
131
Parcours des chaînes d'une liste RAD Studio 2.5 Procédures VCL
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
133
Eviter les accès de threads simultanés RAD Studio 2.5 Procédures VCL
134
2.5 Procédures VCL RAD Studio Définition de l'objet thread
135
Définition de l'objet thread RAD Studio 2.5 Procédures VCL
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);
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);
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)
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)
{
}
}
138
2.5 Procédures VCL RAD Studio Initialisation d'un thread
Eviter les accès de threads simultanés dans la même mémoire ( see page 134)
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
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.
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.
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.
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.
, 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)
Eviter les accès de threads simultanés dans la même mémoire ( see page 134)
141
Attente des threads RAD Studio 2.5 Procédures VCL
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.
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)
Eviter les accès de threads simultanés dans la même mémoire ( see page 134)
143
Insertion d'une image bitmap dans un RAD Studio 2.5 Procédures VCL
Eviter les accès de threads simultanés dans la même mémoire ( see page 134)
144
2.5 Procédures VCL RAD Studio Lecture d'une chaîne et écriture de cette
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.
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.
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.
147
Création d'un bouton ActiveX Fiches VCL RAD Studio 2.5 Procédures VCL
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.
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 :
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.
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.
Création d'une fiche active ActiveX Fiches VCL ( see page 150)
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 :
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.
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.
Composants :
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.
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
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)
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
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 :
157
Construction d'une application "Hello RAD Studio 2.6 Procédures WebSnap
158
2.6 Procédures WebSnap RAD Studio Construction d'une application "Hello
159
Débogage d'une application WebSnap à RAD Studio 2.6 Procédures WebSnap
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.
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)
161
Construction d'une application de services RAD Studio 2.7 Procédures 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 :
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.
163
Accès à une application services Web RAD Studio 2.7 Procédures de services Web
L'accès à une application "Hello World" simple avec des services Web ASP.NET comprend quatre étapes principales :
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.
164
2.7 Procédures de services Web RAD Studio Construction d'une application de services
Construction d'une application de services Web "Hello World" ( see page 165)
165
Construction d'une application de services RAD Studio 2.7 Procédures de services Web
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++
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)
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 :
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 :
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
171
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++
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++
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.
-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
• 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
• 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.
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.
175
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++
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
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.
176
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande
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.
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)
177
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++
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.
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)
178
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande
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.
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++).
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.
180
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande
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.
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")
Voir aussi
BCC32.EXE ( see page 171)
181
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++
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.
183
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++
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.
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 (|).
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
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)
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++
192
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande
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.
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.
Voir aussi
RLINK32.EXE ( see page 220)
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.
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
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)
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).
<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.
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
Remarque: Une DLL peut également avoir l'extension .EXE ou .DRV, pas seulement .DLL.
Voir aussi
IMPDEF.EXE ( see page 194)
• 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.
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.
ou :
make —h
198
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande
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.
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.
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
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.
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 $&
!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)
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 :
202
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande
.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
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
• 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 :
205
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++
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.
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
• 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.
207
Utilitaires en ligne de commande RAD Studio 3.1 Référence C++
Voir aussi
Utilisation de MAKE.EXE ( see page 198)
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
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
.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
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.
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.
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
© $** 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é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)
• 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
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
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.
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;
[ 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)
Pour utiliser les fichiers en-tête précompilés, spécifiez les diverses options -H dans votre commande BCC32.
-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)
220
3.1 Référence C++ RAD Studio Utilitaires en ligne de commande
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.
• <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?.
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.
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.
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.
• /C (sensible à la casse)
• /P (taille de page)
• /0 (zéro ; purger les enregistrements de commentaire)
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.
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 :
• 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
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.
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
??- ~
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 :
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 :
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 :
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 :
• 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 :
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 :
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 :
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
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 :
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 :
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 :
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 :
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
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 :
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
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 :
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 :
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 :
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.
272
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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.
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
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.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.
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
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
};
276
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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)
278
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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 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
281
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
Par exemple :
template <class T> int main() // Ceci provoque une erreur
{}
Voir aussi
functiontemplates.xml ( see page 451)
282
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
283
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
284
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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
285
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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
287
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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
289
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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
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
Ce message d'erreur ne doit pas se produire car il a été remplacé par un autre message (E2475).
292
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
293
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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
}
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++
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.
• user
• lib
• exestr
• linker
3 Le type doit figurer ici mais la chaîne est facultative.
296
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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++
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.
298
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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'
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.
299
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
Solutions
Si le disque est protégé en écriture, placez les fichiers source sur un autre disque accessible en écriture et relancez la
compilation.
300
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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.
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.
Solutions
Vérifiez que le répertoire de sortie dans la boîte de dialogue Répertoires est un répertoire valide.
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++
• 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.
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.
302
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Les variables, les procédures, les fonctions et les libellés sont des symboles relogeables.
Modifiez l'ordre des paramètres ou le type d'un paramètre dans une déclaration.
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.
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;
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
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);
304
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Exemple :
struct__declspec(delphiclass) clxclass
{
__automated:
int__fastcall fooInt(int);// OK
clxclass() {}// Erreur
};
Exemple :
struct__declspec(delphiclass) clxclass
{
__automated:
int__fastcall fooInt(int);// OK
int__cdecl barInt(int);// Erreur
};
Exemple :
struct__declspec(delphiclass) clxclass
{
__automated:
int__fastcall fooInt(int);// OK
intmemInt;// Erreur
};
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++
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
};
Dans ces deux cas, il doit s'agir d'un élément auquel l'opérateur '->' peut s'appliquer.
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.
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
307
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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.
308
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Si vous utilisez la seconde méthode, elle sera utilisée de préférence à la première version.
Cet opérateur delete surchargé C++ a été déclaré d'une autre façon.
Si vous utilisez la seconde méthode, elle sera utilisée de préférence à la première version.
309
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
Si une macro était utilisée, le texte d'expansion n'est pas entouré par des guillemets.
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
Cause possible
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( /*...*/ );
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.
Exemple
int main (void)
{
int p;
*p = 10; /* ERREUR : indirection incorrecte */
return 0;
}
• expressions constantes ;
• adresse d'une variable extern globale ou statique, plus ou moins une constante.
Les membres statiques doivent être initialisés en dehors de la classe, par exemple :
• 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)();
}
313
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
Cette erreur peut également se produire si vous utilisez une option #pragma dans votre code avec une option non valide.
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
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.
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++
• 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;
}
316
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Il est probable que deux classes de stockage ont été spécifiées, alors qu'une seule ne peut l'être.
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
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++
• Type de retour
• Convention d'appel
• Spécification d'exception (liste throw)
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.
318
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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.
Cette erreur indique qu'un libellé CASE peut transférer le contrôle au-delà de cette variable locale.
L'expression dans cette instruction ne comportait pas de signe deux-points ou comportait un symbole de trop avant le signe.
319
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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.
Un seul modificateur de langage (par exemple, __cdecl, __pascal, ou __fastcall) peut être spécifié pour une fonction.
320
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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++
A ce jour, les tables virtuelles réparties dynamiquement ne gèrent pas l'utilisation des héritages multiples.
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.
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
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.
323
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
324
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Si un destructeur de classe est privé, la classe ne peut pas être détruite ni utilisée. Ceci est probablement une erreur.
Ceci garantit qu'aucune instance d'une classe de base n'est créée et que seules des classes en sont dérivées.
Cette fonction a été déclarée avec des modificateurs différents en deux endroits.
Ce spécificateur d'accès ne peut apparaître plusieurs fois pour une classe de base.
325
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
class A {
public:
A();
virtual myex();
};
A::A() {}
• char
• class
• int
• float
• double
• struct
• union
• enum
• typedef name
326
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Par exemple, vous ne pouvez pas fournir à __emit__ une variable locale comme paramètre.
ANSI C et C++ exigent qu'un élément soit déclaré dans l'unité de compilation.
Si vous avez besoin d'une constante de cette valeur, utilisez un entier const.
Cette erreur est généralement due à l'omission d'un symbole de fermeture de commentaire (*/).
327
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
Cause possible
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.
328
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Vérifiez que votre appel à la fonction a le même nombre de paramètres que son prototype.
Les noms de fichiers complets sous DOS ne doivent pas comporter plus de 79 caractères.
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.
Les fonctions sous forme de champs ne sont autorisées qu'en langage C++.
• 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.
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.
Solutions
Recherchez dans les déclarations les tableaux trop volumineux. Vous pouvez également supprimer des variables de DGROUP.
Voici comment :
3 Cette erreur indique une instruction goto qui peut transférer le contrôle au-delà de cette variable locale.
330
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Ceci peut également être causé par des paramètres superflus transmis à une macro de fonction.
Cause possible
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++
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
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
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.
Par exemple :
void func()
{
template <class T> myClass { // Erreur
T i;
};
}
333
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
Le compilateur a détecté autre chose qu'un caractère identificateur alors qu'un argument était attendu.
334
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
L'ensemble d'une structure ou d'une union peut être initialisé à l'aide d'initialisateurs placés entre accolades.
Seule une fonction membre ou un membre non statique peut avoir le même nom que sa classe.
Vous avez sans doute oublié de placer des crochets autour d'un opérande de registre d'index.
335
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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)();
}
• 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.
• 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.
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.
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++
(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).
Le caractère ":" a peut-être été oublié, ou des parenthèses sont mal imbriquées ou manquantes.
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.
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
Dans cette déclaration, un paramètre avec une valeur par défaut était suivi d'un paramètre sans valeur par défaut.
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.
3
3.1.2.354 E2272: Identificateur attendu
Un identificateur était attendu ici, mais aucun n'a été détecté.
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.
Chaque déclaration de modèle doit inclure des paramètres formels placés entre "< >", immédiatement après le mot clé template.
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
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++
Cela est autorisé en C++, mais il n'existe aucun moyen de faire référence au paramètre dans la fonction.
• 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.
342
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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.
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'.
Cette erreur peut se produire également si vous tentez de modifier les droits d'accès de 'class::constructor.'
Cette erreur est généralement causée par une faute de frappe dans une constante #define.
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++
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.
• 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
• 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.
Le constructeur, appelé constructeur de copie, n'accepte qu'un paramètre (une référence à sa classe).
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++
Vous pouvez alors définir un constructeur de référence ou laisser le compilateur en créer un.
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.
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.
Exemple :
struct __declspec(delphiclass) base {};
struct derived : virtual base {}; // Erreur
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
Causes possibles
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++
A la différences des fonctions non membre, elles ne peuvent être pas déclarées plusieurs fois, ni à un autre endroit.
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){}
};
Cependant, le type de la variable ou du paramètre ne correspond à aucune fonction surchargée ayant le nom spécifié.
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.
348
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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.
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.
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.
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++
Cette conversion n'est peut-être pas logique, aussi devez-vous vérifier que c'est bien ce que vous souhaitez.
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
• 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.
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
Dans ce cas, l'initialisateur n'était pas une lvalue ou son type ne correspondait pas à la référence initialisée.
Etant donné qu'il n'existe aucun endroit spécifique pour stocker ce temporaire, l'initialisation est illégale.
• [BX]
• [BP]
• [SI]
• [DI]
• [BX+SI]
• [BX+DI]
• [BP+SI]
• [BP+DI]
Les autres combinaisons de registres d'index ne sont pas autorisées.
352
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
i++,10d
x = y, 10m
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.
Cet objet disparaîtra lorsque la fonction renverra son résultat, ce qui rendra la référence illégale.
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++
Les constructeurs, les destructeurs et les autres opérateurs ne peuvent être statiques.
Cette erreur peut également être causée par les actions suivantes :
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
Vous devez pouvoir utiliser un transtypage explicite pour satisfaire à cette obligation.
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.)
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.
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.
Ceci inclut notamment les expressions constantes entières et les adresses d'objets ou de fonctions comportant des membres ou
des liens externes.
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 >.
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.
357
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
de base 'classe'.
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.
Ceci est probablement le fait d'un nom de structure mal orthographié ou d'une déclaration manquante.
Causes possibles
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.
359
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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.
Par exemple :
class myclass
{
public:
virtual int a; //erreur
};
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.
361
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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.
362
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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 */
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++
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.
Vous ne pouvez pas marquer comme delphireturn des classes définies par l'utilisateur.
• __export
• __import
• declspec(naked)
• declspec(package)
• __fastcall
364
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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
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++
366
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Lorsque cela n'est pas possible à cause des règles du langage, le compilateur affiche l'un de ces messages d'erreur.
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.
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++
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.
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.
368
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Exemple :
struct__declspec(delphiclass) clxclass
{
__automated:
int __fastcall foo1(void) __dispid(42);// OK
int __fastcall foo2(void) __dispid(42);// Erreur
};
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++
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
};
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.
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
Le compilateur définira un constructeur par défaut pour une classe si vous n'en définissez aucun.
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.
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
};
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.
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 }
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 };
};
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.
373
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
ou
vous avez tenté de supprimer un pointeur sur un objet d'une classe possédant un destructeur virtuel.
Exemple :
int i = 1234i15; // Erreur : suffixe "i15" erroné
int j = 1234i16; // OK
374
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Cette variable ne se voit jamais affecter de valeur et n'a aucun emplacement de pile.
Exemple :
int GlobalGetter(void)
{
return 0;
}
struct pbase
{
intMemberGetter(void) {return 1;}
int __property ip1 = { read = GlobalGetter }; // Erreur
int __property ip2 = { read = MemberGetter }; // OK
};
Exemple :
structpbase
{
voidSetter1(void){}
voidSetter2(int){}
int __property ip1 = { write = Setter1 }; // Erreur
int __property ip2 = { write = Setter2 }; // OK 3
};
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
};
Exemple :
struct__declspec(delphiclass) clxclass
{
__published:
static intstaticDataMember;// Erreur
};
376
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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
};
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.
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
{
}
}
Exemple :
struct base// la base n'est pas une classe de style Delphi
{
intbasemem;
};
struct __declspec(delphiclass) derived : base // ou
{
intderivedmem;
};
378
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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.
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.
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.
Pour Windows, assurez-vous que la boucle des messages du programme s'est correctement terminée.
PostQuitMessage(0);
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);
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.
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').
Pour supprimer cet avertissement, placez l'affectation entre parenthèses et comparez l'ensemble à zéro de façon explicite.
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++
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.
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.
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
3.1.2.579 W8009: La constante est longue
(Option de ligne de commande affichant cet avertissement : -wcln)
382
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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' */
{
...
}
}
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;
}
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.
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;
}
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.
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 :
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.
384
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
Ceci est une erreur dans C++, mais elle est réduite à un avertissement pour permettre aux programmes existants de s'exécuter.
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.
L'opérateur adresse de (&) n'est pas nécessaire avec un nom de fonction ; ces opérateurs ne sont pas pris en compte.
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.
385
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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).
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é.
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.
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
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.
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.
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.
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.
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.
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++
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.
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.
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.
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.
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
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.
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.)
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.
Cet avertissement s'affiche lorsque le compilateur rencontre une instruction comportant des opérateurs sans effet.
389
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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.
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.
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.
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 }
390
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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.
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.
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.
391
Liste de tous les avertissements et erreurs RAD Studio 3.1 Référence C++
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.
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 &);
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);
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.
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 &);
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);
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);
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.
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.
Le compilateur a détecté une conversion de pointeur à cause de laquelle le pointeur pointe sur un type différent.
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;
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.
394
3.1 Référence C++ RAD Studio Liste de tous les avertissements et erreurs
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.
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.
La variable apparaît dans une affectation mais n'est pas utilisée dans la fonction qui vient de se terminer.
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.
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++
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.
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é.
Par exemple :
int X = 0xFFFF * 0xFFFF;
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
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.
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).
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++
où :
• 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.
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
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".
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
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.
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.
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.
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 :
400
3.1 Référence C++ RAD Studio Guide du langage C++
}
__finally
{
delete pList;
}
}
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.
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:
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
Dans C++, les structures et les unions sont considérées comme des classes avec certaines valeurs d'accès par défaut.
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)
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)
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)
405
Guide du langage C++ RAD Studio 3.1 Référence C++
Amies de classes
• 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)
406
3.1 Référence C++ RAD Studio Guide du langage C++
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)
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.
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).
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++
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)
Fonctions inline
408
3.1 Référence C++ RAD Studio Guide du langage C++
Voir aussi
Classes C++ ( see page 403)
409
Guide du langage C++ RAD Studio 3.1 Référence C++
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)
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++
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 à :
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)
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 :
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)
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++
• à 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)
414
3.1 Référence C++ RAD Studio Guide du langage C++
415
Guide du langage C++ RAD Studio 3.1 Référence C++
Voir aussi
Classes C++ ( see page 403)
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)
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++
Types imbriqués
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)
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 :
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++
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)
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)
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)
421
Guide du langage C++ RAD Studio 3.1 Référence C++
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
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.
En voici un exemple :
TTest = class;
TTest = class
public
// Méthodes de classe
class function add(I, J: Integer): Integer;
class function GetClsName: string;
// 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;
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;
423
Guide du langage C++ RAD Studio 3.1 Référence C++
// 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);
// 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);
• 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.
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++
// 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é.
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();
};
TBase& br = TDerived();
425
Guide du langage C++ RAD Studio 3.1 Référence C++
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
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)
426
3.1 Référence C++ RAD Studio Guide du langage C++
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)
427
Guide du langage C++ RAD Studio 3.1 Référence C++
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),
428
3.1 Référence C++ RAD Studio Guide du langage C++
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)
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.
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 :
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.
431
Guide du langage C++ RAD Studio 3.1 Référence C++
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 :
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 :
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
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)
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++
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++
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)
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)
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 :
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)
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)
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)
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)
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)
• 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)
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 ::.
Voir aussi
Alias d'un espace de nommage ( see page 446)
444
3.1 Référence C++ RAD Studio Guide du langage C++
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.
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)
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.
Directive-using :
446
3.1 Référence C++ RAD Studio Guide du langage C++
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.
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)
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 :
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 :
Voir aussi
Portée de classe ( see page 449)
• 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)
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)
449
Guide du langage C++ RAD Studio 3.1 Référence C++
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)
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).
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 :
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)
451
Guide du langage C++ RAD Studio 3.1 Référence C++
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.
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.
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.
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)
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)
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.
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 :
454
3.1 Référence C++ RAD Studio Guide du langage C++
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)
Voir aussi
Le mot clé new ( see page 561)
455
Guide du langage C++ RAD Studio 3.1 Référence C++
Voir aussi
Const_cast (opérateur de transtypage) ( see page 545)
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 :
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.
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++
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)
Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)
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é.
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)
Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)
Voir aussi
Exemple de surcharge des opérateurs ( see page 456)
3 Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)
460
3.1 Référence C++ RAD Studio Guide du langage C++
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)
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)
Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)
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)
Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)
Voir aussi
Exemple de surcharge des opérateurs ( see page 456)
Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)
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)
462
3.1 Référence C++ RAD Studio Guide du langage C++
Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)
• 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)
Surcharge de l'opérateur d'accès aux membres de classe -> ( see page 460)
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++
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,
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.
464
3.1 Référence C++ RAD Studio Guide du langage C++
Voir aussi
Classes polymorphes ( see page 465)
Voir aussi
Fonctions virtuelles ( see page 467)
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.
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 dynamiques
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 :
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)
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 :
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++
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)
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)
Voir aussi
Référencement ( see page 470)
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.
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)
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
Exemple
class Alpha {
public:
virtual ~Alpha( ) { }
};
void func( Alpha *Aptr ) {
delete Aptr; // Erreur. Alpha n'est pas un type de classe polymorphe
}
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.
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.
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) :
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 :
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);
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 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.
Les littéraux chaîne sont maintenant des constantes ( see page 475)
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)
Les littéraux chaîne sont maintenant des constantes ( see page 475)
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)
Les littéraux chaîne sont maintenant des constantes ( see page 475)
• 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 &)'
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)
Les littéraux chaîne sont maintenant des constantes ( see page 475)
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)
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++
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)
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 :
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
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++
483
Guide du langage C++ RAD Studio 3.1 Référence C++
• 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++
• 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++
• 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++
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.
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
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)
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)
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)
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).
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
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.
489
Guide du langage C++ RAD Studio 3.1 Référence C++
True si __has_trivial_copy_constructor(T).
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
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.
True si __has_trivial_default_constructor(T).
False (mais bien formé) si un type de classe n'a pas de constructeur par défaut.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
3.1.4.1.19.2.8 __has_trivial_assign
Usage : bool __has_trivial_assign (typename T )
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 :
490
3.1 Référence C++ RAD Studio Guide du langage C++
3.1.4.1.19.2.9 __has_trivial_copy_constructor
Usage : bool __has_trivial_copy_constructor ( typename T )
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 :
3.1.4.1.19.2.10 __has_trivial_default_constructor
Usage : bool __has_trivial_default_constructor (typename T )
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 :
3.1.4.1.19.2.11 __has_trivial_destructor
Usage : bool __has_trivial_destructor (typename T )
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 :
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)
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.
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)
3.1.4.1.19.2.13 __is_abstract
Décrit l'utilisation de la fonction trait de type C++0x __is_abstract.
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)
Working Draft
3.1.4.1.19.2.14 __is_arithmetic 3
Usage : bool __is_arithmetic ( typename T )
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
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 )
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)
3.1.4.1.19.2.16 __is_base_of
Usage : bool __is_base_of (typename Base, typename Derived (Typename T)
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)
3.1.4.1.19.2.17 __is_class
Usage : bool __is_class(typename T)
Renvoie true pour les classes déclarées avec la clé-classe "class" ou "struct".
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)
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)
3.1.4.1.19.2.19 __is_compound
Usage : bool __is_compound( typename T )
• 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)
3.1.4.1.19.2.20 __is_const
Usage : bool __is_const(typename T)
Pour les pointeurs, se réfère au type pointeur lui-même, et PAS le type pointé-vers.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
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++
3.1.4.1.19.2.22 __is_empty
Usage : bool __is_empty( typename T )
La définition de __is_empty est donnée dans le tableau de la section 20.4.4.3 du "Working Draft".
Working Draft
3.1.4.1.19.2.23 __is_enum
Usage : bool _is_enum ( typename T )
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)
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)
Working Draft
3.1.4.1.19.2.25 __is_function
Usage : bool __is_function( typename T )
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)
3.1.4.1.19.2.26 __is_fundamental
Usage : bool __is_fundamental( typename T )
Les types fondamentaux sont définis dans la section 3.9.1 du "Working Draft".
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)
Working Draft
3.1.4.1.19.2.27 __is_integral
Usage : bool __is_integral(typename T)
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)
Working Draft
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.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
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.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
3.1.4.1.19.2.30 __is_member_function_pointer
Usage : bool __is_member_function_pointer( typename T )
Voir aussi
3.1.4.1.19.2.31 __is_member_object_pointer
Usage : bool __is_member_object_pointer( typename T )
498
3.1 Référence C++ RAD Studio Guide du langage C++
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
3.1.4.1.19.2.32 __is_member_pointer
Usage : bool __is_member_pointer( typename T )
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
3.1.4.1.19.2.33 __is_object
Usage : bool __is_object( typename T)
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
Working Draft
3.1.4.1.19.2.34 __is_pod
Usage : bool __is_pod( typename T )
Les types POD sont définis dans la section 3.9 p10 du "Working Draft".
Voir aussi
3
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
Working Draft
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 )
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
3.1.4.1.19.2.36 __is_polymorphic
Usage : bool __is_polymorphic( typename T )
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)
Working Draft
3.1.4.1.19.2.37 __is_reference
Usage : bool __is_reference( typename T )
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
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.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
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 )
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)
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)
3.1.4.1.19.2.41 __is_scalar
Usage : bool __is_scalar( typename T )
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)
Working Draft
3.1.4.1.19.2.42 __is_signed
Usage : _bool __is_signed( typename T )
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)
3.1.4.1.19.2.43 __is_standard_layout
Usage : bool __is_standard_layout(typename T)
Les classes d'implémentation standard sont définies dans la section 9, p 6 du "Working Draft".
• 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)
Working Draft
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.
Les types triviaux sont définis dans la section 3.9 p10 du "Working Draft".
502
3.1 Référence C++ RAD Studio Guide du langage C++
• 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)
Working Draft
3.1.4.1.19.2.45 __is_union
Usage : bool __is_union( typename T )
Remarque : les unions sont des types classe déclarés dans l'union clé-classe.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
3.1.4.1.19.2.46 __is_unsigned
Usage : bool __is_unsigned
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)
3.1.4.1.19.2.48 __is_volatile
Usage : bool __is_volatile( typename T )
Pour les pointeurs, se réfère au type pointeur lui-même, et PAS le type pointé-vers.
Voir aussi
Fonctionnalités C++0x (C++Builder 2009) ( see page 480)
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)
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:
};
void m() {
X x;
3
// avec transtypage :
T tc = (T)x;// ok
// sans transtypage :
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)
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.
• 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
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 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
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);
• 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.
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.
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;
};
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)
Specifiers)
510
3.1 Référence C++ RAD Studio Guide du langage C++
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 :
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)
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&
Working Draft - Standard for Programming Language C++ (Sec. 7.1.6.2 - Simple Type Specifiers)
• 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
Character Literals)
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
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.
Voir aussi
floatingfunctions.xml ( see page 514)
514
3.1 Référence C++ RAD Studio Guide du langage C++
515
Guide du langage C++ RAD Studio 3.1 Référence C++
516
3.1 Référence C++ RAD Studio Guide du langage C++
517
Guide du langage C++ RAD Studio 3.1 Référence C++
518
3.1 Référence C++ RAD Studio Guide du langage C++
Voir aussi
tcharmapping.xml ( see page 513)
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++
521
Guide du langage C++ RAD Studio 3.1 Référence C++
522
3.1 Référence C++ RAD Studio Guide du langage C++
523
Guide du langage C++ RAD Studio 3.1 Référence C++
524
3.1 Référence C++ RAD Studio Guide du langage C++
525
Guide du langage C++ RAD Studio 3.1 Référence C++
526
3.1 Référence C++ RAD Studio Guide du langage C++
527
Guide du langage C++ RAD Studio 3.1 Référence C++
3.1.4.2.1 __automated
Catégorie
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)
3.1.4.2.2 __classid
Catégorie
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)
3.1.4.2.3 __closure
Catégorie
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.
Voir aussi
_export ( see page 536)
530
3.1 Référence C++ RAD Studio Guide du langage C++
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)
3.1.4.2.6 __except
Catégorie
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)
3.1.4.2.7 __inline 3
Catégorie
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
Description
Vous pouvez spécifier la taille des types entiers. Vous devez utiliser le suffixe approprié avec les entiers étendus.
Voir aussi
Constantes ( see page 673)
3.1.4.2.9 __msfastcall
Catégorie
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
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
Syntaxe
<déclaration de propriété> ::=
__property <type> <id> [ <liste dim prop> ] = "{" <liste attrib prop> "}"
3.1.4.2.12 __published
Catégorie
533
Guide du langage C++ RAD Studio 3.1 Référence C++
Syntaxe
__published: <déclarations>
Description
Voir aussi
__closure ( see page 529)
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)
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.
3.1.4.2.15 __try
Catégorie
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 :
535
Guide du langage C++ RAD Studio 3.1 Référence C++
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.
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
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.
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.
Remarque: Remarque : Le modificateur __stdcall est soumis au substanstypage. Voir la description de l'option -VC.
3.1.4.2.19 alignof
Catégorie
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
537
Guide du langage C++ RAD Studio 3.1 Référence C++
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.
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
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++
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
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é.
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
Syntaxe
3
Description
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).
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>
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)
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.
Cet exemple illustre l'utilisation des mots clés break, case, default et switch.
#include <iostream>
541
Guide du langage C++ RAD Studio 3.1 Référence C++
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)
3.1.4.2.28 catch
Catégorie
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.
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
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)
543
Guide du langage C++ RAD Studio 3.1 Référence C++
3.1.4.2.32 compl, ~
Catégorie
Syntaxe
Description
compl inverse true en false, et false en true. Le tilde (~) est placé devant l'integer utilisé pour le complément.
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.
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;
// Un pointeur constant
char *const str1 = "Bonjour tout le monde";
544
3.1 Référence C++ RAD Studio Guide du langage 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)
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)
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
3.1.4.2.36 __declspec(dllexport)
Catégorie
Syntaxe
Remarque: dllexport
546
3.1 Référence C++ RAD Studio Guide du langage C++
3.1.4.2.37 __declspec(dllimport)
Catégorie
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
3.1.4.2.38 __declspec(naked)
Catégorie
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
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
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.
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
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
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
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++
//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
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
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 :
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
• 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>
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)
551
Guide du langage C++ RAD Studio 3.1 Référence C++
3.1.4.2.47 delete
Catégorie
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
<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.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++
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)
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)
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
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++
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
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.
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
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
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.
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.
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
<instruction> est exécuté de façon répétitive JUSQU'A CE QUE la valeur de <condition> soit false.
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>.
Opérateurs
Syntaxe
if ( <condition1> ) <instruction1>
if ( <condition1> ) <instruction1>;
else <instruction2>;
if ( <condition1> ) <instruction1>;
else if ( <condition2> ) <instruction2>;
else <instruction3>;
Description
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.
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
Forme 1
559
Guide du langage C++ RAD Studio 3.1 Référence C++
Ce mot clé peut être utilisé comme classe, fonction ou modificateur de données.
3.1.4.2.63 inline
Catégorie
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
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
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.
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
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
Syntaxe
561
Guide du langage C++ RAD Studio 3.1 Référence C++
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)
3.1.4.2.69 noreturn
Catégorie
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
Syntaxe
Description
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
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
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.
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
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
Syntaxe
Description
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
3 Syntaxe
Description
L'opérateur or_eq est une représentation alternative de l'opérateur != (OR inclusif 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).
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
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 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)
3.1.4.2.78 protected
Catégorie
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)
3.1.4.2.79 public
Catégorie
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)
3.1.4.2.80 register
Catégorie
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.
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 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)
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)
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)
3.1.4.2.85 sizeof
Catégorie
Opérateurs
3 Description
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.
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
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
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.
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 :
570
3.1 Référence C++ RAD Studio Guide du langage C++
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
<nom de type struct> Balise facultative qui fait référence au type structure.
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).
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)
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.
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>
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)
572
3.1 Référence C++ RAD Studio Guide du langage C++
3.1.4.2.91 template
Catégorie
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
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
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
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 :
3.1.4.2.95 typedef
Catégorie
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
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
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.
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
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é.
)
bc++bcc32 -A test.cpp
Il en résulte :
Erreur E2089 47071.cpp 7: L'identificateur 'AInt' ne peut pas avoir un qualificateur type
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)
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)
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
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.
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++
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
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
Syntaxe
3
Description
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
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)
3.1.4.2.108 alignas
Catégorie
Syntaxe
alignas
Description
mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.
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
Syntaxe
axiom
Description
mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.
3.1.4.2.111 concept
Catégorie
Syntaxe
concept
Description
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
Syntaxe
concept_map
Description
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++
Syntaxe
constexpr
Description
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
Syntaxe
late_check
Description
mais le traite comme un mot clé quand l'indicateur -Ax du compilateur est défini.
3.1.4.2.115 requires
Catégorie
Syntaxe
requires
Description
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
582
3.1 Référence C++ RAD Studio Guide du langage C++
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
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.
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).
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++.
583
Guide du langage C++ RAD Studio 3.1 Référence C++
Voici les liens aux rubriques des mots clés de représentation alternative :
3.1.4.3.2 Attributs
Cette section contient les rubriques des mots clés des attributs C++.
Voir aussi
Noreturn et final (C++0x)
584
3.1 Référence C++ RAD Studio Guide du langage C++
__int8 __int16 __int32 __int64 Unsigned_int64 (types integer étendus) ( see page 532)
585
Guide du langage C++ RAD Studio 3.1 Référence C++
char16_t
char32_t
586
3.1 Référence C++ RAD Studio Guide du langage C++
3.1.4.3.5 Modificateurs
Cette section contient les rubriques relatives aux mots clés des modificateurs C++.
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++
3 3.1.4.3.9 Instructions
Cette section contient les rubriques relatives aux mots clés des instructions C++.
588
3.1 Référence C++ RAD Studio Guide du langage C++
589
Guide du langage C++ RAD Studio 3.1 Référence C++
char16_t
char32_t
decltype
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++
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
591
Guide du langage C++ RAD Studio 3.1 Référence C++
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"
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.
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++
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.
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
&& 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).
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 à
Dans l'expression
E1 <opérateur> E2
les opérandes doivent être conformes à l'une des conditions suivantes :
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.
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 :
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.
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.
• * (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 à :
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)
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.
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 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.
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)
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 à :
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)
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)
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)
603
Guide du langage C++ RAD Studio 3.1 Référence C++
Voir aussi
Déclarations ( see page 597)
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)
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 :
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
• 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++
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:
609
Guide du langage C++ RAD Studio 3.1 Référence C++
Voir aussi
Syntaxe de déclaration
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.
610
3.1 Référence C++ RAD Studio Guide du langage C++
spécificateur-classe: spécificateur-base:
en-tête-classe: liste-bases:
liste-membres: spécificateur-base:
nom-qualifié ; protected
liste-déclarateurs-membre: public
déclarateur-membre nom-fonction-conversion:
déclarateur-membre: nom-type-conversion:
spécificateur-pur: : liste-initialisateurs-membre
=0
initialisateur-membre, liste-initialisateurs-membre + - * / % ^
[ ] .*
Voir aussi
3
Syntaxe de déclaration
611
Guide du langage C++ RAD Studio 3.1 Référence C++
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++ :
Utilisez les opérateurs sizeof pour trouver la taille en octets de tout type prédéfini ou défini par l'utilisateur.
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
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++
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.
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.
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
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
615
Guide du langage C++ RAD Studio 3.1 Référence C++
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 :
Le nombre des valeurs d'initialisation dans la liste ne doit pas dépasser le nombre des objets à initialiser.
Toutes les expressions doivent être constantes si elles apparaissent dans un de ces emplacements (non requis pour C++) :
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
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 :
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)
618
3.1 Référence C++ RAD Studio Guide du langage 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é.
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
619
Guide du langage C++ RAD Studio 3.1 Référence C++
BCC32.
Voir aussi
Syntaxe de déclaration ( see page 604)
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
Rubriques
Cdecl ( see page 542)
Rubriques
__thread ( see page 535)
620
3.1 Référence C++ RAD Studio Guide du langage 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
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.
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
621
Guide du langage C++ RAD Studio 3.1 Référence C++
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.
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.
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++
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
= *= /= %= += -=
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
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++.
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.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 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
630
3.1 Référence C++ RAD Studio Guide du langage C++
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)
632
3.1 Référence C++ RAD Studio Guide du langage C++
• 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.
Pour toutes les plates-formes, argc et argv sont également disponibles via les variables globales _argc et _argv.
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)
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)
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)
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++
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
635
Guide du langage C++ RAD Studio 3.1 Référence C++
Voir aussi
La fonction main() ( see page 632)
636
3.1 Référence C++ RAD Studio Guide du langage 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.
Voir aussi
A propos de la fonction main ( see page 632)
<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.
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.
• 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.
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.
639
Guide du langage C++ RAD Studio 3.1 Référence C++
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.
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 :
Préprocesseur
641
Guide du langage C++ RAD Studio 3.1 Référence C++
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
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 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).
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++.
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.
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.
Voir aussi
Pointeurs d'objets ( see page 647)
646
3.1 Référence C++ RAD Studio Guide du langage C++
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.
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.
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.
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.
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
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.
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.
Parenthèses (())
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:
expression-primaire:
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.
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)
652
3.1 Référence C++ RAD Studio Guide du langage C++
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.
• 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.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.
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. */
Les membres d'unions et de structures sans sélecteur sont ignorés durant l'initialisation.
Un membre de structure peut avoir n'importe quel type, à deux exceptions près :
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.
656
3.1 Référence C++ RAD Studio Guide du langage C++
• . (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 */
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é
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++
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.
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++
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.
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 :
660
3.1 Référence C++ RAD Studio Guide du langage C++
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.
661
Guide du langage C++ RAD Studio 3.1 Référence C++
• ! Négation logique
• * Indirection
• ++ Incrémentation
• ~ Complément binaire
• -- Décrémentation
• - Moins unaire
• + Plus unaire
• (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.
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
Les opérateurs & et * peuvent être combinés pour référencer ou déréférencer des pointeurs transmis à des fonctions.
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 un pointeur d'objet, le résultat est une lvalue désignant cet objet.
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 :
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=μ
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.
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.
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.
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;
}
• 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.
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.
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)
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.
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.
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.
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 :
Pour de plus amples informations sur les constantes caractère, voir les rubriques suivantes.
#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++
Voir aussi
Constantes ( see page 673)
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.
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.
Voir aussi
Constantes ( see page 673)
671
Guide du langage C++ RAD Studio 3.1 Référence C++
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)
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)
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
673
Guide du langage C++ RAD Studio 3.1 Référence C++
674
3.1 Référence C++ RAD Studio Guide du langage C++
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
Voir aussi
Constantes ( see page 673) 3
Constantes entières ( see page 681)
675
Guide du langage C++ RAD Studio 3.1 Référence C++
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 :
• Affectation
• Virgule
• Décrémentation
• Appel de fonction
• Incrément
Voir aussi
Constantes ( see page 673)
676
3.1 Référence C++ RAD Studio Guide du langage C++
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)
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.
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)
• 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.
Voir aussi
Constantes ( see page 673)
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)
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)
680
3.1 Référence C++ RAD Studio Guide du langage C++
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.
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 :
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)
681
Guide du langage C++ RAD Studio 3.1 Référence C++
Rubriques
Nom Description
Représentation interne des types numériques ( see page 682) Entiers 32 bits
Types virgule flottante, toujours
Voir aussi
Constantes ( see page 673)
682
3.1 Référence C++ RAD Studio Guide du langage C++
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 :
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)
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.
• 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)
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.
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.
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.
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)
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++
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.
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
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
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.
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++
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.
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)
• 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.
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)
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.
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
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++
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)
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.
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).
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
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.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)
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)
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++
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 :
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
698
3.1 Référence C++ RAD Studio Guide du langage C++
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.
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 :
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.
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)
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++
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 curious_george
703
Guide du langage C++ RAD Studio 3.1 Référence C++
Ce pragma imprime l'alignement sur les octets, ainsi que la taille enum en cours.
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 #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++
Description
Erreur E2471 nomfichier : pragma checkoption a échoué : les options ne sont pas celles attendues
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.
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
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.
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.
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 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.
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.
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.
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.
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.
707
Guide du langage C++ RAD Studio 3.1 Référence C++
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)
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 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.
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.
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.
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.
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.
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.
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.
La directive #pragma pack accepte également un argument identificateur qui doit être utilisé en combinaison avec push ou pop.
711
Guide du langage C++ RAD Studio 3.1 Référence C++
Conditions d'erreur
Conditions d'avertissement
#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)
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).
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;
713
Guide du langage C++ RAD Studio 3.1 Référence C++
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.
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.
• 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
714
3.1 Référence C++ RAD Studio Guide du langage C++
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)
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
716
3.1 Référence C++ RAD Studio C Runtime Library Reference
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).
La directive nulle consiste en une ligne contenant le caractère #. Cette ligne est toujours ignorée.
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
719
C Runtime Library Reference RAD Studio 3.1 Référence C++
720
3.1 Référence C++ RAD Studio C Runtime Library Reference
721
C Runtime Library Reference RAD Studio 3.1 Référence C++
3.1.5.1.1 _heapchk
Header File
malloc.h
Category
Memory Routines
Syntax
int _heapchk(void);
Description
_heapchk walks through the heap and examines each block, checking its pointers, size, and other critical attributes.
Return Value
Portability
722
3.1 Référence C++ RAD Studio C Runtime Library Reference
3.1.5.1.2 _heapmin
Header File
malloc.h
Category
Memory Routines
Prototype
int _heapmin(void);
Description
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
Portability
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
723
C Runtime Library Reference RAD Studio 3.1 Référence C++
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
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
_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
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
3.1.5.1.5 _rtl_heapwalk
Header File
malloc.h
Category
3 Memory Routines
Prototype
int _rtl_heapwalk(_HEAPINFO *hi);
Description
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.
Return Value
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
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.
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
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
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
3.1.5.1.8 heapcheck
Header File
alloc.h
Category
Memory Routines
Prototype
int heapcheck(void);
Description
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
3.1.5.1.9 heapcheckfree
Header File
alloc.h
Category
Memory Routines
Prototype
int heapcheckfree(unsigned int fillvalue);
Description
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:
3
Portability
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
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
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++
3.1.5.1.11 heapfillfree
Header File
alloc.h
Category
Memory Routines
Prototype
int heapfillfree(unsigned int fillvalue);
Description
Return Value
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
3.1.5.1.12 heapwalk
Header File
alloc.h
Category
Memory Routines
Prototype
int heapwalk(struct heapinfo *hi);
Description
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
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
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
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 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
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
stackavail returns the number of bytes available on the stack. This is the amount of dynamic memory that alloca can access.
Return Value
Example
#include <malloc.h>
#include <stdio.h>
int main(void)
{
char *buf;
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.h
Description
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
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
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
739
C Runtime Library Reference RAD Studio 3.1 Référence C++
740
3.1 Référence C++ RAD Studio C Runtime Library Reference
741
C Runtime Library Reference RAD Studio 3.1 Référence C++
742
3.1 Référence C++ RAD Studio C Runtime Library Reference
743
C Runtime Library Reference RAD Studio 3.1 Référence C++
744
3.1 Référence C++ RAD Studio C Runtime Library Reference
745
C Runtime Library Reference RAD Studio 3.1 Référence C++
3.1.5.3.1 _setcursortype
Header File
conio.h
Category
3
Console I/O Routines
Prototype
void _setcursortype(int cur_t);
Description
746
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
3.1.5.3.2 cgets
Header File 3
conio.h
Category
Prototype
char *cgets(char *str);
747
C Runtime Library Reference RAD Studio 3.1 Référence C++
Description
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.
Return Value
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
3.1.5.3.3 clreol
Header File
3 conio.h
Category
Prototype
void clreol(void);
Description
748
3.1 Référence C++ RAD Studio C Runtime Library Reference
clreol clears all characters from the cursor position to the end of the line within the current text window, without moving the cursor.
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
3.1.5.3.4 clrscr
Header File
conio.h
Category
Prototype
void clrscr(void);
Description
clrscr clears the current text window and places the cursor in the upper left corner (at position 1,1).
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++
3.1.5.3.5 cprintf
Header File
conio.h
Category
Prototype
int cprintf(const char *format[, argument, ...]);
Description
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.
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.
Return Value
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
3.1.5.3.6 cputs
Header File
conio.h
Category
Prototype
int cputs(const char *str);
Description
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).
Return Value
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
751
C Runtime Library Reference RAD Studio 3.1 Référence C++
3.1.5.3.7 cscanf
Header File
conio.h
Category
Prototype
int cscanf(char *format[, address, ...]);
Description
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.
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.
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.
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
752
3.1 Référence C++ RAD Studio C Runtime Library Reference
3.1.5.3.8 delline
Header File
conio.h
Category
Prototype
void delline(void);
Description
delline deletes the line containing the cursor and moves all lines below it one line up. delline operates within the currently active
text window.
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
3.1.5.3.9 getch
Header File 3
conio.h
Category
Prototype
int getch(void);
753
C Runtime Library Reference RAD Studio 3.1 Référence C++
Description
getch reads a single character directly from the keyboard, without echoing to the screen.
Return Value
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
3.1.5.3.10 getche
Header File
conio.h
Category
Prototype
int getche(void);
Description
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
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
3.1.5.3.11 getpass
Header File
conio.h
Category
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).
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;
755
C Runtime Library Reference RAD Studio 3.1 Référence C++
3.1.5.3.12 gettext
Header File
conio.h
Category
Prototype
int gettext(int left, int top, int right, int bottom, void *destin);
Description
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
Return Value
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
3.1.5.3.13 gettextinfo
Header File
conio.h
Category
Prototype
void gettextinfo(struct text_info *r);
Description
gettextinfo fills in the text_info structure pointed to by r with the current text video information.
Return Value
757
C Runtime Library Reference RAD Studio 3.1 Référence C++
3.1.5.3.14 gotoxy
Header File
conio.h
Category
Prototype
void gotoxy(int x, int y);
Description
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.
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
Prototype
void highvideo(void);
Description
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.
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
3.1.5.3.16 insline
Header File
conio.h
Category
Prototype
void insline(void); 3
Description
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.
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
3.1.5.3.17 kbhit
Header File
conio.h
Category
Prototype
int kbhit(void);
Description
kbhit checks to see if a keystroke is currently available. Any available keystrokes can be retrieved with getch or getche.
Return Value
760
3.1 Référence C++ RAD Studio C Runtime Library Reference
Portability
3.1.5.3.18 lowvideo
Header File
conio.h
Category
Prototype
void lowvideo(void);
Description
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.
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
3.1.5.3.19 movetext
Header File
conio.h
Category
761
C Runtime Library Reference RAD Studio 3.1 Référence C++
Prototype
int movetext(int left, int top, int right, int bottom, int destleft, int desttop);
Description
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.
Return Value
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
3.1.5.3.20 normvideo
Header File
conio.h
Category
3
Console I/O Routines
Prototype
void normvideo(void);
Description
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.
Return Value
None.
Example
#include <conio.h>
int main(void)
{
normvideo();
cprintf("NORMAL Intensity Text\r\n");
return 0;
}
Portability
3.1.5.3.21 putch
Header File
conio.h
Category
Prototype
int putch(int c);
Description
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.
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
3.1.5.3.22 puttext
Header File
conio.h
Category
Prototype
int puttext(int left, int top, int right, int bottom, void *source);
Description
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
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
3.1.5.3.23 textattr
Header File
conio.h
Category
Prototype
void textattr(int newattr);
Description
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.
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
3.1.5.3.24 textbackground
Header File
conio.h
Category
Prototype
void textbackground(int newcolor);
Description
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
3.1.5.3.25 textcolor
Header File
conio.h
Category
Prototype
void textcolor(int newcolor);
Description
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
3.1.5.3.26 textmode
Header File
conio.h
Category
Prototype
void textmode(int newmode);
Description
768
3.1 Référence C++ RAD Studio C Runtime Library Reference
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.
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
769
C Runtime Library Reference RAD Studio 3.1 Référence C++
3.1.5.3.27 ungetch
Header File
conio.h
Category
Prototype
int ungetch(int ch);
Description
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
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
conio.h
Category
770
3.1 Référence C++ RAD Studio C Runtime Library Reference
Prototype
int wherex(void);
Description
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
3.1.5.3.29 wherey
Header File
conio.h
Category
Prototype
int wherey(void);
Description
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++
3.1.5.3.30 window
Header File
conio.h
Category
Prototype
void window(int left, int top, int right, int bottom);
Description
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++
774
3.1 Référence C++ RAD Studio C Runtime Library Reference
775
C Runtime Library Reference RAD Studio 3.1 Référence C++
776
3.1 Référence C++ RAD Studio C Runtime Library Reference
777
C Runtime Library Reference RAD Studio 3.1 Référence C++
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.
ctype.h
Description
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).
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
3.1.5.4.4 _toupper
Header File
ctype.h
Category
Conversion Routines 3
Prototype
int _toupper(int ch);
Description
_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).
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
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
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
780
3.1 Référence C++ RAD Studio C Runtime Library Reference
_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
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
781
C Runtime Library Reference RAD Studio 3.1 Référence C++
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
ctype.h, wctype.h
Category
Classification Routines
Prototype
int isascii(int c);
int iswascii(wint_t c);
Description
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.
Return Value
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
ctype.h
Category
Classification Routines
Prototype
int iscntrl(int c);
int iswcntrl(wint_t c);
Description
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
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
ctype.h, mbstring.h
Category
Classification Routines
Prototype
int isdigit(int c);
int iswdigit(wint_t c);
int _ismbcdigit(unsigned int c);
Description
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
_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
784
3.1 Référence C++ RAD Studio C Runtime Library Reference
ctype.h, mbstring.h
Category
Classification Routines
Prototype
int isgraph(int c);
int iswgraph(wint_t c);
int _ismbcgraph( unsigned int c);
Description
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
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
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
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
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
Category
Classification Routines
3 Prototype
int isprint(int c);
int iswprint(wint_t c);
int _ismbcprint(unsigned int c);
Description
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
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
Category
Classification Routines
Prototype
int ispunct(int c);
int iswpunct(wint_t c);
int _ismbcpunct(unsigned int c);
Description
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
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
Category
Classification Routines
Prototype
int isspace(int c);
int iswspace(wint_t c);
int _ismbcspace(unsigned int c);
Description
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
Category
Classification Routines
Prototype
int isupper(int c);
int iswupper(wint_t c);
int _ismbcupper(unsigned int c);
Description
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
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
789
C Runtime Library Reference RAD Studio 3.1 Référence C++
ctype.h, wctype.h
Category
Classification Routines
Prototype
int isxdigit(int c);
int iswxdigit(wint_t c);
Description
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
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
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
Portability
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
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++
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
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.
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
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.
delayimp.h 3
Category
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
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++
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
szDll is pointer to a name to unload, or NULL to unload all the delay load DLLs in the list.
Return Value
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
3.1.5.6.1 _chdrive
Header File
direct.h
Category
Prototype
int _chdrive(int drive);
Description
_chdrive sets the current drive to the one associated with drive: 1 for A, 2 for B, 3 for C, and so on.
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++
+
797
C Runtime Library Reference RAD Studio 3.1 Référence C++
direct.h
Category
Prototype
char * _getdcwd(int drive, char *buffer, int buflen);
wchar_t * _wgetdcwd(int drive, wchar_t *buffer, int buflen);
Description
_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:
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
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++
dirent.h
Category
Prototype
void closedir(DIR *dirp);
void wclosedir(wDIR *dirp);
Description
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.
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
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
800
3.1 Référence C++ RAD Studio C Runtime Library Reference
dirent.h
Category
Prototype
DIR *opendir(const char *dirname);
wDIR *wopendir(const wchar_t *dirname);
Description
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++
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
Example
/* opendir.c - test opendir(), readdir(), closedir() */
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
802
3.1 Référence C++ RAD Studio C Runtime Library Reference
dirent.h
Category
Prototype
struct dirent *readdir(DIR *dirp);
struct wdirent *wreaddir(wDIR *dirp)
Description
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
3
3.1.5.7.4 rewinddir, wrewinddir
Header File
dirent.h
Category
803
C Runtime Library Reference RAD Studio 3.1 Référence C++
Prototype
void rewinddir(DIR *dirp);
void wrewinddir(wDIR *dirp);
Description
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.
Return Value
None.
Example
/* opendir.c - test opendir(), readdir(), closedir() */
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
804
3.1 Référence C++ RAD Studio C Runtime Library Reference
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.
805
C Runtime Library Reference RAD Studio 3.1 Référence C++
806
3.1 Référence C++ RAD Studio C Runtime Library Reference
807
C Runtime Library Reference RAD Studio 3.1 Référence C++
• 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
3.1.5.8.1 chdir
Header File
dir.h
Category
Prototype
int chdir(const char *path);
int _wchdir(const wchar_t *path);
Description
chdir causes the directory specified by path to become the current working directory; path must specify an existing directory.
but this method changes only the current directory on that drive; it does not change the active drive.
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
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
dir.h
Category
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
• -1 is returned
• errno is set to
Portability
Voir aussi
findfirst ( see page 811)
dir.h
Category
Prototype
int findfirst(const char *pathname, struct ffblk *ffblk, int attrib);
int _wfindfirst( const wchar_t *pathname, struct _wffblk *ffblk, int attrib);
Description
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];
};
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:
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:
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
When no more files can be found, or if there is an error in the file name:
• -1 is returned
• errno is set to
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
Voir aussi
findclose ( see page 810)
dir.h
Category
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
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
Portability
Voir aussi
findfirst ( see page 811)
findnext
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
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 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
815
C Runtime Library Reference RAD Studio 3.1 Référence C++
_wfnmerge NT only
dir.h
Category
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
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.
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
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 ?)
dir.h
Category
Prototype
817
C Runtime Library Reference RAD Studio 3.1 Référence C++
Description
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
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
dir.h
Category
3 Prototype
char *getcwd(char *buf, int buflen);
wchar_t *_wgetcwd(wchar_t *buf, int buflen);
Description
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
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
dir.h
Category
Prototype
int getdisk(void);
int setdisk(int drive); 3
Description
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;
}
dir.h
Category
Prototype
int mkdir(const char *path);
int _wmkdir(const wchar_t *path);
Description
Creates a directory.
mkdir creates a new directory from the given path name path.
Return Value
A return value of -1 indicates an error, and the global variable errno is set to one of the following values:
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
dir.h
Category
Prototype
char *_mktemp(char *template);
wchar_t *_wmktemp(wchar_t *template);
Description
_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++
dir.h
Category
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:
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
dir.h
Category
Miscellaneous Routines
Prototype
char *searchpath(const char *file);
wchar_t *wsearchpath( const wchar_t *file );
Description
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
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
825
C Runtime Library Reference RAD Studio 3.1 Référence C++
826
3.1 Référence C++ RAD Studio C Runtime Library Reference
827
C Runtime Library Reference RAD Studio 3.1 Référence C++
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
dos.h
Description
3.1.5.9.3 _getdrive
Header File
dos.h
Category
Prototype
int _getdrive(void);
Description
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.)
829
C Runtime Library Reference RAD Studio 3.1 Référence C++
3.1.5.9.7 _sleep
Header File
dos.h
Category
Prototype
void _sleep(unsigned seconds);
Description
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
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
dos.h
Category
Miscellaneous Routines
Prototype
void disable(void);
void _disable(void);
void enable(void);
void _enable(void);
Description
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
3.1.5.9.10 dostounix
Header File
dos.h
Category
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
3.1.5.9.11 geninterrupt
Header File
Category
Prototype
void geninterrupt(int intr_num);
Description
Return Value
Portability
Category
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
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.
Return 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
Prototype
void getdfree(unsigned char drive, struct dfree *dtable);
Description
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.
833
C Runtime Library Reference RAD Studio 3.1 Référence C++
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
dos.h
Category
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
3.1.5.9.15 unixtodos
Header File
dos.h
Category
Prototype
void unixtodos(long time, struct date *d, struct time *t);
Description
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++
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.
_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 error, it returns -1 and sets the global variable errno to one of the following values:
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
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++
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.
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.
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.
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
Prototype 3
void perror(const char *s);
void _wperror(const wchar_t *s);
Description
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.
Bad address
Broken pipe
Cross-device link
Error 0
Illegal seek
Input/output error
Invalid environment
Invalid format
Is a directory
Math argument
842
3.1 Référence C++ RAD Studio C Runtime Library Reference
No child processes
No more files
No such device
No such process
Not a directory
Permission denied
Possible deadlock
Resource busy
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
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.
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
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
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 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 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.
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
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.
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.
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++
_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
fcntl.h 3
Description
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
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.
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
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.
853
C Runtime Library Reference RAD Studio 3.1 Référence C++
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].
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
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
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.
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.
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:
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
856
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
_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
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.
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++
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.
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
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++
860
3.1 Référence C++ RAD Studio C Runtime Library Reference
861
C Runtime Library Reference RAD Studio 3.1 Référence C++
3 float.h
Description
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
_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
float.h
Category
Math Routines
Prototype
unsigned int _clear87 (void);
unsigned int _clearfp (void);
Description
_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.
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
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
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.
_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
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
float.h
Category
Math Routines
3
Prototype
int _finite(double d);
int _finitel(long double ld);
Description
865
C Runtime Library Reference RAD Studio 3.1 Référence C++
Return Value
Portability
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
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
_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.
float.h
Category
Prototype
int _isnan(double d);
int _isnanl(long double ld);
Description
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++
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
Portability
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
float.h
Category
Math Routines
Prototype
double _scalb(double d, long exp);
long double _scalbl(long double ld, long exp);
Description
_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
float.h
Category
Math Routines
3
Prototype
unsigned int _status87(void);
unsigned int _statusfp(void);
Description
_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++
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.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
871
C Runtime Library Reference RAD Studio 3.1 Référence C++
872
3.1 Référence C++ RAD Studio C Runtime Library Reference
873
C Runtime Library Reference RAD Studio 3.1 Référence C++
874
3.1 Référence C++ RAD Studio C Runtime Library Reference
875
C Runtime Library Reference RAD Studio 3.1 Référence C++
876
3.1 Référence C++ RAD Studio C Runtime Library Reference
877
C Runtime Library Reference RAD Studio 3.1 Référence C++
• 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
879
C Runtime Library Reference RAD Studio 3.1 Référence C++
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
Return Value
On success, returns 0.
Portability
Voir aussi
_findfirst ( see page 881)
io.h, wchar.h
Category
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.
Return Value
On success, returns a unique search handle to a file or group of files matching the filter specification.
881
C Runtime Library Reference RAD Studio 3.1 Référence C++
Voir aussi
_findclose ( see page 880)
io.h, wchar.h
Category
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.
Portability
3 io.h, wchar.h
Category
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.
Return Value
On success, returns 0.
Portability
Voir aussi
_findclose ( see page 880)
io.h, wchar.h
Category
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++
Portability
3.1.5.15.6 _get_osfhandle
Header File
io.h
Category
Input/output Routines
Prototype
long _get_osfhandle(int filehandle);
Description
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
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
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
3.1.5.15.7 _open_osfhandle
Header File
io.h
Category
Input/output Routines
Prototype
int _open_osfhandle(long osfhandle, int flags);
Description
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
Portability
3.1.5.15.8 _pclose
Header File
stdio.h
Category
Prototype
int _pclose(FILE * stream);
Description
_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.
Portability
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
887
C Runtime Library Reference RAD Studio 3.1 Référence C++
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.
Return Value
On error, it returns a value of -1 and sets the global variable errno to one of the following values:
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
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.
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 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
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
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
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):
Return Value
On error, it returns -1 and sets the global variable errno to one of the following values:
3 EACCESPermission denied
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
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
_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.
891
C Runtime Library Reference RAD Studio 3.1 Référence C++
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.
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:
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
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
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
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++
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.
_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:
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
3.1.5.15.15 _snprintf;_snwprintf
Header File
stdio.h
Category
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.
io.h
Category
Input/output Routines
Prototype
int access(const char *filename, int amode);
int _waccess(const wchar_t *filename, int amode);
Description
access checks the file named by filename to determine if it exists, and whether it can be read, written to, or executed.
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:
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
io.h
Category
Input/output Routines
Prototype
int chmod(const char *path, int amode);
int _wchmod(const wchar_t *path, int amode);
Description
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).
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:
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
3.1.5.15.18 chsize
Header File
io.h
Category
Input/output Routines
Prototype
int chsize(int handle, long size);
Description
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:
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
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
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
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
io.h
Category
Input/output Routines
Prototype
int creat(const char *path, int amode);
int _wcreat(const wchar_t *path, int amode);
Description
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.
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:
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
3.1.5.15.21 creatnew
Header File
io.h
Category
Input/output Routines
Prototype
int creatnew(const char *path, int mode);
3
Description
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++
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:
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
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):
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:
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
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
• 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:
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
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
• 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++
3.1.5.15.25 eof
Header File
io.h
Category
Input/output Routines
Prototype
int eof(int handle);
Description
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
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
3.1.5.15.26 filelength
Header File
io.h
Category
Input/output Routines
Prototype
long filelength(int handle);
Description
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
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
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
_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
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
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
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.
Return Value
In the event of an error return -1 is returned and the global variable errno is set to one of the following values:
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
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
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
Description
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
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
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
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:
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
3.1.5.15.32 lseek
Header File
io.h
Category
Input/output Routines
Prototype
long lseek(int handle, long offset, int fromwhere);
Description
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):
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:
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
3.1.5.15.33 read
Header File
io.h
Category
Input/output Routines
Prototype
int read(int handle, void *buf, unsigned len);
Description
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:
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
3.1.5.15.34 setmode
Header File
io.h
Category
Input/output Routines
Prototype
int setmode(int handle, int amode);
Description
Return Value
setmode returns the previous translation mode if successful. On error it returns -1 and sets the global variable errno to
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
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
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
3.1.5.15.36 umask
Header File
io.h, sys\stat.h
Category
Input/output Routines
Prototype
unsigned umask(unsigned mode);
Description
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:
Return Value
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
3.1.5.15.37 unlock
Header File
io.h
Category
Input/output Routines
Prototype
int unlock(int handle, long offset, long length);
Description
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
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
3.1.5.15.38 vsscanf
Header File
io.h
Category
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.
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.
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
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:
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
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
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.
limits.h
Description
Name Meaning
INT_MAX Type int, maximum value
922
3.1 Référence C++ RAD Studio C Runtime Library Reference
limits.h
Description
Name Meaning
LONG_MAX Type long, maximum value
LONG_MIN Type long, minimum value
limits.h
Description
Name Meaning
SCHAR_MAX Type char, maximum value
SCHAR_MIN Type char, minimum value
limits.h
Description
Name Meaning
SHRT_MAX Type short, maximum value
SHRT_MIN Type short, minimum value
limits.h
Description
923
C Runtime Library Reference RAD Studio 3.1 Référence C++
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
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
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:
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 = ≪
/* 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
locale.h
Category
Miscellaneous Routines
Prototype
char *setlocale(int category, const char *locale);
3
wchar_t * _wsetlocale( int category, const wchar_t *locale);
Description
C++ Builder supports all locales supported in Win95/98/2000 operating systems. See your system documentation for details.
926
3.1 Référence C++ RAD Studio C Runtime Library Reference
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++
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.
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.
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
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++
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
931
C Runtime Library Reference RAD Studio 3.1 Référence C++
932
3.1 Référence C++ RAD Studio C Runtime Library Reference
933
C Runtime Library Reference RAD Studio 3.1 Référence C++
934
3.1 Référence C++ RAD Studio C Runtime Library Reference
935
C Runtime Library Reference RAD Studio 3.1 Référence C++
936
3.1 Référence C++ RAD Studio C Runtime Library Reference
937
C Runtime Library Reference RAD Studio 3.1 Référence C++
938
3.1 Référence C++ RAD Studio C Runtime Library Reference
939
C Runtime Library Reference RAD Studio 3.1 Référence C++
Description
940
3.1 Référence C++ RAD Studio C Runtime Library Reference
math.h
Description
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)
math.h
Description
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++
stdlib.h, math.h
Category
Prototype
double atof(const char *s);
double _wtof(const wchar_t *s);
Description
• 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.
math.h
Category
3 Conversion Routines, Math Routines
Prototype
long double _atold(const char *s);
long double _wtold(const wchar_t *s);
Description
942
3.1 Référence C++ RAD Studio C Runtime Library Reference
An optional sign
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
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
math.h, stdlib.h
Category
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
943
C Runtime Library Reference RAD Studio 3.1 Référence C++
Portability
math.h
Category
Prototype
int _matherr(struct _exception *e);
int _matherrl(struct _exceptionl *e);
Description
_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.
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:
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
Prototype
945
C Runtime Library Reference RAD Studio 3.1 Référence C++
Description
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
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
math.h
Category
Math Routines
Prototype
double acos(double x);
long double acosl(long double x);
Description
3 Calculates the arc cosine.
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:
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
math.h
Category
Math Routines
Prototype
double asin(double x);
long double asinl(long double x);
Description
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
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
math.h
Category
Math Routines
Prototype
double atan(double x);
long double atanl(long double x);
Description
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
948
3.1 Référence C++ RAD Studio C Runtime Library Reference
math.h
Category
Math Routines
Prototype
double atan2(double y, double x);
long double atan2l(long double y, long double x);
Description
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
Category
Math Routines
Prototype
double cabs(struct complex z);
949
C Runtime Library Reference RAD Studio 3.1 Référence C++
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;
};
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
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
math.h
Category
Math Routines
Prototype
double ceil(double x);
long double ceill(long double x);
Description
Rounds up.
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
951
C Runtime Library Reference RAD Studio 3.1 Référence C++
math.h
Category
Prototype
double cos(double x);
long double cosl(long double x);
Description
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
Category
Math Routines
Prototype
double cosh(double x);
952
3.1 Référence C++ RAD Studio C Runtime Library Reference
Description
coshl is the long double version; it takes a long double argument and returns a long double result.
Return Value
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
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
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
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
math.h
Category
Math Routines
Prototype
double fabs(double x);
long double fabsl(long double x);
Description
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
Example
#include <stdio.h>
#include <math.h>
int main(void)
{
954
3.1 Référence C++ RAD Studio C Runtime Library Reference
math.h
Category
Math Routines
Prototype
double floor(double x);
long double floorl(long double x);
Description
Rounds down.
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
Category
Math Routines
Prototype
double fmod(double x, double y);
955
C Runtime Library Reference RAD Studio 3.1 Référence C++
Description
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
math.h
Category
Math Routines
Prototype
double frexp(double x, int *exponent);
long double frexpl(long double x, int *exponent);
Description
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
math.h
Category
Math Routines
Prototype
double hypot(double x, double y);
long double hypotl(long double x, long double y);
Description
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
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
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
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
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.
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
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
logl is the long double version; it takes a long double argument and returns a long double result.
Return Value
errno
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
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
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
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
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
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
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
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
math.h
Category
Math Routines
Prototype
double pow(double x, double y);
long double powl(long double x, long double y);
Description
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
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
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
963
C Runtime Library Reference RAD Studio 3.1 Référence C++
powl + + +
math.h
Category
Math Routines
Prototype
double pow10(int p);
long double pow10l(int p);
Description
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
math.h
Category
Math Routines
Prototype
964
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
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
math.h
Category
Prototype
double sinh(double x);
long double sinhl(long double x);
Description
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
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
math.h
Category
Math Routines
Prototype
double sqrt(double x);
long double sqrtl(long double x);
Description
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
966
3.1 Référence C++ RAD Studio C Runtime Library Reference
return 0;
}
Portability
math.h
Category
Math Routines
Prototype
double tan(double x);
long double tanl(long double x);
Description
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
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
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
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
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
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:
969
C Runtime Library Reference RAD Studio 3.1 Référence C++
970
3.1 Référence C++ RAD Studio C Runtime Library Reference
3.1.5.20.1 memccpy
Header File
mem.h, string.h
Category
Prototype
void *memccpy(void *dest, const void *src, int c, size_t n);
Description
memccpy copies a block of n bytes from src to dest. The copying stops as soon as either of the following occurs:
971
C Runtime Library Reference RAD Studio 3.1 Référence C++
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
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
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
Prototype
int memcmp(const void *s1, const void *s2, size_t n);
Description
memcmp compares the first n bytes of the blocks s1 and s2 as unsigned chars.
Return Value
973
C Runtime Library Reference RAD Studio 3.1 Référence C++
mem.h, string.h
Category
Prototype
void *memcpy(void *dest, const void *src, size_t n);
void *_wmemcpy(void *dest, const void *src, size_t n);
Description
memcpy copies a block of n bytes from src to dest. If src and dest overlap, the behavior of memcpy is undefined.
Return Value
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
3
3.1.5.20.5 memicmp
Header File
mem.h, string.h
Category
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
memicmp compares the first n bytes of the blocks s1 and s2, ignoring character case (upper or lower).
Return Value
3.1.5.20.6 memmove
Header File
mem.h, string.h
Category
Prototype
3
void *memmove(void *dest, const void *src, size_t n);
Description
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
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
mem.h, string.h
Category
Prototype
void *memset(void *s, int c, size_t n);
void *_wmemset(void *s, int c, size_t n);
Description
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
3.1.5.20.8 setmem
Header File
mem.h
Category
Prototype
void setmem(void *dest, unsigned length, char value);
Description
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
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
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.
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
981
C Runtime Library Reference RAD Studio 3.1 Référence C++
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++
process.h
Description
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
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
Using _adopt_thread thereby allows C++Builder compiled DLLs to be used from non-C++Builder EXEs. _adopt_thread works by:
3.1.5.22.3 _beginthread
Header File
process.h
Category
Prototype
unsigned long _beginthread(void (_USERENTRY *__start)(void *), unsigned __stksize, void
*__arg);
Description
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.
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:
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
986
3.1 Référence C++ RAD Studio C Runtime Library Reference
3.1.5.22.4 _beginthreadNT
Header File
process.h
Category
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
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.
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:
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++
988
3.1 Référence C++ RAD Studio C Runtime Library Reference
3.1.5.22.5 _beginthreadex
Header File
process.h
Category
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.
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();
3.1.5.22.6 _c_exit
Header File
process.h
Category
Prototype
3
void _c_exit(void);
Description
_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;
3.1.5.22.7 _cexit
Header File
process.h
Category
Prototype
void _cexit(void);
Description
_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
3.1.5.22.8 _endthread
Header File
process.h
Category
Prototype
void _endthread(void);
Description
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
992
3.1 Référence C++ RAD Studio C Runtime Library Reference
3.1.5.22.9 _endthreadex
Header File
process.h
Category
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
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++
3.1.5.22.11 _unadopt_thread
Header File
process.h
Category
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
3.1.5.22.12 cwait
3 Header File
process.h
Category
Prototype
int cwait(int *statloc, int pid, int action);
994
3.1 Référence C++ RAD Studio C Runtime Library Reference
Description
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:
If the child process terminated abnormally, the termination status word is defined as follows:
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:
Portability
995
C Runtime Library Reference RAD Studio 3.1 Référence C++
process.h
Category
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
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:
Example
/* execl() example */
#include <stdio.h>
#include <process.h>
997
C Runtime Library Reference RAD Studio 3.1 Référence C++
int loop;
printf("%s running...\n\n", argv[0]);
3.1.5.22.14 getpid
Header File
process.h
Category
Prototype
unsigned getpid(void)
Description
This function returns the current process ID--an integer that uniquely identifies the process.
Return Value
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
998
3.1 Référence C++ RAD Studio C Runtime Library Reference
process.h
Category
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:
1000
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
Prototype
int wait(int *statloc);
Description
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:
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:
Portability
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
3.1.5.23.1 longjmp
Header File
setjmp.h
Category
Miscellaneous Routines
Prototype
void longjmp(jmp_buf jmpb, int retval);
Description
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.
• 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
3.1.5.23.2 setjmp
Header File
setjmp.h
Category
Miscellaneous Routines
Prototype
int setjmp(jmp_buf jmpb);
Description
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.
1004
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
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++
share.h
Description
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.h
Description
(*) Signal types marked with a (*) aren't generated by Borland C++ during normal operation. However, they can be generated
with raise.
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
Prototype
int raise(int sig);
Description
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.
Remarque: SIGABRT isn’t generated by C++Builder during normal operation. It can, however, be generated by abort, raise, or
unhandled exceptions.
Return Value
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
signal.h
Category
Prototype
void (_USERENTRY *signal(int sig, void (_USERENTRY *func)(int sig[, int subcode])))(int);
Description
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.
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.
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.)
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.
1010
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
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)
stdarg.h
Category
Prototype
void va_start(va_list ap, lastfix);
type va_arg(va_list ap, type);
3
void va_end(va_list ap);
Description
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
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
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
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.
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.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++
1016
3.1 Référence C++ RAD Studio C Runtime Library Reference
1017
C Runtime Library Reference RAD Studio 3.1 Référence C++
1018
3.1 Référence C++ RAD Studio C Runtime Library Reference
1019
C Runtime Library Reference RAD Studio 3.1 Référence C++
1020
3.1 Référence C++ RAD Studio C Runtime Library Reference
1021
C Runtime Library Reference RAD Studio 3.1 Référence C++
1022
3.1 Référence C++ RAD Studio C Runtime Library Reference
1023
C Runtime Library Reference RAD Studio 3.1 Référence C++
1024
3.1 Référence C++ RAD Studio C Runtime Library Reference
1025
C Runtime Library Reference RAD Studio 3.1 Référence C++
1026
3.1 Référence C++ RAD Studio C Runtime Library Reference
1027
C Runtime Library Reference RAD Studio 3.1 Référence C++
1028
3.1 Référence C++ RAD Studio C Runtime Library Reference
1029
C Runtime Library Reference RAD Studio 3.1 Référence C++
1030
3.1 Référence C++ RAD Studio C Runtime Library Reference
stdio.h
Description
Description
Name Meaning
_F_RDWR Read and write
1031
C Runtime Library Reference RAD Studio 3.1 Référence C++
stdio.h
Description
Name Meaning
FOPEN_MAX Maximum files per process
SYS_OPEN Maximum files for system
stdio.h
Description
stdio.h
3 Description
stdio.h
1032
3.1 Référence C++ RAD Studio C Runtime Library Reference
Description
stdio.h
Description
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.
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
_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:
Return Value
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
1034
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
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 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.
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
3.1.5.28.10 _vsnprintf;_vsnwprintf
Header File
stdio.h
Category
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.
• < 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
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
stdio.h
Description
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
Portability
3.1.5.28.14 _fcloseall
Header File
stdio.h
Category
Input/output Routines
Prototype
int _fcloseall(void);
Description
stdauxstdstreams
When _fcloseall flushes the associated buffers before closing a stream. The buffers allocated by the system are released.
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
stdio.h
Category
Input/output Routines
Prototype
FILE *_fdopen(int handle, char *type);
FILE *_wfdopen(int handle, wchar_t *type);
Description
_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.
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++
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
3.1.5.28.17 ferror
Header File
stdio.h
Category
Input/output Routines
Prototype
int ferror(FILE *stream);
Description
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
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
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
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
stdio.h
Category
Input/output Routines
Prototype
int fgetc(FILE *stream);
wint_t fgetwc(FILE *stream);
Description
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++
stdio.h
Category
Prototype
int _fgetchar(void);
wint_t _fgetwchar(void);
Description
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
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
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
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
1045
C Runtime Library Reference RAD Studio 3.1 Référence C++
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
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
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
_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
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:
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,
stdio.h
Category
Input/output Routines
Prototype
int fprintf(FILE *stream, const char *format[, argument, ...]);
Description
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.
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
stdio.h
Category
Input/output Routines
Prototype
int fputc(int c, FILE *stream);
wint_t fputwc(wint_t c, FILE *stream);
Description
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
stdio.h
Category
Input/output Routines
Prototype
int _fputchar(int c);
wint_t _fputwchar(wint_t c);
Description
Return Value
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
1050
3.1 Référence C++ RAD Studio C Runtime Library Reference
_fputwchar +
stdio.h
Category
Input/output Routines
Prototype
int fputs(const char *s, FILE *stream);
int fputws(const wchar_t *s, FILE *stream);
Description
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
Example
#include <stdio.h>
int main(void)
{
/* write a string to standard output */
fputs("Hello world\n", stdout);
return 0;
}
Portability
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
fread reads n items of data each of length size bytes from the given input stream into a block pointed to by ptr.
Return Value
On success fread returns the number of items (not bytes) actually read.
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
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
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:
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,
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
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.
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
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
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 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:
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
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
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 failure it returns a nonzero value and also sets the global variable errno to a nonzero value.
Portability
3.1.5.28.34 ftell
Header File
stdio.h
Category
Input/output Routines
Prototype
long int ftell(FILE *stream);
Description
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
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
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.
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++
stdio.h
Category
Input/output Routines
Prototype
int getc(FILE *stream);
wint_t getwc(FILE *stream);
Description
getc returns the next character on the given input stream and increments the stream's file pointer to point to the next character.
Return Value
On success, getc returns the character read, after converting it to an int without sign extension.
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
1058
3.1 Référence C++ RAD Studio C Runtime Library Reference
getwc + + +
stdio.h
Category
Prototype
int getchar(void);
wint_t getwchar(void);
Description
getchar is a macro that returns the next character on the named input stream stdin. It is defined to be getc(stdin).
Return Value
On success, getchar returns the character read, after converting it to an int without sign extension.
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
stdio.h
Category
1059
C Runtime Library Reference RAD Studio 3.1 Référence C++
Prototype
char *gets(char *s);
wchar_t *_getws(wchar_t *s); // Unicode version
Description
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.
Return Value
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
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
_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
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++
+
1061
C Runtime Library Reference RAD Studio 3.1 Référence C++
stdio.h
Category
Prototype
int printf(const char *format[, argument, ...]);
int wprintf(const wchar_t *format[, argument, ...]);
Description
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
stdio.h
Category
Input/output Routines
Prototype
int putc(int c, FILE *stream);
wint_t putwc(wint_t c, FILE *stream);
Description
putc is a macro that outputs the character c to the stream given by stream.
Return Value
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
stdio.h
Category
Prototype
int putchar(int c);
wint_t putwchar(wint_t c);
Description
Return Value
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
stdio.h
Category
Prototype
int puts(const char *s);
int _putws(const wchar_t *s);
Description
puts copies the null-terminated string s to the standard output stream stdout and appends a newline character.
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
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
_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
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.
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:
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
1067
C Runtime Library Reference RAD Studio 3.1 Référence C++
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 error (if the file cannot be renamed), it returns -1 and the global variable errno is set to one of the following values:
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
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
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
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
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;
stdio.h
Category
Prototype
int scanf(const char *format[, address, ...]);
int wscanf(const wchar_t *format[, address, ...]);
Description
1070
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
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
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
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.
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.
_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++
Return Value
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
3.1.5.28.52 snprintf;snwprintf
Header File
stdio.h
Category
Prototype
Description
• < 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.
stdio.h
Category
Prototype
int sprintf(char *buffer, const char *format[, argument, ...]);
int swprintf(wchar_t *buffer, const wchar_t *format[, argument, ...]);
Description
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.
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++
stdio.h
Category
Syntax
int sscanf(const char *buffer, const char *format[, address, ...]);
int swscanf(const wchar_t *buffer, const wchar_t *format[, address, ...]);
Description
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.
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
stdio.h
Description
Name Meaning
stdin Standard input device
stdout Standard output device
stderr Standard error output device
stdio.h
Category
Input/output Routines
Prototype
char *_tempnam(char *dir, char *prefix)
wchar_t *_wtempnam(wchar_t *dir, wchar_t *prefix)
Description
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
3.1.5.28.57 tmpfile
Header File
stdio.h
Category
Input/output Routines
Prototype
3 FILE *tmpfile(void);
Description
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
stdio.h
Category
Input/output Routines
Prototype
char *tmpnam(char *s);
wchar_t *_wtmpnam(wchar_t *s);
Description
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
stdio.h
Category
Input/output Routines
Prototype
int ungetc(int c, FILE *stream);
wint_t ungetwc(wint_t c, FILE *stream);
Description
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
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
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
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.
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
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++
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
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.
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.
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
stdio.h
Category
Prototype
int vprintf(const char *format, va_list arglist);
int vwprintf(const wchar_t * format, va_list arglist);
Description
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.
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
3.1.5.28.63 vscanf
Header File
stdio.h
Category
Prototype
int vscanf(const char *format, va_list arglist);
Description
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.
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.
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
3.1.5.28.64 vsnprintf;vsnwprintf
Header File
stdio.h
Category
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
• < 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.
stdio.h
Category
Prototype
int vsprintf(char *buffer, const char *format, va_list arglist);
int vswprintf(wchar_t *buffer, const wchar_t *format, va_list arglist);
Description
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
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++
1088
3.1 Référence C++ RAD Studio C Runtime Library Reference
1089
C Runtime Library Reference RAD Studio 3.1 Référence C++
1090
3.1 Référence C++ RAD Studio C Runtime Library Reference
1091
C Runtime Library Reference RAD Studio 3.1 Référence C++
1092
3.1 Référence C++ RAD Studio C Runtime Library Reference
1093
C Runtime Library Reference RAD Studio 3.1 Référence C++
1094
3.1 Référence C++ RAD Studio C Runtime Library Reference
1095
C Runtime Library Reference RAD Studio 3.1 Référence C++
1096
3.1 Référence C++ RAD Studio C Runtime Library Reference
1097
C Runtime Library Reference RAD Studio 3.1 Référence C++
1098
3.1 Référence C++ RAD Studio C Runtime Library Reference
1099
C Runtime Library Reference RAD Studio 3.1 Référence C++
1100
3.1 Référence C++ RAD Studio C Runtime Library Reference
stdlib.h
Description
Name Meaning
EXIT_SUCCESS Normal program termination
EXIT_FAILURE Abnormal program termination
stdlib.h 3
Syntax
Description
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.
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.
Portability
stdlib.h
Category
Description
1102
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
stdlib.h
Category
Math Routines
Prototype
unsigned char _crotl(unsigned char val, int count);
unsigned char _crotr(unsigned char val, int count);
Description
_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
1103
C Runtime Library Reference RAD Studio 3.1 Référence C++
3.1.5.29.7 _exit
Header File
stdlib.h
Category
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
Category
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
_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.
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
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++
stdlib.h
Category
Math Routines
Prototype
unsigned long _lrotl(unsigned long val, int count);
unsigned long _lrotr(unsigned long val, int count);
Description
_Irotlrotates the given val to the left count bits. _lrotr rotates the given val to the right count bits.
Return Value
1106
3.1 Référence C++ RAD Studio C Runtime Library Reference
stdlib.h
Category
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
_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.
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
stdlib.h
Category
Math Routines
3 Prototype
unsigned short _rotl(unsigned short value, int count);
unsigned short _rotr(unsigned short value, int count);
Description
1108
3.1 Référence C++ RAD Studio C Runtime Library Reference
Return Value
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
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);
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
_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
stdlib.h
Category
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
_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.
1112
3.1 Référence C++ RAD Studio C Runtime Library Reference
stdlib.h
Category
Prototype
char *_ui64toa(unsigned __int64 value, char *string, int radix);
wchar_t *_ui64tow(unsigned __int64 value, wchar_t *string, int radix);
Description
_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
Portability
3.1.5.29.17 abort
Header File
3
stdlib.h
Category
Prototype
void abort(void);
1113
C Runtime Library Reference RAD Studio 3.1 Référence C++
Description
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
3.1.5.29.18 atexit
Header File
stdlib.h
Category
Prototype
int atexit(void (_USERENTRY * func)(void));
Description
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
stdlib.h
Category
Prototype
int atoi(const char *s);
int _wtoi(const wchar_t *s);
Description
• 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
stdlib.h
Category
Prototype
long atol(const char *s);
long _wtol(const wchar_t *s);
Description
• 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
3.1.5.29.21 bsearch
Header File
stdlib.h
Category
Prototype
void *bsearch(const void *key, const void *base, size_t nelem, size_t width, int (_USERENTRY
*fcmp)(const void *, const void *));
Description
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.
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
3.1.5.29.22 div
Header File
stdlib.h
Category
Math Routines
Prototype
div_t div(int numer, int denom);
Description
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
3.1.5.29.23 ecvt
Header File
stdlib.h
Category
Prototype
char *ecvt(double value, int ndig, int *dec, int *sign);
Description
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++
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
3.1.5.29.25 exit
Header File
stdlib.h
Category
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
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
3.1.5.29.26 fcvt
Header File
stdlib.h
Category
Prototype
char *fcvt(double value, int ndig, int *dec, int *sign);
Description
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
3.1.5.29.27 gcvt
Header File
stdlib.h
Category
Prototype
char *gcvt(double value, int ndec, char *buf);
Description
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
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
stdlib.h
Category
Prototype
char *getenv(const char *name);
wchar_t *_wgetenv(const wchar_t *name);
Description
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.
Remarque: Environment entries must not be changed directly. If you want to change an environment value, you must use
putenv.
Return Value
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
stdlib.h
Category
Prototype
char *itoa(int value, char *string, int radix);
wchar_t *_itow(int value, wchar_t *string, int radix);
Description
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
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
3.1.5.29.30 labs
Header File
stdlib.h
Category
Math Routines
Prototype
long labs(long int x);
Description
Return Value
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
3.1.5.29.31 lfind
Header File
3
stdlib.h
Category
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++
Description
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
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
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.
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++
stdlib.h
Category
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
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
1128
3.1 Référence C++ RAD Studio C Runtime Library Reference
3.1.5.29.34 max
Header File
stdlib.h
Category
Prototype
(type) max(a, b);
template <class T> T max( T t1, T t2 ); // C++ only
Description
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
Portability
3.1.5.29.35 mblen
Header File
stdlib.h
Category
Prototype
int mblen(const char *s, size_t n);
Description
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
3.1.5.29.36 mbstowcs
Header File
stdlib.h
Category
Prototype
size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n);
Description
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
3.1.5.29.37 mbtowc
Header File
stdlib.h
Category
Prototype
int mbtowc(wchar_t *pwc, const char *s, size_t n);
Description
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.
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++
3.1.5.29.38 min
Header File
stdlib.h
Category
Prototype
(type) min(a, b); /* macro version */
template <class T> T min( T t1, T t2 );// C++ only
Description
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
stdlib.h
Category
Prototype
int putenv(const char *name);
1132
3.1 Référence C++ RAD Studio C Runtime Library Reference
Description
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
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
3
3.1.5.29.40 qsort
Header File
stdlib.h
Category
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
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.
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
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
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
3.1.5.29.42 random
Header File
stdlib.h
Category
Math Routines
Prototype
int random(int num);
Description
Return Value
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
3.1.5.29.43 randomize
Header File
stdlib.h, time.h
Category
Math Routines
Prototype
void randomize(void);
Description
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
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
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
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++
Description
_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
stdlib.h
Category
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
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
where:
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
1139
C Runtime Library Reference RAD Studio 3.1 Référence C++
stdlib.h
Category
Prototype
long strtol(const char *s, char **endptr, int radix);
long wcstol(const wchar_t *s, wchar_t **endptr, int radix);
Description
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:
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
Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
1140
3.1 Référence C++ RAD Studio C Runtime Library Reference
stdlib.h
Category
Prototype
unsigned long strtoul(const char *s, char **endptr, int radix);
unsigned long wcstoul(const wchar_t *s, wchar_t **endptr, int radix);
Description
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
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
1141
C Runtime Library Reference RAD Studio 3.1 Référence C++
3.1.5.29.49 swab
Header File
stdlib.h
Category
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
stdlib.h
Category
3 Process Control Routines
Prototype
int system(const char *command);
int _wsystem(const wchar_t *command);
Description
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 not a NULL pointer, system returns 0 if the command processor was successfully started.
Example
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
printf("About to spawn a command-line program.\n");
system("dir");
return 0;
}
Portability
stdlib.h
Category
Prototype
char *ultoa(unsigned long value, char *string, int radix);
3
wchar_t *_ultow(unsigned long value, wchar_t *string, int radix);
Description
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
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
3.1.5.29.52 wcstombs
Header File
stdlib.h
Category
Prototype
size_t wcstombs(char *s, const wchar_t *pwcs, size_t n);
Description
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!";
}
Portability
3.1.5.29.53 wctomb
Header File
stdlib.h
Category
Prototype
int wctomb(char *s, wchar_t wc);
Description
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++
}
Portability
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
1147
C Runtime Library Reference RAD Studio 3.1 Référence C++
1148
3.1 Référence C++ RAD Studio C Runtime Library Reference
1149
C Runtime Library Reference RAD Studio 3.1 Référence C++
1150
3.1 Référence C++ RAD Studio C Runtime Library Reference
1151
C Runtime Library Reference RAD Studio 3.1 Référence C++
1152
3.1 Référence C++ RAD Studio C Runtime Library Reference
1153
C Runtime Library Reference RAD Studio 3.1 Référence C++
1154
3.1 Référence C++ RAD Studio C Runtime Library Reference
1155
C Runtime Library Reference RAD Studio 3.1 Référence C++
1156
3.1 Référence C++ RAD Studio C Runtime Library Reference
1157
C Runtime Library Reference RAD Studio 3.1 Référence C++
1158
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
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.
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
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.
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
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.
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
mbstring.h
Category
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
_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
mbstring.h
Category
Prototype
int _mbsnbcoll(const unsigned char *s1, const unsigned char *s2, maxlen);
int _mbsnbicoll(const unsigned char *s1, const unsigned char *s2, maxlen);
Description
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
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
3.1.5.30.11 _mbsnbicmp
Header File
mbstring.h
Category
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.
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
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
mbstring.h
Category
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.
mbstring.h
Category
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.
mbstring.h, tchar.h
Category
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.
Return Value
3.1.5.30.16 _strerror
Header File
string.h, stdio.h
3
Category
Prototype
char *_strerror(const char *s);
Description
1166
3.1 Référence C++ RAD Studio C Runtime Library Reference
_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
mbstring.h, tchar.h
Category
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.
Return Value
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
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
***/
string.h
Category
Description
_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
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
string.h, mbstring.h
Category
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
strcat appends a copy of src to the end of dest. The length of the resulting string is strlen(dest) + strlen(src).
Return Value
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
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
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)
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
string.h, mbstring.h
Category
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
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
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
3.1.5.30.23 strcmpi
Header File
string.h, wchar.h
Category
Prototype
int strcmpi(const char *s1, const char *s2);
int _wcscmpi(const wchar_t *s1, const wchar_t *s2);
Description
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
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
string.h, mbstring.h
Category
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
strcoll compares the string pointed to by s1 to the string pointed to by s2, according to the current locale's LC_COLLATE
category.
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
1173
C Runtime Library Reference RAD Studio 3.1 Référence C++
3.1.5.30.25 strcpy
Header File
Category
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 string src to dest, stopping after the terminating null character has been moved.
Return Value
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
Category
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++
string.h, mbstring.h
Category
Prototype
char *strdup(const char *s);
wchar_t *_wcsdup(const wchar_t *s);
unsigned char *_mbsdup(const wchar_t *s);
Description
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
3 3.1.5.30.28 strerror
Header File
string.h
Category
Prototype
1176
3.1 Référence C++ RAD Studio C Runtime Library Reference
Description
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
string.h, mbstring.h
Category
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
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++
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
string.h, mbstring.h
Category
Prototype
char *strlwr(char *s);
wchar_t *_wcslwr(wchar_t *s);
unsigned char *_mbslwr(unsigned char *s);
Description
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
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
3.1.5.30.31 strncat
Header File
string.h, mbstring.h
Category
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
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
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
string.h, mbstring.h
Category
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
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
string.h
Category
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
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
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
string.h, mbstring.h
Category
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.
Return Value
string.h, mbstring.h
1182
3.1 Référence C++ RAD Studio C Runtime Library Reference
Category
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
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
string.h, mbstring.h
Category
Description
1183
C Runtime Library Reference RAD Studio 3.1 Référence C++
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
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
string.h
Category
Description
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
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
string.h, mbstring.h
Category
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
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
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
string.h, mbstring.h
Category
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
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
1187
C Runtime Library Reference RAD Studio 3.1 Référence C++
_mbsrev +
_wcsrev +
string.h, mbstring.h
Category
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
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
string.h, mbstring.h
Category
1188
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
string.h
Category
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
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
string.h, mbstring.h
Category
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.
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
string.h, mbstring.h
Category
Prototype
char *strupr(char *s);
wchar_t *_wcsupr(wchar_t *s);
unsigned char *_mbsupr(unsigned char *s);
Description
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
string.h
Category
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
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
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++
sys\stat.h
Description
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
sys\stat.h, tchar.h
Category
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.
st_ino0
st_nlink1
st_uid0
st_gid0
st_rdevsame as st_dev
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++
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
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:
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:
The HPFS and NTFS file-management systems make the following distinctions:
1196
3.1 Référence C++ RAD Studio C Runtime Library Reference
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
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 ;
};
3.1.5.32.1 ftime
Header File
sys\timeb.h
Category
Prototype
void ftime(struct timeb *buf)
Description
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
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
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
1201
C Runtime Library Reference RAD Studio 3.1 Référence C++
1202
3.1 Référence C++ RAD Studio C Runtime Library Reference
1203
C Runtime Library Reference RAD Studio 3.1 Référence C++
time.h
1204
3.1 Référence C++ RAD Studio C Runtime Library Reference
Category
Prototype
char *_strdate(char *buf);
wchar_t *_wstrdate(wchar_t *buf);
Description
_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
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
time.h
Category
Prototype
3
char *_strtime(char *buf);
wchar_t *_wstrtime(wchar_t *buf);
Description
_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++
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
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
3.1.5.34.3 asctime
Header File
time.h
Category
Prototype
char *asctime(const struct tm *tblock);
wchar_t *_wasctime(const struct tm *tblock);
Description
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:
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
3.1.5.34.4 clock
Header File
time.h
Category
Prototype
clock_t clock(void);
3
Description
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
3.1.5.34.5 clock_t
Header File
time.h
Syntax
typedef long clock_t;
Description
Portability
time.h
Category
Description
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
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
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++
Prototype
double difftime(time_t time2, time_t time1);
Description
Return Value
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
3.1.5.34.9 gmtime
Header File
time.h
Category
Prototype
struct tm *gmtime(const time_t *timer);
3
Description
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
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
3.1.5.34.10 localtime
Header File
time.h
Category
1211
C Runtime Library Reference RAD Studio 3.1 Référence C++
Prototype
struct tm *localtime(const time_t *timer);
Description
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.
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
3.1.5.34.11 mktime
Header File
time.h
Category
Prototype
time_t mktime(struct tm *t);
Description
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 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++
3.1.5.34.12 stime
Header File
time.h
Category
Prototype
int stime(time_t *tp);
Description
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
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
time.h
1214
3.1 Référence C++ RAD Studio C Runtime Library Reference
Category
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
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.
Return Value
On error (if the number of characters required is greater than maxsize), strftime returns 0.
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
3.1.5.34.14 time 3
Header File
time.h
Category
Prototype
1215
C Runtime Library Reference RAD Studio 3.1 Référence C++
Description
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
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
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.
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
Description
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.
time.h
Category
Prototype
3
void _tzset(void)
void _wtzset(void)
Description
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
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
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.
typeinfo.h
Description
When the operand of typeid is a dereferenced null pointer, the typeid operator can throw bad_typeid.
Description
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++
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)
utime.h
Category
Input/output Routines
Prototype
int _utime(char *path, struct utimbuf *times);
int _wutime(wchar_t *path, struct _utimbuf *times);
Description
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 error, it returns -1, and sets the global variable errno to one of the following values:
Example
/* Copy timestamp from one file to another */
#include <sys\stat.h>
#include <utime.h>
#include <stdio.h>
if (stat(argv[1],&src_stat) != 0) {
perror("Unable to get status of source file");
return 1;
}
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:
values.h
Description
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
values.h
Description
1222
3.1 Référence C++ RAD Studio C Runtime Library Reference
Name Meaning
MAXSHORT Largest short
MAXINT Largest int
MAXLONG Largest long
values.h
Description
1223
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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.
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
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 :
1226
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants
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 :
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
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é.
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
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 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.
1230
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants
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 :
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
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
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
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.
1235
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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
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
1238
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants
}
}
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 :
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 :
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.
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 :
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.
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.
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.
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.
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.
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.
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.
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.
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.
Les trois points suivants sont à prendre en compte pour incorporer des événements standard dans vos 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.
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.
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.
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.
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.
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.
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
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".
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é.
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
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.
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
1251
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
• 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.
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
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
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).
• 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é.
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.
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
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 :
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 :
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 :
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 :
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.
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.
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.
• 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
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.
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.
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
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.)
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();
}
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.
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.
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.
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é.
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.
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
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.
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.
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
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;
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.
• 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);
}
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;
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 :
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 :
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.
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).
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)
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.
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);
}
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
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.
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
}
1279
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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
1281
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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
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.
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
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
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.
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 }
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.
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
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)
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)
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
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
1294
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants
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)
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
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)
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 :
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
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)
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)
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)
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
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
Voir aussi
Accès aux services de l'API Tools ( see page 1305)
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
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 :
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).
1307
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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)
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)
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 plus en détail les interfaces de module et d'éditeur :
1309
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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
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 :
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 :
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 :
1313
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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)
• 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)
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 :
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)
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)
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)
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.
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.
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
};
• 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 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
}
La définition d'un message est un processus à deux étapes : Les étapes sont les suivantes :
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.
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
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 :
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.
1321
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
end;
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.
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.
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 );
.
.
.
}
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,
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 :
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.
Utilisation des graphiques et des composants : Vue globale ( see page 1399)
Accessibilité des composants au moment de la conception : Vue globale ( see page 1367)
1327
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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)
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
1328
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants
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)
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)
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.
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
Lorsque vous créez un composant, vous créez une nouvelle unité pour ce composant ou bien vous l'ajoutez à une unité
existante.
3
2. Dérivez la classe composant.
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éé.
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.
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.
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).
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.
• 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.
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)
1334
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants
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.
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.
1335
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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
}
}
1337
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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.
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.
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.
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.
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 :
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 :
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 :
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).
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.
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
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
Pour notre exemple, suivez la procédure générale de création d'un composant en tenant compte des spécificités suivantes :
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).
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
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
Voir aussi
Déclaration des propriétés d'accès d'un contrôle orienté données ( see page 1346)
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
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.
1349
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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.
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é.
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é.
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
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
• 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
}
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 :
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 :
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 :
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 :
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 :
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);
}
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.
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.
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 :
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 :
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
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.
• 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 #.
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.
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
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;
}
}
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
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
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.
1367
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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.
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
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.
dans l'EDI, le code requis pour recenser votre composant est automatiquement ajouté. Les étapes d'un recensement manuel
de composant sont :
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
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.
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()
{
1370
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants
• 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.
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.
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 :
1371
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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.
1372
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants
Voici les causes les plus courantes de l'absence des composants dans la liste des composants ou sur la palette :
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
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);
}
}
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 :
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 :
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.
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.
Pour notre exemple, suivez la procédure générale de création d'un composant en tenant compte des spécificités suivantes :
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.
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.
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.
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.
• 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)
Pour notre exemple, suivez la procédure générale de création d'un composant en tenant compte des spécificités suivantes :
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.
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.
• 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.
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.
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.
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 :
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
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) :
1387
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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)
• 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.
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.
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
Le tableau ci-dessous montre les niveaux de visibilité, en allant du plus restrictif au plus accessible :
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)
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)
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)
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)
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)
1391
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
• Statique
• Virtuel
• 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.
Voir aussi
Définir l'interface avec le concepteur des composants ( see page 1391)
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)
Pour redéfinir une méthode dans une classe descendante, ajoutez la directive override à la fin de la déclaration de méthode.
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
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.
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 :
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 :
1396
3.2 Guide du développeur Win32 RAD Studio Guide du concepteur de composants
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é.
Les points suivants sont à prendre en compte lorsque vous travaillez avec des palettes :
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 :
1397
Guide du concepteur de composants RAD Studio 3.2 Guide du développeur Win32
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.
• 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.
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.
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.
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.
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.
1399
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32
Les trois sujets suivants sont nécessaires à la compréhension du travail sur les images 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
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
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 :
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)
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).
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)
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.
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.
• 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)
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)
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)
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.
• 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)
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)
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)
• 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)
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)
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)
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.
1411
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32
L'Automation peut être utilisée sur des serveurs en processus, locaux ou distants.
• 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
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)
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)
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.
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).
• 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
• 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 :
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)
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
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 :
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.
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+.
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.
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)
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).
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.
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.
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.
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.
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.
Voir aussi
Création d'ASP pour des serveurs en et hors processus ( see page 1425)
1424
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM
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)
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.
Pour annuler le recensement d'un serveur en processus, choisissez Exécuter Dé-recenser le serveur ActiveX.
Pour annuler le recensement d'un serveur hors processus, exécutez le serveur avec l'option en ligne de commande /unregserver. 3
1425
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32
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.
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)
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).
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)
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.
1429
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32
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
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.
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)
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;
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)
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
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)
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.
1434
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM
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)
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.
1435
Développement d'applications COM RAD Studio 3.2 Guide du développeur Win32
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)
Voir aussi
3 Création d'une page de propriétés pour un contrôle ActiveX ( see page 1435)
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)
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)
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 :
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)
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)
• 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)
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 :
1442
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM
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.
Deuxièmement, une fois la valeur de ConnectKind spécifiée, il y a trois manières de connecter le composant au serveur :
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)
Les rubriques suivantes décrivent comment implémenter les diverses actions que votre contrôleur Automation doit effectuer.
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)
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)
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
Voir aussi
Contrôle d'un serveur Automation en utilisant une interface double ( see page 1445)
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 :
1446
3.2 Guide du développeur Win32 RAD Studio Développement d'applications COM
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.
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.
Ecriture de code client basé sur les définitions de la bibliothèque de types ( see page 1444)
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)
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');
{ Ajouter un élément }
dotNetArrayList.Add('Un élément chaîne');
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);
}
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).
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
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 :
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 :
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.
• 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.
• 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.