Определим две String – сравнение на меньше и сложение:
class String
{
public:
. . .
String operator+(const String s) const;
bool operator<(const String s) const;
};
String s1, s2; . . . s1 + s2
Объект s1 выполнит метод operator с объектом s2 в качестве аргумента.
Результатом String. Никакой из аргументов const при описании аргумента говорит о том, что s2 не может измениться при выполнении сложения, а описатель const в конце определения
Реализация может выглядеть следующим образом:
String
String::operator+(const String s) const
{
String result;
result.length = length + s.length;
result.str = new char[result.length + 1];
strcpy(result.str, str);
strcat(result.str, s.str);
return result;
}
При сравнении на меньше мы будем сравнивать строки в лексикографической последовательности. Проще говоря, меньше та строка, которая должна стоять раньше по алфавиту:
bool
String::operator<(const String s) const
{
char* cp1 = str;
char* cp2 = s.str;
while (true) {
if (*cp1 < *cp2)
return true;
else if (*cp1 > *cp2)
return false;
else {
cp1++;
cp2++;
if (*cp2 == 0) // конец строки
return false;
else if (*cp1 == 0) // конец строки
return true;
}
}
}
Если для класса определяют
Прежде всего, определим
class String
{
public:
// объявление операции присваивания
String operator=(const String s);
};
// Реализация присваивания
String
String::operator=(const String s)
{
if (this == s)
return *this;
if (str != 0) {
delete [] str;
}
length = s.length;
str = new char[length + 1];
if (str == 0) {
// обработка ошибок
}
strcpy(str, s.str);
return *this;
}
Обратим внимание на несколько важных особенностей
s1 = s2 = s3;
Во-вторых, в начале s1 = s1 выполняется правильно и быстро.
В-третьих, перед тем как скопировать новое значение,
Аналогично +=.
Набор String в различных выражениях, представлен ниже:
class String
{
public:
String();
String(const String s);
String(const char*);
String operator=(const String s);
String operator+=(const String s);
bool operator==(const String s) const;
bool operator!=(const String s) const;
bool operator<(const String s) const;
bool operator>(const String s) const;
bool operator<=(const String s) const;
bool operator>=(const String s) const;
String operator+(const String s) const;
};
Определяя класс, программист задает методы и
Первый этап – попытка воспользоваться
Если перед выражением указать имя типа в круглых скобках, то значение выражения будет
double x = (double)1; void* addr; Complex* cptr = (Complex*) addr;
Такие
Для того чтобы преобразовывать типы, хотя бы с минимальным контролем, можно записать
static_cast < тип > (выражение)
позволяет преобразовывать типы, основываясь лишь на сведениях о типах выражений, известных во время компиляции не проверяет типы выражений во время выполнения. С одной стороны, это возлагает на программиста большую ответственность, а с другой — ускоряет выполнение программ. С помощью можно выполнять как позволяет преобразовывать типы, связанные отношением наследования, указатель к указателю, один числовой тип к другому, перечислимое значение к целому. В частности, с помощью можно преобразовывать не только
указатель на производный класс к базовому классу, но и указатель на базовый класс к производному, что в общем случае небезопасно.
Однако попытка преобразовать целое число к указателю приведет к ошибке компиляции. Если все же необходимо преобразовать совершенно не связанные между собой типы, можно вместо записать reinterpret_cast:
void* addr; int* intPtr = static_cast < int* > (addr); Complex* cPtr = reinterpret_cast < Complex* > (2000);
Если необходимо ограниченное const ), можно воспользоваться :
const char* addr1; char* addr2 = const_cast < char* > addr1;
Использование , и reinterpret_cast вместо явного
К
char, unsigned char, short или unsigned short преобразуются к типу int, если точность типа int достаточна, в противном случае они преобразуются к типу unsigned int.wchar_t и константы перечисленных типов преобразуются к первому из типов int, unsigned int, long и unsigned long, точность которого достаточна для представления данной величины.int, если точность типа int достаточна, или к unsigned int, если точность unsigned int достаточна. В противном случае преобразование не производится.int, false становится 0 и true становится 1.Эти четыре типа преобразований мы будем называть безопасными преобразованиями.
Язык Си (от которого Си++ унаследовал большинство
Правила
long double, то другой преобразуется также к long double ;double, то другой преобразуется также к double ;float, то другой преобразуется также к float ;unsigned long, то другой также преобразуется к unsigned long ;long, а другой – unsigned int, и тип long может представить все значения unsigned int, то unsigned int преобразуется к long, иначе оба операнда преобразуются к unsigned long ;long, то другой преобразуется также к long ;unsigned, то другой преобразуется также к unsigned ;int.(1L + 2.3) результат типа double (8u + 4) результат типа unsigned long
Все приведенные
Как мы уже отмечали ранее, при выполнении
long x; char c; c = x;
если значение x равно 20, то и c будет равно 20. Но если x равно 500, значение c будет равно -12 (при условии выполнения на персональном компьютере), поскольку старшие биты, не помещающиеся в char, будут обрезаны. Именно поэтому большинство компиляторов выдаст ошибку и не будет транслировать подобные конструкции.
При работе с указателями и ссылками компилятор автоматически выполняет только два вида преобразований.
Если имеется указатель или ссылка на производный тип, а требуется, соответственно, указатель или ссылка на базовый тип.
Если имеется указатель или ссылка на изменяемый объект, а требуется указатель или ссылка на неизменяемый объект того же типа.
size_t strlen(const char* s);
// прототип функции
class A { };
class B : public A { };
char* cp;
strlen(cp);
// автоматическое преобразование из
// char* в const char*
B* bObj = new B;
// преобразование из указателя на производный класс
A* aObj = bObj;
// к указателю на базовый класс
Если требуются какие-то другие преобразования, их необходимо указывать явно, но в этом случае вся ответственность за правильность преобразования лежит на программисте.
В языке Си++ можно определить гораздо больше типов, чем в Си. Казалось бы, и правила
Прежде всего, выполнение тех или иных Complex:
class Complex {
. . .
friend Complex operator+(const Complex x,
int y);
friend Complex operator+(int y,
const Complex x);
};
При наличии таких функций никаких
int x; Complex y; . . . Complex z = x + y;
Тем не менее, в других ситуациях
Задав конструктор класса, имеющий в качестве аргумента величину другого типа, программист тем самым определяет правило
class Complex
{
public:
// неявное правило преобразования
// из целого типа в тип Complex
Complex(int x);
};
operator имя_типа ();
Например,
class Complex
{
public:
// операция преобразования из типа
// Complex в целый тип
operator int();
};
При записи:
Complex cmpl; int x = cmpl;
будет вызвана функция operator int().
Определим две String – сравнение на меньше и сложение:
class String
{
public:
. . .
String operator+(const String s) const;
bool operator<(const String s) const;
};
String s1, s2; . . . s1 + s2
Объект s1 выполнит метод operator с объектом s2 в качестве аргумента.
Результатом String. Никакой из аргументов const при описании аргумента говорит о том, что s2 не может измениться при выполнении сложения, а описатель const в конце определения
Реализация может выглядеть следующим образом:
String
String::operator+(const String s) const
{
String result;
result.length = length + s.length;
result.str = new char[result.length + 1];
strcpy(result.str, str);
strcat(result.str, s.str);
return result;
}
При сравнении на меньше мы будем сравнивать строки в лексикографической последовательности. Проще говоря, меньше та строка, которая должна стоять раньше по алфавиту:
bool
String::operator<(const String s) const
{
char* cp1 = str;
char* cp2 = s.str;
while (true) {
if (*cp1 < *cp2)
return true;
else if (*cp1 > *cp2)
return false;
else {
cp1++;
cp2++;
if (*cp2 == 0) // конец строки
return false;
else if (*cp1 == 0) // конец строки
return true;
}
}
}
Если для класса определяют
Прежде всего, определим
class String
{
public:
// объявление операции присваивания
String operator=(const String s);
};
// Реализация присваивания
String
String::operator=(const String s)
{
if (this == s)
return *this;
if (str != 0) {
delete [] str;
}
length = s.length;
str = new char[length + 1];
if (str == 0) {
// обработка ошибок
}
strcpy(str, s.str);
return *this;
}
Обратим внимание на несколько важных особенностей
s1 = s2 = s3;
Во-вторых, в начале s1 = s1 выполняется правильно и быстро.
В-третьих, перед тем как скопировать новое значение,
Аналогично +=.
Набор String в различных выражениях, представлен ниже:
class String
{
public:
String();
String(const String s);
String(const char*);
String operator=(const String s);
String operator+=(const String s);
bool operator==(const String s) const;
bool operator!=(const String s) const;
bool operator<(const String s) const;
bool operator>(const String s) const;
bool operator<=(const String s) const;
bool operator>=(const String s) const;
String operator+(const String s) const;
};
Определяя класс, программист задает методы и
Первый этап – попытка воспользоваться
Если перед выражением указать имя типа в круглых скобках, то значение выражения будет
double x = (double)1; void* addr; Complex* cptr = (Complex*) addr;
Такие
Для того чтобы преобразовывать типы, хотя бы с минимальным контролем, можно записать
static_cast < тип > (выражение)
позволяет преобразовывать типы, основываясь лишь на сведениях о типах выражений, известных во время компиляции не проверяет типы выражений во время выполнения. С одной стороны, это возлагает на программиста большую ответственность, а с другой — ускоряет выполнение программ. С помощью можно выполнять как позволяет преобразовывать типы, связанные отношением наследования, указатель к указателю, один числовой тип к другому, перечислимое значение к целому. В частности, с помощью можно преобразовывать не только
указатель на производный класс к базовому классу, но и указатель на базовый класс к производному, что в общем случае небезопасно.
Однако попытка преобразовать целое число к указателю приведет к ошибке компиляции. Если все же необходимо преобразовать совершенно не связанные между собой типы, можно вместо записать reinterpret_cast:
void* addr; int* intPtr = static_cast < int* > (addr); Complex* cPtr = reinterpret_cast < Complex* > (2000);
Если необходимо ограниченное const ), можно воспользоваться :
const char* addr1; char* addr2 = const_cast < char* > addr1;
Использование , и reinterpret_cast вместо явного
К
char, unsigned char, short или unsigned short преобразуются к типу int, если точность типа int достаточна, в противном случае они преобразуются к типу unsigned int.wchar_t и константы перечисленных типов преобразуются к первому из типов int, unsigned int, long и unsigned long, точность которого достаточна для представления данной величины.int, если точность типа int достаточна, или к unsigned int, если точность unsigned int достаточна. В противном случае преобразование не производится.int, false становится 0 и true становится 1.Эти четыре типа преобразований мы будем называть безопасными преобразованиями.
Язык Си (от которого Си++ унаследовал большинство
Правила
long double, то другой преобразуется также к long double ;double, то другой преобразуется также к double ;float, то другой преобразуется также к float ;unsigned long, то другой также преобразуется к unsigned long ;long, а другой – unsigned int, и тип long может представить все значения unsigned int, то unsigned int преобразуется к long, иначе оба операнда преобразуются к unsigned long ;long, то другой преобразуется также к long ;unsigned, то другой преобразуется также к unsigned ;int.(1L + 2.3) результат типа double (8u + 4) результат типа unsigned long
Все приведенные
Как мы уже отмечали ранее, при выполнении
long x; char c; c = x;
если значение x равно 20, то и c будет равно 20. Но если x равно 500, значение c будет равно -12 (при условии выполнения на персональном компьютере), поскольку старшие биты, не помещающиеся в char, будут обрезаны. Именно поэтому большинство компиляторов выдаст ошибку и не будет транслировать подобные конструкции.
При работе с указателями и ссылками компилятор автоматически выполняет только два вида преобразований.
Если имеется указатель или ссылка на производный тип, а требуется, соответственно, указатель или ссылка на базовый тип.
Если имеется указатель или ссылка на изменяемый объект, а требуется указатель или ссылка на неизменяемый объект того же типа.
size_t strlen(const char* s);
// прототип функции
class A { };
class B : public A { };
char* cp;
strlen(cp);
// автоматическое преобразование из
// char* в const char*
B* bObj = new B;
// преобразование из указателя на производный класс
A* aObj = bObj;
// к указателю на базовый класс
Если требуются какие-то другие преобразования, их необходимо указывать явно, но в этом случае вся ответственность за правильность преобразования лежит на программисте.
В языке Си++ можно определить гораздо больше типов, чем в Си. Казалось бы, и правила
Прежде всего, выполнение тех или иных Complex:
class Complex {
. . .
friend Complex operator+(const Complex x,
int y);
friend Complex operator+(int y,
const Complex x);
};
При наличии таких функций никаких
int x; Complex y; . . . Complex z = x + y;
Тем не менее, в других ситуациях
Задав конструктор класса, имеющий в качестве аргумента величину другого типа, программист тем самым определяет правило
class Complex
{
public:
// неявное правило преобразования
// из целого типа в тип Complex
Complex(int x);
};
operator имя_типа ();
Например,
class Complex
{
public:
// операция преобразования из типа
// Complex в целый тип
operator int();
};
При записи:
Complex cmpl; int x = cmpl;
будет вызвана функция operator int().
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.