3
votes

Constructeur de classe qui prend une référence à un objet différent et je voudrais ne pas copier l'objet

Je suis un étudiant qui apprend le C ++.
J'ai deux objets ("City" et "Parser") et j'aimerais qu'un objet ("Parser") change en un autre ("City").
Le seul "problème" est que je dois envoyer l'objet ("City") dans le constructeur de l'autre (Le code montre ce que je veux dire).

    class City {
    public:
        City()
            : peopleCount { 0 }
        {};

        int peopleCount;
    };

    class Parser {
    public:
        Parser(const char *filename, City &c)
            : _filename { filename },
              _c { c }
        {};

        void fillCity() { _c.peopleCount = 3; };

        const char *_filename;
        City _c;
    };

    int main(int argc, char *argv[])
    {
        City c;
        Parser p(argv[1], c);

        p.fillCity();
        std::cout << c.peopleCount << std::endl; // I would like my output to be "3"
        return 0;
    }

Je pourrais le faire en C en envoyant un pointeur brut dans le constructeur.
Mais depuis que je découvre ce langage, tout le monde dit qu'il faut éviter le pointeur brut.
J'ai vérifié les pointeurs intelligents mais ils "supprimeraient" ma variable (ma variable provient de la pile, c'est pourquoi je ne veux pas la supprimer).
Je ne veux pas copier la "Ville" dans le "Parser" (parce que la copie d'objets peut être évitée?).

Je suis conscient que je pourrais envoyer une référence d'un objet City à la fonction membre " fillCity "mais j'aimerais savoir si un objet peut contenir un autre objet sans le copier.

Y a-t-il une autre façon de faire cela sans utiliser de pointeur brut?

Merci d'avance.


1 commentaires

Sur une note sans rapport: n'utilisez jamais d'éléments de argv sans vérifier d'abord argc .


3 Réponses :


2
votes

Dans le constructeur Parser , vous passez l'argument City par référence. Mais ensuite, vous copiez l'objet pour le stocker dans _c .

Vous devez également faire de _c une référence.


1 commentaires

Ça marche ! Merci. Je ne savais pas que nous pourrions déclarer des références.



2
votes

Une autre option (après la bonne réponse de Some Programmer Dude) est de passer c comme référence à certaines des fonctions membres de P, par exemple:

int main(int argc, char *argv[])
{
    City c;
    Parser p(argv[1]);

    p.fillCity(c);
    std::cout << c.peopleCount << std::endl; // I would like my output to be "3"
    return 0;
}

Utilisé comme:

class Parser {
public:
    Parser(const char *filename)
        : _filename { filename }
    {};
    void fillCity(City &c) { c.peopleCount = 3; };
    const char *_filename;
};

C'est peut-être ce que vous voulez ou non - mais si vous n'avez qu'une ou un petit nombre de fonctions, c'est assez pratique.

Sur un autre point - je le ferais pas dire que le passage par pointeur est si mauvais, par exemple vous pouvez au moins construire par défaut avec un pointeur (la valeur par défaut étant nullptr) et ensuite passer plus tard dans l'objet C . Le seul "problème" est que vous devez faire attention à ce que C existe pour la durée de vie de P ou que vous disiez à P si / quand C disparaît ... pas vraiment fusée sceince :) et ça peut être assez pratique.


0 commentaires

3
votes

Si vous souhaitez partager des objets tout en maîtrisant la durée de vie de ces objets, vous pouvez utiliser shared_ptr . Ainsi, l'objet partagé sera détruit une fois que toutes les références à celui-ci auront été libérées (c'est-à-dire que le dernier shared_ptr -wrapper a été détruit):

class City {
public:
    City()
    : peopleCount(0)
    {};

    int peopleCount;
};

class Parser {
public:
    Parser(const char *filename, std::shared_ptr<City> c)
    : _filename (filename),
    _c (c) {};

    void fillCity() { _c->peopleCount = 3; };

    const char *_filename;
    std::shared_ptr<City> _c;
};

int main(int argc, char *argv[])
{
    std::shared_ptr<City> c = std::make_shared<City>();
    Parser p("somefilename", c);

    p.fillCity();
    std::cout << c->peopleCount << std::endl;

    return 0;
}


0 commentaires