Прокси-класс в C ++ используется для реализации Прокси-шаблона , в котором объект является интерфейсом или посредником для какого-либо другого объекта.
Типичное использование прокси-класса в C ++ - реализация оператора [], поскольку оператор [] может использоваться для получения данных или для установки данных внутри объекта. Идея состоит в том, чтобы предоставить прокси-класс, который позволяет обнаруживать использование данных получения оператором [] по сравнению с использованием набора данных оператора []. Оператор [] класса использует прокси-объект, чтобы помочь сделать правильные вещи, определяя, используется ли оператор [] для получения или установки данных в объекте.
Компилятор C ++ выбирает подходящие операторы и операторы преобразования из предоставленного целевого класса и определений прокси-классов для конкретного использования оператора [].
Однако существуют и другие варианты использования прокси-класса в C ++. Например, см. Эту статью о Самостоятельной регистрации объектов в C ++ от доктора Доббса, в которой описывается использование прокси-класса в качестве части фабрики объектов. Фабрика объектов предоставляет определенный тип объекта в зависимости от некоторых критериев, в этом примере формат графического изображения. Каждый из различных конвертеров графических изображений представлен прокси-объектом.
Все эти требования могут быть выполнены с помощью «специализированного магазина» в
которого нет ни одного места в коде во время компиляции, который знает
обо всех поддерживаемых форматах. Список поддерживаемых объектов построен на
время выполнения, когда каждый объект формата файла регистрирует свое существование с
объект специализированного магазина.
Создание специализированного магазина состоит из четырех частей:
- Каждый класс, который идет в хранилище, будет представлен прокси-классом. Прокси знает, как создавать объекты для магазина и
предоставляет стандартный интерфейс для информации о классе.
- Вы должны решить, какие критерии специализированный магазин будет предоставлять звонящим, а затем реализовать интерфейсы для этих критериев в хранилище, в
класс прокси и в исходном классе.
- Все прокси-классы будут производными от общего базового класса, чтобы специализированный магазин мог использовать их взаимозаменяемо. Каждый прокси-класс будет
реализован в виде шаблона, который вызывает статические функции в оригинале
класс.
- Прокси-классы будут регистрироваться автоматически при запуске программы путем определения глобальной переменной для каждого прокси-класса, конструктор которого
зарегистрирует прокси-класс в специализированном магазине.
См. Также этот ответ https://stackoverflow.com/a/53253728/1466970, на вопрос об итераторах C ++, в которых прокси-класс используется для представления в качестве уникального объекта каждого из членов массива структуры. Структура является резидентной базой данных для встроенного приложения. Несколько различных видов мнемоники хранятся в виде текстовых символьных массивов в резидентной базе данных памяти. Прокси-класс предоставляет представление, которое затем можно использовать с итератором для обхода списка мнемоник в определенной области. Итератор обращается к прокси-объекту через базовый класс и сведения о том, сколько мнемоник представляет прокси-объект, а длина каждого мнемоника находится в самом прокси-объекте.
Другим примером может быть то, как объекты Microsoft DCOM (Distributed COM) используют прокси на хост-компьютере пользователя объекта DCOM для представления фактического объекта, который находится на другом хост-компьютере. Прокси-сервер предоставляет интерфейс для реального объекта на другом компьютере и обрабатывает взаимодействие между пользователем объекта и фактическим объектом.
Подводя итог, прокси-объект используется в качестве посредника для фактического объекта. Прокси-объект используется, когда когда-либо требуется какое-то преобразование или преобразование между пользователем объекта и фактическим объектом с некоторой косвенной направленностью, которая предоставляет услугу, позволяющую использовать фактический объект, когда есть некоторое препятствие в использовании фактический объект напрямую.
EDIT - простой пример использования прокси с оператором [] для простого хранилища данных массива
Следующий источник использует прокси-объект для оператора [] класса. Ниже приведен вывод тестового набора, чтобы показать создание и уничтожение различных прокси-объектов, поскольку прокси-класс используется для доступа к фактическому классу и манипулирования им. Поучительно запустить его в отладчике, чтобы посмотреть, как он выполняется.
// proxy.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string.h>
#include <iostream>
class TArrayProxy;
// The actual class which we will access using a proxy.
class TArray
{
public:
TArray();
~TArray ();
TArrayProxy operator [] (int iIndex);
int operator = (TArrayProxy &j);
void Dump (void);
char m_TarrayName[4]; // this is the unique name of a particular object.
static char TarrayName[4]; // This is the global used to create unique object names
private:
friend class TArrayProxy; // allow the proxy class access to our data.
int iArray[10]; // a simple integer array for our data store
};
// The proxy class which is used to access the actual class.
class TArrayProxy
{
public:
TArrayProxy(TArray *p = 0, int i=0);
~TArrayProxy();
TArrayProxy & operator = (int i);
TArrayProxy & operator += (int i);
TArrayProxy & operator = (TArrayProxy &src);
operator int ();
int iIndex;
char m_TarrayproxyName[4]; // this is the unique name of a particular object.
static char TarrayproxyName[4]; // This is the global used to create unique object names
private:
TArray *pArray; // pointer to the actual object for which we are a proxy.
};
// initialize the object names so as to generate unique object names.
char TArray::TarrayName[4] = {" AA"};
char TArrayProxy::TarrayproxyName[4] = {" PA"};
// Construct a proxy object for the actual object along with which particular
// element of the actual object data store that this proxy will represent.
TArrayProxy::TArrayProxy(TArray *p /* = 0 */, int i /* = 0 */)
{
if (p && i > 0) {
pArray = p;
iIndex = i;
strcpy (m_TarrayproxyName, TarrayproxyName);
TarrayproxyName[2]++;
std::cout << " Create TArrayProxy " << m_TarrayproxyName << " iIndex = " << iIndex << std::endl;
} else {
throw "TArrayProxy bad p";
}
}
// The destructor is here just so that we can log when it is hit.
TArrayProxy::~TArrayProxy()
{
std::cout << " Destroy TArrayProxy " << m_TarrayproxyName << std::endl;
}
// assign an integer value to a data store element by using the proxy object
// for the particular element of the data store.
TArrayProxy & TArrayProxy::operator = (int i)
{
pArray->iArray[iIndex] = i;
std::cout << " TArrayProxy assign = i " << i << " to " << pArray->m_TarrayName << " using proxy " << m_TarrayproxyName << " iIndex " << iIndex << std::endl;
return *this;
}
TArrayProxy & TArrayProxy::operator += (int i)
{
pArray->iArray[iIndex] += i;
std::cout << " TArrayProxy add assign += i " << i << " to " << pArray->m_TarrayName << " using proxy " << m_TarrayproxyName << " iIndex " << iIndex << std::endl;
return *this;
}
// assign an integer value that is specified by a proxy object to a proxy object for a different element.
TArrayProxy & TArrayProxy::operator = (TArrayProxy &src)
{
pArray->iArray[iIndex] = src.pArray->iArray[src.iIndex];
std::cout << " TArrayProxy assign = src " << src.m_TarrayproxyName << " iIndex " << src.iIndex << " to " << m_TarrayproxyName << " iIndex "<< iIndex << " from" << std::endl;
return *this;
}
TArrayProxy::operator int ()
{
std::cout << " TArrayProxy operator int " << m_TarrayproxyName << " iIndex " << iIndex << " value of " << pArray->iArray[iIndex] << std::endl;
return pArray->iArray[iIndex];
}
TArray::TArray()
{
strcpy (m_TarrayName, TarrayName);
TarrayName[2]++;
std::cout << " Create TArray = " << m_TarrayName << std::endl;
for (int i = 0; i < sizeof(iArray)/sizeof(iArray[0]); i++) { iArray[i] = i; }
}
// The destructor is here just so that we can log when it is hit.
TArray::~TArray()
{
std::cout << " Destroy TArray " << m_TarrayName << std::endl;
}
TArrayProxy TArray::operator [] (int iIndex)
{
std::cout << " TArray operator [" << iIndex << "] " << m_TarrayName << std::endl;
if (iIndex > 0 && iIndex <= sizeof(iArray)/sizeof(iArray[0])) {
// create a proxy object for this particular data store element
return TArrayProxy(this, iIndex);
}
else
throw "Out of range";
}
int TArray::operator = (TArrayProxy &j)
{
std::cout << " TArray operator = " << m_TarrayName << " from" << j.m_TarrayproxyName << " index " << j.iIndex << std::endl;
return j.iIndex;
}
void TArray::Dump (void)
{
std::cout << std::endl << "Dump of " << m_TarrayName << std::endl;
for (int i = 0; i < sizeof(iArray)/sizeof(iArray[0]); i++) {
std::cout << " i = " << i << " value = " << iArray [i] << std::endl;
}
}
// ----------------- Main test harness follows ----------------
// we will output the line of code being hit followed by the log of object actions.
int _tmain(int argc, _TCHAR* argv[])
{
TArray myObj;
std::cout << std::endl << "int ik = myObj[3];" << std::endl;
int ik = myObj[3];
std::cout << std::endl << "myObj[6] = myObj[4] = 40;" << std::endl;
myObj[6] = myObj[4] = 40;
std::cout << std::endl << "myObj[5] = myObj[5];" << std::endl;
myObj[5] = myObj[5];
std::cout << std::endl << "myObj[2] = 32;" << std::endl;
myObj[2] = 32;
std::cout << std::endl << "myObj[8] += 20;" << std::endl;
myObj[8] += 20;
myObj.Dump ();
return 0;
}
А вот вывод этого примера из консольного приложения с Visual Studio 2005.
Create TArray = AA
int ik = myObj[3];
TArray operator [3] AA
Create TArrayProxy PA iIndex = 3
TArrayProxy operator int PA iIndex 3 value of 3
Destroy TArrayProxy PA
myObj[6] = myObj[4] = 40;
TArray operator [4] AA
Create TArrayProxy PB iIndex = 4
TArrayProxy assign = i 40 to AA using proxy PB iIndex 4
TArray operator [6] AA
Create TArrayProxy PC iIndex = 6
TArrayProxy assign = src PB iIndex 4 to PC iIndex 6 from
Destroy TArrayProxy PC
Destroy TArrayProxy PB
myObj[5] = myObj[5];
TArray operator [5] AA
Create TArrayProxy PD iIndex = 5
TArrayProxy operator int PD iIndex 5 value of 5
TArray operator [5] AA
Create TArrayProxy PE iIndex = 5
TArrayProxy assign = i 5 to AA using proxy PE iIndex 5
Destroy TArrayProxy PE
Destroy TArrayProxy PD
myObj[2] = 32;
TArray operator [2] AA
Create TArrayProxy PF iIndex = 2
TArrayProxy assign = i 32 to AA using proxy PF iIndex 2
Destroy TArrayProxy PF
myObj[8] += 20;
TArray operator [8] AA
Create TArrayProxy PG iIndex = 8
TArrayProxy add assign += i 20 to AA using proxy PG iIndex 8
Destroy TArrayProxy PG
Dump of AA
i = 0 value = 0
i = 1 value = 1
i = 2 value = 32
i = 3 value = 3
i = 4 value = 40
i = 5 value = 5
i = 6 value = 40
i = 7 value = 7
i = 8 value = 28
i = 9 value = 9