Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Visual_C_console.pdf
Скачиваний:
34
Добавлен:
16.05.2015
Размер:
954.14 Кб
Скачать

120

Сводная таблица форм объявления указателей

Ниже приведена сводная таблица различных форм объявления указателей с объяснением объявления

Форма объ-

Объяснение

явления

 

 

 

int p

p - целое число

 

 

int *p

p - указатель на целое число

 

 

int *p[3]

p - массив указателей на целые числа (квадратные

 

скобки имеют больший приоритет, чем звездочка)

 

 

int (*p)[3]

p - массив целых чисел (звездочка имеет больший

 

приоритет внутри скобок)

 

 

int p()

p - функция, возвращающая целое число

 

 

int *p()

p - функция, которая возвращает указатель на целое

 

число (скобки имеют более высокий приоритет)

 

 

int (*p)()

p - указатель на функцию, которая возвращает це-

 

лое число (звездочка имеет более высокий при-

 

оритет)

 

 

int *(*p)()

p - указатель на функцию, которая возвращает ука-

 

затель на целые числа

 

 

int (*p[3])()

p - массив из трех указателей на функции, которые

 

возвращают целые числа

 

 

Преобразование типов

Когда в арифметическом выражении в любой из пар операндов типы данных не совпадают, автоматически выполняется преобразование к такому типу данных, который обеспечивает наибольший диапазон значений.

Неявное преобразование можно применять и к указателям. Указатель void* может быть неявно преобразован к любому другому типу указателя.

Например,

int *pi; char *pc;

121

void *pv1, *pv2;

Тогда возможны присваивания с неявным преобразованием типа pv1 = pi; pv2 = pc;

Но записи вида pc = pv2; не допускаются, поскольку в этом случае тип данного для указателя с правой стороны знака равенства не определен. Не допускается также смешивание при неявном преобразовании указателей на константные и не константные типы данных.

Явное преобразование типов выполняется в случаях, когда компилятор не может определить тип данного, но этот тип известен программисту или изменяется в процессе выполнения программы. Ответственность за правильность таких преобразований возлагается на программиста. Явное преобразование реализуется с помощью операторов static_cast, const_cast, dynamic_cast и reinterpret_cast.

Например, не допускаемая при неявном преобразовании запись pc = pv2; теперь может быть реализована с помощью оператора

static_cast <char*> (pv2);

Обратите внимание на форму записи: в угловых скобках записан указатель, к которому выполняется преобразование, а в круглых скобках имя преобразуемого указателя. Эта форма едина для всех четырех операторов явного преобразования. Преобразование static_cast применяют для обычных переменных (не указателей), когда надо исключить предупреждения компилятора о возможной потере значащих цифр в старших разрядах или точности, которые могут возникнуть при использовании перегруженных знаков операций с неявным преобразованием типов.

С помощью преобразования static_cast можно изменить значение для константы перечисляемого типа данных. В приведенном ниже фрагменте программы значение для константы REG будет заменено значением, введенным с клавиатуры.

enum sam {REG = 135, TAR = 24}; int num;

122

cout << "Введите значение для REG" << endl; cin >> num;

sam REG = static_cast <sam> (num); cout << "Значение для REG = " << REG;

При получении адреса для переменной с атрибутом const получают указатель-константу, иначе эта переменная перестанет быть константой. Если в функцию передают параметр по ссылке с атрибутом const, такой параметр (указатель-константу) использовать в качестве рабочего нельзя, поэтому появляется ограничение на использование параметров функций. Преобразование const_cast применяется для преобразования указателя константы в обычный указатель, чтобы снять такое ограничение. Такое преобразование выполняется в приведенном ниже фрагменте программы:

const int cst = 5; int *pst;

pst = const_cast <int *>(&cst); cout << *pst;

Оператор dynamic_cast применяется для изменения типа объекта в объектно-ориентированном программировании во время выполнения программы и здесь не рассматривается.

Оператор reinterpret_cast позволяет изменить точку зрения компилятора на тип объекта без изменения объекта. В примере ниже введенное с клавиатуры число типа double и распечатывается в шестнадцатеричном коде. Для получения целого беззнакового восьми байтового числа используется тип unsigned long long.

double num; // Это число с плавающей точкой из 8 байт unsigned long long *pt; // Это целое число из 8 байт cout << "Введите число" << endl;

cin >> num;

pt = reinterpret_cast <unsigned long long*>(&num); cout<<"Шестнадцатеричный код для "<< num <<“ = “

<< hex<< *pt;

Результат выполнения программы:

123

Применение этого преобразования достаточно опасно, и оно в основном применяется в объектно-ориентированном программировании.

Операторы явного преобразования типов появились в стандарте нового языка С++. Для совместимости с ранее разработанными программами из языка не исключены устаревшие формы явного преобразования типов. Общий вид такого преобразования:

(<тип данного>)<имя переменной>

Или

<тип данного>(<имя переменной>)

Например, (double) num или double (num)

Ссылки

Когда функция должна возвратить один объект (одиночное значение или массив), обычно используют функцию-подпрограмму. Когда же требуется возвратить более одного объекта, приходится либо использовать глобальные переменные, либо применять для этого параметры списка аргументов.

При возврате объектов из функций можно применять как указатели, так и ссылки. В любом из этих случаев для размещения объекта используется память вызывающей программы. Другими словами, вызывающая функция указывает адрес размещения объекта для функции, поэтому все изменения объекта в функции выполняются в памяти вызывающей программы Различие между ссылками и указателями влияет на оформление функции. При использовании указателя при вызове функции в нее передается адрес объекта в списке параметров, а при ссылке в функцию передается объект, а адрес этого объекта в вызывающей программе вычисляет функция. В этом случае при оформлении функции перед именем формального параметра в списке аргументов записывают символ '&', что задает адрес объекта в вызывающей программе.

124

Ниже приведен пример программы, которая переставляет местами два введенных числа с помощью функций. В одной функции (swap1) используются указатели, а в другой (swap2) передача осуществляется по ссылке. При оформлении этих функций амперсанд (‘&’) записан в разных местах (в первом случае он записан перед фактическими параметрами, а во втором перед формальными), но во втором случае более естественна форма вызова функции.

// Передача параметров с помощью указателей и по ссылке

#include "stdafx.h" #include <conio.h> #include <iostream> using namespace std; void swap1 (int *a, int *b); void swap2 (int &a, int &b); void _tmain()

{

int k, n, p, q;

cout << "Введите два числа\n"; cin >> k >> n ;

cout << "\nВозврат с помощью указателей";

p = k; // Сохранение чисел для последующего вызова q = n;

cout << "\n"Исходные числа " << k << " " << n; swap1(&p, &q);

cout << "\nПосле перестановки \n" << p << " " << q; cout << "\nВозврат с помощью ссылки \n";

cout <<"\n Исходные числа \n" << k << " " << n; swap2(k,n);

cout << "\nПосле перестановки \n" << p << " " << q; getch();

}

125

//Передача (и возврат) с помощью указателей void swap1 (int *a, int *b)

{

int temp; temp = *a; *a = * b; *b = temp;

}

//Передача (и возврат) с помощью ссылки void swap2 (int &a, int &b)

{

int temp; temp = a; a = b;

b = temp;

}

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

Ссылка может использоваться в качестве возвращаемого значения функции. Любопытной особенностью функций, возвращающих ссылку, является возможность их записи с левой стороны от знака равенства в операции присваивания. Такая функция возвращает НЕ значение глобальной переменной, а адрес объекта, которому что-то присваивается.

// Ссылка в качестве возвращаемого параметра

#include "stdafx.h" #include <conio.h> #include <iostream> using namespace std;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]