Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1668 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  [C++]appel de fonction pure

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C++]appel de fonction pure

n°1257723
shaman3
Posté le 02-12-2005 à 18:09:21  profilanswer
 

Code :
  1. #include <iostream>
  2. #include <conio.h>
  3. using namespace std;
  4. class BaseValue
  5. {
  6. public:
  7. virtual ~BaseValue(){}
  8. virtual const type_info & GetType() const = 0;
  9. };
  10. template<class ValueType>
  11. class TypeValue : public BaseValue
  12. {
  13. public:
  14. TypeValue(const ValueType & value)
  15.  : Value(value){ }
  16. virtual const type_info & GetType() const {
  17.  return typeid(Value);
  18. }
  19. ValueType Value;
  20. };
  21. class RefAny
  22. {
  23. public: // structors
  24. RefAny(){ }
  25. template<class ValueType>
  26.  RefAny(const ValueType & value)
  27.  : content(&TypeValue<ValueType>(value)) { }
  28. template<typename ValueType>
  29.  void GetValue(ValueType * value){
  30.   *value = static_cast<TypeValue<ValueType>*>(content)->Value;
  31.  }
  32. template<typename ValueType>
  33.  void GetValueType(ValueType * value){
  34.   if (content->GetType() == typeid(ValueType)) // content->type() plantage appel de fonction pure
  35.    *value = static_cast<TypeValue<ValueType>*>(content)->Value;
  36. //   else
  37. //    wxASSERT(false);
  38.  }
  39. BaseValue* content;
  40. };
  41. int main()
  42. {
  43. int  Entier;
  44. double Reel;
  45. RefAny hTemp(3.14);
  46. hTemp.GetValue(&Reel);
  47. hTemp = 345;
  48. hTemp.GetValue(&Entier);
  49. hTemp = 784;
  50. hTemp.GetValueType(&Entier); // --> plantage appel de fonction pure
  51. hTemp.GetValueType(&Reel); // --> plantage appel de fonction pure
  52. std::cout << "Appuyer sur une touche..." << endl;
  53. _getch();
  54. }


 
content->GetType()  devrait faire un appel à la méthode GetType() de TypeValue mais produit soit un plantage soit un appel de fonction pure de BaseValue
Je pense que le problème doit venir de l'utilisation de template, mais j'aimerais bien comprendre...


---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
mood
Publicité
Posté le 02-12-2005 à 18:09:21  profilanswer
 

n°1257746
jesus_chri​st
votre nouveau dieu
Posté le 02-12-2005 à 18:52:08  profilanswer
 

(&TypeValue<ValueType>(value))    
 
adresse d'une variable locale à durée de vie courte ?

n°1257758
shaman3
Posté le 02-12-2005 à 19:21:57  profilanswer
 

: content(&TypeValue<ValueType>(value))    {    } initialise le pointeur BaseValue* content; avec l'adresse de la variable passée au constructeur par exemple "&Reel",
cette variable est détruite à la fin du main() il n'y a donc pas ce problème surtout que les appels hTemp.GetValue(&Entier); fonctionnent bien.


---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
n°1257778
++fab
victime du syndrome IH
Posté le 02-12-2005 à 19:57:54  profilanswer
 

shaman3 a écrit :

: content(&TypeValue<ValueType>(value))    {    } initialise le pointeur BaseValue* content; avec l'adresse de la variable passée au constructeur par exemple "&Reel",


 
non, jesus a (presque) raison. tu initialises BaseValue* avec l'adresse d'un temporaire ... Après, t'as une splendide erreur. je suis étonné que ton compilateur ne t'ai pas averti.


Message édité par ++fab le 02-12-2005 à 20:02:05
n°1257808
shaman3
Posté le 02-12-2005 à 21:09:40  profilanswer
 

Merci pour votre aide, effectivement j'ai zappé la création de cette variable temporaire, mais ce qui est étonnant dans cette erreur c'est que visual studio ne la pas signalée et que le plantage se produise après les appels hTemp.GetValue(&Reel);et de hTemp.GetValue(&Entier); qui fonctionne !!! sur une variable qui aurait du déjà être détruite à ce moment... Le fait que cette variable n'est pas détruite immédiatement génère des erreurs à des endroits différents (bonjour la prise de tête).
jesus_christ : Je te donne le droit de me crucifier sur la place publique :)


---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
n°1257832
++fab
victime du syndrome IH
Posté le 02-12-2005 à 21:41:12  profilanswer
 

shaman3 a écrit :

Merci pour votre aide, effectivement j'ai zappé la création de cette variable temporaire, mais ce qui est étonnant dans cette erreur c'est que visual studio ne la pas signalée et que le plantage se produise après les appels hTemp.GetValue(&Reel);et de hTemp.GetValue(&Entier); qui fonctionne !!!


 
BaseValue* content pointe on ne sait ou, en tout cas, plus vers une instance de BaseValue ou une instance d'une classe dérivée de BaseValue.
D'ou l'appel irréel à une fonction virtuelle pure.
 
D'autre part, tes warnings ne sont pas bien positionnés, c'est pas possible que ton compilo ne puissent rien dire !


Message édité par ++fab le 02-12-2005 à 21:43:32
n°1257856
shaman3
Posté le 02-12-2005 à 22:19:08  profilanswer
 

"warnings"  tu veux dire les points d'arrêt non ? En mode debug avec visual studio 2003 puis en mode pas à pas (touche F10 et F11) il exécute sans problèmes les deux appels hTemp.GetValue(&Reel);et hTemp.GetValue(&Entier); et le contenu des variables est correct, bref je suis aussi étonné que toi de ce comportement. Que dit la norme la dessus ? comment se comporte les d'autres compilateurs comme Gcc sur ce problème ?


---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
n°1257857
scol30
Posté le 02-12-2005 à 22:19:55  profilanswer
 

Juste pour info le programme pris sans modif ne compile pas sous devC++. Avec un message indiquant ce que jesus mentionnait.
 
Stef

n°1257863
++fab
victime du syndrome IH
Posté le 02-12-2005 à 22:28:58  profilanswer
 

si warning, prendre l'adresse d'un temporaire pour l'affecter à un pointeur, c'est tres louche.
gcc réagit de la meme maniere, mais emet des warnings explicite.

n°1257867
shaman3
Posté le 02-12-2005 à 22:45:52  profilanswer
 

En fait si, mais il faut passer en Niveau 4 (/W4) pour avoir ça :
e:\programmation\SOURCE_dotnet\console\Array_multi_type\Array_multi_type.h(246) : warning C4238: extension non standard utilisée : classe rvalue utilisée comme lvalue
        main.cpp(552) : voir la référence à l'instanciation du modèle de fonction 'RefAny::RefAny<double>(const ValueType & )' en cours de compilation
        with
        [
            ValueType=double
        ]
e:\programmation\SOURCE_dotnet\console\Array_multi_type\Array_multi_type.h(246) : warning C4238: extension non standard utilisée : classe rvalue utilisée comme lvalue
        main.cpp(557) : voir la référence à l'instanciation du modèle de fonction 'RefAny::RefAny<int>(const ValueType & )' en cours de compilation
        with
        [
            ValueType=int
        ]
pour le plantage différé quelqu'un m'indique que c'est normal :
>il s'agit de ce qu'on appelle un "comportement
>indéfini" -- la norme ne prévoit pas ce qui va se passer, et
>effectivement on a un plantage à un endroit bizarre, éventuellement
>aléatoire."
Donc c'est moi qui à tout faux(comme dab), et visual fonctionne parfaitement.


Message édité par shaman3 le 02-12-2005 à 22:59:51

---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
mood
Publicité
Posté le 02-12-2005 à 22:45:52  profilanswer
 

n°1257891
++fab
victime du syndrome IH
Posté le 02-12-2005 à 23:28:45  profilanswer
 

je viens de voir le thread. Oui, c'est UB, mais je ne sais pas si le warning que donne VS est bon.  
3.10.6 dit que ton temporaire est une rvalue. Jusque la, c'est bon, sauf erreur. Apres du demandes l'adresse de la rvalue, il me semblait que c'était illégal mais je n'en suis plus du tout sur puisque je ne retrouve pas la référence :/

n°1257969
Taz
bisounours-codeur
Posté le 03-12-2005 à 08:42:41  profilanswer
 

virtual const type_info & GetType() const = 0;
 
moi j'adhère pas trop à ça parce que ça a une utilité très limité (voire aucune). Par contre, l'idiome du constructeur virtuel et une fonction membre clone(), ça c'est utile.

n°1258014
shaman3
Posté le 03-12-2005 à 12:21:02  profilanswer
 

virtual const type_info & GetType() const = 0;  
me permet de faire une comparaison de type depuis un pointeur BaseValue* ce qui rend le static_cast suivant sûr.
Effectivement le constructeur virtuel (ou plutôt une fonction membre virtual clone() qui appelle le constructeur de l'objet) peut être utile à la création d'un objet de même type et de contenu depuis un type de base.


Message édité par shaman3 le 03-12-2005 à 12:29:47

---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
n°1258138
jesus_chri​st
votre nouveau dieu
Posté le 03-12-2005 à 16:42:27  profilanswer
 

Citation :

comparaison de type depuis un pointeur BaseValue* ce qui rend le static_cast suivant sûr.


et le dynamic_cast ?

n°1258177
Taz
bisounours-codeur
Posté le 03-12-2005 à 19:15:40  profilanswer
 

+1 pour dynamic_cast.
 
Ce que tu fais c'est mauvais (et potentiellement lent) et peu souple car tu brides ton système de typage.
 
et si tu veux comparer, tu fais
 
typeid(*object) == typeid(TonType)
 
et voilà.
 
 

n°1258782
shaman3
Posté le 05-12-2005 à 01:27:46  profilanswer
 

Après vérification  

Code :
  1. TypeValue<ValueType>* ptCastValue = dynamic_cast<TypeValue<ValueType>*>(content);
  2. if (ptCastValue)
  3. *value = ptCastValue->Value;


le dynamic_cast est plus de 2x plus lent que :

Code :
  1. if (content->GetType() == typeid(ValueType))
  2.        *value = static_cast<TypeValue<ValueType>*>(content)->Value;


En quoi je bride mon système de typage ?
pour typeid(*object) == typeid(TonType)  
BaseValue* n'a pas accès à Value, je ne vois pas comment tu veux le tester directement.
 


---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
n°1258861
Taz
bisounours-codeur
Posté le 05-12-2005 à 10:09:31  profilanswer
 

déjà c'est
 
if (T* t = dynamic_cast<T*>(x)) {
 
}
 
ensuite je ne vois pas pourquoi ça serait plus lent.
Et ça bride parce que tu fais des tests d'équivalence, tu testes : "est-ce que le type réel de truc est Machin ?" et non pas "est-ce que truc est un Machin ?"

n°1258914
shaman3
Posté le 05-12-2005 à 11:16:30  profilanswer
 

Même chose pour :

Code :
  1. if (TypeValue<ValueType>* ptCastValue = dynamic_cast<TypeValue<ValueType>*>(content))
  2.        *value = ptCastValue->Value;


c'est toujours 2 x plus lent(c'est exactement le même code asm une fois compilé), d'ailleurs ce n'est pas pour rien que la technique(virtual const type_info & GetType() const = 0; ) est utilisée dans la librairie boost.
"est-ce que le type réel de truc est Machin ?" et non pas "est-ce que truc est un Machin ?" oui et alors ca ne change rien au niveau utilisation, je préfère avoir de meilleurs perfs.


Message édité par shaman3 le 05-12-2005 à 11:17:59

---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
n°1258979
Taz
bisounours-codeur
Posté le 05-12-2005 à 12:33:02  profilanswer
 

bien sur que si ça change ... mais bon, on va pas t'apprendre la POO

n°1259073
shaman3
Posté le 05-12-2005 à 14:40:05  profilanswer
 

Mais j'apprends des choses tous les jours en c++, pour info :  
Performance of typeid vs. dynamic_cast<>
As far as design is concerned, dynamic_cast<> should be preferred to typeid because the former enables more flexibility and extensibility. Notwithstanding that, the runtime overhead of typeid can be less expensive than dynamic_cast<>, depending on the operands. An invocation of operator typeid is a constant time operation--it takes the same length of time to retrieve the runtime type information of every polymorphic object, regardless of the object's derivational complexity. On the other hand, dynamic_cast<> is not a constant time operation. It has to traverse the derivation tree of the operand until it has located the target object in it. The worst case scenario is when the operand is a deeply derived object and the target is a non-related class type. Then, dynamic_cast<> has to traverse the entire derivation tree before it can confidently decide that requested cast cannot be done.
 
Et je pense que c'est pour cette raison que les developpeurs de boost utilisent typeid


---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
n°1259171
HelloWorld
Salut tout le monde!
Posté le 05-12-2005 à 15:46:40  profilanswer
 

Tu devrais jeter un oeil à boost::any.


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°1259241
shaman3
Posté le 05-12-2005 à 16:22:48  profilanswer
 

Justement ca s'adresse à Taz alors parce qu'ils utilisent un joli :
virtual const std::type_info & type() const = 0;
puis pour faire un cast :

Code :
  1. template<typename ValueType>
  2.     ValueType * any_cast(any * operand)
  3.     {
  4.         return operand && operand->type() == typeid(ValueType)
  5.                     ? &static_cast<any::holder<ValueType> *>(operand->content)->held
  6.                     : 0;
  7.     }



---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
n°1259307
HelloWorld
Salut tout le monde!
Posté le 05-12-2005 à 16:54:31  profilanswer
 

boost a aussi la contrainte d'être hautement portable, et certains compilos ne supportent / supportait pas le rtti peut être.
Après faut voir. Dans le cas général, avec hiérarchie de classes, dynamic_cast est préférable car il gère le polymorphisme. Dans ton cas particulier, ça se défend.
Si tu vises vraiments les performances, faut rester en typage statique (genre union à la VARIANT). Je suis pas sûr que le rtti impacte beaucoup en comparaison de l'allocation dynamique.
Et personnelement c'est plutôt l'existance même de ta classe que je trouve discutable. C'est pas trop dans l'esprit C++ ce genre de pratiques. Dans quel contexte tu t'en sers ?


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°1259428
++fab
victime du syndrome IH
Posté le 05-12-2005 à 19:01:50  profilanswer
 

HelloWorld a écrit :

boost a aussi la contrainte d'être hautement portable, et certains compilos ne supportent / supportait pas le rtti peut être.


 
typeid sans support du rtti, ça va poser problème aussi.

n°1259430
shaman3
Posté le 05-12-2005 à 19:03:30  profilanswer
 

C'est juste une class de test, car je voulais stoker un pointeur et éviter la recopie des gros objets comme dans boost::any.Le but est de pouvoir transmettre des paramètres "multi-type" à une fonction, mais j'ai beau chercher il n'y a pas de solution-miracle à ce problème (rapide comme un void* mais avec un typage fort). Au final je vais garder mes fonctions surchargées par type de paramètre.


---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
n°1259431
++fab
victime du syndrome IH
Posté le 05-12-2005 à 19:05:13  profilanswer
 

shaman3 a écrit :

Mais j'apprends des choses tous les jours en c++, pour info :  
Performance of typeid vs. dynamic_cast<>
As far as design is concerned, dynamic_cast<> should be preferred to typeid because the former enables more flexibility and extensibility. Notwithstanding that, the runtime overhead of typeid can be less expensive than dynamic_cast<>, depending on the operands. An invocation of operator typeid is a constant time operation--it takes the same length of time to retrieve the runtime type information of every polymorphic object, regardless of the object's derivational complexity. On the other hand, dynamic_cast<> is not a constant time operation. It has to traverse the derivation tree of the operand until it has located the target object in it. The worst case scenario is when the operand is a deeply derived object and the target is a non-related class type. Then, dynamic_cast<> has to traverse the entire derivation tree before it can confidently decide that requested cast cannot be done.
 
Et je pense que c'est pour cette raison que les developpeurs de boost utilisent typeid


 
la, on compare les performances de 2 opérations qui ont des objectifs différents ... boost::any utilise typeid parce que c'est le comportement qu'on s'attend à trouver.

n°1259843
HelloWorld
Salut tout le monde!
Posté le 06-12-2005 à 10:33:17  profilanswer
 

shaman3 a écrit :

C'est juste une class de test, car je voulais stoker un pointeur et éviter la recopie des gros objets comme dans boost::any.Le but est de pouvoir transmettre des paramètres "multi-type" à une fonction, mais j'ai beau chercher il n'y a pas de solution-miracle à ce problème (rapide comme un void* mais avec un typage fort). Au final je vais garder mes fonctions surchargées par type de paramètre.


Et une fonction template ?


---------------
FAQ fclc++ - FAQ C++ - C++ FAQ Lite
n°1260200
shaman3
Posté le 06-12-2005 à 16:05:29  profilanswer
 

oui afin dans mon cas, il me faut également y avoir accès via pointeur depuis la class de base abstraite.  
Je vois quelques possibilités mais l'utilisation des templates me pose des problèmes d'instanciation, de spécialisation de méthode, en plus avec les templates l'implémentation se retrouve dans la déclaration ce qui génére des définitions multiples, des dépendances, une moins bonne lisibilité du code, et la recompilation des fichiers dépendants lorsqu'il y a modification de l'implémentation, bref je commence à me demander s'il faut les utilisées dans mon cas.


---------------
L'agence www.PolyDev.com, entreprise spécialisée dans l'accompagnement et le suivi de vos projets multimédia (3d, 3d web, site web,  logiciels spécialisés).
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  [C++]appel de fonction pure

 

Sujets relatifs
[C] fonction free[PHP] fonction mkdir
fonction include et GETFortran 77 fonction time
probleme de fonctionProbleme declaration fonction
vecteur de poiteur sur fonctionLien de téléchargement en fonction de la date ?
[VBS][RESOLU] Fonction "Replace" non-case-sensitivetrouver une date en access en fonction d'un certain nb de jours
Plus de sujets relatifs à : [C++]appel de fonction pure


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR