Непрозрачный указатель в C++

Опубликовано: 11 Января, 2023

Непрозрачный, как следует из названия, — это то, через что мы не можем видеть. например, древесина непрозрачна. Непрозрачный указатель — это указатель, указывающий на структуру данных, содержимое которой не раскрывается во время ее определения.

Следующий указатель является непрозрачным. Нельзя узнать данные, содержащиеся в структуре STest, посмотрев на определение.

struct STest* pSTest;

Безопасно присваивать NULL непрозрачному указателю.

pSTest = NULL; 

Почему непрозрачный указатель?

Есть места, где мы просто хотим намекнуть компилятору, что «Эй! Это некоторая структура данных, которая будет использоваться нашими клиентами. Не волнуйтесь, клиенты предоставят его реализацию при подготовке модуля компиляции». Такой тип дизайна надежен, когда мы имеем дело с общим кодом. См. приведенный ниже пример:

Допустим, мы работаем над приложением для работы с изображениями. Поскольку мы живем в мире, где все перемещается в облако, а устройства очень доступны для покупки, мы хотим разрабатывать приложения для платформ Windows, Android и Apple. Итак, было бы неплохо иметь хороший дизайн, надежный, масштабируемый и гибкий в соответствии с нашими требованиями. У нас может быть общий код, который будет использоваться на всех платформах, а затем разные конечные точки могут иметь специфичный для платформы код. Для работы с изображениями у нас есть класс CImage, предоставляющий API для работы с различными операциями с изображениями (масштабирование, поворот, перемещение, сохранение и т. д.).

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

Image.h: файл заголовка для хранения объявления класса. Мы создадим заголовочный файл, который будет содержать класс CImage, предоставляющий API для обработки операций с изображениями.

// This class provides API to deal with various
// image operations. Different platforms can 
// implement these operations in different ways.
class CImage
{
public:
    CImage();
    
    ~CImage();
    
    
// Opaque pointer
    

    struct SImageInfo* pImageInfo;
    
    void Rotate(double angle);
    
    void Scale(double scaleFactorX, 
double scaleFactorY);
    
    void Move(int toX, int toY);    
    
private:

    void InitImageInfo();
};

Image.cpp: код, который будет совместно использоваться разными конечными точками. Этот файл используется для определения конструктора и деструктора класса CImage. Конструктор вызовет метод InitImageInfo() и код внутри этого метода будет написан в соответствии с операционной системой, на которой он будет работать.

// Constructor for CImage

CImage::CImage() { 
    InitImageInfo(); 
}


// destructor for CImage class 

CImage::~CImage()
{
    // Destroy stuffs here
}

Image_windows.cpp : в этом файле будет находиться код, относящийся к операционной системе Windows.

struct SImageInfo {
    // Windows specific DataSet
};

void CImage::InitImageInfo()
{
    pImageInfo = new SImageInfo;
    // Initialize windows specific info here
}

void CImage::Rotate()
{
    // Make use of windows specific SImageInfo
}

Image_apple.cpp : код, относящийся к операционной системе Mac, будет находиться в этом файле.

struct SImageInfo {
    // Apple specific DataSet
};
void CImage::InitImageInfo()
{
    pImageInfo = new SImageInfo;

    // Initialize apple specific info here
}
void CImage::Rotate()
{
    // Make use of apple specific SImageInfo
}

Как видно из приведенного выше примера , при определении схемы класса CImage мы только упоминаем, что существует структура данных SImageInfo.

Содержимое SImageInfo неизвестно. Теперь клиенты (Windows, Apple, Android) должны определить эту структуру данных и использовать ее в соответствии со своими требованиями . Если в будущем мы захотим разработать приложение для новой конечной точки «X», дизайн уже есть. Нам нужно только определить SImageInfo для конечной точки «X» и использовать его соответствующим образом.

Обратите внимание, что приведенный выше пример является одним из способов сделать это. Дизайн — это обсуждение и требования. Хороший дизайн решается с учетом многих факторов. У нас также могут быть специфичные для платформы классы, такие как CImageWindows и CImageApple, и помещать туда весь специфичный для платформы код.

Вопросы? Пусть они приходят. Мы хотели бы ответить.

Эта статья предоставлена Аашишем Барнвалом . Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное, или если вы хотите поделиться дополнительной информацией по теме, обсуждаемой выше.

C++