C ++ создает экземпляр объекта через построитель - PullRequest
0 голосов
/ 08 мая 2020

Я недавно узнал о шаблоне проектирования, я прочитал статью о шаблоне построителя, https://riptutorial.com/cplusplus/example/30166/builder-pattern-with-fluent-api. У меня вопрос по поводу создания объекта. Вот код внутри статьи:

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

// Forward declaring the builder
class EmailBuilder;

class Email
{
  public:
    friend class EmailBuilder;  // the builder can access Email's privates

    static EmailBuilder make();

    string to_string() const {
        stringstream stream;
        stream << "from: " << m_from
               << "\nto: " << m_to
               << "\nsubject: " << m_subject
               << "\nbody: " << m_body;
        return stream.str();
    }

  private:
    Email() = default; // restrict construction to builder

    string m_from;
    string m_to;
    string m_subject;
    string m_body;
};

class EmailBuilder
{
  public:
    EmailBuilder& from(const string &from) {
        m_email.m_from = from;
        return *this;
    }

    EmailBuilder& to(const string &to) {
        m_email.m_to = to;
        return *this;
    }

    EmailBuilder& subject(const string &subject) {
        m_email.m_subject = subject;
        return *this;
    }

    EmailBuilder& body(const string &body) {
        m_email.m_body = body;
        return *this;
    }

    operator Email&&() {
        return std::move(m_email); // notice the move
    }

  private:
    Email m_email;
};

EmailBuilder Email::make()
{
    return EmailBuilder();
}

// Bonus example!
std::ostream& operator <<(std::ostream& stream, const Email& email)
{
    stream << email.to_string();
    return stream;
}


int main()
{
    Email mail = Email::make().from("me@mail.com")
                              .to("you@mail.com")
                              .subject("C++ builders")
                              .body("I like this API, don't you?");

    cout << mail << endl;
}

Кто-нибудь может объяснить Email mail = Email::make().from("me@mail.com"), как это работает?

Ответы [ 2 ]

2 голосов
/ 08 мая 2020

Давайте посмотрим на оператор:

Email mail = Email::make().from("me@mail.com");

В первой части мы вызываем Email::make(), это возвращает новый временный EmailBuilder. Этот объект отвечает за заполнение Email, который является его закрытым членом. Мы можем заполнить внутреннюю структуру Email, поскольку это класс friend (который следует использовать с осторожностью !! Не злоупотребляйте им!).

Теперь мы вызываем метод члена from, который заполняет член m_form в Email, а возвращает EmailBuilder. Это позволяет использовать объединенное использование функций EmailBuilder, например:

Email mail = Email::make().from("me@mail.com").to("other@mail.com");

Является ли действительной командой , которая заполняет поля от и до (и это часто можно увидеть такое использование).

Наконец, у нас есть operator Email&&(). Это оператор преобразования из EmailBuilder в ссылку на r-значение Email. Это перемещает внутреннее Email, которое мы создали, наружу, позволяя захватить внутренности Email в Email mail. И здесь происходит « magi c» преобразования этого конструктора в фактическую почту.

0 голосов
/ 08 мая 2020

Email::make() возвращает новый экземпляр Email, который изменен (фактически его член m_email) на from(), который возвращает ссылку на экземпляр, позволяющую его снова изменить на to() et c и, наконец, оператор, определяющий преобразование, позволяет получить Email. Экземпляр EmailBuilder - временная переменная. Примечание friend class EmailBuilder позволяет EmailBuilder получать доступ / изменять частные поля Email

Если to() et c не возвращает ссылку на экземпляр, вы не можете передать изменения по конвейеру и должны сохранить экземпляр EmailBuilder сначала, чтобы применить from() et c к нему

То же самое в cout << mail << endl;, вы можете передать << по конвейеру, потому что operator << возвращает экземпляр std::ostream, но на этот раз временной переменной нет.

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