2009-06-15 4 views
31

C++のプロキシクラスとは何ですか?なぜそれが作成され、どこに役立つのですか?C++のプロキシクラスとは

+1

プロキシ(他の多くの意味の中)である**デザインパターン**のVisual Studioでコンソールアプリケーションから、この例の出力であります](http://en.wikipedia.org/wiki/Proxy_pattern)を参照してください。 –

+0

は完全に同意します。この質問にここで提供された優れた答えがあります。 – vsoftco

答えて

58

プロキシは、別のクラスに変更されたインターフェイスを提供するクラスです。ここでは一例である - 我々は唯一ここ進数1または0を含めることができるようにしたい配列クラスは最初の試みであるとします

struct array1 { 
    int mArray[10]; 
    int & operator[](int i) { 
     /// what to put here 
    } 
}; ` 

私たちは、私たちが言うならば、オペレータは[]文句を言うしたいですa [1] = 42のようなものですが、演算子は格納されている値ではなく、配列のインデックスのみを参照するため、これは不可能です。

我々はプロキシを使用してこの問題を解決することができます

#include <iostream> 
using namespace std; 

struct aproxy { 
    aproxy(int& r) : mPtr(&r) {} 
    void operator = (int n) { 
     if (n > 1) { 
      throw "not binary digit"; 
     } 
     *mPtr = n; 
    } 
    int * mPtr; 
}; 

struct array { 
    int mArray[10]; 
    aproxy operator[](int i) { 
     return aproxy(mArray[i]); 
    } 
}; 

int main() { 
    try { 
     array a; 
     a[0] = 1; // ok 
     a[0] = 42; // throws exception 
    } 
    catch (const char * e) { 
     cout << e << endl; 
    } 
} 

プロキシクラスは、今、私たちは二進数のチェックず、私たちは、アレイのオペレータは[]へのアクセスが制限されているプロキシのインスタンスを返すよう配列の内部。

+1

'aproxy :: void operator =(int n)'を 'int'として返します。' a [0 ] = a [1] = 0 'となる。それ以外の場合は、 'a [1] = 0'によって返された' aproxy'を 'a [0]'にコピーしていて、期待どおりに動作しています。それ以外の、偉大で簡潔な答え! – vsoftco

2

プロキシクラスを使用すると、のクラスのクライアントからのクラスのプライベートデータを非表示にすることができます。

クラスへのパブリックインターフェイスのみを知っているプロキシクラスをクライアントに提供すると、クライアントはクラスの実装の詳細にクライアントからアクセスすることなく、クラスのサービスを使用できます。

8

C++のプロキシクラスは、オブジェクトが他のオブジェクトのインタフェースまたはメディエータであるProxy Patternを実装するために使用されます。

C++でのプロキシクラスの一般的な使用は[]演算子を実装しているため、[]演算子を使用してデータを取得したり、オブジェクト内のデータを設定したりすることができます。この考え方は、[]演算子の取得データ使用と、[]演算子の設定データ使用の検出を可能にするプロキシクラスを提供することです。クラスの[]演算子は、プロキシオブジェクトを使用して、[]演算子がオブジェクト内のデータを取得または設定するために使用されているかどうかを検出することによって適切な処理を支援します。

C++コンパイラは、指定されたターゲットクラスとプロキシクラス定義から適切な演算子と変換演算子を選択して、[]演算子を特に使用します。

しかし、C++のプロキシクラスには他にも用途があります。たとえば、Dobbs博士の記事Self-Registering Objects in C++については、プロキシクラスをオブジェクトファクトリの一部として使用する方法について説明しています。オブジェクトファクトリは、いくつかの基準(この例ではグラフィックスイメージフォーマット)に応じて、特定のタイプのオブジェクトを提供します。異なるグラフィックイメージ変換器の各々は、代理オブジェクトによって表される。

これらの要件のすべては、コードには、単一の場所は、すべてのサポートされる形式について を知って、コンパイル時には存在しない の「専門店」を使用することによって満たすことができます。サポートされているオブジェクトのリストは、 実行時に構築され、各ファイル形式オブジェクトは、その存在を 特殊ストアオブジェクトで登録します。

専門店を構築するための四つの部分があります

  • 店に行くの各クラスはプロキシクラスで表現されますが。プロキシはストアのオブジェクトを作成する方法を知っており、 はクラスに関する情報の標準インターフェースを提供します。
  • スペシャリストストアが発信者に公開する条件を決定し、ストア内のこれらの基準のインターフェイスを実装し、 プロキシクラスおよび元のクラスに実装する必要があります。
  • すべてのプロキシクラスは、共通の基本クラスから派生します。そのため、専門店はそれらを交換可能に使用できます。各プロキシクラスは、 クラスの静的関数を呼び出すテンプレートとして実装されます
  • コンストラクタ がプロキシクラスを専門店に登録するプロキシクラスごとにグローバル変数を定義することにより、プロキシクラスがプログラムの起動時に自動的に登録されます。マイクロソフトDCOM(分散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; 
} 

そしてここでは、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 
関連する問題