Ввод класса в СТД::вектор


Это небольшой тест, чтобы попробовать и добавить копию содержащего класса в вектор. Для меня это выглядит очень некрасиво. Я ненавижу то, что мне нужно написать конструктор на основе указателя для того, чтобы добавить класс к вектору. Есть ли лучший способ организовать это?

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

Функция поддержки (не суть вопроса):

template <class T>
std::string to_string(const T& number) {
    if (std::is_arithmetic<T>::value) {
        std::stringstream ss;
        ss << number;
        return ss.str();
    } // else
    return "to_string not implemented"; // I could throw here...
}

Основной код:

class Return_Self_Test {
private:
    std::string name;

public:
    Return_Self_Test(const std::string& name_in) : name(name_in) { }

    Return_Self_Test(Return_Self_Test* rst) : name(rst->name) {
    }

    Return_Self_Test(const Return_Self_Test &obj) : name(obj.name) {
    }

    void output() const {
        std::cout << "name: " << name;
    }

    std::vector<Return_Self_Test> get_in_vector() const {
        std::vector<Return_Self_Test> rst;
        rst.emplace_back(Return_Self_Test("new one 1"));
        rst.emplace_back(*this);
        rst.emplace_back(Return_Self_Test("new one 2"));
        return rst;
    }
};

void return_self_test() {
    Return_Self_Test rst_a("Original");

    auto a_vect = rst_a.get_in_vector();
    for (size_t i = 0; i < a_vect.size(); i++) {
        std::cout << to_string(i) + ": ";
        a_vect.at(i).output();
    }
}

return_self_test() вызывается из основного;

Любые комментарии приветствуются!



169
1
задан 10 марта 2018 в 09:03 Источник Поделиться
Комментарии
1 ответ

#include <iostream>
#include <ostream>
#include <string>
#include <vector>

class Return_Self_Test {
std::string name;

public:
Return_Self_Test(std::string const& name_in) : name(name_in) { }

std::string const& get_name() const noexcept {
return name;
}

std::vector<Return_Self_Test> get_in_vector() const {

using std::literals::string_literals::operator""s;

std::vector<Return_Self_Test> rst;

rst.emplace_back(Return_Self_Test("new one 1"s));
rst.emplace_back(*this);
rst.emplace_back(Return_Self_Test("new one 2"s));

return rst;
}
};

std::ostream& operator<<(std::ostream& os, Return_Self_Test const& rst) {
return os << "Name: " << rst.get_name();
}

void return_self_test() {

Return_Self_Test rst_a("Original");
auto a_vect = rst_a.get_in_vector();

for (size_t i = 0; i < a_vect.size(); i++) {
std::cout << std::to_string(i) + ": " << a_vect[i] << '\n';
}
}

Это мое предложение для более организованного решения вашей проблемы. Давайте идти этим путем и посмотреть, что я сделал по-другому от вас, и почему.

Конструкторы

C++ на самом деле достаточно хороший, когда дело доходит до того, что специальные функции-члены должны быть объявлены пользователем и те, которые генерируются компилятором. Для большинства простых классов, вам не нужно ничего определять на всех! Конструктор копирования, конструктор перемещения, копирования и оператор присваивания, оператор присваивания перемещения и деструктор все неявно определяется в вашем случае, поэтому я пошел дальше и удалил ваше определение конструктора копирования.

Вы должны также заметить, что я удалил, что указатель-для-себя определенному вами конструктору, который вы также выразил обеспокоенность по поводу. У меня есть хорошие новости для вас: этот конструктор является абсолютно ненужным! На самом деле, ваш исходный код даже не использовать его, а не моя.

Где to_string?

Я не знаю, почему ты счел нужным написать собственную версию этой функции, но стандартный что-то с точно такой же функциональностью в string заголовок (ну, помимо того, что std::to_string будет просто отвергать все, что не число).

Все-таки, давайте занять некоторое время и поговорить о своей версии этой общей функциональности. Три вещи, которые приходят мне на ум здесь:


  1. Почему вы берете number купить ссылку? Вы ожидаете числовых типов, которые достаточно малы, чтобы эффективно передать как значения.

  2. Имея нормальный if на времени компиляции тип черта-это немного плохо, если у вас есть доступ к C++17. В таком случае, это должно быть четко if constexpr (...).

  3. Связи и обработки ошибок, как ошибки. Не вернуть некоторые слабовыраженные фиктивное значение если функция не увенчается успехом. Есть много способов, чтобы сигнализировать об ошибке, бросать исключение для возврата std::optional. В этом особом случае, однако, фактически ошибка диагностируемые во время компиляции. Хотя это делает две бесполезные, проверить свой тип во время компиляции и SFINAE, если это не число. Вы сэкономите большое отладки головные боли вниз по линии.

Выполнять Операции Ввода/Вывода Правильно

Возможно, вы задавались вопросом: "Эй, где моя output способ пойти?". Наверное, вы уже поняли, что я превратил его в не член operator<<и у меня есть веские причины для этого:

Представьте, что вы работаете с огромными проектами с тысячами и тысячами классов. Ваша задача заключается в том, чтобы осуществлять ведение журнала системы: иногда что-то идет не так, и это ваша задача, чтобы собрать все сообщения об ошибках, которые возникают вследствие этого, заказать их по определенным критериям, и отправлять их на различные мероприятия (например, лог-файл, стандартный поток вывода, веб-сокет). Однако, всех классов только один output() метод, как Return_Self_Test делает, что пишет сообщение std::cout.

Поэтому вы тратите полгода делать самой скучной, отупляющей рефакторинг работы кто-либо мог себе представить.

Вы понимаете, что я клоню? Вы в основном заряжает ружье, чтобы выстрелить себе в ногу, через несколько лет, когда вы пишите такой код. C++ предоставляет много гибкости по всей istream/ostream понятие, и в настоящее время используется именно об этом.

Вот почему вы должны начать писать operator<< вместо своих собственных output или write или любые методы. Это делает интеграцию выход подпрограммы в уже существующий контекст намного приятнее, так как вы можете просто оставить эти ценности std::cout как вы привыкли со всеми основными типами. Кроме того, используя общие std::ostream вместо std::cout поможет вам сэкономить много страданий, когда вы оказываетесь в ситуации, где вы должны написать то, что не в стандартный вывод.

3
ответ дан 10 марта 2018 в 03:03 Источник Поделиться