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 et variable statique


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 51
    Points : 46
    Points
    46
    Par défaut Héritage et variable statique
    Bonsoir,
    Je suis en train de créer une classe mère qui s'occupe de gèrer mes modèles :

    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
    #ifndef __ABSTRACTMODEL_H__
    #define __ABSTRACTMODEL_H__
     
    #include <string>
    #include <vector>
     
    #include <boost/property_tree/ptree.hpp>
     
    class AbstractModel
    {
    public:
        AbstractModel();
        virtual ~AbstractModel();
     
        void LoadFromFile(const std::string& path);
        void LoadFromName(const std::string& name);
     
        static std::vector<std::string> GetAvaibleModels();
     
    protected:
        virtual void parse(boost::property_tree::ptree data) = 0;
     
        // functions related to files location
        static std::string basedir();
        static std::string filename();
    };
     
    #endif // __ABSTRACTMODEL_H__
    Voici son implémentation :

    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
    #include "AbstractModel.h"
     
    #include <boost/filesystem.hpp>
    #include <boost/property_tree/info_parser.hpp>
     
    AbstractModel::AbstractModel()
    {
     
    }
     
    AbstractModel::~AbstractModel()
    {
     
    }
     
    void AbstractModel::LoadFromFile(const std::string& path)
    {
        boost::property_tree::ptree data;
        read_info(path, data); 
     
        parse(data);
    }
     
    void AbstractModel::LoadFromName(const std::string& name)
    {
        namespace fs = boost::filesystem;
     
        fs::path location = fs::path(basedir()) / name / filename();
        LoadFromFile(location.string());
    }
     
    std::vector<std::string> AbstractModel::GetAvaibleModels()
    {
        namespace fs = boost::filesystem;
     
        std::vector<std::string> results;
     
        for(fs::directory_iterator it(basedir()); it != fs::directory_iterator(); ++it)
        {
            if(fs::is_directory(*it))
                results.push_back(it->path().string());
        }
    }
     
    std::string AbstractModel::basedir()
    {
        return "models";
    }
     
    std::string AbstractModel::filename()
    {
        return "model.info";
    }
    Comme vous le devinez, j'ai besoin que basedir() et éventuellement filename() soient redéfinis par chaque classe fille qui représentera un modèle (PersonnageModel, ArmeModel, etc...) pour ne pas que les modèles soient mélangés.

    Cepedant, lorsque je redéfini basedir() dans la classe fille BlockModel, l'appel à LoadFromName("test") va me chercher le fichier du modèle par défaut, à savoir models/test/model.info et non pas blocks/test/model.info.

    Je ne vois pas comment faire pour que chaque classe fille aie son propre dossier et que cela soit directement gèré par la classe mère.

    Auriez-vous des (belles) solutions à me proposer ? À la base je voulais définir ces constantes spécifiques comme ça pour faire plus propre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    namespace
    {
        const std::string MODEL_BASEDIR = "blocks";
    }
    Il faudrait que cette variable soit également accessible pour les méthodes statiques telles que GetAvaibleModels().

    Merci d'avance, darkrojo.

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Qu'est-ce qui t'empêche de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class AbstractModel
    {
    public:
        static std::string baseDir;
    protected:
        virtual std::string getBasedir() {return AbstractModel::baseDir;}
    };
     
    std::string AbstractModel::baseDir = "Base";
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 51
    Points : 46
    Points
    46
    Par défaut
    Je ne peux pas redéfinir la variable static AbstractModel::baseDir via ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::string BlockModel::baseDir = "blocks";
    erreur: redefinition of 'std::string AbstarctModel::baseDir'
    erreur: 'std::string AbstractModel::baseDir' previously declared here
    Quand à la méthode virtuelle, j'y avais pensé mais il faut que baseDir soit accessible dans les méthodes statiques telles que AbstractModel::GetAvaibleModels(), or les méthodes virtuelles sont disponibles uniquement pour les méthodes non-statiques.

    Des idées ?

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par darkrojo Voir le message
    Je ne peux pas redéfinir la variable static AbstractModel::baseDir via ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::string BlockModel::baseDir = "blocks";
    J'ai oublié de préciser que cette ligne devait être dans un .cpp, pas dans un .h
    Citation Envoyé par darkrojo Voir le message


    Quand à la méthode virtuelle, j'y avais pensé mais il faut que baseDir soit accessible dans les méthodes statiques telles que AbstractModel::GetAvaibleModels(), or les méthodes virtuelles sont disponibles uniquement pour les méthodes non-statiques.
    L'idée est que dans les fonctions statiques, tu connais le vrai type que tu veux manipuler, donc tu utilises baseDir. Par contre, dans les contextes où tu ne connais pas ce vrai type (par exemple pour sauver une instance d'une classe dérivée), tu utilises la fonction virtuelle.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 51
    Points : 46
    Points
    46
    Par défaut
    Voilà ce que j'ai quand je déplace la redéfinition de la variable statique dans leurs .cpp respectifs :

    erreur: ISO C++ does not permit 'AbstractModel::baseDir' to be defined as 'BlockModel::baseDir' [-fpermisive]
    Je tiens à préciser que je n'ai pas remis le 'static std::string baseDir;' dans le header de BlockModel comme je l'ai fait dans celui de AbstractModel.

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Je ne suis pas certain de ce que tu as fait.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // A.h
    class A {
    static string name;
    };
    // A.cpp
    string A::name="A";
     
    // B.h
    class B : public A{
    static string name;
    };
    // B.cpp
    string B::name="B";
    Devrait à mon sens marcher, même si je n'ai pas vérifié dans le standard. L'idée est que dans B, name va cacher le nom name défini dans A et définir une nouvelle variable, mais ce n'est pas gênant, puisque c'est ce que tu veux.

    Quoi qu'il en soit, dans le pire des cas, défini des variables avec des noms différents dans chaque classe, encore une fois, comme dans l'appel depuis une fonction statique, tu sais exactement à quelle classe tu fais référence, tu sais aussi exactement quel nom utiliser (sauf si tu veux utiliser ton code dans des templates, c'est pourquoi la solution avec le même nom me semblait préférable).
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 51
    Points : 46
    Points
    46
    Par défaut
    Citation Envoyé par darkrojo Voir le message
    Je tiens à préciser que je n'ai pas remis le 'static std::string baseDir;' dans le header de BlockModel comme je l'ai fait dans celui de AbstractModel.
    En le rajoutant comme le montrait ton code, ça fonctionne !
    Merci beaucoup et bonne soirée (:

    EDIT : Je ne comprends plus rien... J'ai une exeption de boost::filesystem qui me dit que le dossier "models" n'existe pas, normal puisque la méthode devrai aller chercher le dossier "blocks".

    Je joins mes sources qui ont changé depuis le dernier post où je les ai présentées pour que l'on soit sur la même longueur d'onde
    Fichiers attachés Fichiers attachés

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    J'ai l'impression que tu n'as pas compris les deux aspect du ma première réponse (ma réponse avec A et B ne détaillait que l'implémentation d'un de ces aspects).

    L'idée est que dans les fonctions statiques, tu connais le vrai type que tu veux manipuler, donc tu utilises baseDir. Par contre, dans les contextes où tu ne connais pas ce vrai type (par exemple pour sauver une instance d'une classe dérivée), tu utilises la fonction virtuelle.
    Là, tu n'as pas du tout fait la fonction virtuelle. Donc ton GetAvaibleModels marche bien (fonction statique) mais pas ton LoadFromName (qui devrait utiliser une fonction virtuelle).

    Si je détaille mon exemple raccourci :
    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
     
    // A.h
    class A {
    static string name;
    virtual string getName() {return A::name;}
    };
    // A.cpp
    string A::name="A";
     
    // B.h
    class B : public A{
    static string name;
    virtual string getName() {return B::name;}
    };
    // B.cpp
    string B::name="B";
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 51
    Points : 46
    Points
    46
    Par défaut
    Désolé, je ne devais pas être très en forme et je n'avais pas compris ; j'avoue que l'exemple me parle un peu plus

    Cependant, après avoir implémenté cette fonction virtuelle, cela marche bien pour les méthodes membres de B mais pas pour la méthode statique qui se sert de A::baseDir au lieu de B:baseDir !

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 51
    Points : 46
    Points
    46
    Par défaut
    Je me permet de "upper" le topic en vous joignant mes sources (juste deux classes et un main) pour vous permettre de m'aider ; en effet je n'ai toujours pas trouvé d'où cela venait et je suis coincé sur mon projet : je ne peux pas prendre le risque d'avancer si la méthode que JolyLoic s'avère ne pas marcher.

    Merci d'avance
    Fichiers attachés Fichiers attachés

Discussions similaires

  1. [Débutant] héritages de propriétés friend/public et variables statiques/modules
    Par billybobbonnet dans le forum Développement Windows
    Réponses: 0
    Dernier message: 05/09/2014, 13h03
  2. Variable statique et l'héritage
    Par naou18 dans le forum Débuter avec Java
    Réponses: 24
    Dernier message: 09/02/2012, 20h00
  3. [PHP 5.0] [POO] Héritages de variables statiques
    Par LogistiX dans le forum Langage
    Réponses: 7
    Dernier message: 21/01/2009, 18h07
  4. [héritage] Héritage et champs statiques.
    Par salome dans le forum Langage
    Réponses: 4
    Dernier message: 03/04/2005, 20h21
  5. [héritage] Héritage et champs statiques.
    Par salome dans le forum Langage
    Réponses: 2
    Dernier message: 02/04/2005, 00h11

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