Pour un projet C++, j’ai besoin de créer des tableaux d’objets abstraits, et je vois vraiment pas comment faire.
en fait, j’ai une class A abstraite dont dérivent les classes B et C instanciables. je vais devoir mettre toutes mes instances des classes B et C dans un tableau, mais sans savoir àl’avance si l’objet de la case 1 sera un B ou un C. Dont a priori, j’ai besoin de créer un tableau d’objets de type A. Et c’est là que ca part en sucette : il me dit (et c’estlogique) que l’objet A est pas instanciable… alors si vous avez une solution, je suis preneur.
J’ai bien pensé à faire un tableau de pointeurs qu’on allouerait avec des new au fur et mesure du besoin, mais ca m’étonne qu’il n’y ait pas mieux…
Y’a pas mieux… En fait la solution c’est bien d’allouer tes objets en B ou C dynamiquement et de sauver la référence (castée en pointeur de A) dans ton tableau.
Genre:
[codebox]
…
class_a* array_a = new class_a[n];
…
array_a[i] = (class_a*) new class_b b;
[/codebox]
Effectivement, en C un tableau ne peut contenir que des éléments de types identiques, car cela simplifie pas mal de choses et le C est un langage conçu à l’époque où la moindre petite économie de performances valait la peine. Le C++ ayant hérité les tableaux du C, le problème y est identique.
Vu que tous les éléments doivent être du même type, un tableau de pointeurs A est la seule solution, car directement stocker des A n’est pas possible. Premièrement car dans ton cas la classe A est abstraite et donc non-instanciable, mais même si ce n’était pas le cas ce serait une erreur, car on aurait alors ce qu’on appelle du “slicing”. C’est à dire que si tu as un objet de type B qui dérive d’un type A, et que tu assignes ton objet B à une instance du type A, bah tu perds tout ce qui n’est pas contenu dans A. (je ne sais pas si c’est très clair)
Tu dois omettre de nous préciser qq chose parce qu’il est autorisé de stocker un pointeur de type B dans une variable de type A puisque B EST aussi de type A (abstract ou non). Le cast, oublie.
En clair, ce qui suit compile sans problème
[codebox]#include <stdio.h>
class A
{
public:
virtual void f(void) = 0 ;
virtual ~A() {} ;
} ;
class B : public A
{
public:
void f(void) { } ;
} ;
class C : public A
{
} ;
int main(void)
{
A * tab[5] ;
tab[0] = new B() ;
delete tab[0] ;
return( 0 ) ;
Comme Drealmer y fait allusion, si tu suis le squelette que j’ai écrit, toutes les variables membres déclarées dans la classe B (par ex) ne seront pas accessible directement via une syntaxe de type :
[codebox]tab[0]->the_variable_declared_in_B[/codebox]
Il faut dans ce cas utiliser une méthode virtuelle de façon à remonter au niveau de la class B et ainsi avoir accès a ses membres… Merde, pas sûr d’être plus clair B)
EDIT: Drealmer a en parti raison sur son mode “emmerdeur”. Oui, en partie car sa correction (juste) semble insinuer qu’un pointeur n’est pas une variable, et c’est faux … hihihi… j’aurais dû écrire “dans une variable de type A *” pour être cohérent avec la tournure B)
Ici tu fais un tableau dynamique de A, or c’est une classe abstraite on peut pas. Ce dont on a besoin ici c’est d’un tableau de pointeurs A, voire code de Moktar.
Et ici… ça part totalement en vrille, déjà le b ne veut rien dire, ensuite tu cast explicitement un pointeur B en pointeur A, alors que c’est déjà un pointeur A par définition, et ensuite, tu mets le pointeur A comme élément d’un tableau d’objets A, qui en plus ne peut pas exister.
T’as vraiment fait très fort B)
Ah, et puis j’oubliais, le cast « (type) valeur » c’est un cast C, pas un cast C++… static_cast(valeur) ça c’est du C++.
Non j’ai totalement raison d’abord ! Un pointeur est toujours une variable (ou une constante, héhé), mais une variable n’est pas toujours un pointeur.
EDIT: Juste pour le goût de l’exactitude, je ne suis pas certains qu’une constante puisse être considérée comme un pointeur voire je suis convaincu du contraire :D. Ce n’est pas parce qu’on manipule une adresse, que ça s’appelle “pointeur”
Un truc du type
((struct machin *)0xAABB)->one_member = one_value ;
Je ne pense pas que l’on puisse décemment appeler 0xAABB un pointeur B)
[quote=« Moktar, post:9, topic: 32766 »]Un truc du type
((struct machin *)0xAABB)->one_member = one_value ;
Je ne pense pas que l’on puisse décemment appeler 0xAABB un pointeur B)[/quote]
Non 0xAABB n’est un pointeur car tu dois le caster explicitement pour l’utiliser… Quand je disais constante, je parlais de ça:
Drealmer s’élance et dans une tentative désespérée, reprend la balle sur un retourné spectaculaire mais malheureusement, la balle vient heurter la barre transversale. Moktar a déjà plongé envoyant la balle au fond des filets d’un grand coup de tête B)
const char * hello = "hello world";
Dans cet exemple, hello est bien un pointeur mais ce n’est pas la variable hello qui est constante mais son contenu, c’est à dire la zone mémoire occupée par « hello world ». Si je voulais décrire le pointeur constant (la variable donc), j’aurais écrit.
char * const hello = "hello world";
Pointeur : variable contenant une adresse. C’est bon ça ? B)
Je crois que c’est un concours à celui qui coupe en deux le plus petit bout de papier
Alors je vais faire mon boulet mais de toute façon je suis un asocial, mais personellement on prend jamais trop tôt le pli des smarts pointers et des vectors. Je suis sans doute méga idiot mais je veux qu’on m’explique l’avantage d’un tableau C en C++.
Etant donnée la question de molyss, j’en déduis qu’il apprend le C++. Et qu’on le veuille ou non les tableaux et les pointeurs font partie du C++, c’est important de les apprendre tout comme le reste pour ensuite apprécier la valeur des concepts plus avancés comme les smarts pointers et les containers STL. En partisan de l’apprentissage de la marche avant la course, je le soutiens dans sa démarche B)