Читайте также: |
|
Ключевое слово operator предоставляет объявление функции, указывающей что operator-symbol означает при его применении к экземплярам класса. Это предоставляет оператору многозначность или "перегружает" его. Компилятор различает разные виды одного и того же оператора, изучая типы его операндов.
type operator operator-symbol (parameter-list)
Доступом к члену класса можно управлять путем перегрузки оператора доступа к члену (–>). В данном случае этот оператор считается унарным оператором, и функция перегруженного оператора должна быть функцией-членом класса. Поэтому объявление такой функции выглядит следующим образом.
class-type *operator–>()
Перегрузке могут быть подвергнуты следующие унарные операторы.
! (логическое НЕ) & (взятие адреса) ~ (дополнение до единицы) * (разыменование указателя) + (унарный плюс) - (унарное отрицание) ++ (инкремент) -- (декремент) операторы преобразования
Имеется возможность перегрузить new и delete. Это можно сделать в том случае, если необходимо использовать какой-то особый способ выделения памяти. Например, может понадобиться процедура выделения памяти, автоматически использующая дисковый файл в качестве виртуальной памяти в том случае, когда куча оказывается исчерпанной. Какой бы ни была причина, осуществить такую перегрузку очень просто.
Для перегрузки операторов new и delete может использоваться следующий формат:
void *operator new(size_t размер)
{
// выполнение выделения
return указатель_на_память;
}
void operator delete(void *p)
{
// освобождение памяти, на которую указывает р
}
Параметр размер будет содержать число в байтах, которое необходимо выделить для размещения объекта. Это значение будет сформировано автоматически. Перегруженная функция new должна возвращать указатель на выделенную память. За исключением этих ограничений перегруженная функция new может выполнять все, что необходимо.
Функция delete получает указатель на область памяти, которую необходимо освободить. Она обязана освободить эту память. Для перегрузки операторов new и delete применительно к массивам надо использовать следующий формат:
void *operator new[](size_t размер)
{
// выполнение выделения
return указатель_на_память;
}
void operator delete[](void *р)
{
// освобождение памяти, на которую указывает р
}
Можно перегрузить операторы new и delete глобально или относительно класса. Для того чтобы перегрузить их по отношению к классу, просто надо сделать их функциями-членами этого класса.
Преобразование позволяет получить новое значение некоторого типа из значения другого типа. Стандартные преобразования основаны на языке C++ и поддерживают его встроенные типы; кроме того, можно создать пользовательские преобразования для выполнения преобразования в, из или между пользовательскими типами.
Стандартные преобразования выполняют преобразование между встроенными типами, между указателями или ссылками на типы, связанные наследованием, в и из указателей void и в пустой указатель. Для получения дополнительной информации см. Стандартные преобразования. Пользовательские преобразования выполняют преобразование между пользовательскими типами или между пользовательскими и встроенными типами. Их можно реализовать как conversion constructors илиconversion functions.
Преобразования могут быть явными, когда программист вызывает преобразование одного типа в другой (как в приведении или прямой инициализации) или неявными, когда язык или программа вызывают типы, которые отличаются от заданных программистом.
Попытка неявного преобразования выполняется, когда тип аргумента, предоставленного для функции, не совпадает с соответствующим параметром; тип значения, возвращаемого функцией, не совпадает с типом возвращаемого значения функции; тип выражения инициализатора не совпадает с типом инициализируемого объекта; тип результата выражения, которое управляет условным оператором, циклической конструкцией или параметром, не совпадает с тем, который требуется для управления; тип операнда, предоставленного для оператора, не совпадает с соответствующим параметром операнда.
Для встроенных операторов тип обоих операндов должен совпадать; он преобразуется в общий тип, который может представлять оба операнда. Для получения дополнительной информации см. Арифметические преобразования. Для пользовательских операторов тип каждого операнда должен совпадать с соответствующим параметром операнда.
Если не удается выполнить неявное преобразование с помощью стандартного преобразования, компилятор может использовать пользовательское преобразование, за которым (при необходимости) будет следовать дополнительное стандартное преобразование.
Если на сайте преобразования есть два и более пользовательских преобразования, выполняющих одно преобразование, преобразование называется неоднозначным. Неоднозначность подразумевает ошибку, так как компилятор не может определить, какое из доступных преобразований выбрать. Тем не менее, не будет ошибкой определить несколько способов выполнения одного преобразования, так как набор доступных преобразований может отличаться в разных участках исходного кода, например в зависимости от того, какие файлы заголовков входят в исходный файл. Пока на сайте преобразования доступно только одно преобразование, о неоднозначности речь не идет. Существует несколько путей возникновения неоднозначных преобразований, однако самые распространенные перечислены ниже.
Множественное наследование. Преобразование определено в нескольких базовых классах. Для получения дополнительной информации см. Неоднозначность.
Вызов неоднозначной функции. Преобразование определено как конструктор преобразования типа целевого объекта и как функция преобразования типа источника. Для получения дополнительной информации см. conversion functions.
Неоднозначность, как правило, можно устранить, просто более полно указав имя соответствующего типа или выполнив явное приведение для пояснения намерения.
Конструкторы преобразования и функции преобразования подчиняются правилам управления доступом членов, однако доступность преобразований учитывается, только если можно определить неоднозначное преобразование. Это означает, что преобразование может быть неоднозначным, даже если уровень доступа конкурирующего преобразования будет блокировать его использование. Дополнительные сведения о доступности членов см. в разделе Управление доступом к членам.
Функции преобразования определяют преобразования из пользовательского в другие типы. Эти функции иногда называют "операторами приведения", так как они, наряду с конструкторами преобразования, вызываются, когда значение приводится к другому типу. В следующем примере показана функция преобразования, которая преобразует пользовательский тип Money во встроенный тип double.
#include <iostream>
class Money
{
public:
Money(): amount{ 0.0 } {};
Money(double _amount): amount{ _amount } {};
operator double() const { return amount; }
private:
double amount;
};
void display_balance(const Money balance)
{
std::cout << "The balance is: " << balance << std::endl;
}
Обратите внимание, что переменная-член amount объявлена закрытой, а открытая функция преобразования в тип double добавлена только для возврата значения переменной amount. В функции display_balance неявное преобразование возникает, когда значение balance направляется в стандартный вывод с помощью оператора вставки в поток <<. Поскольку оператор вставки в поток не определен для пользовательского типа Money, но имеется для встроенного типа double, компилятор может использовать функцию преобразования Money в double, чтобы удовлетворить требования оператора вставки в поток.
Функции преобразования наследуются производными классами. Функции преобразования в производном классе переопределяют наследуемую функцию преобразования, только когда выполняют преобразование в точно такой же тип. Например, пользовательская функция преобразования производного классаoperator int не переопределяет (и даже вообще не влияет) на пользовательскую функцию базового класса operator short, даже если стандартное преобразование определяет отношение преобразования между int и short.
Объявление функций преобразования
Следующие правила применяются к объявлению функции преобразования.
Целевой тип преобразования должен быть объявлен до объявления функции преобразования. Классы, структуры, перечисления и определения типа нельзя объявлять в объявлении функции преобразования.
operator struct String { char string_storage; }() // illegal
Функции преобразования не принимают аргументов. Указание любых параметров в объявлении является ошибкой.
Функции преобразования имеют тип возвращаемого значения, задаваемый именем функции преобразования, которое также является именем типа целевого объекта преобразования. Указание типа возвращаемого значения в объявлении является ошибкой.
Функции преобразования могут быть виртуальными.
Функции преобразования могут быть явными.
Дата добавления: 2015-09-03; просмотров: 177 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
УПРАВЛЕНИЕ «НАМЕРЕНИЕМ». ТРЕТЬЯ ТОЧКА. | | | Полиморфизм и виртуальные функции. Раннее и позднее связывание. Динамический полиморфизм. Виртуальные функции. Виртуальные и невиртуальные функции. |