[c++] dynamic_cast...

dynamic_cast... [c++] - Programmation

Marsh Posté le 21-01-2002 à 15:28:32    

saluti,
 
 
est-il possible de faire  
 
A * machin;
B * brol;
brol = dynamic_cast <B *> (machin);
cout << brol->data();
 
 
mais en plus court ; sans passer par une variable intermediaire (brol) ?

Reply

Marsh Posté le 21-01-2002 à 15:28:32   

Reply

Marsh Posté le 21-01-2002 à 15:35:06    

logiquement, ça:
 

Code :
  1. A* pTaClasse = new A();
  2. cout << (dynamic_cast <B*> (pTaClasse))->data();


 
devrait passer sans pb...

Reply

Marsh Posté le 21-01-2002 à 15:35:59    

merci monsieur :)

Reply

Marsh Posté le 21-01-2002 à 15:39:23    

de rien.
J'parle; g jammais utilisé ce truc, ms ça parait logique.
c quoi l'intéret de ça par rapport à un cast "normal" ?  
style :

Code :
  1. A* pTaClasse = new A();
  2. cout << ((B*)pTaClasse)->data();


 
tu connaissais ça !?

 

[edtdd]--Message édité par El_Gringo--[/edtdd]

Reply

Marsh Posté le 21-01-2002 à 15:43:17    

ben en fait j'ai  
 
class A
 
class B : public A
{
  int data();
}
 
class C : public A
{
  string data();
}
 
et apparement, il faut employer dynamic_cast
 
parce que data() n'existe pas dans A
sinon, suffit de mettre virtual data() dans A (je crois)
 
enfin, je sais pas si je dis des conneries, mais c'est ce que j'ai compris

Reply

Marsh Posté le 21-01-2002 à 15:55:59    

Bah oui, mais le pb, c que, c pas juste en castant A* en B* que tu vas mettre des données dans ce vers quoi pointe pTaClasse.
je suis curieux de voir ce qu'y se passe qd tu fais le:
cout << ((B*)pTaClasse)->data();
 
Le cast, ça peut foutre une merde pas possible si c mal utilisé.
Tu peut toujours caster une classe en n'importe quelle classe dont elle hérite (directement ou non)
par exemple, dans ton cas, tu peut caster B en A, ou C en A, sans pb.
Par contre, pour caster un pointeur vers un objet de type A en un pointant sur un objet de type B, il faut que l'objet pointé par le pointeur de type A soit en fait un objet de type B...
oula... embrouillé tt ça...dsl :D

Reply

Marsh Posté le 21-01-2002 à 16:03:45    

arrete de m'embrouiller euh :na:  
 
 
bong, je te donne mon programme et t'as qu'à voir:
 

Code :
  1. #include <vcl.h>
  2. #include <iostream.h>
  3. #include <fstream.h>
  4. #include <iomanip.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <math.h>
  8. #define MAX 100
  9. class tevenement
  10. {
  11. short flag;
  12. string name;
  13. float time;
  14. public:
  15.       tevenement() { flag=0; name=""; time=0;}
  16.  tevenement(short court, string corde, float bateau) { flag=court; name=corde; time=bateau;}
  17.       virtual void affiche() { cout << flag << " " << name << " " << time << " ";}
  18.  ~tevenement() {}
  19.       string namek() { return name;}
  20.       float tempete() { return time;}
  21.       short flagada() { return flag;}
  22.      tevenement & operator=(const tevenement &);
  23. };
  24. tevenement & tevenement::operator=(const tevenement & kablouille)   //------  =
  25. {
  26.    flag = kablouille.flag;
  27.    name = kablouille.name;
  28.    time = kablouille.time;
  29.    return *this;
  30. }
  31. class tdroit : public tevenement
  32. {
  33. string fichier;
  34. public:
  35.       tdroit() { fichier="";}
  36.  tdroit(short, string, float, string);
  37.       void affiche()
  38.       {
  39.          tevenement::affiche();
  40.          cout << fichier << endl;
  41.       }
  42.  ~tdroit() {}
  43.       string fitchier() { return fichier;}
  44.      tdroit & operator=(const tdroit &);
  45. };
  46. class tpermission : public tevenement
  47. {
  48. float number;
  49. public:
  50.       tpermission() { number=0;}
  51.  tpermission(short, string, float, float);
  52.       void affiche()
  53.       {
  54.          tevenement::affiche();
  55.          cout << number << endl;
  56.       }
  57.  ~tpermission() {}
  58.       float prems() { return number;}
  59.       tpermission & operator=(const tpermission &);
  60. };
  61. tdroit::tdroit(short court, string corde, float bateau, string fil) : tevenement(court, corde, bateau)
  62. {
  63. fichier = fil;
  64. }
  65. tpermission::tpermission(short court, string corde, float bateau, float barque) : tevenement(court, corde, bateau)
  66. {
  67. number = barque;
  68. }
  69. tdroit & tdroit::operator=(const tdroit & kablouille)   //------  =
  70. {
  71.    tevenement::operator=(kablouille);
  72.    fichier = kablouille.fichier;
  73.    return *this;
  74. }
  75. tpermission & tpermission::operator=(const tpermission & kablouille)   //------  =
  76. {
  77.    tevenement::operator=(kablouille);
  78.    number = kablouille.number;
  79.    return *this;
  80. }
  81. /**********************************************************************/
  82. //    fin déclaration des classes
  83. /**********************************************************************/
  84. template <class T> int compare(T a, T b)
  85. {
  86. if(a < b)
  87. {
  88.  return (-1);
  89. }
  90. else if(a > b)
  91. {
  92.  return 1;
  93. }
  94. else return 0;
  95. }
  96. int sort_name(const void *a, const void *b);
  97. int sort_time(const void *a, const void *b);
  98. /*************************************************************************/
  99. /*
  100. //      main()
  101. */
  102. /*************************************************************************/
  103. int main()
  104. {
  105.    int cptr;
  106.    ifstream entree("sys.log", ios::in);
  107.    if(!entree)
  108.    {
  109.       cerr << "le fichier n'a pas pu être ouvert.\n";
  110.       exit(1);
  111.    }
  112.    char lettre;
  113.    int abs = 1;
  114.    int ligne = 0;
  115. // tevenement **vecteur = new tevenement*[MAX];
  116. // delete[] vecteur;
  117.    tevenement *vecteur[MAX];
  118.    float time = 0;
  119.    int moiur;
  120.    int barque=0;
  121.    int etre_decimal = 0;
  122.    int nb_decimales = 0;
  123.    float decitime = 0;
  124.    short flag;
  125.    string nom = "";
  126.    string string_time = "";   // à transformer en float
  127.    string fichier = "";
  128.    while(entree.get(lettre))
  129.    {
  130.       if((int) lettre == 10)
  131.       {
  132.          if(nb_decimales)
  133.          {
  134.             time += decitime / pow(10,nb_decimales);
  135.          }
  136.          if(!flag) // permission
  137.          {
  138.             vecteur[ligne] = new tpermission(flag, nom, time, barque);
  139.          }
  140.          else   // droit
  141.          {
  142.             vecteur[ligne] = new tdroit(flag, nom, time, fichier);
  143.          }
  144.          ligne++; abs = 1;
  145.          nom = ""; string_time = ""; etre_decimal = 0; nb_decimales = 0;
  146.          time = 0; decitime = 0; fichier = ""; barque = 0;
  147.       }
  148.       else if((int) lettre == 59)
  149.       {
  150.          abs++;
  151.       }
  152.       else
  153.       {
  154.          if(abs == 1)
  155.          {
  156.             flag = lettre-'0';
  157.             if(flag)
  158.                barque = 0;
  159.             else
  160.                fichier = "";
  161.          }
  162.          else if(abs == 2)
  163.          {
  164.             nom += lettre;
  165.          }
  166.          else if(abs == 3)
  167.          {
  168.             if((int)lettre == 46) { etre_decimal = 1;}
  169.             else
  170.             {
  171.                moiur = lettre-'0';
  172.                if(!etre_decimal)
  173.                {
  174.                   time = 10 * time + moiur;
  175.                }
  176.                else
  177.                {
  178.                   decitime = 10 * decitime + moiur;
  179.                   nb_decimales++;
  180.                }
  181.             }
  182.          }
  183.          else
  184.          {
  185.             if(!flag)
  186.             {
  187.                moiur = lettre-'0';
  188.                barque = 10 * barque + moiur;
  189.             }
  190.             else
  191.             {
  192.                fichier += lettre;
  193.             }
  194.          }
  195.       }
  196.    }
  197.    entree.close();
  198.    if((int) lettre != 10)
  199.    {
  200.       if(nb_decimales)
  201.       {
  202.          time += decitime / (pow(10,nb_decimales));
  203.       }
  204.       if(!flag)      // permission
  205.       {
  206.   vecteur[ligne] = new tpermission(flag, nom, time, barque);
  207.       }
  208.       else        // droit
  209.       {
  210.   vecteur[ligne] = new tdroit(flag, nom, time, fichier);       
  211.       }
  212.       ligne++;
  213.    }
  214.    ofstream name_file("sys_name.log", ios::out);
  215.    if(!name_file)
  216.    {
  217.       cout << "creation fichier impossible\n";
  218.       exit(1);
  219.    }
  220. qsort((void *)vecteur, ligne, sizeof(vecteur[0]), sort_name);
  221. for(int i=0; i<ligne; i++)
  222. {
  223.       name_file << vecteur->flagada() << ";" << vecteur[i]->namek() << ";"
  224.                 << vecteur[i]->tempete() << ";";
  225.       if(vecteur[i]->flagada())
  226.       {
  227.          name_file <<  (dynamic_cast <tdroit *> (vecteur[i]))->fitchier() << endl;
  228.       }
  229.       else
  230.       {
  231.          name_file << (dynamic_cast <tpermission *> (vecteur[i]))->prems() << endl;
  232.       }
  233. }
  234.    cout << "fichier sys_name.log encode\n";
  235.    name_file.close();
  236.    ofstream time_file("sys_time.log", ios::out);
  237.    if(!time_file)
  238.    {
  239.       cout << "creation fichier impossible\n";
  240.       exit(1);
  241.    }
  242. qsort((void *)vecteur, ligne, sizeof(vecteur[0]), sort_time);
  243. for(int i=0; i<ligne; i++)
  244. {
  245.       time_file << vecteur[i]->flagada() << ";" << vecteur[i]->namek() << ";"
  246.                 << vecteur[i]->tempete() << ";";
  247.       if(vecteur[i]->flagada())
  248.       {
  249.          time_file <<  (dynamic_cast <tdroit *> (vecteur[i]))->fitchier() << endl;
  250.       }
  251.       else
  252.       {
  253.          time_file << (dynamic_cast <tpermission *> (vecteur[i]))->prems() << endl;
  254.       }
  255. }
  256.    cout << "fichier sys_time.log encode\n";
  257.    time_file.close();
  258.    for(int i=0; i<ligne; i++)
  259.    {
  260.       delete vecteur[i];
  261.    }
  262. //   cin >> cptr;
  263. return 0;
  264. }
  265. /***********************************************/
  266. /*
  267. //    fonctions de tri
  268. */
  269. /***********************************************/
  270. int sort_name(const void *a, const void *b)
  271. {
  272.    tevenement *alpha, *beta;
  273.    string corde, cordelette;
  274.    alpha = *((tevenement**)a);
  275.    beta = *((tevenement**)b);
  276.    corde = alpha->namek();
  277.    cordelette = beta->namek();
  278.    return compare(corde, cordelette);
  279. }
  280. int sort_time(const void *a, const void *b)
  281. {
  282.    tevenement *alpha, *beta;
  283.    float tempete, tempest;
  284.    alpha = *((tevenement**)a);
  285.    beta = *((tevenement**)b);
  286.    tempete = alpha->tempete();
  287.    tempest = beta->tempete();
  288.    return compare(tempete, tempest);
  289. }


 
 
il faut aussi faire un fichier [i]sys.log avec ca dedans :
 
0;frodon;3.76;36
0;aragorn;4.37;42
1;bilbon;2.76;test.dat
0;sauron;8.32;41
1;saroumane;7.75;mechant.dat
1;gandalf;7.37;gentil.dat
0;legolas;5.25;54
0;gimli;4.32;22
1;boromir;2.83;hom.dat
0;elrond;5.13;12
 
 
ps : bong, j'ai fait ca comme une tache, mais je sais pas programmer, alors voili :na:  :D  
 
pps : en fait oui, ca doit être parce que c'est des pointeurs vers des classes dérivées qu'il faut dynamic_caster...
 
mais bong, le monsieur il a dit de dynamic_cast alors je dynamic_cast :sweat:  
 
 
 
 :hello:

Reply

Marsh Posté le 21-01-2002 à 16:09:41    

...quel monsieur !?
g pas le temps de lire tout ton listing là, désolé !
Mais essaye, tu verras bien si ça marche.

Reply

Marsh Posté le 21-01-2002 à 16:35:23    

ben ca marche.
 
c'était juste pour essayer de répondre à ta question...
 
le monsieur, c'est le monsieur qui me donne cours. Enfin, qui aurait dû me donner cours parce que je suis arrivé avec quelques mois de retard :sweat:  
 
 
enfin bong, ca marche, c'est le principal.  
Pour la théorie, je capte rieng. Alors je teste en mettant une étoile ici, puis je le mets ailleurs si ca marche pas, ... , et si ca ne marche toujours pas, je demande ici :)
 
voili :hello:

Reply

Marsh Posté le 21-01-2002 à 17:03:35    

El_Gringo a écrit a écrit :

 
J'parle; g jammais utilisé ce truc, ms ça parait logique.
c quoi l'intéret de ça par rapport à un cast "normal" ?  




 
Soit classe B : public A
le cast normal B* b =(B*) a;
est un maquillage qui sert juste a faire taire le compilateur
quand il s'agit de pointeurs (sinon il refusera quand meme
de faire des casts de types incompatibles a la compilation).
Mais cela suppose que la personne sait ce qu'elle fait;
c'est a dire qu'elle sait que 'a' pointe vers un objet de type 'B' a l'execution ce qui n'est pas evident dans ton exemple.
 
le dynamic_cast est plus safe. C'est a dire qu'avant de te rendre
ton pointeur vers un objet de type B elle verifiera au préalable que 'a' est bien de type 'B' (grace aux informations de types).
Sinon elle levera une exception. (Bad_cast).
 
A+
LEGREG

Reply

Marsh Posté le 21-01-2002 à 17:03:35   

Reply

Marsh Posté le 21-01-2002 à 17:05:25    

legreg a écrit a écrit :

 
 
Soit classe B : public A
le cast normal B* b =(B*) a;
est un maquillage qui sert juste a faire taire le compilateur
quand il s'agit de pointeurs (sinon il refusera quand meme
de faire des casts de types incompatibles a la compilation).
Mais cela suppose que la personne sait ce qu'elle fait;
c'est a dire qu'elle sait que 'a' pointe vers un objet de type 'B' a l'execution ce qui n'est pas evident dans ton exemple.
 
le dynamic_cast est plus safe. C'est a dire qu'avant de te rendre
ton pointeur vers un objet de type B elle verifiera au préalable que 'a' est bien de type 'B' (grace aux informations de types).
Sinon elle levera une exception. (Bad_cast).
 
A+
LEGREG  




 
Ok, merci pour cet éclaircissemment.

Reply

Marsh Posté le 21-01-2002 à 17:16:33    

art_dupond a écrit a écrit :

 
parce que data() n'existe pas dans A
sinon, suffit de mettre virtual data() dans A (je crois)




 
non il ne suffit pas de mettre virtual parce que  
tes deux fonctions n'ont pas la meme signature
B::data() renvoie un int
et C::data() renvoie un string.
 
Il n'y a pas d'autre solution que de caster lors de l'execution.
 
il faut compiler en precisant que tu veux les RTTI (runtime type information) et evidemment catcher les exceptions ou verifier le type avant de faire ton cast.
 
Il y a des solutions plus propres pour faire ce que tu veux
faire une fonction virtuelle definie dans A
qui A::PrintOnStream(ostream os)
que tu redefinis pour chacune des sous-classes B et C.
ce qui n'impose pas de savoir combien de classes
derivant de A tu auras au final. (c'est l'interet d'avoir
des fonctions virtuelles par rapport au switch)
 
A+
Gregory

Reply

Marsh Posté le 21-01-2002 à 21:10:32    

legreg a écrit a écrit :

 
le dynamic_cast est plus safe. C'est a dire qu'avant de te rendre
ton pointeur vers un objet de type B elle verifiera au préalable que 'a' est bien de type 'B' (grace aux informations de types).
Sinon elle levera une exception. (Bad_cast).
 
A+
LEGREG  




Une exception est levée pour des dynamic_cast ratés sur des références.
Par contre  avec des pointeurs, NULL est retourné si le cast échoue.

 

[edtdd]--Message édité par Verdoux--[/edtdd]

Reply

Marsh Posté le 22-01-2002 à 00:22:15    

oops oui.
 
Quel debutant je fais :D
 
LEGREG

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed