#c #constructor
#c #constructor
Вопрос:
Я читаю некоторый текст на C . В примере текст, написанный:
class Student {
int no;
char grade[M 1];
public:
Student();
Student(int, const char*);
const Studentamp; set(int, const char*);
void display() const;
};
Student::Student() {
no = 0;
grade[0] = '';
}
Student::Student(int n, const char* g) {
*this = Student(); // initialize to empty
set(n, g); // validate, reset if ok
}
Я не понимаю эту строку: *this = Student();
Почему мы должны это делать, в то время как простой вызов Student();
также вызывает конструктор по умолчанию? Спасибо
Ответ №1:
Невозможно вызвать конструктор по умолчанию напрямую (C FAQ). ie.
Student::Student(int n, const char* g){
Student();
set(n, g); // validate, reset if ok
}
не работает. Однако я также не уверен в решении, которое у вас есть.
*this = Student()
вызовет Student::operator=(const Studentamp;)
. В этом конкретном классе это нормально (эта функция является копией элемента по умолчанию), но это может быть не так в целом, потому что объект Student только «частично сконструирован» при вызове этого метода.
Лучше иметь частную функцию инициализации
void Student::init() {
no = 0;
grade[0] = '';
}
и вызовите его из обоих конструкторов.
Ответ №2:
Хотя, имхо, было бы лучше использовать общую функцию инициализации, что-то вроде этого:
class Student {
(...)
private:
void initMe();
};
Student::Student() {
initMe();
}
Student::Student(int n, const char* g) {
initMe(); // initialize to empty
set(n, g); // validate, reset if ok
}
void Student::initMe() {
no = 0;
grade[0] = '';
}
Это позволило бы избежать ненужного создания объектов.
Ответ №3:
Он создает временный Student
объект, а затем копирует его в *this
. Я бы просто инициализировал переменные-члены как пустые во втором конструкторе. Идея в том, что вам не нужно писать один и тот же код, который дважды инициализирует переменные-члены как пустые, но здесь это довольно тривиальная проблема.
Комментарии:
1. это плохой совет. Дублирование — это плохо. Там, где этого тривиально можно избежать, это особенно непростительно. Придерживайтесь кода в вопросе, и когда вам нужно расширить класс, вам нужно добавить инициализацию только в одном месте.
2. Вы также могли бы добавить частный метод init() для значений по умолчанию и вызывать его из всех конструкторов, экономя накладные расходы на создание временного объекта.
3. хорошо, я мало что знаю о деталях конструкторов c . Но я знаю, что дублирование кода — это плохо, и если частная инициализация — лучший способ добиться этого, то это правильный путь.
4. Дэвид, я не пытался защищать дублирование кода, я просто имел в виду, что в этом тривиальном случае было бы неплохо просто использовать список инициализаторов конструктора для инициализации переменных-членов вместо ненужного создания пустого объекта. Для любой нетривиальной инициализации или ну, было бы дублирование кода, вы, очевидно, должны разделить его на отдельный метод инициализации, чтобы избежать дублирования.
Ответ №4:
*this = Student();
это просто инициализация переменных-членов относительно вызываемого конструктора по умолчанию. Такого дизайна следует избегать, поскольку он создает временное и копирует его содержимое.
Используйте что-то вроде приведенного ниже:
void reset() { // introduce this method inlined in the class
grade[no = 0] = '';
}
Student::Student() {
reset(); // call it when needed
}
Student::Student(int n, const char* g) {
reset(); // initialize to empty
set(n, g); // validate, reset if ok
}