ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 10) онлайн

Указатель на void

Перед тем как мы продолжим рассматривать работу указателей, необходимо от- метить одну их особенность. Адрес, который помещается в указатель, должен быть одного с ним типа. Мы не можем присвоить указателю на int адрес пере- менной типа float,

float flovar = 98.6;

int* ptrint = &flovar; // Так нельзя; типы int* и float* несовместимы

Однако есть одно исключение. Существует тип указателя, который может указывать на любой тип данных. Он называется указателем на void и определя- ется следующим образом:

void* ptr; // указатель, который может указывать на любой тип данных

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

Рассмотрим пример использования указателя на void. В этой программе так- же показано, что если вы не используете указатель на void, то вам нужно быть осторожными, присваивая указателю адрес того же типа, что и указатель. Вот листинг программы PTRVOID:

// ptrvoid.cpp

// указатель на void

#include <iostream>

using namespace std;

 

int main ( )

{

  int intvar;           // целочисленная переменная

  float flovar;         // вещественная переменная

 

  int* ptrint;          // указатель на int

  float* ptrflo;        // указатель на float

  void* ptrvoid;        // указатель на void

 

  ptrint = &intvar;     // так можно: int* = int*

//ptrint = &flovar;     // так нельзя: int* = float*

//ptrflo = &intvar;     // так нельзя: float* = int*

  ptrflo = &flovar;     // так можно: float* = float*

 

  ptrvoid = &intvar;    // так можно: void* = int*

  ptrvoid = &flovar;    // так можно: void* = float*

 

  return 0;

}

Мы можем присвоить адрес intvar переменной ptrint, потому что обе этих пе- ременных имеют тип int*. Присвоить же адрес flovar переменной ptrint мы не можем, поскольку они разных типов: переменная flovar типа float*, а переменная

ptrint типа int*. Однако указателю ptrvoid может быть присвоено значение любо- го типа, так как он является указателем на void.

Если вам по некоторым причинам необходимо присвоить одному типу указа- теля другой тип, то вы можете использовать функцию reinterpret_cast. Для строк программы PTRVOID, которые мы закомментировали, это будет выглядеть сле- дующим образом:

 

ptrint = reinterpret_cast<int*>( &flovar ); ptrflo = reinterpret_cast<float*>( &intvar );

 

Использование функции reinterpret_cast в этом случае нежелательно, но мо- жет оказаться выходом из сложной ситуации. Нединамические вычисления не работают с указателями. В старой версии C с вычислениями можно было так поступать, но для C++ это будет плохим тоном. Мы рассмотрим примеры функ- ции reinterpret_cast в главе 12 «Потоки и файлы», где она используется для изме- нения способа интерпретации данных из буфера.

 

9