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 :

Borland C++ Builder : Portée du this, fonctions dans un formulaire, et espions [Débutant]


Sujet :

C++Builder

  1. #1
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juillet 2011
    Messages : 20
    Par défaut Borland C++ Builder : Portée du this, fonctions dans un formulaire, et espions
    Bonjour à tous, et à toutes,

    Arrivant de .Net C# je démarre un projet en Borland C++ Builder (Embarcadero RAD Studio XE v2010), et bien entendu c’est comme si je devais tout réapprendre à comparer à .NET C#.

    J’ai trois questions toutes connes, et malheureusement je ne trouve pas de réponses dans le forum, d’où ce sujet.


    Mes deux premières questions sont extrêmement liées, donc je vais essayer de faire simple pour vous expliquer mon problème.

    Je créer dynamiquement un formulaire via un new dans une fenêtre SDI de base avec un menu test perso :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void __fastcall TSDIAppForm::Action_MenuTest_ContexteExecute(TObject *Sender)
    {
    	TFormContexte* l_ptTFormContexte = new TFormContexte(NULL);
    	l_ptTFormContexte->ShowModal();
    	delete(l_ptTFormContexte);
    }
    Dans ce formulaire TFormContexte j’ai un StringGrid StringGridCoef.
    Sur le show de mon formulaire, je veux lancer une fonction qui va initialiser mon StringGrid.
    J’ai donc fait ceci :

    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
    //------------------------------------------------------
     
    #include <vcl.h>
    #pragma hdrstop
     
    #include "FrmContexte.h"
    //-------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TFormContexte *FormContexte;
     
    void FctInitialisation(){
    	//1er TEST qui ne marche pas??? ---------------------------------
    	unsigned short l_usNbLigne= -1;
     
    	FormContexte ->StringGridCoef->RowCount = 10;
     
    	l_usNbLigne = FormContexte ->StringGridCoef->RowCount;
    }
     
    void __fastcall TFormContexte::FormShow(TObject *Sender)
    {
    	FctInitialisation() ;
     
    	//2nd TEST qui marche -----------------------------------------
    	unsigned short l_usNbLigne= -1;
     
    	this ->StringGridCoef->RowCount = 10;
     
    	l_usNbLigne = this ->StringGridCoef->RowCount;
    }
    La ou je commence à avoir des trucs étranges voir incompréhensible c’est dans ma fonction FctInitialisation.

    Déjà je ne peux pas utiliser le this pour pointer sur les éléments de mon formulaire ???
    Cela me donne une erreur : [BCC32 Erreur] FrmContexte_CoefFiltrScan.cpp(75): E2297 'this' ne peut être utilisé que dans une fonction membre

    Bon soit je vais faire sans…
    Donc je pointe sur mon formulaire, et sur un élément de mon formulaire :
    FormContexte ->StringGridCoef->RowCount = 10;

    A priori le code est bien pris en compte… Sauf qu’à l’affichage rien ne se passe????
    Si je vérifie en debug sur le bouton OK de mon formulaire, la valeur de FormContexte ->StringGridCoef->RowCount, il m’annonce bien 10…

    Bon, ça sent à plein nez la mauvaise instance du formulaire!

    Comme par hasard si je mets presque le même code dans le show du formulaire, miracle tout marche!

    Donc, comment augmenter la portée du this dans une fonction, ou comment atteindre la bonne instance de mon formulaire dans une fonction?



    Ensuite j’ai encore des choses plus bizarres dans ma fonction :
    Dans ma fonction FctInitialisation, j’ai déclaré la variable l_usNbLigne que j’ai initialisée à -1.
    Ensuite dans la suite de la fonction je l’affecte à la valeur du nombre de lignes de mon StringGrid.

    Alors là c’est trop fort, en debug je m’aperçois que ma variable est bien déclarée, mais que mon initialisation à -1 n’est pas prise en compte ???
    Pire mon affectation elle aussi n’est pas prise en compte ???

    Alors là je reste con de chez con! Je n’y comprends rien de rien… Ça me parait tellement évident que je suis sur que je ne fais pas ce qu’il faut, et que quelqu’un d’un brin expérimenté avec Borland C++ Builder va de suite pourvoir m’aider à coup sûr…



    Ma dernière question est aussi toute conne :
    Est-ce qu’il existe dans Borland C++ Builder une vraie fenêtre d’espion comme dans Visual Studio, afin de pouvoir espionner les variables que j’aurais glissées dedans ???

    Merci d’avance à tous et à toutes pour votre aide

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 017
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 017
    Par défaut
    Citation Envoyé par otacon ghost Voir le message
    Arrivant de .Net C# je démarre un projet en Borland C++ Builder (Embarcadero RAD Studio XE v2010), et bien entendu c’est comme si je devais tout réapprendre à comparer à .NET C#.

    J’ai trois questions toutes connes, et malheureusement je ne trouve pas de réponses dans le forum, d’où ce sujet.
    N'oublie pas les Cours comme Introduction à la conception objet et à C++

    L'implémentation et la déclaration de la classe étant séparée, tu dois spécifier à quelle classe appartient la méthode

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void TFormContexte::FctInitialisation()
    {
    ...
    }
    Tu dois bien sur déclarer la méthode dans le Header dans la section de visibilité private par exemple

    Ensuite, avant de faire une telle fonction, pense qu'il y le constructor que tu peux redéfinir, l'évèmenent OnCreate pour une TForm ou même qu'il est possible de redéfinir AfterConstruction pour un TObject ou encore Loaded
    Je n'utilise OnShow ou OnActivate que très rarement, il m'arrive même de redéfinir ShowModal (sa nature virtuelle étant très pratique)
    Enfin, parfois je créais une méthode InternalCreate ou Initialize lorsque j'ai plusieurs constructeurs
    En C++ les constructeurs ne peuvent pas s'appeler mutuellement contrairement à Delphi ou au C#, impossible de faire this()
    D'ailleurs, il n'y a pas d'équivalent pour base(), il faut explictement faire TForm() si l'on hérite d'une TForm, cela s'explique, c'est pour supporter l'héritage multiple !
    Comme je fais 99% d'objet VCL, pas d'héritage multiple (une restriction liée à Delphi), je déclare un typedef inherited (comme dans les .HPP générés) à la sauce Delphi, ainsi lorsque j'intercale des classes intermédiaires dans ma chaine d'héritage, je modifie juste mon typedef, cela m'évite de corriger le code de mes appels de méthodes ancêtres.
    (oui oui, je conçois mon modèle de classe en fonction de la pression atmosphérique pas celle du comptoir, quoi que ... et de l'age du capitaine)


    FormContexte et l_ptTFormContexte ne sont pas la même chose !
    il n'y a pas de lien entre les deux !
    Tu ne peux pas utiliser FormContexte avec ton code actuel

    Personnellement, la variable globale déclarée automatiquement, je l'a supprime pour toutes les autres fenêtres que la MainForm !
    Soit parce qu'il peut y avoir des instances multiples et j'utilise donc des variables locales
    Soit parce que l'instance est unique et dans ce cas, j'utilise une variable static pour faire un singleton !

    Citation Envoyé par otacon ghost Voir le message
    Bon, ça sent à plein nez la mauvaise instance du formulaire!


    Tu as bien retiré TFormContexte de la liste des fiches instanciées automatiquement ?
    Certe créé mais pas affiché !
    Je pense que tu l'as oublié car sinon tu aurais des violations d'accès en 00000000 (NULL) et tu as donc deux instances !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned short l_usNbLigne= -1;
    -1 pour un nombre sans signe, c'est osé non ! tu risque d'avoir à la place 65535, tu n'aurais pas un Warning ?
    En plus, comme tu affectes deux fois de suite sans utiliser la variable, le compilateur est un malin, il optimise et retire l'init inutile !

    Pour les Espions, tu n'es plus dans un environnement managé !
    Pas de GarbageCollector !
    Idem la Reflexion est très limité, je ne connais que les RTTI (RunTime Type Info) pour le TObject (en réalite TPersistent ou M+) et ses descendants, cela correspond à __published !
    XE fourni des RTTI plus poussés que je n'ai pas encore eu le temps d'étudier !

    Pour les Forms, tu peux leur affecter un Owner comme Application
    Screen te permet aussi de gérer la collection de Form

    Pour les type comme short, int, ... là c'est des zones mémoires, une fois compilé, le programme ne connait plus le nom des variables, juste les adresses !
    Jette un coup d'oeil à la fenêtre CPU (CTRL + ALT + C lorsque tu es sur un point d'arrêt), tu verras tous les codes ASM directement exécuté par le processeur (à quelle bidouille NT)


    CodeGuard te permet de détecter les fuites mémoires mais il te fourni parfois les lignes de code mais hier je débuggais une DLL et je n'avais que les lignes dans l'exe pas dans la DLL, j'ai utilisé les adresses de la pile d'appel pour savoir quelle ligne de code allouait la mémoire ce qui ma permis de comprendre qu'il me manquait un delete dans une classe de l'exe qui ne libérait pas un objet qui donc n'appelait pas le destructeur (qui lui devait appeler la fonction qui libère le pointeur d'interface issu de la DLL)

    D'ailleurs, tu verras que la gestion des DLL, des interfaces pure C++ et des interfaces Delphi, c'est plus subtile que les Assembly !

    Bienvenu dans la VRAI programmation !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre Expert
    Avatar de sat83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2004
    Messages
    1 040
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2004
    Messages : 1 040
    Par défaut
    Le this ne peux être utilisé que dans une fonction membre. Déclare ta fonction dans la classe (*.h), puis dans ton *.cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void TFormContexte::FctInitialisation(){
    this->...
    }
    FormContexte n'est qu'une instance de ta classe!
    Puisque dans ton code tu instancie toi même dynamiquement ta classe via:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TFormContexte* l_ptTFormContexte = new TFormContexte(NULL);
    ,
    c'est normal qu'une action sur FormContexte ne se voit pas à l'execution.

    La bonne méthode est de déclaré tes fonctions comme membre (publique ou privé) de ta classe dans le *.h, et d'utiliser this dans l’implémentation pour que le code affecte n'importe quelle instance de ta classe.

  4. #4
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juillet 2011
    Messages : 20
    Par défaut
    Bonjour et merci à tous les deux pour vos réponses.

    Alors bien entendu entre-temps j'avais retrouvé mes petits... Dur, dur de revenir au C++ (je reviens 13ans en arrière)...

    @ShaiLeTroll: en effet toutes les réponses étaient bien dans ce Tuto...
    Je suis tombé dessus ce midi, et j'ai donc résolu mes soucis tous seul quand un grand avant de voir vos réponses...

    Bon au pire ça pourra servir à d'autre.

    Maintenant je vais regarder tout ce que tu m'as dit dans ta réponse, car il ya encore tout plein de choses que je ne dois pas connaître ou que j'ai oubliées depuis...

    @sat83 : Merci pour le complément d'info


    En tout cas une chose est sure, c'est que c'est super d'avoir trouvé un forum avec des gens réactifs et qui s'y connaissent.
    Encore merci à vous deux.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 03/04/2013, 20h06
  2. Deux fonctions dans un formulaire!
    Par laipreu dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 29/10/2008, 15h38
  3. Réponses: 10
    Dernier message: 06/07/2007, 02h54
  4. Fonction dans sous formulaire
    Par Junior_jef dans le forum IHM
    Réponses: 18
    Dernier message: 25/06/2007, 14h17
  5. saisir une fonction dans un formulaire
    Par arnogef dans le forum IHM
    Réponses: 14
    Dernier message: 12/12/2005, 10h40

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