IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Héritage initialisation membre const


Sujet :

C++

  1. #1
    Membre confirmé Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Points : 496
    Points
    496
    Par défaut Héritage initialisation membre const
    Bonjour,

    Je suis confronté à un petit problème pour l'initialisation d'un membre const avec une fonction.
    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
    #include <map>
    #include <string>
    #include <iostream>
     
    using namespace std ;
     
    class Toto
    {
    	const map<string,string> s_map;
     
    protected:
    	virtual const map<string,string> init()
    	{
    		map<string,string> ret ;
    		ret["h1"] = "value1" ;
    		return ret ;
    	}
    public:
    	Toto() : s_map( init() ) {}
    	~Toto() {}
    	inline const map<string,string>& getMap() { return s_map; }
    };
     
    class SuperToto : public Toto
    {
    protected:
    	virtual const map<string,string> init()
    	{
    		map<string,string> ret = Toto::init();
    		ret["h2"] = "value2" ;
    		return ret ;
    	}
     
    public:
    	SuperToto() {}
    };
     
    int main()
    {
    	SuperToto toto ;
    	map<string,string>::const_iterator it = toto.getMap().find("h2");
    	if ( it != toto.getMap().end() )
    		cout << (*it).second << endl ;
    	else
    		cout << "Not found" << endl ;
    }
    Ma question est pourquoi la fonction SuperToto::init() n'est pas appeler automatiquement? Merci d'avance.
    ________________________________________________
    http://bliquid.fr : Blog sur Android et l'Acer Liquid

  2. #2
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Salut

    Tu ne peux pas appeler une méthode de l'objet dans la liste d'initialisation ! Une solution est de passer la méthode en statique :

    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
    class Toto
    {
    	const map<string,string> s_map;
     
    protected:
    	static map<string,string> init()
    	{
    		map<string,string> ret ;
    		ret["h1"] = "value1" ;
    		return ret ;
    	}
    public:
      Toto() : s_map( init() ) {}
    	~Toto() {}
    	inline const map<string,string>& getMap() { return s_map; }
    };
    Find me on github

  3. #3
    Membre confirmé Avatar de themadmax
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    446
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 446
    Points : 496
    Points
    496
    Par défaut
    Euh, en fait mon exemple compile et fonctionne (VS2008) mais c'est la surcharge de la fonction init qui n'est pas appeler, je ne pense pas que l’utilisation d'une déclaration static résolve mon problème.
    ________________________________________________
    http://bliquid.fr : Blog sur Android et l'Acer Liquid

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,

    Pendant la construction (ou du destruction) d'un objet, la fonction virtuelle appelée est celle du type du constructeur/destructeur en cours d'exécution et non du type final de l'objet en cours de construction/destruction. Pour une fonction virtuelle pure, le comportement dans la classe abstraite est indéterminée.

    Cf Quand est construit le type dynamique ou quel est l'impact des appels de fonctions virtuelles dans un constructeur ?

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    En d'autres termes et compte tenu que ta map est const, tu ne peux pas faire de cette façon. Une solution est de passer un initialiseur à ton constructeur en s'appuyant éventuellement sur une fonction statique comme proposée par Jean Bernard :
    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
    68
    69
    70
    71
    72
    73
    74
    #include <map>
    #include <string>
    #include <iostream>
    #include <algorithm>
     
     
    class Toto
    {
    	const std::map<std::string,std::string> s_map;
     
    protected:
    	static const std::map<std::string,std::string> init()
    	{
    		std::map<std::string,std::string> ret ;
    		ret["h1"] = "value1" ;
    		return ret ;
    	}
    public:
        template<class T >
    	Toto(T callable_) : s_map( callable_() ) {}
     
     
        Toto()
        :
        // en C++ 0x, avec la délégation de constructeur :
        // Toto( &Toto::init ) {}
        s_map(init())
        {
     
        }
     
     
    	virtual ~Toto() {}
    	inline const std::map<std::string,std::string>& getMap() { return s_map; }
    };
     
    class SuperToto : public Toto
    {
    private:
    	static const std::map<std::string,std::string> init()
    	{
    		std::map<std::string,std::string> ret = Toto::init();
    		ret["h2"] = "value2" ;
    		return ret ;
    	}
     
    public:
    	SuperToto():Toto(&SuperToto::init) {}
    };
     
     
    template<class T>
    void test()
    {
    	T toto ;
    	auto toto_map = toto.getMap(); // auto de C++0x
       std::for_each(
           toto_map.begin(),
           toto_map.end(),
           [](std::pair<std::string,std::string> const&pair_) // et un p'tit foncteur C++ 0x car cela le vaut bien ;)
            {
                std::cout<<"["<<pair_.first<<"] = "<<pair_.second<<" ; ";
            }
       );
       std::cout<<"\n";
    }
     
    int main()
    {
        test<Toto>();
     
        test<SuperToto>();
        return 0;
    }

  6. #6
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Je comprend ce que tu veux faire, mais il va à mon avis falloir passer par une autre solution.

    Ce que je ferais à ta place, c'est passer la map à initialiser en argument et créer les objets avec des factory. Tu peux par exemple utiliser une factory statique ou bien l'amitié pour bien protéger tout ça.
    Find me on github

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Ce que je ferais à ta place, c'est passer la map à initialiser en argument et créer les objets avec des factory. Tu peux par exemple utiliser une factory statique ou bien l'amitié pour bien protéger tout ça.
    La map est const, elle ne peut donc être passée à une fonction pour construction. La solution que je propose avec une 'fabrique de map' en paramètre template du constructeur permet de construire la map en déléguant la construction effective à l'extérieur de la classe toto. Le paramètre template peut être un membre (static il va de soi) de la classe de base, de la classe dérivée ou un 'callable' externe (jouant le rôle de fabrique de la map) sans besoin d'amitié.

  8. #8
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    La map est const, elle ne peut donc être passée à une fonction pour construction.
    Pourquoi ne pourrait-elle pas être passée en argument du constructeur ? La factory appelle le constructeur de l'objet avec la bonne map. Il suffit de protéger le constructeur de sorte que seule la factory y ait accès et le tour est joué. Mais je ne me suis pas très bien exprimé. Je parlais bien sûr d'une fabrique de Toto et pas d'une fabrique de map.

    Mais sinon ça marche aussi avec ta technique, oui.
    Find me on github

Discussions similaires

  1. Classe avec membres const dans un vecteur
    Par PilloBuenaGente dans le forum Langage
    Réponses: 17
    Dernier message: 18/04/2013, 14h27
  2. précisions sur les fonctions membres const
    Par deubelte dans le forum Débuter
    Réponses: 3
    Dernier message: 07/03/2012, 00h08
  3. fonction membre const
    Par salseropom dans le forum C++
    Réponses: 10
    Dernier message: 21/10/2010, 19h06
  4. Initialisation de membres static const
    Par NiamorH dans le forum C++
    Réponses: 16
    Dernier message: 14/01/2008, 16h50
  5. Initialisation membre statique
    Par vandamme dans le forum C++
    Réponses: 6
    Dernier message: 06/07/2007, 20h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo