Comment calculer le décalage d'un membre de la classe au moment de la compilation?
Donné une définition de classe en C++
class A
{
public:
//methods definition
....
private:
int i;
char *str;
....
}
Est-il possible de calculer le décalage d'un membre de la classe au moment de la compilation à l'aide de C++ modèle de méta-programmation? La classe n'est pas de la GOUSSE, et peut avoir des méthodes virtuelles, primitif et les données de l'objet membre.
Que voulez-vous dire exactement par "décalage d'un membre de la classe"? Voulez-vous dire combien d'octets que vous avez à ajouter à un pointeur vers une instance de la classe (après, disons,
Vous pouvez utiliser
Voici le lien pour un exemple de code qui utilise offsetof().
et Hindol: en Raison de l'étendue de la fonctionnalité des structures en C++, dans cette langue, l'utilisation de offsetof est limitée aux "POD types", qui pour les classes, correspond plus ou moins à la C concept de struct (bien que non-classes dérivées uniquement avec des publics non-virtuel fonctions de membre et avec aucun constructeur et/ou le destructeur est aussi considérée comme POD).
D'accord, donc le subjonctif de l'humeur dans ma phrase, "si que ont été défini."
reinterpret_cast
'ing à char *
) pour obtenir le membre? Si oui, ne serait pas simple soustraction dites-vous?Vous pouvez utiliser
offsetof(A, i)
si qui ont été définis pour ces types. Consultez votre documentation du compilateur pour voir si elle est.Voici le lien pour un exemple de code qui utilise offsetof().
et Hindol: en Raison de l'étendue de la fonctionnalité des structures en C++, dans cette langue, l'utilisation de offsetof est limitée aux "POD types", qui pour les classes, correspond plus ou moins à la C concept de struct (bien que non-classes dérivées uniquement avec des publics non-virtuel fonctions de membre et avec aucun constructeur et/ou le destructeur est aussi considérée comme POD).
D'accord, donc le subjonctif de l'humeur dans ma phrase, "si que ont été défini."
OriginalL'auteur Jun Yuan | 2012-11-01
Vous devez vous connecter pour publier un commentaire.
Basé sur Matthieu M. de la réponse, mais plus court et sans macros:
Et il est appelé comme ceci:
Edit:
Jason Riz est correct. Ce ne sera pas produire une constante réelle expression en C++11. Il ne semble pas possible, compte tenu des restrictions dans http://en.cppreference.com/w/cpp/language/constant_expression -- en particulier, aucun pointeur de la différence et de la
reinterpret_cast
peut être une expression constante.Faible: avons-nous vraiment besoin de la
- (char*)nullptr
partie? Ne sommes-nous pas simplement en soustrayant de zéro? Je crois que l'on peut faire plus court 🙂Qui semble fonctionner sur gcc, mais pas llvm: erreur: impossible d'initialiser le retour de l'objet de type "size_t' (aka "unsigned int") avec une valeur r de type 'char *'
Si fait, si j'utilise le ci-dessus pour initialiser un constexpr il ne compile pas avec clang/llvm.
Cela provoque un comportement indéterminé par un déréférencement de pointeur null, et aussi par la soustraction de pointeurs quand les deux pointeurs ne pointent pas vers le même objet
OriginalL'auteur Glen Low
Bien... en C++11, vous pouvez calculer de telles compensations de droit régulières en C++ installations (c'est à dire, sans déléguer à un compilateur intrinsèque).
En action à liveworkspace:
Cependant cela repose sur la
t
être une référence à unconstexpr
exemple, ici, ce qui pourrait ne pas être applicable à toutes les classes. Il n'interdit pasT
d'avoir unvirtual
méthode bien que, ni même un constructeur, tant qu'il est unconstexpr
constructeur.Encore, c'est un obstacle. Dans des contextes non évaluée nous pourrions utiliser
std::declval<T>()
de simuler la présence d'un objet; tout en ayant aucun. Cela ne pose pas de conditions spécifiques sur le constructeur d'un objet, donc. D'autre part, les valeurs que nous pouvons extraire de ce contexte sont rares... et ils ne posent de problèmes avec les compilateurs gcc, trop... eh Bien, nous allons faux!En action à liveworkspace:
La seule question que je prévois, c'est avec
virtual
héritage, en raison de son exécution placement de l'objet de base. Je serais heureux d'être présenté avec d'autres défauts, si il y a des.href="http://en.cppreference.com/w/cpp/types/offsetof" >Attention => Si le type n'est pas un standard type de mise en page ou si le membre est un membre de données statiques ou une fonction de membre, alors le comportement est indéfini de l'aide de l'
offsetof
macro comme spécifié par la norme C est pas défini. En d'autres termes, laoffsetof
macro de C ne fonctionne qu'avec les C-tels que les types.Pourquoi êtes-vous à l'aide de
T const*
etchar const*
au lieu de simplementT*
etchar*
?pour le rendre plus explicite le fait que la fonction ne modifie pas son entrée (il n'est pas à travers la macro, mais il peut être utilisé sans).
Juste mordu par le nouveau compilateur ici 🙂 je suppose que le intentioin des normes est de rendre le financement de la compensation des classes de base dans une classe non-constante, mais si un champ est dans une classe de base, même si la classe de base dans la non-virtuel, il ne fonctionne pas. Je peux comprendre pourquoi virtuel classes de base serait tous sur la place, mais pour de simples bases ? J'avais un ancien modèle où vous mettez dans une classe de base, le "nœud" pour une liste ( un intrusive noeud sur l'objet ) Et la liste générique de code nécessaire uniquement le décalage vers le nœud. Hélas ne pouvez pas le faire 😐
OriginalL'auteur Matthieu M.
Non, pas en général.
La offsetof macro existe pour POD (plain old données) les structures, il peut être prolongé légèrement avec le C++0x à disposition standard des structures (ou d'autres semblables à de légères extensions). Donc, pour ceux des cas restreints, vous avez une solution.
C++ offre beaucoup de liberté aux rédacteurs du compilateur. Je ne sais pas de toute clause qui permettrait d'éviter certaines classes de la variable de compensations pour les membres de la classe -- cependant, je ne suis pas sûr de savoir pourquoi un compilateur pourrait le faire. 😉
Maintenant, une approche pour garder votre code conforme aux standards, mais ont encore des décalages, serait de coller vos données dans un POD (ou C++0x extension) sous-structure, sur laquelle offsetof de travail, puis de travailler sur la sous-structure, plutôt que sur l'ensemble de la classe. Ou vous peuvent renoncer à l'application des normes. Le décalage de votre structure au sein de votre classe ne serait pas connu, mais le décalage du membre au sein de la structure serait.
Une question importante à se poser est "pourquoi dois-je veux et dois-je vraiment avoir une bonne raison"?
C'est un cas d'ennemi de la plaine des données anciennes: mettre un non-standard de la classe de mise en page dans une base de données de cette façon va être une mauvaise idée.
OriginalL'auteur Yakk - Adam Nevraumont
Dans le livre de 1996, "à l'Intérieur de l'Objet C++ Modèle", écrit par Stanley B. Lippman, l'un des premiers C++ designer, fait référence à de Pointeur vers des Fonctions de Membre dans le Chapitre 4.4
la valeur retournée de prendre l'adresse d'un non membre de données est la valeur de l'octet de la situation du membre dans la classe de mise en page (plus 1). On peut penser que c'est un incomplètes valeur. Il doit être lié à l'adresse d'un objet de classe avant qu'une instance de membre ne peut être consulté.
Alors que j'ai vaguement rappeler que +1 à partir de quelque part dans certains vie antérieure, je n'ai jamais vu ou fait usage de cette syntaxe avant.
Au moins d'après la description, ce qui semble être une manière sympa de faire "presque" le décalage.
Mais Il ne semble pas fonctionner, au moins dans GCC. Je reçois un
Quelqu'un at-il une histoire derrière ce qui se passe ici? C'est quelque chose comme ce encore possible?
Problème avec le site web -- obsolète livres ne meurent jamais...
int (t::*pmf)()
est qu'un pointeur de fonction membre?OriginalL'auteur In Question