J'essaie d'utiliser des modèles méta-programmation pour déterminer la classe de base. Existe-t-il un moyen d'obtenir automatiquement la classe de base sans se spécialiser explicitement pour chaque classe dérivée?
class foo { public: char * Name() { return "foo"; }; }; class bar : public foo { public: char * Name() { return "bar"; }; }; template< typename T > struct ClassInfo { typedef T Base; }; template<> struct ClassInfo<bar> { typedef foo Base; }; int main() { ClassInfo<foo>::Base A; ClassInfo<bar>::Base B; std::cout << A.Name(); //foo std::cout << B.Name(); //foo }
6 Réponses :
Je ne suis pas au courant d'un modèle de sélection de la classe de base et je ne suis pas sûr que l'un existe ou c'est même une bonne idée. Il y a beaucoup de façons dont cela brise l'extensibilité et va à l'encontre de l'esprit d'héritage. Lorsque Un Public Typedef dans la classe de base se gratte souvent les démches que vous pourriez avoir besoin d'avoir rayé et plus clair: p> bar code> hérités publiques
foo code>,
bar code> est un fort>
foo code> de tous les objectifs pratiques, et le code client ne doit pas nécessiter de distinguer la classe de base et la classe dérivée.
class foo { public: typedef foo name_making_type; ... };
int main() {
Foo::name_making_type a;
Bar::name_making_type b;
}
Bon. J'étais sur le point d'écrire ceci.
C'est pour un système de réflexion C ++ très léger. Le code "Client" fait la sérialisation et la messagerie de classe générales avec la déformation minimale possible de et / ou des ajouts à la classe d'origine.
Il est possible avec C ++ 11 et Par exemple: P> DeclType Code>. Pour cela, nous allons exploit qu'un pointeur à un membre n'est pas un pointeur dans la classe dérivée lorsque le membre est hérité d'une classe de base.
struct base2{ void f(){} };
struct not_deducible2 : base, base2{};
int main(){
decltype(base_of(¬_deducible2::f)) x; // error: 'f' is ambiguous
}
Merci Xeo, c'est une solution partielle très intéressante et très similaire à ce que je cherche. Je vais examiner ça plus loin
Pouvez-vous étendre votre solution pour accepter également le cas, où 'Base' contient la fonction membre de Const et non Const "F '?
Qu'est-ce qu'il y a avec la classe de base em>? Êtes-vous un programmeur .NET ou Java? P>
C ++ prend en charge plusieurs héritages et n'a pas non plus de classe de base courante globale. Ainsi, un type C ++ peut avoir zéro, un ou plusieurs classes de base. L'utilisation de l'article défini est donc contre-indiquée. P>
Étant donné que la classe de base em> n'a aucun sens, il n'y a aucun moyen de le trouver. p>
Il existe de fortes raisons d'efficacité que Java n'autorise qu'une classe de base et j'ai tendance à restructurer mon code C ++ pour les mêmes raisons - il est donc logique de créer un sous-ensemble utile.
@Vonriphenburger: la question doit alors indiquer: "Pour une classe avec une classe de base immédiate, héritée du public et non-virtuellement, est-il possible de découvrir le type de classe de base?" Et il n'est toujours pas clair si vous recherchez la classe de base immédiate, ou un autre ancêtre. Et Java permettant qu'une seule classe de base n'a rien à voir avec l'efficacité et beaucoup à voir avec la conception de la langue souhaitée pour forcer les codeurs "Le seul chemin véritable à OUP". Idem pour manque de fonctions libres.
J'ai dit pour la première base déclarée. Il semblait évident que la base immédiate était recherchée et non un ancêtre aléatoire, mais cela aurait pu être plus clairement indiqué. UM, merci pour votre contribution, Ben.
Mes solutions ne sont pas vraiment automatiques, mais le mieux que je puisse penser.
Solution intrusive C ++ 03 03: p>
class B {}; class A : public B {}; template<class T> struct TypeInfo; template<> struct TypeInfo<A> { typedef B Base; };
C'est à peu près exactement ce que je suis venu avec aussi. J'espérais qu'il y avait un truc de modèle hardcore que je n'étais pas au courant de cela pourrait l'extraire .. Je vais probablement utiliser la forme intrusive pour les classes avec contrôle de création complète et la forme non intrusive pour les classes semi-étrangères - Merci
Je recherche une résolution portable pour des problèmes similaires pendant des mois. Mais je ne trouve pas encore. P>
g ++ a Cependant, ce n'est pas portable. Clang ++ n'a actuellement pas de telle intrinsique. P> __ bases code> et
__ directe_bases code>. Vous pouvez les envelopper dans une liste de types, puis accéder à l'un de ses éléments, par ex. A
std :: tuple code> avec
std :: tuple_element code>. Voir libstDC ++ 's
avec C ++ 11, vous pouvez créer une méthode intrusive pour toujours avoir un membre avec Cette classe, vous aurez toujours un Le Cette base doit avoir 0 à l'heure d'exécution ou l'espace aérien car ses méthodes sont en ligne, ne faites rien et n'a aucun attribut. P > p> base_t code> lorsque votre classe n'hérite qu'à partir d'un parent:
parent_t code> alias, pour appeler les constructeurs parent comme s'il s'agissait de la base code> constructeurs avec un nom (probablement) plus court et un
base_t code> alias, pour rendre votre classe non consciente du type de type de classe de base s'il est long ou fortement modélisé. p>
parent_t code> est protégé pour ne pas l'exposer au public. Si vous ne voulez pas que le
base_t code> alias est public, vous pouvez toujours hériter
étiqued_base code> comme
protégé code> ou
privé code>, Aucun besoin de modification de la définition de la classe
marquéeded_base code>. p>
Utilisez
std :: is_base_of code>
@iammilind: Ce n'est que pour tester si une classe est la base d'une autre, vous devez connaître la classe de base à tester avec déjà.
De quoi en avez-vous besoin? Je ne pense pas que ce soit possible, mais il y a peut-être une approche différente pour résoudre le problème réel.
Ce n'est pas possible et je me soutiens avec le problème actuel - une connaissance explicite de la classe de base ne devrait généralement pas être nécessaire.
Au fait, la liaison d'une chaîne littéral à
Char * code> est obsolète i>. Utilisez
const char * code> à la place.