Конструкторы преобразований
Если конструктор класса А воспринимает единственный аргумент типа В, то говорят, что В может быть приведен к А с помощью преобразования конструктором. Другими словами, компилятор может использовать конструктор класса А с аргументом типа В, чтобы получить А из В. Сказанное рассмотрим на примере комплексных чисел.
Пример.
class comp
{
float Re, Jm;
public:
comp (float a, float b)
{
Re = a;
Jm = b;
}
comp ( float a )
{
Re = a;
Jm = Ø;
}
comp ( )
{
}
};
void main ( )
{
float r = 96;
comp a(2, -2), b = r;
comp c;
c = b;
}
При создании объекта а вызывается конструктор с двумя параметрами.
В результате a. Re = 2
a. Jm = -2.
Затем вызывается конструктор с одним параметром. Создается объект b c элементами данных b. Re = 96
b. Jm = Ø.
Из объекта r типа float с помощью конструктора создан объект класса comp.
При создании объекта c вызывается «пустой» конструктор. Далее в результате присваивания будет получено
с. Re = 96
с. Jm = Ø.
Операция приведения
Это функции–элементы класса, которые осуществляют явное преобразование типа класса к другому типу. Они имеют следующий вид:
Оperator имя_нового_типа ( )
{
: : : :
}
Вызов: имя_нового_типа (имя_объекта_класса);
Операторы приведения подчиняются следующим правилам:
1) Не имеют формальных аргументов; Считается по умолчанию, что это имя объекта данного класса.
2) Нет явного описания типа возвращаемого результата. Считается, что тип результата тот, к которому приводит оператор приведения.
3) Может описываться как virtual.
4) Наследуется.
Пример.
# include < stdio. h>
class A
{
int k;
char * str;
public:
A (int a, char * s)
{
k = a
str = s;
}
operator int ( )
{
return k;
}
};
void, main ( )
{
A q (12, “Coretta”);
printf (“Целая часть для q = % i \ n “, int (q);
}
В описании класса А определена функция-элемент этого класса operator int ( ). Она преобразует объект q класса А в переменную типа int. Это происходит в результате вызова операции приведения int (q). Подобным образом можно преобразовать объект класса А в переменную (объект) типа char.
Лекция 19
19.1 Друзья
Язык С++ разрешает использовать в качестве аргументов объекты одного класса другому классу или функции, которая не является членом этого класса. Для этого используется ключевое слово friend.
Дружественные функции
Можно разрешить обычной функции или функции – элементу другого класса пользоваться объектами класса , который объявил эту функцию дружественной с помощью описания friend при определении класса. То есть при определении класса приводится прототип дружественной функции, перед которым стоит слово friend. Ниже приводится пример дружественной функции kuma (man&), у которой в качестве аргумента является ссылка на класс man. Класс man объявил функцию kuma ( ) дружественной для себя.
# include <stdio.h>
Class man
{
char name [20];
char adres [25];
public:
friend void kuma (man& x);
void get_info ( );
void put_info ( );
};
Void man :: get_info ( )
{
puts (“Введите имя”);
fflush (stdin);
scanf (“%s”, &name);
puts (“Введите адрес”);
fflush (stdin);
scanf (“%s”, &adres);
}
Void man :: put_info ( )
{
printf (“Имя %s, адрес %s \n”, name, adres);
}
Void main ( )
{
man V;
V.get_info ( );
V.put_info ( );
kuma (V);
}
void kuma (man& x)
{
printf (“Я кума у %s. Его адрес %s \n”, х.name, х.adres);
}
Дружественные классы
При определении класса можно объявить другой класс в качестве друга. Такое объявление выглядит так:
friend class имя_дружественного_класса;
При этом слово class можно не писать.
Благодаря этому объявлению функции-члены дружественного класса могут использовать в качестве аргумента объекты того класса, который объявил его другом.
В приведенном ниже примере в классе man объявлен в качестве дружественного класс kum.
Функция-элемент kum () класса kum использует объект класса man.
# include <stdio.h>
Class man
{
char name [10];
public:
friend class kum; // classможно не писать
void get_info_man (char* nm)
{
printf (“Введите имя для %s \n”, nm);
fflush (stdin);
scanf (“%s”, &name);
}
};
Class kum
{
char name_children [15];
public:
void get_kum_info ( );
{
puts (“Введите имя ребенка”);
fflush (stdin);
scanf (“%s”, &name_children);
}
void kuma (man& x)
{
printf (“У меня есть кум %s \n”, х.name);
printf (“Имя ребенка %s \n”, name_children);
}
};
Void main ( )
{
man a;
a.get_info_man (“a”);
kum b;
b.get_kum_info ( );
b.kuma (a);
}
Следует обратить внимание, что функция-член kuma ( ) должна быть описана после спецификатора public, так как иначе b.kuma (a) выполнить невозможно.
Правила по отношению к друзьям
1) На описание friend не действуют спецификаторы public, protected, private.
2) Описание friend не взаимное: если А объявляет В другом, то это не означает, что А является другом для В.
3) Дружественность не наследуется. Если А объявляет В другом, то классы, производные от А, не будут автоматически признавать дружественность В.
Лекция 20
Перегруженные операции
Для типов float, double, int, long определены операции +, -, *, /, %, +=, -= и др. Но для типов, которые получены с помощью классов, эти операции надо реализовать самостоятельно. С этой целью можно было бы применить
функции-члены, например: plus ( ) для сложения, plusequal ( ) для += и т.д. Но это неудобно. Значительно лучше применить общеупотребительные знаки +, += и прочие. А для этого надо перегрузить упомянутые или другие операции для объектов описанного класса.
Перегрузить можно любую операцию, кроме следующих: ., .*, ::, ?:.
Это можно сделать двумя способами:
1) С помощью перегруженных операторов – функций, которые являются членами класса;
2) С помощью перегруженных функций, которые являются friend (дружественными функциями) для данного класса.
Рассмотрим первый способ. В этом случае синтаксис для перегруженной операции имеет вид:
имя_класса& operator операция (имя_класса& параметр)
Рассмотрим пример для перегруженной операции += для комплексных чисел.
# include <stdio.h>
Class comp
{
float Re, Im;
public:
Comp (float a, float b)
{
Re=a;
Im=b;
}
comp& operator += (comp& x)
{
Re+=x.Re;
Im+=x.Im;
return *this;
}
void put_info (char *Str)
{
printf (“%s.Re=%f %s.Im=%f\n”, Str, Re, Str, Im);
}
};
Void main ( )
{
comp C1 ( 2, -2), C2 (-2, 2);
C1+=C2;
C1.put_info (“C1”);
}
В результате перегруженной операции += значение С1 изменится. Ее адрес при вызове операции += был передан в this. Второй параметр был передан в качестве фактического параметра вместо формального х. Результат возвращается через *this. Если нужно сложить два комплексных числа и при этом оставить их значения без изменений, можно использовать второй способ перегрузки операции с помощью дружественной функции. Для этого примера прототип такой функции следующий:
friend comp operator + (comp& C1, comp& C2);
Необходимо еще раз обратить внимание на то, что эта функция не являеться членом класса. Программа для этого случая следующая:
# include <stdio.h>
Class comp
{
float Re, Im;
public:
Comp (float a, float b)
{
Re=a;
Im=b;
}
Comp ( )
{
}
friend comp operator + (comp& C1, comp& C2);
void put_info (char *Str)
{
printf (“%s.Re=%f %s.Im=%f\n”, Str, Re, Str, Im);
}
};
Void main ( )
{
comp C1 ( 2, -2), C2 (-2, 2);
comp C3;
C3=C1+C2;
C3.put_info (“C3”);
}
comp operator + (comp& C1, comp& C2);
{
comp V;
V.Re=C1.Re + C2.Re;
V.Im=C1.Im + C2.Im;
return V;
}
При перезагрузке операций следует выполнять следующие правила:
1) Приоритеты операций и правила ассоциаций, принятые для типов float, double, int, long, должны оставаться неизменными также и для перегруженных функций-операций;
2) Функции-операции не могут изменить поведение операции по отношению к стандартным типам float, double, int, long;
3) Функция-операция должна быть или элементом класса, или воспринимать один или несколько аргументов, которые имеют тип класса;
4) Функция-операция не может иметь аргументы по умолчанию;
5) За исключением operator = ( ) все функции-операции наследуются.
Лекция 21
Статические элементы
Статические элементы-данные
Статические элементы-данные - это глобальные переменные, доступные только в пределах области класса. Объявляются при описании класса, а инициализируются после того, как класс описан. Признаком статического элемента является ключевое слово static. Синтаксис написания имеет вид
static тип имя_элемент-данных.
Например,
Сlass A
{
static int x ; // Объявление
: : : : :
};
int A :: x = 125; //Инициализация
Здесь приведен статический элемент данных целого типа. После завершения описания класса А этот элемент инициализирован. Инициализация обязательна! Элемент данных, определенный как static, используется всеми объектами данного класса. Существует только один экземпляр переменной независимо от числа созданных объектов. На самом деле, память под статический элемент выделяется, даже если не существует ни одного объекта данного класса. Именно потому, что это только один экземпляр, обращение к нему имеет вид:
имя_класса : : имя_элемента=данных.
Тот факт, что статический элемент данных инициализируется, не означает, что существует запрет на изменение его значения в ходе работы программы.
Не нашли, что искали? Воспользуйтесь поиском по сайту:
©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.
|