Classes, objets, ... [C++] - Programmation
Marsh Posté le 20-11-2001 à 14:10:24
Moi j'ai du mal comprendre ta question
le premier principe de l'objet c'est l'encapsulation...
donc si tu fait tes classes consciencieusement, les membres sont tjs prives et tu ajoutes des methodes pour y acceder...
si tu a le membre Temperature;
tu aurras SetTemperature et GetTemperature pour le modifier et le lire, ce qui te permet d'avoir des variables en lecture seule,
Energie par exemple avec une seule methode public GetEnergie, ce qui te permet d'ajouter dans SetTemperature
Energie = Cp*(T-T0) par exemple...
Je ne suis pas sure de repondre a ta question...
Bien sur tout cela est fastidieux, mais quand tu debug il suffit de mettre un point d'arret dans ces methodes... Pour la vitesse d'exection mettre ces methodes en inline. En plus ces methodes permettent de controller les valeurs proposee... et eviter par exemple que Temperature soit negatif...
[edtdd]--Message édité par BENB--[/edtdd]
Marsh Posté le 20-11-2001 à 14:21:16
En fait toute reponse est bonne a prendre puisque ca me permet de comprendre un peu mieux le pourquoi du comment
Pis je me pose surement plein de questions qu'il n'y a pas raison de poser (mais ca c'est tout moi).
En fait, comme je l'avais demande a chris, je suis bloque sur un truc vraiment bidon.
A savoir si je dois faire
maclasse
{
public:
char titre[255];
afficherTitre() {printf("%s", titre)};
et dans le main:
strcpy(classe.titre, "jjj" );
afficherTitre();
ou plutot
maclasse
{
public:
afficherTitre(char *titre);{printf("%s", titre)};
avec dans le main
classe.afficherTitre("kjk" );
Mais bon il m'a donne une soluce differente de mes deux propositions.
Marsh Posté le 20-11-2001 à 14:31:47
Je ne vois pas trop l'interet de la deuxieme proposition...
Je ne connais vraiment le contexte...
mais je te propose :
class TaClass
{
public:
TaClass();
void SetTitle(const char* title);
const char* GetTitle(void) const;
void printTitle(void) const ;
~TaClass();
private:
char *title
};
TaClass::TaClass()
{
Title = NULL;
}
void TaClass::SetTitle(const char* title)
{
if (Title)
free(Title);
Title = strdup(title);
}
const char* TaClass::GetTitle(void) const
{
return Title;
}
void TaClass::printTitle(void) const
{
printf ...;
}
~TaClass::TaClass()
{
if(Title)
free(Title);
}
et le main
{
TaClass toto;
toto.SetTitle("Gloups" );
toto.PrintTitle();
}
Voila....
Marsh Posté le 20-11-2001 à 14:36:55
Ok, je capte deja plus le truc.
Je savais pas trop pour les parametres des fonctions, comment ca marchait, etc...
Je crois que ca va deja aller mieux merci
Marsh Posté le 20-11-2001 à 14:41:43
mais de toute facon c'est un peu plus complique ca mon truc, bref pas de variable a mettre comme ca.
Marsh Posté le 20-11-2001 à 14:42:02
'tain j'suis pas clair la
j'me demande meme si c'est clair dans mon cerveau...
Marsh Posté le 20-11-2001 à 14:47:54
chrisbk > Je reconnais que le strdup...
mais tu aurrais pu aussi dire que tu aurrais fait comme moi...
Globalement peu importe l'auteur, ca montre que la solution a une certaine valeur
Godbout >
le Pb de ta premiere solution est que tu accede directement au membre Title, des lors imagine que quelqu'un de mal intentionne (ou distrait) mette n'importe quoi dans Title... L'utlisation du SetTitle te permet de controler Title et de savoir par ex que il a ete alloue par malloc et devra donc etre desalloue par free.
Dans ta deuxieme solution il n'y a plus de membre alors pourquoi faire une classe ?
A ce propos quand une methode de classe ne fait reference a aucun membre de cette classe, il faut la mettre en static, comme cela elle peut etre appelle meme s'il n'y a pas d'instance de la classe. Quand une methode de classe devient static il faut se poser la question de savoir ce que cette methode fait dans la classe... bien souvent on se rend compte qu'elle n'a rien a y faire... Dans ton cas autant utiliser directement printf...
Marsh Posté le 20-11-2001 à 15:00:08
Evidemment c'est pas aussi simple dans mon cas, c'etait juste pour avoir un exemple sur lequel m'appuyer, et aisin mieux comprendre.
Pour le strdup, quelle est sa fonction exactement ?
Je sais qu'elle copie la chaine dans la chaine de destination, mais je ne pense pas que ca vaut un strcpy. Quelle est la diff ?
Et si ca cree un nouveau pointeur, il ne faut pas liberer l'autre ?
Marsh Posté le 20-11-2001 à 15:07:45
Je devrais laisser repondre chrisbk
le strdup copy la chaine apres avoir alloue l'espace necessaire,
c'est equivalent a
malloc(strlen());
+
strcpy
Dans ton cas la chaine est une litterale elle ne doit donc pas etre liberee...
Marsh Posté le 20-11-2001 à 15:17:52
benb je voua pas de koi tu parle
je suis un grand fan de strdup mais heuh..... bref, ou c kilai mon bout de code a moi que tu cites ?
Marsh Posté le 20-11-2001 à 15:20:53
Godbout a écrit a écrit : pfiou trop d'mal moi... |
ahh les douleurs de l'enfantement ...
pour stdrup, oui, il faut free ce qu'il te rend quand t'en a plus besoin
Marsh Posté le 20-11-2001 à 15:22:20
ouais mais deja que j'avais du mal avec les free avant, alors la avec les classes j'suis encore + perdu, meme si je suis sur que ca change rien
Marsh Posté le 20-11-2001 à 15:24:14
alors qu'en fait c'est plus simple : tout (ou presque) dans le destructeur
si une variable membre a ete cree avec un malloc / new, alors le destructeur est un bon endroit pour faire le free
(enfin perso generalement je met tout ca dans une fonction nommee release, et j'apelle cette fonction dans le destructeur, mais l'idee est la meme)
(a ce propos, exit malloc, passe au new / delete maintenant )
[edtdd]--Message édité par chrisbk--[/edtdd]
Marsh Posté le 20-11-2001 à 15:42:23
chrisbk > je ne sais plus ou il est mais je me rappelle que tu faisait le dieu avec ton strdup
Pour le douleurs de l'enfantement pensez au bebe ca aide
pour le release c'est une idee, je ne vois pas l'interet, mais je suis sur que tu vas me le dire (au pire pour l'esthetisme )
Godbout > aller courage... Pousse je crois que vois la tete
(pour une fois que c'est moi qui dis ca...)
En fait les classes rendent ca plus simple d'un cote en ajoutant de nouveaux Pb
Ce qui est plus simple :
Comme Title est encapsule dans ta classe tu le maitrise mieux, et tu connais reelement son cycle de vie puisque etant private il ne peut etre utilise que par les methodes de la classe...
quand tu ecris une chaine "Gloups" c'est une litterale, une forme de variable statique, donc pas desoin de desallouer puisqu'elle n'a pas ete allouee dynamiquement...
Marsh Posté le 20-11-2001 à 15:45:52
arf, faire le dieu avec mon strdup, on aura tout entendu (mais moi et cette fonction on s'entend bien, c vrai )
le release,ca me sert par exemple quand la classe "ressert"
genre ta classe bitmap . tu charge un bitmap, puis un autre, la le release me sert a etre sur que tout est propre, ptr a NULL, memoire videe et tout le bataclan
(pis oui, ca donne un certain estetisme je trouve )
Marsh Posté le 20-11-2001 à 15:53:34
si je reponds pas c'est normal j'ai pas grand chose a dire a part merci mais je lis tout ce que vous ecrivez.
Marsh Posté le 21-11-2001 à 09:28:37
j'ai essaye de faire une petite classe.
Ca fonctionne mais j'aimerais savoir si y a des erreurs de prog a pas faire
merci
DEF:
class Test
{
public:
Test();
virtual ~Test();
// Set fileName
void SetFileName(const char *);
// Remove file
void RemoveFile();
// Open file
void CreateFile();
// Write file
void WriteFile();
private:
char *fileName;
FILE *file;
};
CPP:
Test::Test()
{
file == NULL;
}
Test::~Test()
{
if (file)
fclose(file);
}
void Test::SetFileName(const char *fileName)
{
Test::fileName = strdup(fileName);
}
void Test::RemoveFile()
{
if(fileName)
remove(fileName);
}
void Test::CreateFile()
{
if (fileName)
file = fopen(fileName, "w" );
}
MAIN:
Test essai;
essai.SetFileName("C:\\Temp\\TransLpv.txt" );
essai.CreateFile();
Marsh Posté le 21-11-2001 à 09:51:15
voui, c'est
Test::Test()
{
file = NULL;
}
et non
Test::Test()
{
file == NULL;
}
sinon je te deconseille fortement les :
void Test::SetFileName(const char *fileName)
{
Test::fileName = strdup(fileName);
}
c a d mettre des variable dans les param qui ont le meme nom qu'un variable membre, c'est source de pepin....
tu peux faire, c'st prefixe tes variables membres par un "m_"
genre :
private:
char *m_fileName;
FILE *m_file;
};
perso je trouve pas ca super beau, mais ca evite des blagues, alors...
[edtdd]--Message édité par chrisbk--[/edtdd]
Marsh Posté le 21-11-2001 à 09:53:43
ouais, erreur de frappe
Mais le reste ca va ?
c'est normal que je passe rien en parametre dans mes fonctions ?
Marsh Posté le 21-11-2001 à 09:55:28
cf edit
vi vi c normal, si la fonction ne travaille que sur les var membre, elle a pas besoin d'autre chose
Marsh Posté le 21-11-2001 à 10:00:04
ok pour l'edit.
Pour les fonctions je vois pas dans quel cas elles ont besoin d'argument.
Et je crois que hier si j'etais bloque c'est parce que je voulais passer du C a l'objet. Je crois qu'il faut que je laisse tomber cette maniere de faire et que je refasse completement tout le truc en objet.
Marsh Posté le 21-11-2001 à 10:01:33
Alors, j'te marque les différentes remarques qui me viennent...
-Quand tu construit ton objet, tu ferais mieux d'écrire:
Test essai();
pour bien te rappeler que c un appel au constructeur (que t's défini sans paramètres, ms t'aurais bien sur pu en mettre).
-Dans SetFileName, pour désigner le fileName de l'instance en cours (par opposition à celui passé en paramètre), tu ferais mieux de mettre:
this->fileName , this étant le pointeur vers l'instance en cours
Et puis, perso, tous ce qui est en paramètre, je le fais précéder par _, et tout ce qui est attributs membre de ma classe, je le fais précéder par m_ ,c vachement plus clair, exemple ta fonction deviendrai(juste sur cette fonction; le reste en découle):
void Test::SetFileName(const char* _szFileName)
{
m_szFileName = strdup(_szFileName);
}
-Tes fonction devraient pour la plupart rendre des BOOL. comme ça, tu sais si elle à marché ou pas, exemple:
BOOL Test::CreateFile()
{
if (fileName)
file = fopen(fileName, "w" );
if (file != NULL)
return TRUE;
return FALSE;
}
voila...
mais sinon, ça vient
Marsh Posté le 21-11-2001 à 10:04:18
Godbout a écrit a écrit : ok pour l'edit. Pour les fonctions je vois pas dans quel cas elles ont besoin d'argument. Et je crois que hier si j'etais bloque c'est parce que je voulais passer du C a l'objet. Je crois qu'il faut que je laisse tomber cette maniere de faire et que je refasse completement tout le truc en objet. |
Tu passes des paramètres à tes fonctions quand elles ont besoin d'éléments qui sont pas des membres de ta classe...
Marsh Posté le 21-11-2001 à 10:07:40
El_Gringo a écrit a écrit : Tu passes des paramètres à tes fonctions quand elles ont besoin d'éléments qui sont pas des membres de ta classe... |
exemple a la con :
class vecteur
{
int produitScalaire(vecteur &);
....
};
Marsh Posté le 21-11-2001 à 10:08:08
En fait je me rends compte que je connais les reponses a mes questions, seulement je ne vois pas quand je vais devoir utiliser telle ou telle chose.
C'est un peu comme les pointeurs au debut. Impossible de savoir a koi ca sert.
Je crois que j'ai juste besoin d'un peu d'entrainement, mais j'ai peur de partir dans une mauvaise direction
Marsh Posté le 21-11-2001 à 10:27:38
Il sont galants, ils me laissent quelques remarques...
tu as oublier de liberer FileName dans le destructeur...
moins important : j'initialiserais FileName a NULL aussi sinon les if(FileName) n'ont plus d'interet...
totalement futile...
j'ai pas les m_ devant les membres... le prefere les _p derriere les parametres... en cas de confusion possible...
mais en Gal les membres de mes classe commencent par une Majuscule, et les variable de pile (locales - parametre) commencent par une minuscule... je sais que certains n'aiment pas avoir deux variables de meme nom differenciee uniquement par la casse mais dans ce cas la casse a un sens semantique fort et c'est donc acceptable (a mon avis ) evidement il faut suivre cette nomenclature tout le temps pour que ca puisse etre acceptable. Utilisant des noms long je ne trouve pas utile de faire commencer le nom de la variable par son type, mais il est vrai que j'ai surout des doubles et des tableaux de doubles
Marsh Posté le 21-11-2001 à 10:32:50
Citation : Utilisant des noms long je ne trouve pas utile de faire commencer le nom de la variable par son type |
moi non plus, surtout que ca deviend laid quand tu cummule :
m_fX;
mais l'autre avec qui je bosse il y tient absolument
(pis ta manip minuscule / majuscule, y'a trop pas moyen enfinf chacun ses gouts)
Marsh Posté le 21-11-2001 à 10:34:24
BENB a écrit a écrit : tu as oublier de liberer FileName dans le destructeur... |
Ben je croyais qu'on avait pas besoin de le liberer parce que c'etait statique
BENB a écrit a écrit : moins important : j'initialiserais FileName a NULL aussi sinon les if(FileName) n'ont plus d'interet... |
Ouaip j'ai pas ose le faire, j'ai cru que ce serait encore une connerie
En fait je voulais faire un memset, pis je me suis dit que forcement ca allait pas aller, donc j'ai rien fait
BENB a écrit a écrit : totalement futile... j'ai pas les m_ devant les membres... le prefere les _p derriere les parametres... en cas de confusion possible... |
confusions dans koi ??
Marsh Posté le 21-11-2001 à 10:39:12
attention jeune homme,
strdup == malloc + strcpy
donc tu dois free() quand plus besoin
Marsh Posté le 21-11-2001 à 10:39:13
chrisbk a écrit a écrit :
|
Tu bosses dans la prog 3d toi en fait !?
Marsh Posté le 21-11-2001 à 10:40:00
El_Gringo a écrit a écrit : Tu bosses dans la prog 3d toi en fait !? |
voui, enfin, bosser, c'est juste pour le fun (en loisir quoi)
mais ptet plus tard, pkoi pas ? (si on veut bien de moi qqpart )
Marsh Posté le 21-11-2001 à 10:53:39
Godbout a écrit a écrit : confusions dans koi ?? |
confusion entre membres et variables de pile (locales - parametres) parce que meme nom....
mon truc majuscule minuscule c'est :
SetTemperature (double temperature)
{
Temperature = temperature;
}
mais tu peux faire aussi
SetTemperature (double temperature_p)
{
Temperature = temperature_p;
}
enfin chacun ses gouts et ses conventions...
Marsh Posté le 21-11-2001 à 10:58:37
BENB a écrit a écrit : confusion entre membres et variables de pile (locales - parametres) parce que meme nom.... mon truc majuscule minuscule c'est : SetTemperature (double temperature) { Temperature = temperature; } mais tu peux faire aussi SetTemperature (double temperature_p) { Temperature = temperature_p; } enfin chacun ses gouts et ses conventions... |
n'oublions pas
SetTemperature (double temperature)
{
this->temperature = temperature;
}
comme tu le disais, chacun ses goûts ... depuis que je fais pas mal de javascript & co, j'ai adopté leur convention de nommage : tout en minuscule, pas d'underscore, une majuscule pour séparer les mots (comme maxTemperature).
Marsh Posté le 21-11-2001 à 10:59:15
BENB a écrit a écrit : confusion entre membres et variables de pile (locales - parametres) parce que meme nom.... mon truc majuscule minuscule c'est : SetTemperature (double temperature) { Temperature = temperature; } |
personnellement je pense que c'est sale(tm)
et que ce n'est pas qu'un probleme de gout .
Enfin bon.. tu dois surement etre une deesse de la programmation qui a toujours l'esprit clair quand elle attaque son code et ne fait jamais d'erreur de frappe
LEGREG
Marsh Posté le 21-11-2001 à 11:04:53
Eh ben au moins j'ai le choix avec tout ca
C'est vrai que les Maj/min j'aime pas trop.
Pour le reste je crois que ca va venir en programmant.
Marsh Posté le 20-11-2001 à 14:01:13
Je cree un topic pour eviter d'embeter mon pauvre chrisbk a chaque fois
Bon ben je vois a peu pres comment marche une classe, mais j'ai du mal a en creer une. Je sais pas si je dois passer les arguments par les fonctions, ou si je dois les declarer, etc...
Je suis sur que certains vont remettre de l'ordre dans ma tete