Que crois tu faire avec le code suivant (qui se trouve dans ton constructeur)?
QLabel *m_label_image = new QLabel;
Notes d'ailleurs que je pourrais te poser la même question pour
QGridLayout *m_layout1 = new QGridLayout;
et pour
QPushButton *m_bouton_quitter = new QPushButton("Quitter");
Ne te méprends pas, je sais ce que tu veux faire, mais, pas de bol, ce n'est pas ce que tu fais
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
A priori, je crois déclarer et instancier dynamiquement des objets (plus précisément des pointeurs qui pointent vers un espace mémoire 'custumisé' avec respectivement les types QLabel, QPushbutton...).
Je ne me suis pas posé d'autres questions dans la mesure où lorsque j'enlève la ligne 36 du .cpp, ça compile et ça s'exécute sans erreur...
Et, là, je donne ma langue au chat. : au vu de tes questions que j'adore, je pense qu'il manque quelque chose qui va dire à l'ordinateur que tel objet va prendre tel ou tel espace dans la mémoire...
J'attends la suite avec impatience.
- Edité par FranckRAZAFIMAHARO 20 janvier 2018 à 22:27:29
A priori, je crois déclarer et instancier dynamiquement des objets...
Sauf que ce n'est visiblement pas ce que tu fais
Alors, essayons de réfléchir un peu: où ta variable m_label_image est-elle sensée être déclarée? et où est-elle sensée être définie?
Je ne me suis pas posé d'autres questions dans la mesure où lorsque j'enlève la ligne 36 du .cpp, ça compile et ça s'exécute sans erreur...
Et c'est normal, car la ligne 36 n'est que l'endroit du code où un problème qui trouve son origine (beaucoup) plus tôt devient apparent parce que tu essaye de déréférencer une adresse invalide
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
apparemment, il faut que je comprenne déclaration et définition...je préfère m'abstenir (je lis, relis, re-relis différentes sources)
afin d'utiliser m_label_image dans les méthodes/fonctions de Fenetre1, il faut que je déclare m_label_image en dehors du constructeur de la classe Fenetre1.
Ai-je bien compris? Il faut que je déclare m_label_image avec une portée qui englobe le constructeur et les fonctions de la classe Fenetre1. Faut-il donc que la déclaration de m_label_image se fasse aussi en dehors du prototype de Fenetre1
il y a peut-être un mot clé à ajouter, mais, là, je ne vais pas me lancer à l'aveugle...et vu le sens de ta réponse, je ne pense pas que ce soit la bonne voie (ou du moins, il faut que je mette les déclarations ailleurs pour qu'elles soient visibles dans toute la classe Fenêtre).
après, pour les définitions...j'aurai bien été tenté de le faire dans le constructeur (.cpp), les déclarations dans le .h.
En tout cas, c'est bien agréable d'être guidé de la sorte. même si je patauge dans le potage.
Allez, je me lance avec le risque de me faire gronder :
Faut-il que m_label_image soit un attribut "statique" de la classe Fenetre1? J'ai mis les guillemets car j'entends par statique : "accessible par les fonctions de la classe" , mais je veux que chaque instance de la classe aura son propre m_label_image?
..
Puis : j'essaie de voir le "où on fait ceci"...mais, ensuite, j'aimerai aussi trouve le "comment", i.e., "comment on l'écrit".
Ainsi, est-ce que l'on définit l'attribut m_label_image avec un signe "=" et la déclare-t-on avec "QLabel m_label_image;"? Je pose cette question car j'ai l'impression que parfois définition et déclaration sont faites sur la même ligne et suis incapable de dire ce qui est fait exactement.
Mille merci pour la décomposition du problème.
- Edité par FranckRAZAFIMAHARO 21 janvier 2018 à 9:28:02
On va poser la question comme cela: qu'est-ce qui fait que le compilateur sait que l'on déclare une variable? et, d'un autre coté, qu'est ce qui fait que le compilateur sait qu'on utilise une variable (par exemple, pour la définir ou... pour faire appel à une de ses fonctions membres?
Pour t'aider à comprendre, quelle différence y aura-t-il entre le code
int main(){
int i = 3;
std::cout<<"i = "<<i<<"\n";
{
int i = 5;
std::cout<<"i = "<<i<<"\n";
}
std::cout<<"i = "<<i<<"\n";
}
et le code
int main(){
int i = 3;
std::cout<<"i = "<<i<<"\n";
{
i = 5;
std::cout<<"i = "<<i<<"\n";
}
std::cout<<"i = "<<i<<"\n";
}
Pourquoi les deux codes provoqueront-ils un résultat différent?
- Edité par koala01 21 janvier 2018 à 12:56:34
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
En espérant avoir compris, mais surtout en m'exprimant de manière la plus rigoureuse possible :
En écrivant ceci, que
int i=5;
cela revient à :
int i; // Déclaration d'une variable i de type int
i=5; //Définition de i
Dans le premier programme proposé, int i=5; apparaît deux fois. La première en dehors du bloc, et la deuxième à l'intérieur de ce dernier.
Ainsi, on créée deux variables de type int qui sont homonymes, mais, ces deux variables sont totalement indépendantes. La portée de celle dans le bloc {} est justement limitée entre les deux {}.
Lorsque l'on exécute ce premier programme, on obtient :
i=3 (premier retour du flux cout)
i=5 (deuxième retour du flux : il s'agit de la valeur du deuxième homonyme)
et enfin i=3 : le deuxième homonyme a été zigouillé par l' "ordinateur" car on est en dehors du bloc.
Dans le deuxième programme proposé, il n'y a pas d'autre déclaration avec type nom_de_variable;.
Ainsi, lorsque l'on écrit dans le bloc
{
i = 5;
std::cout<<"i = "<<i<<"\n";
}
Il n'y a qu'une seule variable dont le nom est i, et surtout, la ligne 2 ci-dessus attribut la valeur 5 à la variable que l'on a définit en dehors du bloc.
On obtient donc
i=3
i=5
i=5
Enfin, la variable i est bien reconnue dans le bloc, car le bloc est dans le bloc où i a été déclarée.
{//début du bloc principal
//Déclaration + définition de i
{\* début du bloc intermédiaire
changement de la valeur de i
toute variable définie ici sera morte à la
fin de ce bloc intermédiaire */
} // fin du bloc intermédiaire
} // fin du bloc principal
La difficulté est que j'ai le main.cpp, le .h et le .cpp de la classe...Sans oublier l'instance de la classe que j'ai crée dans le main.
Merci Koala one! Mon cerveau tourne à plein pôt! J'essaie d'avancer sur mon problème, en attendant impatiemment la suite! et en espérant me coucher moins bête ce soir.
koala01 a écrit:
On va poser la question comme cela: qu'est-ce qui fait que le compilateur sait que l'on déclare une variable? et, d'un autre coté, qu'est ce qui fait que le compilateur sait qu'on utilise une variable (par exemple, pour la définir ou... pour faire appel à une de ses fonctions membres)?
Réponse de Franck
Pour "Qu'est-ce qui fait que le compilateur sait que l'on déclare une variable": je pense qu'il faut déclarer la variable au bon endroit. m_Label_image dans mon cas doit être déclarée pour tous les membres de la classe Fenetre1 et en particulier pour les méthodes membre de la classe.
Pour la deuxième partie de la question"qu'est-ce qui fait que le compilateur sait que l'on utilise une variable" : je ne sais pas , à moins que : pour le faire il suffit d'écrire son nom.
- Edité par FranckRAZAFIMAHARO 21 janvier 2018 à 16:36:03
Maintenant, observe un tout petit peu ta classe et ton constructeur, que je vais mettre dans le même bloc de code:
class Fenetre1 : public QWidget
{
public:
Fenetre1();
//Essai
void essai();
QLabel *get_label();
QPixmap *get_image();
private :
QLabel *m_label_image;
QPixmap *m_image;
QGridLayout *m_layout1;
QPushButton *m_bouton_quitter;
};
Fenetre1::Fenetre1() : QWidget()
{
QGridLayout *m_layout1 = new QGridLayout;
QPushButton *m_bouton_quitter = new QPushButton("Quitter");
QLabel *m_label_image = new QLabel;
QPixmap *m_image = new QPixmap;
/* ... */
}
A ton avis, que se passe-t-il?
PS: ou bien on m'appelle koala, ou bien on m'appelle koala01, mais pas koala one
- Edité par koala01 21 janvier 2018 à 16:36:29
Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
je sens que ça chauffe, mais bon, je n'ai aucun recul.
C'est comme si j'avais pour chaque variable : deux attributs homonymes avec seulement le deuxième qui est défini.
Là, je surchauffe du cerveau.
Il faut sûrement que je me débrouille pour n'avoir qu'une seule déclaration comme pour l'exemple que tu m'as soumis avec l' "int i;" du post précédent...mais, je suis à deux doigts de la syncope : il est très difficile de voir l'évidence, et encore plus de corriger ses propres fautes!
J'vois rien, merci koala...
J’essaye d'enlever tous les types au début du constructeur pour ne pas me retrouver avec des homonymes, mais, ensuite je me retrouve avec des problèmes d'homogénéité dans les types..est-ce quand même la bonne voie?
Voilà ...ça fonctionne!
Fenetre.h
#ifndef FENETRE1_H
#define FENETRE1_H
#include <QApplication>
#include <QWidget>
#include <QGridLayout>
#include <QPushButton>
#include <QLabel>
#include <QPixmap>
class Fenetre1;
class Fenetre1 : public QWidget //Définition de la classe
{
public:
Fenetre1(); //Déclaration du constructeur
~Fenetre1(); //Déclaration du destructeur
void essai();
QLabel *get_label() const;
QPixmap *get_image() const;
private :
QPixmap *m_image; //Déclaration d'un pointeur qui ne pointe sur rien pour le moment
QGridLayout *m_layout1;
QPushButton *m_bouton_quitter;
QLabel*m_label_image;
};
#endif // FENETRE1_H
Fenetre.cpp
#include "Fenetre1.h"
Fenetre1::Fenetre1() : QWidget()
{
m_layout1 = new QGridLayout;
m_bouton_quitter = new QPushButton("Quitter");
m_label_image = new QLabel(); // Ici, le pointeur créé dans .h. grâce à new, on affecte une adresse au pointeur.
m_image = new QPixmap;
*m_image=QPixmap("../test-vide/images/IMG_0021.JPG");
*m_image=m_image->scaled(100,100,Qt::KeepAspectRatio,Qt::FastTransformation);
m_label_image->setPixmap(*m_image);
m_layout1->addWidget(m_bouton_quitter,2,2);
m_layout1->addWidget(m_label_image,0,0);
this->setLayout(m_layout1);
this->setWindowTitle("Fenêtre à modifier");
//*** essai
this->setGeometry(50,50,300,200);
m_label_image->resize(20,20);
//******
essai();
QObject::connect(m_bouton_quitter,SIGNAL(clicked()), qApp,SLOT(quit()));
}
Fenetre1::~Fenetre1() //destructeur
{
// Inutile car Qt le fait pour nous
}
void Fenetre1::essai()
{
this->m_label_image->setFixedHeight(50);
}
QLabel* Fenetre1::get_label() const
{
return this->m_label_image ;
}
QPixmap* Fenetre1::get_image() const
{
return this->m_image;
}
Et, là, pas de fuite de mémoire....Je vais pouvoir dormir, me laver, manger avec sérénité et joie!
Le sujet est donc résolu.
Koala, you are the one! Je n'aurai jamais compris cette finesse seul.
Franck.
- Edité par FranckRAZAFIMAHARO 21 janvier 2018 à 21:29:19
Astromout
C++ - Qt: Segmentation fault dans une fonction
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.