Главная Случайная страница Контакты | Мы поможем в написании вашей работы! | ||
|
Конструктор приведення класу — це конструктор з єдиним аргументом, тип якого відрізняється від типу класу. Такий конструктор звичайно ініціалізує новий об'єкт, використовуючи літерали, або дані змінних або об'єктів інших типів.
Наприклад, в клас CMoney можна додати конструктор приведення, який дасть можливість ініціалізувати об'єкт, використовуючи суму гривень і копійок, виражену одним дійсним числом з плаваючою крапкою:
class CMoney
{
// …
public:
// …
CMoney (double GrivnasAndCopecks)
{
Grivnas = long(GrivnasAndCopecks);
Copecks = int((GrivnasAndCopecks - Grivnas)* 100.0 + 0.5);
}
};
Конструктор округляє число копійок, що зберігається в аргументі GrivnasAndCopecks, до найближчого цілого числа. Крім того, конструктор виконує явне приведення типів даних, використовуючи дозволений в мові C++ альтернативний синтаксис, що відрізняється від традиційного запису операції приведення типів; у конструкторі використовується вираз long(GrivnasAndCopecks), а не традиційний запис (long)GrivnasAndCopecks.
Наведений вище конструктор приведення дозволяє ініціалізувати об'єкти класу CMoney таким чином:
CMoney Bucksl(29.63);
CMoney Bucks2 = 43.247; // буде округлено до 43.25
CMoney Bucks3 (2.0e9); // майже максимально допустиме
// число копійок
CMoney *Bucks = new CMoney(534.85);
Приведене раніше оголошення класу CMoney містило наступний конструктор:
CMoney (long Grn, int Cop)
{
SetAmount (Grn, Cop);
}
Цей конструктор можна переробити в конструктор приведення, додавши для другого аргументу значення за умовчанням:
CMoney (long Grn, int Cop = 0)
{
SetAmount(Grn, Cop);
}
Оскільки так написаний конструктор може тепер приймати один фактичний аргумент, його можна використовувати для ініціалізації об'єктів класу CMoney, задаючи тільки кількість гривень:
// обидві інструкції встановлюють значення: Grivnas = 25 і Copecks = 0
CMoney Dough = 25L;
CMoney *PDough = new CMoney (25L);
Символ L додається в кінець кожної цілочисельної константи, задаючи їй тип long. Якщо даний символ не вказаний, константа розглядатиметься як константа типу int. У цій ситуації компілятор не визначить, чи приводити значення типу int до типу double, щоб викликати конструктор для double, або приводити значення тип int до значення типу long з тим, щоб викликати конструктор для long.
Така ситуація називається неоднозначним викликом перевантаженої функції і породжує помилку компіляції. Приведення типу int до double або long є стандартними приведеннями. Хоча змінні типів int та long мають однаковий розмір в Visual C++, вони розглядаються як різні типи, які вимагають приведення.
Розглянемо приклад з включенням конструктора приведення в клас CMessage:
class CMessage
{
//...
public:
//...
CMessage (const char *String)
{
Buffer = new char[strlen (String)+1];
strcpy (Buffer, String);
}
};
Тепер об'єкт повідомлення можна ініціалізувати одним рядком:
CMessage Note = "Зроби це зараз!";
CMessage *PNote = new CMessage ("Пам'ятай це завжди!");
Нижче приведена остаточна версія класу CMessage, включаючи нові конструктори копіювання і приведення.
// CMess.h: файл заголовків класу CMessage
#include <string.h>
#include <iostream>
using namespace std;
class CMessage
{
private:
char *Buffer;
public:
CMessage () // конструктор за умовчанням
{
Buffer = new char ('\0');
}
CMessage (const CMessage SMessage) // конструктор копіювання
{
Buffer = new char[strlen (Message.Buffer) + 1];
strcpy (Buffer, Message.Buffer);
}
CMessage (const char *String) // конструктор приведення
{
Buffer = new char[strlen (String) + 1];
strcpy (Buffer, String);
}
~CMessage ()
{
delete [] Buffer;
}
void Display ()
{
cout << Buffer << '\n';
}
void Set (char *String)
{
delete [] Buffer;
Buffer = new char[strlen (String) + 1];
strcpy (Buffer, String);
}
CMessage& operator= (const CMessage Message)
{
if (Message = this)
return *this;
delete [] Buffer;
Buffer = new char[strlen(Message.Buffer) + 1];
strcpy (Buffer, Message.Buffer);
return *this;
}
};
7.5 Динамічна ідентифікація типу
В мові C++ для підтримки об’єктно – орієнтованого програмування разом з приведеннями типів в стилі мови C++, розглянутими в підрозділі 2.7.2, є ще один допоміжний засіб – ідентифікація типу під час виконання (Run – Time Type Identification - RTTI).
Ідентифікація типу під час виконання здійснюється спеціальним оператором typeid(), який оголошений в заголовному файлі <typeinfo> в двох варіантах:
typeid(object)
typeid(type)
Обидва варіанти оператора під час виконання програми повертають посилання на об'єкт класу type_info, який також оголошений в заголовному файлі <typeinfo>. Об'єкт класу type_info, посилання на який повертається оператором, містить розгорнену інформацію про тип аргументу, заданого як об'єкт object в першому варіанті або як ім'я типу type – в другому варіанті оператора.
Клас type_info містить закриті члени і наступні відкриті члени класу:
const char* name();
bool operator==(const type_info &ob);
bool operator!=(const type_info &ob);
bool before(const type_info &ob);
Функція name() повертає вказівник на рядок, що містить ім'ям типу аргументу оператора.
Перевантажені оператори == та!= дають можливість порівнювати типи об'єктів: викликаючого об'єкту і об'єкту, заданого аргументом.
Функція before(), як правило, використовується для внутрішніх цілей; вона повертає true, якщо викликаючий об'єкт передує об'єкту, заданому як аргумент.
Найбільшу користь можна отримати від оператора type_info(), застосовуючи його до вказівника на об'єкт базового класу. При такому використанні він автоматично повертає тип реального об'єкту, адресу якого містить в даний момент вказівник, наприклад:
#include <iostream>
#include <typeinfo>
using namespace std;
class A
{
public:
virtual bool f(){return false;}
…
};
class B: public A
{
public:
…
};
int main()
{
A *p;
A obA;
B obB;
p = &obA;
cout << “Вказівник p містить адресу об'єкту типу ”;
cout << typeid(*p).name() << ‘n’;
p = &obB;
cout << “Вказівник p містить адресу об'єкту типу ”;
cout << typeid(*p).name() << ‘n’;
return 0;
}
Після виконання даної програми на екрані з'являться два рядки:
Вказівник p містить адресу об'єкту типу class A
Вказівник p містить адресу об'єкту типу class B
Дата публикования: 2014-11-03; Прочитано: 644 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!