Конструктор класса, который принимает ссылку на другой объект, и я хотел бы не копировать объект - PullRequest
0 голосов
/ 05 февраля 2019

Я студент, изучающий c ++.
У меня есть два объекта ("Город" и "Парсер"), и я хотел бы изменить один объект ("Парсер") на другой ("Город").
Единственная «проблема» заключается в том, что мне нужно отправить объект («Город») в конструктор другого (код показывает, что я имею в виду).

    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;
    }

Я мог бы сделать это вC, отправив необработанный указатель в конструктор.
Но так как я обнаружил этот язык, все говорят, что необязательного указателя следует избегать.
Я проверил умные указатели, но они "удалили" мою переменную (моя переменная изстек, по этой причине я не хочу его удалять).
Я не хочу копировать «Город» в «Парсер» (потому что можно избежать копирования объектов?).

Мне известно, что я мог бы отправить ссылку на объект City в функцию-член "fillCity", но я хотел бы знать, может ли один объект содержать другой объект, не копируя его.

Есть ли другой способ сделатьчто без использования необработанного указателя?

Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 05 февраля 2019

Другой вариант (после правильного ответа программиста) - передать c в качестве ссылки на некоторые функции-члены P, например:

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

Используется как:

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;
}

Это может или не может быть так, как вы хотите - но если у вас есть только одна или небольшое количество функций, это довольно удобно.

По другому вопросу - я бы не сказал, что передача по указателю такплохо, например, вы можете, по крайней мере, создать конструкцию по умолчанию с указателем (значением по умолчанию является nullptr), а затем передать объект C.Единственная «проблема» заключается в том, что вам нужно быть осторожным, что C существует в течение жизни P или что вы говорите P, если / когда C исчезнет ... на самом деле не ракета :) и это можетбыть достаточно удобным.

0 голосов
/ 05 февраля 2019

Если вы хотите обмениваться объектами, имея время жизни этих объектов под контролем, вы можете использовать shared_ptr.Таким образом, общий объект будет уничтожен после того, как все ссылки на него будут освобождены (т. Е. Уничтожен последний shared_ptr -раппер):

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 голосов
/ 05 февраля 2019

В конструкторе Parser вы передаете аргумент City по ссылке.Но тогда вы копируете объект, чтобы сохранить его в _c.

Вы также должны сделать _c ссылкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...