Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Garantir qu'une classe n'a (presque) pas de données à la compilation

7 réponses
Avatar
ALB
Bonjour,

j'ai une classe qui ne doit avoir qu'un pointeur comme donn=E9e membre.
J'aimerais =EAtre sur que cela ne change pas avec un static assert.

Une id=E9e ?

Adrien

7 réponses

Avatar
Patrick 'Zener' Brunet
Bonsoir.

"ALB" a écrit dans le message de news:


j'ai une classe qui ne doit avoir qu'un pointeur comme
donnée membre.
J'aimerais être sur que cela ne change pas avec un
static assert.

Une idée ?


A des subtilités d'interprétation près peut-être, le meilleur moyen de ne
pas faire grossir la classe, c'est d'interdire le rajout de données membres
réelles ou cachées (vtables)...

Le plus fiable amha, si ça vous convient, c'est de rendre cette classe non
héritable. Dans ces conditions, à moins de la modifier, sa taille est
verrouillée.

J'avais fait comme ça à une époque, avec une classe outil:

class CMakeNotInheritable
{
/* No data, but WARNING : sizeof != 0 */
protected:
inline
CMakeNotInheritable( void) {};
};

/*
* Directions for use :
* Just include in the superclass list of the class to
* become size-locked the following :
* private virtual CMakeNotInheritable
* The last derivated class if any will have to but
* will be unable to call the constructor (Gnark !)
*/

Mais ce n'est pas parfait, car en fait ça rajoute à votre classe le sizeof
de la classe outil: une classe ne peut pas avoir une taille nulle en
principe, car une instance ne pourrait plus être identifiée de manière
unique par son adresse.

En fait mon problème était différent: je travaille avec des classes qui
doivent être relogeables, et donc ne pas contenir de pointeur ou toute autre
donnée qui serait invalidée par un memcpy().
Le but était donc d'interdire uniquement l'incursion de vtables suite à des
extensions inconsidérées: virtual verboten !

Si ça peut vous aider...

--
Cordialement.
--
* Patrick BRUNET www.ipzb.fr
* E-mail: lien sur http://zener131.free.fr/ContactMe

Avatar
Fabien LE LEZ
On Tue, 3 Jun 2008 07:35:08 -0700 (PDT), ALB :

j'ai une classe qui ne doit avoir qu'un pointeur comme donnée membre.


A priori, la seule solution que je verrais est :

class MaClasse
{
...
};

class Reference
{
void* membre;
};

static_assert (sizeof(MaClasse) == sizeof(Reference));

Toutefois, le fonctionnement n'est pas garanti. Et en particulier, si
MaClasse a des fonctions virtuelles, je ne peux rien pour toi.

Avatar
Fabien LE LEZ
On Tue, 3 Jun 2008 19:45:32 +0200, "Patrick 'Zener' Brunet" :

Mais ce n'est pas parfait, car en fait ça rajoute à votre classe le sizeof
de la classe outil:


Pas forcément.
Une classe n'ayant aucune donnée membre a une taille "logique" de 0.
La taille d'un objet de cette classe est forcément supérieure à 0, à
cause d'une règle du C++ (liée à l'arithmétique des pointeurs).
Mais il n'y a pas de telle règle pour l'héritage simple. Faire hériter
une classe d'une classe vide peut ne pas changer sa taille.

Par contre, je crois que ça ne fonctionne pas en cas d'héritage
multiple.

Par ailleurs, si la classe de base contient des fonctions virtuelles,
elle contient forcément des données (au minimum, la vtable), et n'est
donc pas vide.

Avatar
Patrick 'Zener' Brunet
Bonsoir.

"Fabien LE LEZ" a écrit dans le message de news:

On Tue, 3 Jun 2008 19:45:32 +0200, "Patrick 'Zener' Brunet" :

Mais ce n'est pas parfait, car en fait ça rajoute à votre
classe le sizeof de la classe outil:


Pas forcément.
Une classe n'ayant aucune donnée membre a une taille
"logique" de 0.
La taille d'un objet de cette classe est forcément supérieure
à 0, à cause d'une règle du C++ (liée à l'arithmétique des
pointeurs).


Bon, on est d'accord là dessus: pas d'instance fantôme.

Mais il n'y a pas de telle règle pour l'héritage simple.
Faire hériter une classe d'une classe vide peut ne pas
changer sa taille.


Cela supprime la nécessité formelle de générer une taille factice en effet,
mais ça doit dépendre du compilo...
J'avais expérimenté ça avec MS Visual C++ v.6 et pour la classe "vide" toute
seule, il allouait 1 octet.
J'avoue n'avoir pas testé la variation du sizeof de la classe utilisatrice.

Donc j'ai préféré signaler l'éventualité.

Par contre, je crois que ça ne fonctionne pas en cas
d'héritage multiple.



J'imagine que des experts vont confirmer, mais en fait hériter plusieurs
fois de cette classe outil/verrou ne présente pas d'intérêt, et son mode
normal d'utilisation ne le permet pas.

Elle est faite pour verrouiller la taille d'une classe particulière, qui
peut avoir d'autres superclasses, mais qui ne pourra plus être elle-même
dérivée, c'est le but.
Donc il ne peut y avoir qu'une seule classe verrou dans tout le schéma
d'héritage.

Par ailleurs, si la classe de base contient des fonctions virtuelles,
elle contient forcément des données (au minimum, la vtable), et
n'est donc pas vide.



Donc comme je l'explique, le but était précisément d'éviter de compromettre
sa relogeabilité de cette manière.

Mais dans le principe ça ne change rien: quelle que soit sa généalogie, une
classe que l'on fait hériter en plus de ce verrou devient non héritable,
donc sa taille est verrouillée en l'état, sauf édition du code.

--
Cordialement.
--
* Patrick BRUNET www.ipzb.fr
* E-mail: lien sur http://zener131.free.fr/ContactMe


Avatar
Fabien LE LEZ
On Tue, 3 Jun 2008 23:54:27 +0200, "Patrick 'Zener' Brunet" :

J'imagine que des experts vont confirmer, mais en fait hériter plusieurs
fois de cette classe outil/verrou ne présente pas d'intérêt,


Non, mais il est commun d'hériter de plusieurs classes différentes.

Avatar
James Kanze
On Jun 3, 4:35 pm, ALB wrote:

j'ai une classe qui ne doit avoir qu'un pointeur comme donnée
membre. J'aimerais être sur que cela ne change pas avec un
static assert.


Je ne comprends pas trop le problème. Tu veux que la classe ne
change pas ; la solution la plus simple, c'est de protéger le
fichir où elle est définie contre l'écriture. Mais quelqu'un
peut toujours le copier, et en créer une autre classe qu'il peut
changer.

Une idée ?


Quel est le problème que tu cherches à résoudre ?

--
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
ALB
On 4 juin, 09:15, James Kanze wrote:
...
Quel est le problème que tu cherches à résoudre ?
...


En fait, je cherche à circonscrir l'aspect virtuel et à mettre des
assertions statiques sur l'interface :
pour schématiser :
- une classe NoeudMem (concrete (et copiable)) qui représente un noeud
d'arbre qui est responsable de ses fils (en terme de mémoire)
- une classe (virtuelle (et à peu près clonable)) NoeudInterface qui
gère les opérations "métiers" sur un noeud.
- NoeudMem a un pointeur intelligent vers NoeudInterface (qui permet
de simuler que l'"objet" NoeudInterface est une donnée membre)
- NoeudInterface a un pointeur (simple ou faible) vers NoeudMem (d'ou
le "*à peu près* clonable")
Pour éviter de mettre trop de friend, j'en arrive à exposer la méthode
clone de NoeudInterface. En contre partie, j'aimerais mettre un
static_assert sur le nombre de données membres de NoeudInterface pour
ne pas oublier les risques de l'ajout d'une donnée dans
NoeudInterface.


Adrien