bon, je sais qu´on en a parlé beaucoup de fois, mais je comprends pas très bien comment stocker une chaine de caractères dans un tableau..
si qqun pouvait me faire un exemple, je lui en serais grandement reconnaissant.
Tu n´as pas le choix de toute facon, les chaines de caractères sont des tableaux, terminée par le caractère ´\0´ / NULL ou 0x00 ( pour indiquer la fin de la chaine).
Tu as plusieurs solutions pour stocker une chaine :
1) char *pChaine = " Bonjour";
Le compilateur identifiera la constante chaine " Bonjour" ( à laquelle il rajoute tout seul le 0 de fin de chaine) et ta variable ( pointeur) pChaine pointera sur la zone mémoire allouée à la compilation pour stocker " Bonjour" ( + le ´\0´). A noter qu´ici il s´agit d´une constante chaine donc il sera impossible de la modifier, en clair tu pourras pas écrire :
pChaine[0] = ´t´;
-> violation de privilège
2) char TabChaine[] = " Bonjour";
Cette fois le compilo va déclarer un tableau d´une longueur calculée en fonction de la longueur de la chaine " Bonjour" ( + toujours le 0 de fin de chaine)
Tu peux cette fois la modifier sans problème, car l´espace mémoire est alloué à l´exécution.
3)
char TabChaine[10];
strcpy(TabChaine,"Bonjour");
Ici, tu réserves un tableau de 10 caractères maxi et strcpy recopie la chaine " Bonjour" ( + le 0 ( bis bis)) à partir de l´adresse indiquée par le pointeur TabChaine. La déclaration d´un tableau est en fait le pointeur sur le début de la zone allouée :
TabChaine < => &[0] < => ( TabChaine+0)
En utilisant la 3e méthode tu devras donc toujours prévoir une espace suffisant pour stocker tes chaines de caractères SANS OUBLIER le caractère de fin de chaine ( ´\0´).
( pffiou)
Merci d´avoir pris le temps de répondre, mais j´y arrive tjrs pas..
en fait j´ai une classe:
***
class Ship
{
public :
char Name[];
}
***
et après je veux mettre une chaine de caractères:
***
Ship a;
a.Name[] = " blabla";
***
bah fonctionne pas :/.
ptite correction:
en fait j´ai une classe:
***
class Ship
{
public :
char Name[];
};
***
et après je veux mettre une chaine de caractères:
***
Ship a;
a.Name[] = " blabla";
***
j´avais oublié le ; après la classe, mais ca n´arrange pas le pb
bin c´est normal, déjà tu ne déclares pas de dimension pour ton tableau !
si tu veux faire
a.Name = " blabla";
il te faut déclarer Name comme ceci :
char *Name;
= un pointeur sur une chaine de caractères mais sache que ca peut être dangereux écrit comme ca.
Autre solution comme je le disais :
char Name[20];
et plus loin tu fais
strcpy(a.Name,"blabla");
ok ca fonctionne thx ![]()
oué mais euh c statique comme dimension, si jamais la chaine entrée est plus grande ca va faire des buffers overrun.
c´est ce qu´on appelle une faille de sécurité.
le mieux est d´allouer la taille dynamiquement.
ou au moins de faire des tests strlen < 20 partout mais c´est risqué si jamais on l´oublie qq part ca fait une faille de securité.
moi j cherche a savoir si on peu téléchargé C++ ?
telecharger c++? c´est fort ca^^
sinon pour les failles, bah disons que c´est pas mon principaux pb.. mais si je met la place pour 30 caractères dans le tableau et que j´en mets que 20, ca faitqqchose ?
et aussi une autre question:
si qqun pouvait m´expliquer le fonctionnement et à quoi servent les constructeurs et les destructeurs, ça serait cool, parce que j´ai vraiment pas tout compris
.
pour faire simple, sur les ctor/dtor...
le constructeur correspond au code qui initialise ton objet, lorsqu´il est créé. Quand un objet est crée, il se passe deux choses : 1) une alloc mémoire ( de la taille de l´objet) 2) une initialisation
l´alloc mémoire, c´est de le boulot de " operator new" ( ::operator new est toujours utilisé par defaut, mais on peut le surcharger pour chaque classe ; on aime bien aussi surcharger ::operator new pour détecter des memory leaks).
L´initialisation de la zone mémoire réservée, c´est le boulot du constructeur : tu y fixes la valeur initiale des membres de l´instance.
tu peux écrire le ctor par défaut, ou alors avec des paramètres, selon ton objet.
Il faut bien voir une chose, d´abord l´objet est crée en mémoire, puis ce sont les membres qui sont construits, et seulement ensuite le constructeur de l´objet est appelé. On peut utiliser une syntexe un peu particulière dite de liste d´initialisation qui permet de construire les membres avec des valeurs spécifiques. Comme c´est pas clair du tout, exemple
class A
{
public:
A(const Objet &) { m_o = o; }
Objet m_o;
};
quand on fait A a; &) réservation memoire ( transparent) 2) le ctor par defaut de Objet est appelé pour le membre m_o 3) le ctor de A est appelé ; on peut écrire ça comme ça :
class A
{
public:
A(const Objet &) : m_o(o) { }
Objet m_o;
};
ce qui signifie, " lors de la création des membres, appelle directement le ctor par copie de Objet pour construire m_o". Quel interet ? pas d´appel de constructeur ni d´opérateur d´affectation qui ne sert à rien, donc c´est plus rapide
pour le destructeur, il sert à dire comment libérer proprement la mémoire utilisée par une instance de classe. Tant qu´on a que des membres primitifs ( entiers, etc.) ou des objets ( qui fournissent leur propre dtor), pas de soucis. Le seul cas interessant,c´est quand il y a des pointeurs. Là, en règle générale, le dtor doit etre symétrique du ctor : pour chaque new, faire un delete et pour chaque new[] faire une delete[]. Dans certains cas on procède autrement, mais quand tu auras besoin de telles astuces, tu ne poseras plus ces questions ![]()
Bien évidemment, quand le dtor est appelé, ceux des membres également.
là où ça devient marrant c´est quand on utilise la dérivation
pour le ctor, celui du parent est appelé avant celui de l´objet ; on peut forcer l´appel avec des paramètres avec la liste d´initialisation. Exemple :
class A
{
public:
A(params) { code }
virtual ~A() { code }
};
class B : public A
{
public:
B(params) : A(params) { code }
~B() { code }
;
};
sinon c´est le ctor par défaut de A qui est utilisé ( encore faut-il qu´il existe et soit accessible)
pour le dtor, on note qu´il DOIT etre virtuel dans le cas de dérivation ; en effet, ça peut conduire à des memory leaks si on utilise le polymorphisme. Ex :
class A
{
A() { }
~A() { }
};
class B : public A
{
B() { m_p = new Object(); }
~B() { delete m_p; }
};
si on fait :
A *p = new B();
delete p;
on gagne un beau leak
en effet c´est ~A() qui est appelé alors que B() fait des alloc mémoires. C´est pourquoi ~A() doit etre virtual.
pour simplifier, à retenir :
1) dtor symétrique du ctor
2) la classe est dérivée ? => dtor virtual
je recommande aussi d´écrire la forme canonique à chaque fois, ça évite des ennuis ; cette forme étant ctor + copy ctor + assignment op + dtor soit:
A();
A(const A &);
const A & =(const A &);
~A(); / / éventuellement virtual
maintenant, astuce pour ceux qui ont suivi : comment initialiser un tableau d´objets n´ayant pas de ctor par défaut ? . .. faire l´alloc et la construction à la main ! soit :
class A
{
public:
A(int);
. ..
};
A *p_array = reinterpret_cast<A *>(::operator new(4*sizeof(A))); / / alloc pour 4 objets
for ( int index = 0; index < 4; ++index)
{
new ( p_array + index) A(9);
}
/ / initialise les 4 objets en utilisant le ctor avec un paramètre valant 9
mais bon, là on tape déjà dans le placement new, ce qui n´est pas forcément trivial.
Je sais pas si ça réponds à tes questions, mais sinon précise ou tu coinces ![]()
olala, tu m´as fait un très grand texte et je t´en remercie, seulement mon père me gueule dessus et je dois stopper l´ordi^^.
je lirai tout ça demain matin, en plus je suis fatigué ^^.
merci encore !
et pour Tibo[FR] -> C++ c´est un langage de programmation, pas un logiciel... Tu peux télécharger un compilateur C++, qui fera de tn code un fichier éxécutable ou autres.
Sur http://www.telecharger.com tu trouveras Dev-C++
Et sur http://casteyde.christian.free.fr un excellent tuto pour apprendre ce langage
Voilà ![]()
hahaha c´est la meilleurs: " précise ou tu coinces", mais je coince partout ^^´.
non plus sérieusement, je VIENS à l´instant de lire le chapitre sur les membres virtuelles et le polymorphisme, donc c´est un peu flou...
et je suis en train de relire le chapitre sur les constructeurs/destructeurs, je te redis si j´ai compris après avoir relu, je crois que c´est la meilleure choses à faire ^^
ok j´ai un peu mieux compris, mais il n´est pas possible de faire ça par exemple:
***
classe A
{
public:
int super;
float cool;
protected:
int megabien = 5;
char ok = a;
};
***
?
ah et puis une autre question, c´est quoi le heap ^^ ?
euh excusez ce up mais vu que le topic était plus sur la première page et que j´aimerais bien avoir des réponses ^^
nan c´est pas possible de faire ce que tu proposes : on initialise pas directement des champs, on passe par le constructeur.
Il y a UN cas où tu pourras voir qqch de similaire à ce que tu proposes : avec des static const ; sous un VC++ on aurait :
class A
{
public:
static const int MY_CONST;
};
const int A::MY_CONST = 12;
et sous un gcc on pourrai directement faire :
class A
{
public:
static const int MY_CONST = 12;
};
mais là ça vient du fait que 1) c´est statique donc indépendant de l´instance, donc sans rapport avec le constructeur 2) const, ce qui fait qu´on ne peut l´initialiser ailleurs
Sinon, la heap, c´est une zone mémoire ( dissociée du segment de code ou de la stack) dans laquelle se réserve la mémoire que tu demandes avec des malloc et des new.
ah ok thx
.
bon now faut que je relise le chapitre des membres virtuelles car je comprends rien aux classes dérivées ^^