Bonjour, je suis tombé sur un problème de compilation l'autre soir et ça m'a un peu surpris, donc ce soir j'ai essayé avec succès de reproduire le problème de manière simplifiée. Je ne sais pas si c'est parceque je code sur ce projet exclusivement le soir et que la fatigue m'empêche de comprendre une subtilitée, ou si il y a quelque chose que je ne sais pas rapport à la résolution de noms en C++ (si c'est bien comme ça qu'on dit) ou de l'héritage, ou encore si c'est un bug ou une limitation du compilateur (ici vc9 -- VS2008) donc je vous expose le prbolème. Il n'est pas bien grave puisque facile a contourner, mais juste pour être sur je préfère demander une explication.
Voici le code en question, dans sa version qui compile et s'execute -- j'ai mis la ligne qui ne compile pas en commentaire:
Pour être sur d'être dans les mêmes conditions j'ai gardé la hierarchie d'héritage et de typedefs qu'on retrouve dans le vrai programme.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 #include <iostream> #include <string> template< typename T > class Something { T m_data; public: Something( const T& data ) : m_data( data ) { } }; template <typename T> class Tester { public: void test( const Something<T> something ) const { std::cout << "TEST : " << typeid(something).name() << '\n'; } }; template <typename T> class Collapser { virtual void collapse( const Something<T>& something, const Tester<T>& tester ) = 0; }; typedef Something< std::string > StringSomething; typedef Tester< std::string > StringTester; typedef Collapser< std::string > StringCollapser; class MyTester : public StringTester { public: MyTester() { std::cout << "OK..." << std::endl; } }; class MyCollapser : private StringCollapser { public: // LE PROBLEME EST ICI : //void collapse(const StringSomething& something, const MyTester& tester ) // ne compile pas void collapse(const StringSomething& something, const StringTester& tester ) { tester.test( something ); } }; int main() { MyTester tester; MyCollapser collapser; StringSomething something("Ok!"); collapser.collapse( something, tester ); std::cin.ignore(); return 0; }
Si je remplace
par
Code : Sélectionner tout - Visualiser dans une fenêtre à part void collapse(const StringSomething& something, const StringTester& tester )
J'ai une erreur de compilation qui suggère que la fonction n'est pas prise en compte comme étant l'implémentation de Collapser< std::string >::collapse() :
Code : Sélectionner tout - Visualiser dans une fenêtre à part void collapse(const StringSomething& something, const MyTester& tester )
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 1>e:\tests\test_wtf_virtual_resolution\test_wtf_virtual_resolution\main.cpp(61) : error C2259: 'MyCollapser' : cannot instantiate abstract class 1> due to following members: 1> 'void Collapser<T>::collapse(const Something<T> &,const Tester<T> &)' : is abstract 1> with 1> [ 1> T=std::string 1> ] 1> e:\tests\test_wtf_virtual_resolution\test_wtf_virtual_resolution\main.cpp(29) : see declaration of 'Collapser<T>::collapse' 1> with 1> [ 1> T=std::string 1> ]
Est-ce qu'on a pas le droit en C++ d'implémenter une fonction virtuelle avec comme paramettre un type hérité du type définis dans la déclaration de la fonction virtuelle?
Ou est-ce le compilateur qui se trompe?
Pour l'instant je parie sur la fatigue mais si vous pouvez m'éclairer, ça m'aiderai a arrêter de me poser des questions ^^;
Partager