Как я мог написать конструкцию c ++ чисто и понятно? - PullRequest
1 голос
/ 16 апреля 2020

Предположим, мой класс выглядит следующим образом:

class Strt {
    public:
        int a{0};
        int b{0};

        Strt(int a, int b): a(a), b(b) {}
        Strt(Strt& s) {a = s.a; b = s.b;} // these two functions have same contents
        Strt(Strt&& s) {a = s.a; b = s.b;}
};

Проблема в том, что инициализация левого значения и инициализация правого значения одинаковы, что делает его не чистым, поскольку, как только я захочу изменить переменные члена класса, Мне нужно изменить две функции таким же образом. Код продублирован. Как я могу сделать это чисто для лучшего чтения и обслуживания?

Редактировать:

В некоторых случаях эти функции конструирования называются:

Strt func() {return Strt(1, 2);}
vector<Strt> v;
Strt s(3, 4);
v.push_back(s); // call left construction function
v.emplace_back(func();} // call right construction function

Есть также некоторые случаи, когда необходимо изменить класс, например, когда мне нужно добавить в него новое поле int c;:

class Strt {
    public:
        int a{0};
        int b{0};
        int c{0};

        Strt(int a, int b, int c): a(a), b(b), c(c) {}
        Strt(Strt& s) {a = s.a; b = s.b; c = s.c;} // The two functions are duplicatedly modified in the same way
        Strt(Strt&& s) {a = s.a; b = s.b; c = s.c;}
};

Должен ли я изменять содержимое Strt(Strt&) и Strt(Strt&&) отдельно, даже если они имеют одинаковое содержимое?

Ответы [ 3 ]

3 голосов
/ 16 апреля 2020

Поскольку ваш класс не владеет какими-либо подвижными ресурсами, нет причин создавать отдельные конструкторы копирования и перемещения. Один конструктор копирования будет работать одинаково:

class Strt {
public:
    int a{0};
    int b{0};

    Strt(int a, int b): a(a), b(b) {}
    Strt(const Strt& s): a(s.a), b(s.b) {}
};

Демонстрация в реальном времени

Конечно, поскольку ваш конструктор копирования в любом случае не делает ничего, кроме копирования по элементам вы можете просто опустить его и позволить компилятору сгенерировать для вас значение по умолчанию:

class Strt {
public:
    int a{0};
    int b{0};

    Strt(int a, int b): a(a), b(b) {}
};

Live Demo

Поскольку a и b оба publi c, и вы ничего не делаете, но инициализируете их из параметров конструктора, вы можете просто полностью опустить ваш конструктор и использовать агрегатную инициализацию:

class Strt {
public:
    int a{0};
    int b{0};
};

Live Demo

2 голосов
/ 16 апреля 2020

Самое чистое решение - удалить объявленные пользователем конструкторы. Они не нужны:

class Strt {
    public:
        int a{0};
        int b{0};
};
0 голосов
/ 16 апреля 2020

В вашем случае вы можете по умолчанию или опустить свой конструктор копирования / перемещения:

class Strt {
public:
    int a{0};
    int b{0};

    Strt(int a, int b): a(a), b(b) {}
    Strt(const Strt&) = default;
    Strt(Strt&&) = default;
};

В общем случае вы можете использовать делегирующий конструктор :

class Strt {
public:
    int a{0};
    int b{0};

    Strt(int a, int b): a(a), b(b) {}
    Strt(const Strt& rhs) : Strt(rhs.a, rhs.b) {}
    Strt(Strt&& rhs) : Strt(rhs) {}
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...