IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

Interface dont l'implémentation est réparti dans plusieurs classes [Langage/Algorithme]


Sujet :

C++Builder

  1. #1
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 713
    Points : 25 605
    Points
    25 605
    Par défaut Interface dont l'implémentation est réparti dans plusieurs classes
    Je suis en ce moment, en train de concevoir une DLL qui echange des objets avec son programme via des Interfaces, j'essaye de rester propres !
    Quand je parle d'interface, je parle de classe abstraite pure !
    Comme IFirstInterface

    Même en Delphi, je n'ai jamais trop poussé cela, Je fais des ActiveX habituellement !
    Là, c'est une DLL normale (pour faciliter son déploiement) avec une fonction exportée qui renvoi un pointeur vers une Interface racine puis à partir de ce moment, tout est objet\interface !

    J'aurais plusieurs DLL avec la même interface, l'implémentation changera en fonction du matériel piloté !
    J'ai commencé par une DLL de démonstration pour construire mon code !
    Je viens de séparer l'implémentation en deux classes, une première qui sera réutilisable (code commun que je peux factoriser), puis une seconde qui sera totalement spécifique

    Lors de la séparation, j'ai eu énormément de problème !
    Au début, lors de mes lectures sur l'utilisation d'interface (classe abstraite pure) en C++ Builder, j'ai compris avec ce sujet, que le support était partiel (surement lié au limite de l'héritage multiple et que la notion d'interface n'existe pas vraiment en C++, cela doit faire paniquer la VMT du TObject)
    Mon modèle tel que je le prévoyais n'aurait pas ce type d'architecture, je ne me suis pas inquiété !
    Cela cache en fait un conflit de la virtualisation des méthodes !
    Effectivement, si l'on prend l'exemple fourni, l'implémentation B de CFirstImplPhase2, n'est pas accessible, l'interface reste sans implementation, le compilateur laisse passer son rien voir !
    A l'execution, ça plante (pas une exception, ça plante bien sévère !)

    J'ai consulté le tutoriel
    Technique : Travailler avec les Interfaces en C++Builder Partie 1
    Cela ne me plaisait pas de partir sur IInterface !
    Est-ce obligatoire si l'objet est de type VCL ?
    Demain, si j'ai le courage, je passe mes interfaces C++ en IInterface, pour voir si mon bug d'implémentation dans deux classes héritées disparait !

    le bug que je souhaite corriger ne concerne que IFirstInterface, TFirstImpl et TFirstImplPhase2

    ISecondInterface et TSecondImpl, c'est un autre bug, surement lié au premier !

    le Tutoriel de DjmSoftware lui concerne TSecondBisImpl, ce qui fonctionne parfaitement !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    class IFirstInterface
    {
    public:
      virtual int A() = 0;
      virtual int B() = 0;
    };
     
    class ISecondInterface
    {
    public:
      virtual int C() = 0;
      virtual int D() = 0;
    };
     
    class CFirstImpl: public IFirstInterface
    {
    public:
      int A() {return -1;}
    };
     
    class CFirstImplPhase2: public CFirstImpl
    {
    public:
      int B() {return -22;}
    };
     
    class CSecondImpl: public CFirstImplPhase2, public ISecondInterface
    {
    public:
      int C() {return -333;}
      int D() {return -4444;}
    };
     
    class TFirstImpl: public TObject, public IFirstInterface
    {
    public:
      int A() {return -1;}
    };
     
    class TFirstImplPhase2: public TFirstImpl
    {
    public:
      int B() {return -22;}
    };
     
    class TSecondImpl: public TFirstImplPhase2, public ISecondInterface
    {
    public:
      int C() {return -333;}
      int D() {return -4444;}
    };
     
    class TSecondBisImpl: public IFirstInterface, public ISecondInterface
    {
    public:
      int A() {return -1;}
      int B() {return -22;}
      int C() {return -333;}
      int D() {return -4444;}
    };
     
     
     
    //---------------------------------------------------------------------------
    void __fastcall TLanguageBasicsForm::BtnInterfaceSeparateImplementsClick(TObject *Sender)
    {
      IFirstInterface* ObjC = new CFirstImplPhase2();
      OutputDebugString(Format("A : %d - B : %d", ARRAYOFCONST((ObjC->A(), ObjC->B()))).c_str());
      delete ObjC;
     
      IFirstInterface* ObjVCL = new TFirstImplPhase2();
      OutputDebugString(Format("A : %d", ARRAYOFCONST((ObjVCL->A()))).c_str());
      // B() plantera : Pure virtual function called
      // Le programme sera probablement totalement dans les choux (CTRL + F2 pour quitter)
      // OutputDebugString(Format("B : %d", ARRAYOFCONST((ObjVCL->B()))).c_str());
      delete (TFirstImplPhase2*)ObjVCL;
     
      CSecondImpl* ObjC2 = new CSecondImpl();
      IFirstInterface* IC = ObjC2;
      ISecondInterface* IC2 = ObjC2;
      OutputDebugString(Format("A : %d - B : %d - C : %d - D : %d", ARRAYOFCONST((IC->A(), IC->B(), IC2->C(), IC2->D()))).c_str());
      delete ObjC2;
     
      TSecondImpl* ObjVCL2 = new TSecondImpl();
      IFirstInterface* IVCL = ObjVCL2;
      ISecondInterface* IVCL2 = ObjVCL2;
      OutputDebugString(Format("A : %d", ARRAYOFCONST((IVCL->A()))).c_str());
      // OutputDebugString(Format("B : %d", ARRAYOFCONST((IVCL->B()))).c_str());
      OutputDebugString(Format("C : %d", ARRAYOFCONST((IVCL2->C()))).c_str());
      OutputDebugString(Format("D : %d", ARRAYOFCONST((IVCL2->D()))).c_str());
      delete ObjVCL2;
     
      TSecondBisImpl* ObjBis = new TSecondBisImpl();
      IFirstInterface* IBis = ObjBis;
      ISecondInterface* IBis2 = ObjBis;
      OutputDebugString(Format("A : %d - B : %d - C : %d - D : %d", ARRAYOFCONST((IBis->A(), IBis->B(), IBis2->C(), IBis2->D()))).c_str());
      delete ObjBis;
     
    }
    //---------------------------------------------------------------------------
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    A : -1 - B : -22
    A : -1
    // Ignore B
    A : -1 - B : -22 - C : -333 - D : -4444
    A : -1
    // Ignore B
    C : -1
    D : -22
    A : -1 - B : -22 - C : -333 - D : -4444

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 713
    Points : 25 605
    Points
    25 605
    Par défaut
    J'ai tenté les DelphiInterface avec mon code de démo !
    Ce n'est pas mieux !

    On voit avec CSecondImplReA, que la virtualisation est correcte et que l'on peut redéfinir une méthode d'interface lors d'un héritage
    Cela fonctionne aussi avec TSecondBisImplReAC car toutes les méthodes ont été implementés avec son ancêtre
    Ce qui ne fonctionne pas avec TSecondImplReC

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    class CFirstImpl: public IFirstInterface
    {
    public:
      int A() {return -1;}
    };
     
    class CFirstImplPhase2: public CFirstImpl
    {
    public:
      int B() {return -22;}
    };
     
    class CSecondImpl: public CFirstImplPhase2, public ISecondInterface
    {
    public:
      int C() {return -333;}
      int D() {return -4444;}
    };
     
    class CSecondImplReA: public CSecondImpl
    {
    public:
      int A() {return 11111;}
      int C() {return -333;}
      int D() {return -4444;}
    };
     
     
    class TFirstImpl: public TObject, public IFirstInterface
    {
    public:
      int A() {return -1;}
    };
     
    class TFirstImplPhase2: public TFirstImpl
    {
    public:
      int B() {return -22;}
    };
     
    class TSecondImpl: public TFirstImplPhase2, public ISecondInterface
    {
    public:
      int C() {return -333;}
      int D() {return -4444;}
    };
     
    class TSecondImplReC: public TSecondImpl
    {
    public:
      int C() {return 333333;}
    };
     
    class TSecondBisImpl: public IFirstInterface, public ISecondInterface
    {
    public:
      int A() {return -1;}
      int B() {return -22;}
      int C() {return -333;}
      int D() {return -4444;}
    };
     
    class TSecondBisImplReAC: public TSecondBisImpl
    {
    public:
      int A() {return 11111;}
      int C() {return 333333;}
    };
     
    class TFirstNoImpl: public TObject, public IFirstInterface
    {
    };
     
    class TFirstNoImplPhase2: public TFirstNoImpl
    {
    public:
      int A() {return -1;}
      int B() {return -22;}
    };
     
    __interface INTERFACE_UUID ("{F95FFF42-F65A-4C3E-99D0-468658ED5641}") IFirstDelphiInterface : public IInterface
    {
    public:
      virtual int __stdcall A() = 0;
      virtual int __stdcall B() = 0;
    };
    typedef System::DelphiInterface<IFirstDelphiInterface> _di_IFirstDelphiInterface; // DelphiInterface
     
    __interface INTERFACE_UUID ("{150AA670-7C9D-4CE7-BE7A-C5AC4CB31DEF}") ISecondDelphiInterface : public IInterface
    {
    public:
      virtual int __stdcall C() = 0;
      virtual int __stdcall D() = 0;
    };
    typedef System::DelphiInterface<ISecondDelphiInterface> _di_ISecondDelphiInterface; // DelphiInterface
     
     
    class TFirstDelphiImpl: public TInterfacedObject, public IFirstDelphiInterface
    {
    public:
      virtual int __stdcall A() {return -1;}
     
      virtual HRESULT __stdcall QueryInterface(const GUID& IID, void **Obj){return TInterfacedObject::QueryInterface(IID, (void *)Obj);}
      virtual ULONG __stdcall AddRef() {return TInterfacedObject::_AddRef();}
      virtual ULONG __stdcall Release() {return TInterfacedObject::_Release();}
    };
     
    class TFirstDelphiImplPhase2: public TFirstDelphiImpl
    {
    public:
      virtual int __stdcall A() {return -11111;}
      virtual int __stdcall B() {return -22;}
    };
     
     
    //---------------------------------------------------------------------------
    void __fastcall TLanguageBasicsForm::BtnInterfaceSeparateImplementsClick(TObject *Sender)
    {
      OutputDebugString("C++ Pur A et B");
      IFirstInterface* ObjC = new CFirstImplPhase2();
      OutputDebugString(Format("A : %d - B : %d", ARRAYOFCONST((ObjC->A(), ObjC->B()))).c_str());
      delete ObjC;
     
      OutputDebugString("TObject A pas B");
      IFirstInterface* ObjVCL = new TFirstImplPhase2();
      OutputDebugString(Format("A : %d", ARRAYOFCONST((ObjVCL->A()))).c_str());
      // B() plantera : Pure virtual function called
      // Le programme sera probablement totalement dans les choux (CTRL + F2 pour quitter)
      OutputDebugString("B plante !");
      // OutputDebugString(Format("B : %d", ARRAYOFCONST((ObjVCL->B()))).c_str());
      delete (TFirstImplPhase2*)ObjVCL;
     
      OutputDebugString("TObject ni A ni B");
      IFirstInterface* ObjVCLNo = new TFirstNoImplPhase2();
      // A() et B() planteront : Pure virtual function called
      // Le programme sera probablement totalement dans les choux (CTRL + F2 pour quitter)
      OutputDebugString("A plante !");
      // OutputDebugString(Format("A : %d", ARRAYOFCONST((ObjVCLNo->A()))).c_str());
      OutputDebugString("B plante !");
      // OutputDebugString(Format("B : %d", ARRAYOFCONST((ObjVCLNo->B()))).c_str());
      delete (TFirstNoImplPhase2*)ObjVCLNo;
     
      OutputDebugString("C++ Pur A, B, C et D");
      CSecondImpl* ObjC2 = new CSecondImpl();
      IFirstInterface* IC = ObjC2;
      ISecondInterface* IC2 = ObjC2;
      OutputDebugString(Format("A : %d - B : %d - C : %d - D : %d", ARRAYOFCONST((IC->A(), IC->B(), IC2->C(), IC2->D()))).c_str());
      delete ObjC2;
     
      OutputDebugString("C++ Pur Re A, B, C et D");
      CSecondImpl* ObjC2ReA = new CSecondImplReA();
      IFirstInterface* ICReA = ObjC2ReA;
      ISecondInterface* ICReA2 = ObjC2ReA;
      OutputDebugString(Format("A : %d - B : %d - C : %d - D : %d", ARRAYOFCONST((ICReA->A(), ICReA->B(), ICReA2->C(), ICReA2->D()))).c_str());
      delete ObjC2ReA;
     
      OutputDebugString("TObject Pur A pas B mais C et D");
      TSecondImpl* ObjVCL2 = new TSecondImpl();
      IFirstInterface* IVCL = ObjVCL2;
      ISecondInterface* IVCL2 = ObjVCL2;
      OutputDebugString(Format("A : %d", ARRAYOFCONST((IVCL->A()))).c_str());
      // OutputDebugString(Format("B : %d", ARRAYOFCONST((IVCL->B()))).c_str());
      OutputDebugString("B plante !");
      OutputDebugString(Format("C : %d", ARRAYOFCONST((IVCL2->C()))).c_str());
      OutputDebugString(Format("D : %d", ARRAYOFCONST((IVCL2->D()))).c_str());
      delete ObjVCL2;
     
      OutputDebugString("TObject Pur A pas B mais Re C et D");
      TSecondImpl* ObjVCLReC2 = new TSecondImplReC();
      IFirstInterface* IVCLReC = ObjVCLReC2;
      ISecondInterface* IVCLReC2 = ObjVCLReC2;
      OutputDebugString(Format("A : %d", ARRAYOFCONST((IVCLReC->A()))).c_str());
      // OutputDebugString(Format("B : %d", ARRAYOFCONST((IVCLReC->B()))).c_str());
      OutputDebugString("B plante !");
      OutputDebugString(Format("C : %d", ARRAYOFCONST((IVCLReC2->C()))).c_str());
      OutputDebugString(Format("D : %d", ARRAYOFCONST((IVCLReC2->D()))).c_str());
      delete ObjVCLReC2;
     
      OutputDebugString("TObject A, B, C et D");
      TSecondBisImpl* ObjBis = new TSecondBisImpl();
      IFirstInterface* IBis = ObjBis;
      ISecondInterface* IBis2 = ObjBis;
      OutputDebugString(Format("A : %d - B : %d - C : %d - D : %d", ARRAYOFCONST((IBis->A(), IBis->B(), IBis2->C(), IBis2->D()))).c_str());
      delete ObjBis;
     
      OutputDebugString("TObject Pur B et C ainsi que Re A et Re C");
      TSecondBisImpl* ObjBisReAC = new TSecondBisImplReAC();
      IFirstInterface* IBisReAC = ObjBisReAC;
      ISecondInterface* IBisReAC2 = ObjBisReAC;
      OutputDebugString(Format("A : %d - B : %d - C : %d - D : %d", ARRAYOFCONST((IBisReAC->A(), IBisReAC->B(), IBisReAC2->C(), IBisReAC2->D()))).c_str());
      delete ObjBisReAC;
     
      OutputDebugString("DelphiInterface A et B");
      TFirstDelphiImplPhase2* ObjVCLDIImpl = new TFirstDelphiImplPhase2();
      OutputDebugString(Format("Direct A : %d", ARRAYOFCONST((ObjVCLDIImpl->A()))).c_str());
      OutputDebugString(Format("Direct B : %d", ARRAYOFCONST((ObjVCLDIImpl->B()))).c_str());
     
      _di_IFirstDelphiInterface ObjVCLDI = ObjVCLDIImpl;
      OutputDebugString(Format("A : %d", ARRAYOFCONST((ObjVCLDI->A()))).c_str());
      OutputDebugString("B plante !");
      // OutputDebugString(Format("B : %d", ARRAYOFCONST((ObjVCLDI->B()))).c_str());
    }
    C++ Pur A et B
    A : -1 - B : -22
    TObject A pas B
    A : -1
    B plante !
    TObject ni A ni B
    A plante !
    B plante !
    C++ Pur A, B, C et D
    A : -1 - B : -22 - C : -333 - D : -4444
    C++ Pur Re A, B, C et D
    A : 11111 - B : -22 - C : -333 - D : -4444
    TObject Pur A pas B mais C et D
    A : -1
    B plante !
    C : -11 // Ici cela devrait être -333, C appele A ! la VMT est dans les choux !
    D : -22 // D appele B, alors que B était introuvable ?
    TObject Pur A pas B mais Re C et D
    A : -1
    B plante !
    C : -1 // Prévisible que la surcharge de C ne fonctionne pas !
    D : -22 // Toujours le B fantome
    TObject A, B, C et D
    A : -1 - B : -22 - C : -333 - D : -4444
    TObject Pur B et C ainsi que Re A et Re C
    A : 11111 - B : -22 - C : 333333 - D : -4444 // La VMT est OK Ici !
    DelphiInterface A et B
    Direct A : -11111
    Direct B : -22
    A : -1 // VMT dans les Choux !
    B plante !

    Pour le moment, j'ai donc implementé mes fonctions d'interface dans la classe commune avec un appel vers des fonctions abstraites !
    C'est comme si je forcais un nouveau contrat !
    Cela reste cohérent même si cela m'oblige à faire du code en plus !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class TFirstImplViaAbstract: public TObject, public IFirstInterface
    {
    protected:
      virtual int _B() = 0;
     
    public:
      int A() {return -1;} // Code Commun
      int B() {return _B();}
    };
     
    class TFirstImplFinal: public TFirstImplViaAbstract
    {
    public:
      int _B() {return -22;} // Code Spécifique
    };
    Peut-être etudier un delegates ?
    Je sais le faire en Delphi mais pas en C++ !
    ça ira pour le moment !

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 713
    Points : 25 605
    Points
    25 605
    Par défaut
    J'ai viens de m'apercevoir que je n'avais pas spécifier la Version de mon C++Builder
    Il s'agit de la Version 2007
    Est-ce qu'il y aurait une ame généreuse (ou plusieurs) pour m'indiquer si dans les versions 2009, 2010 ou XE
    on observe le même comportement ?

    Voici, un code plus simple a tester !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    //---------------------------------------------------------------------------
    class IFirstInterface
    {
    public:
      virtual int A() = 0;
      virtual int B() = 0;
    };
     
    class ISecondInterface
    {
    public:
      virtual int C() = 0;
      virtual int D() = 0;
    };
     
    class TFirstAndSecondImpl: public TObject, public IFirstInterface, public ISecondInterface
    {
    public:
      int A() {return -1;}
      int B() {return -22;}
      int C() {return -333;}
      int D() {return -4444;}
    };
     
    //---------------------------------------------------------------------------
    class IFirstChainedInterface
    {
    public:
      virtual int A() = 0;
      virtual int B() = 0;
    };
     
    class ISecondChainedInterface : public IFirstChainedInterface
    {
    public:
      virtual int C() = 0;
      virtual int D() = 0;
    };
     
    class TGoodChainedImpl: public TObject, public ISecondChainedInterface
    {
    public:
      int A() {return -1;}
      int B() {return -2;}
      int C() {return -3;}
      int D() {return -4;}
    };
     
    //---------------------------------------------------------------------------
    class TSeparateImplA: public TObject, public IFirstInterface
    {
    public:
      int A() {return -1;}
    };
     
    class TSeparateImplAB: public TSeparateImplA
    {
    public:
      int B() {return -2;}
    };
     
    class TSeparateImplABCD: public TSeparateImplAB, public ISecondInterface
    {
    public:
      int C() {return -3;}
      int D() {return -4;}
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    //---------------------------------------------------------------------------
    void __fastcall TInterfaceAbstractionForm::BtnGoodIntfAndImplHierarchyClick(
          TObject *Sender)
    {
      TFirstAndSecondImpl* ObjTogether = new TFirstAndSecondImpl();
     
      IFirstInterface* intfFirst = ObjTogether;
      ISecondInterface* intfSecond = ObjTogether;
     
      MemoTrace->Lines->Add("Together");
      MemoTrace->Lines->Add(Format("A : %d == %d ?", ARRAYOFCONST((ObjTogether->A(), intfFirst->A()))));
      MemoTrace->Lines->Add(Format("B : %d == %d ?", ARRAYOFCONST((ObjTogether->B(), intfFirst->B()))));
      MemoTrace->Lines->Add(Format("C : %d == %d ?", ARRAYOFCONST((ObjTogether->C(), intfSecond->C()))));
      MemoTrace->Lines->Add(Format("D : %d == %d ?", ARRAYOFCONST((ObjTogether->D(), intfSecond->D()))));
      MemoTrace->Lines->Add("");
     
      delete ObjTogether;
     
      // ----
     
      TSeparateImplABCD* ObjSeparate = new TSeparateImplABCD();
     
      intfFirst = ObjSeparate;
      intfSecond = ObjSeparate;
     
      MemoTrace->Lines->Add("Separate");
      MemoTrace->Lines->Add(Format("A : %d == %d ?", ARRAYOFCONST((ObjSeparate->A(), intfFirst->A()))));
     
      // Mon BCB2007 est en version 593, une version 2009 ou plus, devrait avoir un plus grand chiffre !
      #if (__BCPLUSPLUS__ > 0x593)
      MemoTrace->Lines->Add(Format("B : %d == %d ?", ARRAYOFCONST((ObjSeparate->B(), intfFirst->B()))));
      #else
      MemoTrace->Lines->Add("B Ignoré en 2007");
      #endif
      MemoTrace->Lines->Add(Format("C : %d == %d ?", ARRAYOFCONST((ObjSeparate->C(), intfSecond->C()))));
      MemoTrace->Lines->Add(Format("D : %d == %d ?", ARRAYOFCONST((ObjSeparate->D(), intfSecond->D()))));
      MemoTrace->Lines->Add("");
     
      delete ObjSeparate;
      // ----
     
      TGoodChainedImpl* ObjChained = new TGoodChainedImpl();
     
      IFirstChainedInterface* intfChainedFirst = ObjChained;
      ISecondChainedInterface* intfChainedSecond = ObjChained;
     
      MemoTrace->Lines->Add("Chained");
      MemoTrace->Lines->Add(Format("A : %d == %d ?", ARRAYOFCONST((ObjChained->A(), intfChainedFirst->A()))));
      MemoTrace->Lines->Add(Format("B : %d == %d ?", ARRAYOFCONST((ObjChained->B(), intfChainedFirst->B()))));
      MemoTrace->Lines->Add(Format("C : %d == %d ?", ARRAYOFCONST((ObjChained->C(), intfChainedSecond->C()))));
      MemoTrace->Lines->Add(Format("D : %d == %d ?", ARRAYOFCONST((ObjChained->D(), intfChainedSecond->D()))));
      MemoTrace->Lines->Add("");
     
      delete ObjChained;
    }
    //---------------------------------------------------------------------------

    ce que j'obtiens

    Code note : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Together
    A : -1 == -1 ?
    B : -22 == -22 ?
    C : -333 == -333 ?
    D : -4444 == -4444 ?
    
    Separate
    A : -1 == -1 ?
    B Ignoré en 2007
    C : -3 == -1 ?
    D : -4 == -2 ?
    
    Chained
    A : -1 == -1 ?
    B : -2 == -2 ?
    C : -3 == -3 ?
    D : -4 == -4 ?

    ce qu'il faudrait obtenir

    Code note : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    Together
    A : -1 == -1 ?
    B : -22 == -22 ?
    C : -333 == -333 ?
    D : -4444 == -4444 ?
    
    Separate
    A : -1 == -1 ?
    B : -2 == -2 ?
    C : -3 == -3 ?
    D : -4 == -4 ?
    
    Chained
    A : -1 == -1 ?
    B : -2 == -2 ?
    C : -3 == -3 ?
    D : -4 == -4 ?

  4. #4
    Membre émérite Avatar de Godzestla
    Homme Profil pro
    Chercheur de bonheur
    Inscrit en
    Août 2007
    Messages
    2 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de bonheur
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2007
    Messages : 2 392
    Points : 2 985
    Points
    2 985
    Par défaut
    Bonjour,

    si tu expliques à ma petite personne aux connaissances C++ très limitées exactement la procédure à suivre, je ferai le test avec grand plaisir sous C++Builder XE.

    Le plus simple pour moi est que tu me passes la(les) source(s) simple(s) à tester.

  5. #5
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2005
    Messages
    401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 401
    Points : 578
    Points
    578
    Par défaut
    BCB2010 (__BCPLUSPLUS__ == 0x0621)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    Together
    A : -1 == -1 ?
    B : -22 == -22 ?
    C : -333 == -333 ?
    D : -4444 == -4444 ?
     
    Separate
    A : -1 == -1 ?
    B Ignoré en 2010 (sinon pure virtual function called)
    C : -3 == -1 ?
    D : -4 == -2 ?
     
    Chained
    A : -1 == -1 ?
    B : -2 == -2 ?
    C : -3 == -3 ?
    D : -4 == -4 ?
    (Si personne ne se dévoue pour XE, j'essaierai ce soir...)

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 713
    Points : 25 605
    Points
    25 605
    Par défaut
    Merci à vous Deux !

    @Godzestla, pour tester, tu créés un nouveau projet (si tu as déjà un projet à bordel, tu peux l'utiliser)
    Dans une fenêtre, tu ajoutes un bouton, tu peux l'appeler BtnGoodIntfAndImplHierarchy, tu lui crées un Gestionnaire d’Événement OnClick où tu colles le code de TInterfaceAbstractionForm::BtnGoodIntfAndImplHierarchyClick

    tu recopie au dessus de ce OnClick (n'importe où en fait tant que c'est accesible) le code des classes IFirstInterface, ISecondInterface, TFirstAndSecondImpl, IFirstChainedInterface, ISecondChainedInterface, TGoodChainedImpl, TSeparateImplA, TSeparateImplAB, TSeparateImplABCD

    Tu exécutes en débug, ne soit pas surpris d'avoir une erreur, qui pourrait nécessiter d'arrêter le debug par CTRL+F2

    Pour les sources, c'est dans un projet à bordel, chez moi, avec plein d'autres essais sur le langage C++ dans BCB, du Delphi dans BCB et de la VCL ! Cela ne serait pas un cadeau de te le passer

    @totoche76, en BCB 2010 (621), le bug persistait encore !
    Oh !

    Suspens pour XE !

  7. #7
    Membre émérite Avatar de Godzestla
    Homme Profil pro
    Chercheur de bonheur
    Inscrit en
    Août 2007
    Messages
    2 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de bonheur
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2007
    Messages : 2 392
    Points : 2 985
    Points
    2 985
    Par défaut
    Voilà,

    j'exécute en debug et je calle à la compile (1 erreur apparament) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      MemoTrace->Lines->Add("Together");
      MemoTrace->Lines->Add(Format("A : %d == %d ?", ARRAYOFCONST((ObjTogether->A(), intfFirst->A()))));
      MemoTrace->Lines->Add(Format("B : %d == %d ?", ARRAYOFCONST((ObjTogether->B(), intfFirst->B()))));
      MemoTrace->Lines->Add(Format("C : %d == %d ?", ARRAYOFCONST((ObjTogether->C(), intfSecond->C()))));
      MemoTrace->Lines->Add(Format("D : %d == %d ?", ARRAYOFCONST((ObjTogether->D(), intfSecond->D()))));
      MemoTrace->Lines->Add("");
    avec
    [BCC32 Erreur] Unit1.cpp(91): E2451 Symbole 'MemoTrace' non défini
    je corrige comment.

  8. #8
    Membre émérite Avatar de Godzestla
    Homme Profil pro
    Chercheur de bonheur
    Inscrit en
    Août 2007
    Messages
    2 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de bonheur
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2007
    Messages : 2 392
    Points : 2 985
    Points
    2 985
    Par défaut
    J'ai trouvé.....ouf.... Tu me fais souffrir moi pauvre débutant.

    J'ai créé le champ Mémo ad-hoc.

    Voici le résultat.:

    pas de besoin de préciser que je n'ai rien compris ! mais cela à l'air d'être débuggé, non ?

    MemoTrace
    Together
    A : -1 == -1 ?
    B : -22 == -22 ?
    C : -333 == -333 ?
    D : -4444 == -4444 ?

    Separate
    A : -1 == -1 ?
    B : -2 == -2 ?
    C : -3 == -3 ?
    D : -4 == -4 ?

    Chained
    A : -1 == -1 ?
    B : -2 == -2 ?
    C : -3 == -3 ?
    D : -4 == -4 ?

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 713
    Points : 25 605
    Points
    25 605
    Par défaut
    Merci Godzestla !
    Correction en XE ! C'est bon à savoir !

    Bon, je dois limiter mon architecture objetà cause de ce bug pour mes interfaces partagées entre EXE, DCOM et DLL !
    Là je commence mes 1ère DelphiInterface pour la gestion du Support (GUID) que ne propose pas le pseudo interface C++ (classe abstraite pure)

    On a déjà déjà commencé une étude du passage en XE, mais la Trial a expiré, on attend XE2 pour y passer (surtout pour voir la nouvelle VCL Cross-platform même si encore sous win32)

    J'aimerais bien t'expliquer, je vais tenter !

    IFirstInterface et ISecondInterface sont deux classe abstraite pure, cela oblige d'implémenter les méthodes, cela permet de passer un "contrat", ainsi peu importe l'objet, tu utilises l'interface sans avoir besoin comment elle fonctionne, ton seul soucis c'est de connaitre les Entrées \ Sorties de la méthode

    Il semble que lors des affectations d'objets implémentant une interface, il y a des soucis

    les méthodes virtuelles sont spécifiques à chaque instance, c'est la VMT, cela permet le polymorphisme de la POO

    On peut ainsi, créer une Interface BoiteDeVitesse et une fonction abstraite ChangerDeVitesse(+1 ou -1), créer une classe BoiteManuelle (et ses petits BoiteManuelle4Rapport, 5Rapport, 6Rapport) et une classe BoiteAuto héritant de BoiteDeVitesse , chacune implémentant ChangerDeVitesse.
    - BoiteManuelle6Rapport propose le Point Mort jusqu'à la 6 eme vitesse et la Marche Arrière
    - BoiteAuto propose le Point, Vitesse Normal, Vitesse de Dépassement et la Marche Arrière

    Dans le code on manipule que BoiteDeVitesse sans savoir ce qu'il y a derrière !
    ChangerDeVitesse indique si l'on a pu changer
    L'exemple est un peu con mais c'est l'idée

    TSeparateImplA fourni A
    TSeparateImplAB fourni B
    Si l'on instancie un objet TSeparateImplAB et que l'on affecte à un IFirstInterface
    on devrait pouvoir appeler A et B, mais avant la correction, il semble qu'il fasse mal le cast, il prend la VMT qui implemente IFirstInterface donc TSeparateImplA sans voir qu'il y a une partie dans TSeparateImplAB
    Du coup, B ne peut pas être appelé !

    TSeparateImplABCD fourni A, B, C et D (par héritage et par implémentation directe)
    Idem, il semble perdu lorsqu'il faut affecter un ISecondInterface
    Il prend la VMT de TSeparateImplAB au lieu de TSeparateImplABCD, il se mélange les pinceaux !



    En peut penser que TInterfacedObject n'implémente pas directement IInterface (ou IUnknown) tout simplement parce que le compilateur ne le gérait pas, la necessité d'implémenter QueryInterface, AddRef et Release comme expliqué par DjmSoftware dans son tutoriel Travailler avec les Interfaces en C++Builder Partie 1 doit être un subterfuge pour que cela fonctionne le temps de corriger cette histoire !
    Vous noterez l'étrange répétition de QueryInterface, AddRef et Release dans mes classes malgré l'héritage, tout simplement parce qu'il semble les réclamés car il y a de l'héritage multiple de IInterface (ce qui ne se produit pas du tout en Delphi)

    Avec les Delphi Interfarce, la méthode Supports permet de récupérer la Bonne VMT en théorie car en pratique, j'ai juste droits à des violations d'accès !

    E2014 Membre ambigu : 'Interface::Supports<T>' et 'Interface::Supports<T>'
    Cela m'oblige à spécifier le domaine pour son appel
    Alors si pour TFirstAndSecondImplDelphiIntf, il n'y aucun soucis, il compile, il appelle Supports avec success et trouve l'interface
    Pour les deux autres variantes décomposées, cela fait une belle violation d'accès !

    J'ai pu réinstaller une XE entre-temps, j'ai fait le test, et Oh !
    Tout Fonctionne !

    Félicitations à la Team Embarcadero qui nous corrige un bug qui date des fondements de la gestion des Interfaces en C++ sur des Objets dit VCL car héritant de TObject


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //---------------------------------------------------------------------------
    __interface INTERFACE_UUID ("{F95FFF42-F65A-4C3E-99D0-468658ED5641}") IFirstDelphiInterface : public IInterface
    {
    public:
      virtual int __stdcall A() = 0;
      virtual int __stdcall B() = 0;
    };
    typedef System::DelphiInterface<IFirstDelphiInterface> _di_FirstDelphiInterface; // DelphiInterface
     
    __interface INTERFACE_UUID ("{150AA670-7C9D-4CE7-BE7A-C5AC4CB31DEF}") ISecondDelphiInterface : public IInterface
    {
    public:
      virtual int __stdcall C() = 0;
      virtual int __stdcall D() = 0;
    };
    typedef System::DelphiInterface<ISecondDelphiInterface> _di_SecondDelphiInterface; // DelphiInterface

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    //---------------------------------------------------------------------------
    class TStepByStepImplDelphiIntfAB: public TInterfacedObject, public IFirstDelphiInterface
    {
    public:
      int __stdcall A() {return -1;}
      int __stdcall B() {return -2;}
     
      virtual HRESULT __stdcall QueryInterface(const GUID& IID, void **Obj){return TInterfacedObject::QueryInterface(IID, Obj);}
      virtual ULONG __stdcall AddRef() {return TInterfacedObject::_AddRef();}
      virtual ULONG __stdcall Release() {return TInterfacedObject::_Release();}
    };
     
    class TStepByStepImplDelphiIntfABCD: public TStepByStepImplDelphiIntfAB, public ISecondDelphiInterface
    {
    public:
      int __stdcall C() {return -3;}
      int __stdcall D() {return -4;}
     
      virtual HRESULT __stdcall QueryInterface(const GUID& IID, void **Obj){return TInterfacedObject::QueryInterface(IID, Obj);}
      virtual ULONG __stdcall AddRef() {return TInterfacedObject::_AddRef();}
      virtual ULONG __stdcall Release() {return TInterfacedObject::_Release();}
    };
     
    //---------------------------------------------------------------------------
    class TSeparateImplDelphiIntfA: public TInterfacedObject, public IFirstDelphiInterface
    {
    public:
      int __stdcall A() {return -1;}
     
      virtual HRESULT __stdcall QueryInterface(const GUID& IID, void **Obj){return TInterfacedObject::QueryInterface(IID, Obj);}
      virtual ULONG __stdcall AddRef() {return TInterfacedObject::_AddRef();}
      virtual ULONG __stdcall Release() {return TInterfacedObject::_Release();}
    };
     
    class TSeparateImplDelphiIntfAB: public TSeparateImplDelphiIntfA
    {
    public:
      int __stdcall B() {return -2;}
    };
     
    class TSeparateImplDelphiIntfABCD: public TSeparateImplDelphiIntfAB, public ISecondDelphiInterface
    {
    public:
      int __stdcall C() {return -3;}
      int __stdcall D() {return -4;}
     
      virtual HRESULT __stdcall QueryInterface(const GUID& IID, void **Obj){return TInterfacedObject::QueryInterface(IID, Obj);}
      virtual ULONG __stdcall AddRef() {return TInterfacedObject::_AddRef();}
      virtual ULONG __stdcall Release() {return TInterfacedObject::_Release();}
    };
     
    //---------------------------------------------------------------------------
    class TFirstAndSecondImplDelphiIntf: public TInterfacedObject, public IFirstDelphiInterface, public ISecondDelphiInterface
    {
    public:
      int __stdcall A() {return -1;}
      int __stdcall B() {return -22;}
      int __stdcall C() {return -333;}
      int __stdcall D() {return -4444;}
     
      virtual HRESULT __stdcall QueryInterface(const GUID& IID, void **Obj){return TInterfacedObject::QueryInterface(IID, Obj);}
      virtual ULONG __stdcall AddRef() {return TInterfacedObject::_AddRef();}
      virtual ULONG __stdcall Release() {return TInterfacedObject::_Release();}
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    //---------------------------------------------------------------------------
    void __fastcall TInterfaceAbstractionForm::BtnDelphiIntfAndImplHierarchyClick(
          TObject *Sender)
    {
      _di_FirstDelphiInterface intfFirst;
      _di_SecondDelphiInterface intfSecond;
     
      bool FlagFirst;
      bool FlagSecond;
     
      TFirstAndSecondImplDelphiIntf* ObjTogether = new TFirstAndSecondImplDelphiIntf();
     
      FlagFirst = ObjTogether->IFirstDelphiInterface::Supports(intfFirst);
      FlagSecond = ObjTogether->ISecondDelphiInterface::Supports(intfSecond); // La Seule fois où ça passe !
      MemoTrace->Lines->Add("Together");
      if (FlagFirst)
      {
        MemoTrace->Lines->Add(Format("A : %d == %d ?", ARRAYOFCONST((ObjTogether->A(), intfFirst->A()))));
        MemoTrace->Lines->Add(Format("B : %d == %d ?", ARRAYOFCONST((ObjTogether->B(), intfFirst->B()))));
      }
      if (FlagSecond)
      {
        MemoTrace->Lines->Add(Format("C : %d == %d ?", ARRAYOFCONST((ObjTogether->C(), intfSecond->C()))));
        MemoTrace->Lines->Add(Format("D : %d == %d ?", ARRAYOFCONST((ObjTogether->D(), intfSecond->D()))));
      }
      MemoTrace->Lines->Add("");
     
      // ----
     
      TSeparateImplDelphiIntfABCD* ObjSeparate = new TSeparateImplDelphiIntfABCD();
     
      FlagFirst = ObjSeparate->IFirstDelphiInterface::Supports(intfFirst);
      #if (__BCPLUSPLUS__ > 0x593)
      FlagSecond = ObjSeparate->ISecondDelphiInterface::Supports(intfSecond); // Belle VA sous 2007
      #else
      FlagSecond = ObjSeparate->IFirstDelphiInterface::Supports(intfSecond); // Compile, execution sans VA mais renvoie false ! Evidemment !
      #endif
     
      MemoTrace->Lines->Add("Separate");
      if (FlagFirst)
      {
        MemoTrace->Lines->Add(Format("A : %d == %d ?", ARRAYOFCONST((ObjSeparate->A(), intfFirst->A()))));
     
        // Mon BCB2007 est en version 593, une version 2009 ou plus, devrait avoir un plus grand chiffre !
        #if (__BCPLUSPLUS__ > 0x593)
        MemoTrace->Lines->Add(Format("B : %d == %d ?", ARRAYOFCONST((ObjSeparate->B(), intfFirst->B()))));
        #else
        MemoTrace->Lines->Add("B Ignoré en 2007");
        #endif
      }
      if (FlagSecond)
      {
        MemoTrace->Lines->Add(Format("C : %d == %d ?", ARRAYOFCONST((ObjSeparate->C(), intfSecond->C()))));
        MemoTrace->Lines->Add(Format("D : %d == %d ?", ARRAYOFCONST((ObjSeparate->D(), intfSecond->D()))));
      }
      MemoTrace->Lines->Add("");
     
      // ----
     
      TStepByStepImplDelphiIntfABCD* ObjStepByStep = new TStepByStepImplDelphiIntfABCD();
     
      FlagFirst = ObjStepByStep->IFirstDelphiInterface::Supports(intfFirst);
      #if (__BCPLUSPLUS__ > 0x593)
      FlagSecond = ObjStepByStep->ISecondDelphiInterface::Supports(intfSecond); // Belle VA sous 2007
      #else
      FlagSecond = ObjStepByStep->IFirstDelphiInterface::Supports(intfSecond); // Compile, execution sans VA mais renvoie false ! Evidemment !
      #endif
     
      MemoTrace->Lines->Add("StepByStep");
      if (FlagFirst)
      {
        MemoTrace->Lines->Add(Format("A : %d == %d ?", ARRAYOFCONST((ObjStepByStep->A(), intfFirst->A()))));
        MemoTrace->Lines->Add(Format("B : %d == %d ?", ARRAYOFCONST((ObjStepByStep->B(), intfFirst->B()))));
      }
      if (FlagSecond)
      {
        MemoTrace->Lines->Add(Format("C : %d == %d ?", ARRAYOFCONST((ObjStepByStep->C(), intfSecond->C()))));
        MemoTrace->Lines->Add(Format("D : %d == %d ?", ARRAYOFCONST((ObjStepByStep->D(), intfSecond->D()))));
      }
      MemoTrace->Lines->Add("");
     
      // ----
     
    }
    //---------------------------------------------------------------------------

  10. #10
    Membre émérite Avatar de Godzestla
    Homme Profil pro
    Chercheur de bonheur
    Inscrit en
    Août 2007
    Messages
    2 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de bonheur
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2007
    Messages : 2 392
    Points : 2 985
    Points
    2 985
    Par défaut
    Bonjour,

    j'ai bien lu tes explications à plusieurs reprises.
    Mais cela dépasse de très loin mes connaissances, et.... je n'ai rien compris. .

    merci tout de même pour le temps que tu as consacré à expliquer.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL] Problème pour afficher une image dont le chemin est stocké dans la bdd
    Par cel.Saint-Louis dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 12/11/2007, 09h49
  2. Réponses: 4
    Dernier message: 22/02/2007, 11h01
  3. [XSLT] Attribut dont le nom est stocké dans une variable ?
    Par Xfennec dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 15/03/2006, 12h20
  4. Réponses: 7
    Dernier message: 25/10/2005, 16h19
  5. [Reflection] Executer une fonction dont le nom est contenu dans un String
    Par christobal dans le forum API standards et tierces
    Réponses: 8
    Dernier message: 05/07/2004, 16h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo