2009-04-21 6 views
13

J'utilise l'opérateur surcharge pour les enregistrements en Delphi 2006. (S'il vous plaît ne pas répondre à cette question en me disant de ne pas.)Comment définir des opérateurs de conversion implicites pour des enregistrements mutuellement dépendants?

J'ai deux types d'enregistrements avec l'opérateur implicite surchargé. Ils sont tous les deux seulement dans la mise en œuvre du module, non exposés à travers l'interface.

Mon problème est, maintenant qu'ils sont mutuellement dépendants, je ne sais pas comment transmettre le second type au compilateur. Je sais comment faire cela avec des fonctions, des procédures et des classes, mais pas avec des enregistrements.

Voici un exemple simplifié de ce que je suis en train de faire:

implementation 

type 
    TMyRec1 = record 
    Field1 : Integer; 
    class operator Implicit(a: TMyRec2): TMyRec1; // <---- Undeclared Identifier here. 
    end; 

    TMyRec2 = record 
    Field2: Integer; 
    class operator Implicit(a: TMyRec1): TMyRec2; 
    end; 

class operator TMyRec1.Implicit(a:TMyRec2): TMyRec1; 
begin 
    Result.Field1 := a.Field2; 
end; 

class operator TMyRec2.Implicit(a:TMyRec2): TMyRec2; 
begin 
    Result.Field2 := a.Field1; 
end; 
+0

Si chaque type peut implicitement se convertir à l'autre type, vous pourriez vouloir reconsidérer si vous avez vraiment besoin de deux types distincts . –

+0

@Rob: C'est tout à fait possible. J'ai récemment rencontré cette même situation lorsque j'avais deux types de vecteurs différents, l'un constitué d'entiers et l'autre de flotteurs. Vous avez besoin des deux types pour des choses différentes, mais vous voulez que les deux soient mutuellement compatibles. La solution était essentiellement celle que vous avez publiée. –

+1

Les types ne sont nulle part aussi simples. L'un porte des statistiques sommaires sur l'autre. Ils sont utilisés pour regrouper logiquement les données qui sont transmises ailleurs. [reposted pour essayer de se débarrasser de l'espace blanc en excès.] –

Répondre

13

Vous ne pouvez pas avoir des déclarations prévisionnelles pour les types d'enregistrement. Définir les Implicit opérateurs dans le second type:

type 
    TMyRec1 = record 
    Field1 : Integer; 
    end; 

    TMyRec2 = record 
    Field2: Integer; 
    class operator Implicit(a: TMyRec2): TMyRec1; 
    class operator Implicit(a: TMyRec1): TMyRec2; 
    end; 

Je cite the help:

Les conversions implicites doivent être fournies que lorsque cela est absolument nécessaire, et réflexivité doit être évité. Il est préférable de laisser le type B se convertir implicitement en type A, et laisser le type A ignorer le type B (ou vice versa).

+0

Merci Rob. Solution évidente je suppose, mais ils sont tous quand vous le savez. Pourquoi dites-vous que la conversion implicite devrait être évitée? –

+0

* Je * n'ai pas dit qu'il devrait être évité. Je citais la documentation. Mais puisque vous avez demandé, la conversion implicite peut rendre le code plus difficile à lire; il est plus difficile de remarquer une conversion qui se produit quand il n'y a rien qui attire l'attention. J'utiliserais simplement une fonction ordinaire pour convertir d'un type à un autre. Ou vous pouvez utiliser l'opérateur Explicit à la place. –

+0

Merci. Je devrais lire plus attentivement. J'ai parcouru le morceau qui dit 'citer de l'aide'.Oui, je suis un peu nerveux à propos de la surcharge de l'opérateur et des conversions implicites, mais en essayant dans un petit cas pour voir comment ça se passe. Curieusement, certains problèmes de performance majeurs que j'ai dû corriger ont été avec la conversion implicite de types numériques et de chaînes standard. –

3

Vous pouvez pouvez faire cela avec des aides d'enregistrement. Voici ce que j'ai récemment fait pour contourner l'impossibilité d'avoir une déclaration d'enregistrement forward record.

Il utilise la construction record helper qui, comme implicit type casts, présente également des inconvénients.
Le plus important étant que seul le record helper le plus proche pour un type particulier record s'appliquera.

type 
    TIpv4Address = record 
    strict private 
    FAddress: TIpv4Quad; 
    FMask: TIpv4Quad; 
    private 
    class function CreateInternal(const IP_ADDR_STRING: _IP_ADDR_STRING): TIpv4Address; static; 
    public 
    class function Create(const IP_ADDR_STRING: _IP_ADDR_STRING): TIpv4Address; static; 
    class function Count(const IP_ADDR_STRING: _IP_ADDR_STRING): Integer; static; 
    property Address: TIpv4Quad read FAddress; 
    property Mask: TIpv4Quad read FMask; 
    end; 

    TIpv4AddressList = array of TIpv4Address; 

    TIpv4AddressHelper = record helper for TIpv4Address 
    class function CreateList(const IP_ADDR_STRING: _IP_ADDR_STRING): TIpv4AddressList; static; 
    end; 

Vous l'utiliser comme ceci:

function TAdapterInfo.GetIpAddressList: TIpv4AddressList; 
begin 
    Result := TIpv4Address.CreateList(AdapterInfos.IP_ADAPTER_INFO[Index].IpAddressList); 
end; 

--jeroen

+0

Merci. Je regarderai. Je n'étais pas au courant de la construction 'record helper'. –

+1

Il a été introduit silencieusement dans Delphi 2006 pour Win32 et .NET. Les assistants de classe ont été introduits dans Delphi 2005 pour Win32 et la première version Delphi .NET (un numéro de version dont beaucoup de gens ne veulent pas qu'on leur rappelle). –

Questions connexes