Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Пособие-ООП - копия.doc
Скачиваний:
20
Добавлен:
17.08.2019
Размер:
907.78 Кб
Скачать

Преобразования типов, определяемые классом

Преобразование типов данных является одной их форм полиморфизма. При объектно-ориентированном программировании необходимы средства преобразований, определяемые классом (элементы-функции класса). Функциями преобразований являются: конструкторы преобразования и операции преобразования.

Конструктор преобразования - это конструктор класса с одним аргументом, служащий для преобразования из типа аргумента к типу класса.

Конструктор удобен для преобразования из базового типа в тип класса. Возьмем пример (класс complex) с перегруженной операцией +, рассмотренный выше. Пусть необходимо складывать комплексные числа с вещественными числами с получением комплексных чисел. Для этого требуется преобразование вещественного числа в комплексное число с нулевой мнимой частью. Добавим в класс complex конструктор преобразования с аргументом типа float.

Пример 3:

//файл заголовков complex3.hpp

#include <iostream.h>

#include <conio.h>

class complex

{

public:

float d,m;

complex () {d=m=0;}

complex(float x,float y) {d=x;m=y;}

complex operator +(complex& x);

complex(float x) {d=x;m=0;} //конструктор преобразования

};

//файл кодов complex3.cpp

#include "complex3.hpp"

complex complex::operator +(complex& x)

{

complex y;

y.d=d+x.d;

y.m=m+x.m;

return(y);

}

main()

{

clrscr();

complex obj1(0,1);

float a=4.5;

obj1=obj1+a; //a преобразуется из float в complex

cout<<obj1.d<<" "<<obj1.m<<'\n'; //результат: 4.5 1

getch();

}

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

Операция преобразования имеет следующие свойства:

- синтаксис операции преобразования напоминает синтаксис перегруженной операции: operator tip() {...} ,где tip - идентификатор нового типа, в который происходит преобразование;

  • не имеет аргументов и типа возвращаемого значения;

  • должна быть нестатической элементом-функцией класса;

  • наследуется и может быть как virtual.

Операция удобна для преобразования из типа класса в базовый тип. Пусть необходимо складывать комплексные числа с вещественными числами с получением вещественных чисел. Заменим в предыдущем примере в классе complex конструктор преобразования на операцию преобразования с типом float.

Пример 4:

//файл заголовков complex4.hpp, заменим complex(float x) {d=x;

// m=0;} на operator float() {return(d);}

#include <iostream.h>

#include <conio.h>

class complex

{ //... см. complex3.hpp

operator float() {return(d);}

};

//файл кодов complex4.cpp

#include "complex4.hpp"

complex complex::operator +(complex& x)

{

complex y;

y.d=d+x.d;

y.m=m+x.m;

return(y);

}

main()

{

clrscr();

complex obj1(0,1);

float a=4.5;

float b=obj1+a; //obj1 преобразуется из типа complex в тип float

cout<<b<<'\n'; //результат: 4.5

getch();

}

Для преобразования объектов одного и того же класса используются конструкторы копирования, задаваемые явно либо по умолчанию. Пусть выполняется операция присваивания: obj2=obj1; , где obj1 и obj2 объекты одного и того же класса. В этом случае никаких преобразований типов не происходит, а выполняется только неявное поэлементное копирование.

Для преобразования объекта одного класса в объект другого класса (без наследования) используются рассмотренные выше функции преобразования: конструктор преобразования и операция преобразования. Пусть требуется преобразовать объект obj1 класса cl1 в объект obj2 класса cl2, т.е. ,например, obj2=obj1;. Тогда синтаксис функций преобразования будет иметь вид:

  • конструктор класса cl2: cl2::cl2(const cl1&){...}

  • операция класса cl1: cl1::operator cl2(){...}

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

Рассмотрим влияние наследования на преобразование объектов базовых и производных классов. При преобразовании объектов производного класса функции преобразования не требуется. Например, при выполнении операции присваивания происходит неявное поэлементное копирование собственной части и наследуемой (базовой) части одного объекта в другой. Пусть obj1 - объект базового класса cl1, obj2 - объект производного класса cl2. Преобразование объекта производного класса в объект базового класса допустимо без функции преобразования: obj1=obj2; ,т.е. часть объекта obj2, унаследованная от класса cl1, присваивается объекту obj1.

Преобразование объекта базового класса в объект производного класса не допустимо без функции преобразования: obj2=obj1; , это не допустимо, так как нет функции преобразования. Требуется явное преобразование из типа cl1 в тип cl2, поэтому, надо создать либо конструктор преобразования в классе cl2 (cl2::cl2 (const cl1&) {...}), либо операцию преобразования в классе cl1 (cl1::operator cl2(){...}). Теперь можно преобразование: obj2=obj1; , теперь преобразование из типа cl1 в тип cl2 допустимо.