Инструменты пользователя

Инструменты сайта


examination:oop:question35

Использование конструкторов для инициализации объектов и преобразования значений объектов различных классов

Инициализация объектов класса с помощью таких функций как set_date() - неэлегантное и чреватое ошибками решение. Поскольку явно не было указано, что объект требует инициализации, программист может либо забыть это сделать, либо сделать дважды, что может привести к столь же катастрофическим последствиям. Лучше дать программисту возможность описать функцию, явно предназначенную для инициализации объектов.

Поскольку такая функция конструирует значение данного типа, она называется конструктором. Эту функцию легко распознать - она имеет то же имя, что и ее класс:

    class date { 
    // ... 
    date(int, int, int); 
    }; 

Если в классе есть конструктор, все объекты этого класса будут проинициализированы. Если конструктору требуются параметры, их надо указывать:

    date today = date(23,6,1983); 
    date xmas(25,12,0); // краткая форма 
    date my_birthday; // неправильно, нужен инициализатор 

Часто бывает удобно указать несколько способов инициализации объекта. Для этого нужно описать несколько конструкторов:

    class date { 
    int month, day, year; 
    public: 
    // ... 
    date(int, int, int); // день, месяц, год 
    date(int, int); // день, месяц и текущий год 
    date(int); // день и текущие год и месяц 
    date(); // стандартное значение: текущая дата 
    date(const char*); // дата в строковом представлении 
    }; 

Параметры конструкторов подчиняются тем же правилам о типах параметров, что и все остальные функции. Пока конструкторы достаточно различаются по типам своих параметров, транслятор способен правильно выбрать конструктор:

    date today(4); 
    date july4("July 4, 1983"); 
    date guy("5 Nov"); 
    date now; // инициализация стандартным значением 

Размножение конструкторов в примере c date типично. При разработке класса всегда есть соблазн добавить еще одну возможность, - а вдруг она кому-нибудь пригодится. Чтобы определить действительно нужные возможности, надо поразмышлять, но зато в результате, как правило, получается более компактная и понятная программа. Сократить число сходных функций можно с помощью стандартного значения параметра.

В примере с date для каждого параметра можно задать стандартное значение, что означает: «взять значение из текущей даты».

    class date { 
    int month, day, year; 
    public: 
    // ... 
    date(int d =0, int m =0, y=0); 
    // ... 
    }; 
    date::date(int d, int m, int y) 
    { 
    day = d ? d : today.day; 
    month = m ? m : today.month; 
    year = y ? y : today.year; 
    // проверка правильности даты 
    // ... 
    } 

Когда используется стандартное значение параметра, оно должно отличаться от всех допустимых значений параметра. В случае месяца и дня очевидно, что при значении нуль - это так, но неочевидно, что нуль подходит для значения года. К счастью, в европейском календаре нет нулевого года, т.к. сразу после 1 г. до р.х.(year==-1) идет 1 г. р.х. (year==1). Однако для обычной программы это, возможно, слишком тонкий момент.

Объект класса без конструктора может инициализироваться присваиванием ему другого объекта этого же класса. Это незапрещено и в том случае, когда конструкторы описаны:

    date d = today; // инициализация присваиванием 

Преобразование значений объектов

можно описать конструктор, который из параметра double создает complex:

    class complex { 
    // ... 
    complex(double r) { re=r; im=0; } 
    }; 

Этим определяется как получить complex, если задан double. Это традиционный способ расширения вещественной прямой до комплексной плоскости.

Конструктор с единственным параметром не обязательно вызывать явно:

    complex z1 = complex(23); 
    complex z2 = 23; 

Обе переменные z1 и z2 будут инициализироваться вызовом complex(23). Конструктор является алгоритмом создания значения заданного типа. Если требуется значение некоторого типа и существует строящий его конструктор, параметром которого является это значение, то тогда этот конструктор и будет использоваться. Так, класс complex можно было описать следующим образом:

    class complex { 
    double re, im; 
    public: 
    complex(double r, double i =0) { re=r; im=i; } 
    friend complex operator+(complex, complex); 
    friend complex operator*(complex, complex); 
    complex operator+=(complex); 
    complex operator*=(complex); 
    // ... 
    }; 

Все операции над комплексными переменными и целыми константами с учетом этого описания становятся законными. Целая константа будет интерпретироваться как комплексное число с мнимой частью, равной нулю. Так, a=b*2 означает

    
    a = operator*(b, complex( double(2), double(0) ) ) 
examination/oop/question35.txt · Последние изменения: 2014/01/15 08:22 (внешнее изменение)