2012-01-12 3 views
0

Tenir compte l'extrait suivant:Pourquoi les types de pointeurs de caractères suivants sont-ils considérés comme incompatibles?

procedure TForm1.FormCreate(Sender: TObject); 
    {$REGION 'Sealed declarations'} 
    type WCh = WideChar; // (1) 
    type Str = ^WCh;  // (2) 
    { this routine accepts character pointer } 
    procedure Baz(Param: Str); 
    begin 
    end; 
    {$ENDREGION} 
    { this one too, but character pointer type used directly } 
    procedure Bar(Param: PWideChar); 
    begin 
    end; 
    { this constant should be compatible with strings and character pointers } 
    const FOO = 'FOO'; 
begin 
    Bar(FOO); // compiles! 
    Baz(FOO); // BAH! E2010 Incompatible types: 'Str' and 'string' 
end; 

Comment puis-je résoudre ce problème préserver à la fois la saisie structurée dans les déclarations et la clarté et la lisibilité de l'utilisation (je l'espère sans transtypage lourd)?

NB: Par "déclarations scellées" je le pense vraiment. Je préfère ne pas le modifier sauf si c'est absolument nécessaire.

La gestion interne de la conversion entre string et PChar varie d'une version à l'autre, donc l'environnement peut être important - j'ai rencontré ce problème dans Delphi XE.

+0

Très difficile à comprendre pourquoi vous n'utilisez pas WideChar et PWideChar directement –

+3

Et vous pouvez répondre à votre propre question simplement en se référant à la documentation: http: //docwiki.embarcadero.com/RADStudio/fr/Type_Compatibility_and_Identity –

Répondre

4

Comme Rob Kennedy observer à juste titre les commentaires, la question est sur la conversion de la chaîne littérale, liez pas Type.

Pour simplifier le codage, Delphi autorise la conversion implicite du littéral de chaîne en PChar et en PChar.

Pour éviter transtypage vous pouvez utiliser

type Str = PWideChar; 

ou utiliser le type distict

type Str = type PWideChar; 

Je ne l'ai pas remarqué aucune différence dans la chaîne littérale -> PWideChar conversion implicite dans les versions Unicode Delphi (2009 et au dessus).

+0

Pourriez-vous développer la violation des règles? La constante chaîne est compatible avec ** à la fois ** 'chaine' et' PChar', en interne ce n'est pas une vraie chaîne longue mais un tableau [0..X] de Char – OnTheFly

+0

À titre d'illustration, essayez de convertir la constante vraie en constante typée et quand Bar produira aussi une erreur de compilation. Plus probablement, * Delphi autorise la conversion implicite de PChar en chaîne *, et non l'inverse. – OnTheFly

+0

@user il suffit de lire les documents auxquels je suis lié dans mon commentaire à Q, tous expliqués ici –

1

Votre définition WCh = WideChar crée un alias de type pour WideChar - le type qu'ils ont identité - mais la définition Str = ^WCh ultérieure ne pas créer un alias de type pour PWideChar. Lorsque $T+ est en vigueur, ils sont compatibles et compatibles avec les affectations, mais ils ne sont pas suffisants dans cette situation. Ils sont encore des types distincts. La constante FOO est une chaîne . Le documentation for assignment compatibility indique à quels types un littéral de chaîne peut être affecté: "PAnsiChar, PWideChar, PChar ou n'importe quel type de chaîne." Str n'est pas un type de chaîne. C'est un type de pointeur, mais ce n'est pas PWideChar, malgré la similitude de leurs définitions.

Le type d'un littéral de chaîne s'adapte en fonction du contexte. Lorsque le compilateur a besoin d'un PWideChar, le littéral de chaîne est un PWideChar. Lorsque le compilateur a besoin d'un AnsiString, il s'agit d'un AnsiString. (Si le compilateur a besoin de ces deux types, le littéral sera stocké dans le programme dans les deux sens.) Les littéraux de chaîne ne sont pas assignables à votre type Str, donc, selon le message d'erreur, le compilateur choisit apparemment string comme type pour la chaîne littérale dans cette situation. Vous pouvez le transtyper en un autre type prédéfini, mais la meilleure solution serait d'éviter d'utiliser des classes de pointeur de caractères personnalisées.

+0

Dans le fait, '$ T +' a été la première chose que j'ai essayé, sans succès. Oui, j'ai finalement décidé de briser le sceau et d'ajouter de la duplication pour le type intrinsèque afin d'économiser la possibilité d'utiliser des littéraux et des constantes. – OnTheFly

Questions connexes