C++: геттеры и сеттеры?

Я пытаюсь написать некоторый код для создания геттеров и сеттеров для идентификационного номера, имени, фамилии, промежуточной оценки и окончательной оценки следующих данных, которые находятся в текстовом файле, в классе, который я пишу. .

10601   ANDRES HYUN 88 91 94 94 89 84 94 84 89 87 89 91 
10611   THU ZECHER 83 79 89 87 88 88 86 81 84 80 89 81 
10622   BEVERLEE WAMPOLE 95 92 91 96 99 97 99 89 94 96 90 97 
10630   TRUMAN SOVIE 68 73 77 76 72 71 72 77 67 68 72 75 

Идентификатор — это первое число, имя и фамилия говорят сами за себя, промежуточный балл — предпоследнее число, а последнее число — окончательный результат. Я впервые использую геттеры и сеттеры, и до сих пор у меня...

int getID()const{return ID;}
void setID(int i) {ID=i}
string getFname()const{return Fname;}
void setFname(string f) {Fname = f}
string getLname()const{return Lname;}
void setLname(string l) {Lname = l}
int getMidterm()const{return Midterm;}
void setMidterm(int m) {Midterm=m}
int getFinal()const{return Final;}
void setFinal(int fl) {Final=fl}

Я вообще на правильном пути? Кроме того, как мне указать, что первое число в наборе данных — это идентификатор, первая строка — это имя, вторая строка — второе имя, предпоследнее число — промежуточный срок, а последнее число — окончательная оценка?


person Bob    schedule 13.09.2013    source источник
comment
Ваш вопрос о том, как получить ввод из заданного текстового файла и сохранить его в своем классе с помощью этих сеттеров/геттеров? Требуется ли настройка этих установщиков/геттеров?   -  person greatwolf    schedule 13.09.2013
comment
выглядит хорошо, но я бы передал строки вашим сеттерам по константной ссылке, а не по значению (string const & вместо string)   -  person japreiss    schedule 13.09.2013
comment
Мне кажется, все хорошо. Возможно, вы захотите использовать константные ссылки для строк.   -  person Julien Guertault    schedule 13.09.2013
comment
Я пытаюсь написать некоторый код для создания геттеров и сеттеров... Немедленно остановитесь - это уже плохая идея.   -  person Jerry Coffin    schedule 13.09.2013


Ответы (3)


Если вы спрашиваете о написании геттеров и сеттеров, то да, именно столько людей этим занимаются. Чтобы написать «идеальные» средства доступа к сложным типам, вы должны использовать это:

void setLname(const String& input) { Lname = input; }    //copies the string
void setLname(String&& input) { Lname = std::move(input); }    //moves the string
const String& getLname() const { return Lname; }    //allows to get a const String reference from a const object
String& getLname() { return Lname; }    //allows modifying access to Lname if the object is not const.

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

Однако многие методы доступа — это запах кода:

  1. Они засоряют код функциями, которые не обеспечивают какой-либо абстракции.

  2. Всякий раз, когда у вас есть и геттер, и сеттер, у вас практически неограниченный доступ к этому элементу данных; так что вы могли бы также написать public: String Lname.

  3. Множество методов доступа — это верный признак того, что вы моделируете данные, а не поведение. В этих случаях вы должны либо переосмыслить свой дизайн, либо быть честным и пойти дальше и использовать либо общедоступные члены, либо, если все члены будут общедоступными, struct ИМХО.

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

Итак, на вашем месте я бы спросил себя: какое поведение мне нужно от моего класса? Мне действительно нужно говорить обо всех его элементах данных в другом коде, или я могу найти разумные абстракции, которые мой класс может предоставить, что сделало бы методы доступа бесполезными? Возможно ли, что я думаю о моделировании не того класса объектов? Или мне действительно нужен контейнер для моих данных, который можно использовать и изменять везде?

person cmaster - reinstate monica    schedule 13.09.2013
comment
Первые два метода доступа также могут быть записаны как void setLname(String input) { Lname = std::move(input); }. Обратите внимание, что это может вызвать еще один ход, если нельзя применить исключение хода (например, x.setLname(std::move(some_lvalue))). - person dyp; 14.09.2013

выглядит хорошо. некоторые замечания:

  • Передайте string как const string&, чтобы не сделать бесполезную копию.
  • Больше пробелов помогло бы улучшить читаемость
  • Не сокращайте вещи. getFirstName() более читаем, чем getFname()

Что касается вашего второго вопроса, вы можете использовать множество утилит сканирования/потока, доступных на С++, таких как scanf, sscanf, fscanf, stringstream, iostream, fstream и т. д.

std::ifstream inFile("database.txt");
std::string line;
while (std::getline(inFile, line)) // for each line
{
    std::stringstream ss;
    ss << line;

    int id;
    ss >> id;

    std::string firstName;
    ss >> firstName;

    // etc
}
person Nicolas Louis Guillemot    schedule 13.09.2013
comment
Конечно, Боб. ifstream — входной файловый поток. это для чтения в файлах. getline читает одну строку из inFile и сохраняет ее в line и возвращает true до тех пор, пока файл не станет пустым. потоки в C++ позволяют читать и писать из разных типов с помощью операторов >> и <<, поэтому я преобразовываю line в строковый поток, записывая line в поток ss. Теперь я могу свободно извлекать данные из потока. id << ss извлекает первое целое из потока и сохраняет его в id. firstName << ss извлекает одно слово из потока и сохраняет его в firstName. - person Nicolas Louis Guillemot; 13.09.2013
comment
Нет перегрузки operator <<, которая позволяет вызывать его, как вы сделали выше. Чтение из std::stringstream (или любого другого потока STL) выполняется с помощью operator >>, а запись в поток выполняется с помощью operator <<. Для обоих типов операторов первый параметр — это поток, а второй — значение, которое нужно прочитать/записать в него. Итак, в вашем примере чтение int выполняется с помощью ss >> id; - person Ionut; 13.09.2013
comment
Ты совершенно прав, я всегда все путаю. Спасибо, я отредактировал свой пост, чтобы отразить то, что вы сказали. - person Nicolas Louis Guillemot; 13.09.2013

Часть 1:
Именно так должны выглядеть методы получения и установки (по крайней мере, в Java).

Часть 2:
Чтобы установить поля класса, вам все равно придется анализировать ввод вручную. Я рекомендую изучить потоки ввода-вывода C++, особенно оператор >>. для входных потоков.

person BinderNews    schedule 13.09.2013