OVH Cloud OVH Cloud

constructeurs, et autres, privés

9 réponses
Avatar
Manuel Leclerc
Si je d=E9clare un constructeur par d=E9faut priv=E9, ainsi que
copie et affectation, genre

class A {
public:
char * m_p;
A( char * p ) : m_p( p ) {};
private:
A();
A( const A& );
A& operator=3D( const A& );
};

et que en plus, je n'impl=E9mente pas les 3 fonctions priv=E9es,
est-ce que je suis bien certain qu'il n'y a aucun moyen
que je me retrouve a ex=E9cuter du code dans lequel le
membre m_p serait non initialis=E9 ?
Ou bien est-ce que le compilateur est quand m=EAme capable
de construire dans mon dos des objets de la classe A sans
passer par A::A( char * p ) ?

9 réponses

Avatar
Sylvain
Manuel Leclerc wrote on 17/11/2006 18:53:

Ou bien est-ce que le compilateur est quand même capable
de construire dans mon dos des objets de la classe A sans
passer par A::A( char * p ) ?


non, il passera nécessairement par cet unique constructeur, mais
celui-ci peut être appelé avec un p==NULL, si votre souhait est de
pouvoir tjrs accéder à la donnée pointée sans test préalable, c'est raté.

Sylvain.

Avatar
Fabien LE LEZ
On 17 Nov 2006 09:53:38 -0800, "Manuel Leclerc"
:

private:
A();


Celui-là n'est pas utile, si je ne m'abuse.

est-ce que je suis bien certain qu'il n'y a aucun moyen
que je me retrouve a exécuter du code dans lequel le
membre m_p serait non initialisé ?


Si le code utilisateur ne fait pas de trucs vraiment louche, du style
A* ptr_a_bidon= reinterpret_cast<A*> (malloc (256));

alors tu es effectivement certain que le membre m_p sera initialisé
avec la valeur p (qui peut être NULL).
Mais comme il est public, il ne le restera pas forcément !

Exemple de code bien méchant :

A a (NULL);
char* ptr;
a.m_p= ptr;


Enfin bon, AMHA, tu joues avec le feu.
D'une manière générale, il y a deux types de classes :

- les "struct" à la C, n'ayant que des variables membres publiques, et
éventuellement quelques fonctions "helpers" :

struct C
{
int n;
double x;
double CarreDeX() const { return x*x; }
C();
};

- les classes proprement dites, dans lesquelles toutes les variables
membres sont privées.

class C2
{
public:
// Des fonctions
protected:
// Des fonctions
private:
// Des fonctions et des variables
};

Avatar
Manuel Leclerc

Manuel Leclerc:

private:
A();


Celui-là n'est pas utile, si je ne m'abuse.


Bon je viens de faire quelques tests, et effectivement
on dirait que ça revient au même en l'ommetant.

est-ce que je suis bien certain qu'il n'y a aucun moyen
que je me retrouve a exécuter du code dans lequel le
membre m_p serait non initialisé ?


Si le code utilisateur ne fait pas de trucs vraiment louche, du
style A* ptr_a_bidon= reinterpret_cast<A*> (malloc (256));

alors tu es effectivement certain que le membre m_p sera
initialisé avec la valeur p (qui peut être NULL).
Mais comme il est public, il ne le restera pas forcément !

Exemple de code bien méchant :

A a (NULL);
char* ptr;
a.m_p= ptr;


Oui, ou bien :
A a( (char*)0xdeadbeef );

tant qu'on y est, mais c'est un autre problème...

je cherche juste a ce que la construction
sans fournir le char* soit impossible.

Et je dois dire que je suis un peu étonné.
L'erreur provoquée par
A a;
ou
A * pa = new A[8];
m'est signalée par le linker, pas par le compilateur.
Est-ce que c'est parce que j'utilise un vieux machin
(MSCV 6) ?

--
Code qui fait des warnings == code de porc == deux baffes dans ta gueule
--libcaca Documentation, Coding style, General guidelines


Avatar
Sylvain
Manuel Leclerc wrote on 17/11/2006 22:30:

Et je dois dire que je suis un peu étonné.
L'erreur provoquée par
A a;
ou
A * pa = new A[8];
m'est signalée par le linker, pas par le compilateur.
Est-ce que c'est parce que j'utilise un vieux machin
(MSCV 6) ?


dans le même src que la définition de la classe ?
sinon un full rebuild ...

Sylvain.

Avatar
Manuel Leclerc


Et je dois dire que je suis un peu étonné.
L'erreur provoquée par
A a;
ou
A * pa = new A[8];
m'est signalée par le linker, pas par le compilateur.
Est-ce que c'est parce que j'utilise un vieux machin
(MSCV 6) ?


dans le même src que la définition de la classe ?


J'a merdé grave. En reprenant la "bonne" version
des sources après plein de bidouilles, j'ai bien
une erreur du compilateur :

- cannot access private member declared
(si j'inclus A(); en private dans la déclaration de la classe)

- no appropriate default constructor available
(si j'ommets A(); dans la déclaration de la classe)

--
Minitel : 36 15 Boulet
Police/pompier : 18
7+14 : 21
--ackboo


Avatar
Jean-Marc Bourguet
Fabien LE LEZ writes:

On 17 Nov 2006 09:53:38 -0800, "Manuel Leclerc"
:

private:
A();


Celui-là n'est pas utile, si je ne m'abuse.


Tu ne t'abuses pas. Le constructeur par défaut n'est implicitement défini
par le compilateur que si aucun constructeur n'est explicitement défini.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org


Avatar
fabien.chene
Jean-Marc Bourguet writes:

Fabien LE LEZ writes:

On 17 Nov 2006 09:53:38 -0800, "Manuel Leclerc"
:

private:
A();


Celui-là n'est pas utile, si je ne m'abuse.


Tu ne t'abuses pas. Le constructeur par défaut n'est implicitement
défini par le compilateur que si aucun constructeur n'est
explicitement défini.
^^^^^^

Je pense que tu as voulu dire « déclaré ».

--
Fab



Avatar
James Kanze
Fabien LE LEZ wrote:
On 17 Nov 2006 09:53:38 -0800, "Manuel Leclerc"
:

private:
A();


Celui-là n'est pas utile, si je ne m'abuse.


C'est correct. La présence de n'importe quel constructeur
utilisateur (y compris le constructeur de copie) inhibe sa
génération implicite.

est-ce que je suis bien certain qu'il n'y a aucun moyen
que je me retrouve a exécuter du code dans lequel le
membre m_p serait non initialisé ?


Si le code utilisateur ne fait pas de trucs vraiment louche, du style
A* ptr_a_bidon= reinterpret_cast<A*> (malloc (256));

alors tu es effectivement certain que le membre m_p sera initialisé
avec la valeur p (qui peut être NULL).
Mais comme il est public, il ne le restera pas forcément !

Exemple de code bien méchant :

A a (NULL);
char* ptr;
a.m_p= ptr;


Ou simplement :

char* ptr ;
A a( ptr ) ;

Il n'y a malheureusement aucune possibilité de s'assurer que
tous les pointeurs soient correctement initialisés.

(Mais ton point concernant les membres publics est juste.)

--
James Kanze (Gabi Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


Avatar
Jean-Marc Bourguet
(Fabien Chêne) writes:

Jean-Marc Bourguet writes:

Fabien LE LEZ writes:

On 17 Nov 2006 09:53:38 -0800, "Manuel Leclerc"
:

private:
A();


Celui-là n'est pas utile, si je ne m'abuse.


Tu ne t'abuses pas. Le constructeur par défaut n'est implicitement
défini par le compilateur que si aucun constructeur n'est
explicitement défini.
^^^^^^

Je pense que tu as voulu dire « déclaré ».


Oui.

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org