#include <windows.h>
#include <tchar.h>


#include <iostream>
#include <memory>

class o_1
{
public:
 o_1 () : a_ (0) { std::cout << "o_1()"  << std::endl; }
 virtual ~o_1( ) { std::cout << "~o_1()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_1::show("<< a_ <<")" << std::endl;
 }
public:
 int a_;
};

class o_2 : public o_1
{
public:
 o_2 () : o_1(), b_(0) { std::cout << "o_2()"  << std::endl; }
 virtual ~o_2()        { std::cout << "~o_2()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_2::show("<< b_ <<")" << std::endl;
 }
public:
 int b_;
};

class o_3 : public o_2
{
public:
 o_3 () : o_2(), c_(0) { std::cout << "o_3()"  << std::endl; }
 virtual ~o_3()        { std::cout << "~o_3()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_3::show("<< c_ <<")" << std::endl;
 }
public:
 int c_;
};

unsigned int vftable_of____o_1;
unsigned int vftable_of____o_2;
unsigned int vftable_of____o_3;

unsigned int get__vfp  (void* p)
{
 unsigned int __vfp = 0;

 memcpy (&__vfp, p, 4);

 return __vfp;
}

#pragma warning( push )
#pragma warning( disable: 4313 )
// C4313: 'printf' : '%x' in format string conflicts with argument 1 of type 'xxx'

void init (void)
{
 o_1 *o1=new o_1();
 o_2  o2;
 o_3 *o3=new o_3();

 memcpy (&vftable_of____o_1,  o1, 4);
 memcpy (&vftable_of____o_2, &o2, 4);
 memcpy (&vftable_of____o_3,  o3, 4);

 printf (" \r\n");
 printf ("# o_1::vftable_of____o_1=0x%08x \r\n", vftable_of____o_1);
 printf ("# o_2::vftable_of____o_2=0x%08x \r\n", vftable_of____o_2);
 printf ("# o_3::vftable_of____o_3=0x%08x \r\n", vftable_of____o_3);
 printf (" \r\n");

 delete o1;
 delete o3;
}

void test (void)
{
 o_3 *o = new o_3();
 o_1 *p = o;

 o->a_ = 100;
 o->b_ = 200;
 o->c_ = 300;

 printf (" p    's address=0x%08x \r\n", p);
 printf (" p->a_'s address=0x%08x \r\n", &o->a_);
 printf (" p->b_'s address=0x%08x \r\n", &o->b_);
 printf (" p->c_'s address=0x%08x \r\n", &o->c_);
 p->show ();

 printf (" \r\n");
 printf ("# p's __vfp 0x%08x \r\n", get__vfp(p));
 printf (" \r\n");
 printf ("# p->~o_1() \r\n");
 p->~o_1();
 printf (" \r\n");
 printf ("# p's __vfp 0x%08x \r\n", get__vfp(p));
 printf (" \r\n");
 p->show ();

 printf (" \r\n");
 printf ("# let's get fun! \r\n");
 memcpy (p, &vftable_of____o_3, 4); p->show ();
 memcpy (p, &vftable_of____o_2, 4); p->show ();
 memcpy (p, &vftable_of____o_1, 4); p->show ();


 int   v;
 char *member_variable_ptr;

 member_variable_ptr = (char*)p;

 v = 99;
 member_variable_ptr += 4;
 printf (" \r\n");
 printf ("# one more time! (member_variable_ptr=0x%08x) \r\n", member_variable_ptr);
 memcpy (member_variable_ptr, &v, 4);
 memcpy (p, &vftable_of____o_3, 4); p->show ();
 memcpy (p, &vftable_of____o_2, 4); p->show ();
 memcpy (p, &vftable_of____o_1, 4); p->show ();

 v = 98;
 member_variable_ptr+= 4;
 printf (" \r\n");
 printf ("# one more time! (member_variable_ptr=0x%08x) \r\n", member_variable_ptr);
 memcpy (member_variable_ptr, &v, 4);
 memcpy (p, &vftable_of____o_3, 4); p->show ();
 memcpy (p, &vftable_of____o_2, 4); p->show ();
 memcpy (p, &vftable_of____o_1, 4); p->show ();

 v = 97;
 member_variable_ptr+= 4;
 printf (" \r\n");
 printf ("# one more time! (member_variable_ptr=0x%08x) \r\n", member_variable_ptr);
 memcpy (member_variable_ptr, &v, 4);
 memcpy (p, &vftable_of____o_3, 4); p->show ();
 memcpy (p, &vftable_of____o_2, 4); p->show ();
 memcpy (p, &vftable_of____o_1, 4); p->show ();


 printf (" \r\n");
 printf ("# last time ! \r\n");
 memcpy (p, &vftable_of____o_3, 4);

 delete p;
}

#pragma warning( pop )


int _tmain(int argc, _TCHAR* argv[])
{
 std::cout << "==============================================================" <<std::endl;
 std::cout << "init()" <<std::endl;
 std::cout << "==============================================================" <<std::endl;
 init ();
 std::cout << "==============================================================" <<std::endl;
 std::cout <<std::endl;
 std::cout <<std::endl;
 std::cout <<std::endl;


 std::cout << "==============================================================" <<std::endl;
 std::cout << "test()" <<std::endl;
 std::cout << "==============================================================" <<std::endl;
 test ();
 std::cout << "==============================================================" <<std::endl;
 std::cout <<std::endl;
 std::cout <<std::endl;
 std::cout <<std::endl;

 return 0;
}
-----------------------------------------------------------------------------
==============================================================
init()
==============================================================
o_1()
o_1()
o_2()
o_1()
o_2()
o_3()

# o_1::vftable_of____o_1=0x00418890
# o_2::vftable_of____o_2=0x004188c4
# o_3::vftable_of____o_3=0x004188f4

~o_1()
~o_3()
~o_2()
~o_1()
~o_2()
~o_1()
==============================================================


==============================================================
test()
==============================================================
o_1()
o_2()
o_3()
 p    's address=0x003a6858
 p->a_'s address=0x003a685c
 p->b_'s address=0x003a6860
 p->c_'s address=0x003a6864
o_3::show(300)

# p's __vfp 0x004188f4

# p->~o_1()
~o_3()
~o_2()
~o_1()

# p's __vfp 0x00418890

o_1::show(100)

# let's get fun!
o_3::show(300)
o_2::show(200)
o_1::show(100)

# one more time! (member_variable_ptr=0x003a685c)
o_3::show(300)
o_2::show(200)
o_1::show(99)

# one more time! (member_variable_ptr=0x003a6860)
o_3::show(300)
o_2::show(98)
o_1::show(99)

# one more time! (member_variable_ptr=0x003a6864)
o_3::show(97)
o_2::show(98)
o_1::show(99)

# last time !
~o_3()
~o_2()
~o_1()

==============================================================

Posted by 셈말짓기 :

파괴자를 직접 부르면 어떻게 될까?

object o;

o.~object();

궁금해졌다.

-----------------------------------------------------------------------------
#include <windows.h>
#include <tchar.h>

#include <iostream>

class o_1
{
public:
 o_1 ()         { std::cout << "o_1()"  << std::endl; }
 virtual ~o_1() { std::cout << "~o_1()" << std::endl; }
};

class o_2 : public o_1
{
public:
 o_2 () : o_1() { std::cout << "o_2()"  << std::endl; }
 virtual ~o_2() { std::cout << "~o_2()" << std::endl; }
};

class o_3 : public o_2
{
public:
 o_3 () : o_2() { std::cout << "o_3()"  << std::endl; }
 virtual ~o_3() { std::cout << "~o_3()" << std::endl; }
};

void test1 (void)
{
 o_3  o;

 o_1* p = &o;

 std::cout << "-----------" <<std::endl;
 p->~o_1 ();
 std::cout << "-----------" <<std::endl;
}

void test2 (void)
{
 o_1* p = new o_3 ();

 std::cout << "-----------" <<std::endl;
 p->~o_1 ();
 std::cout << "-----------" <<std::endl;

 delete p;
}

void test3 (void)
{
 o_1* p = new o_3 ();

 std::cout << "-----------" <<std::endl;
 //p->~o_1 ();
 std::cout << "-----------" <<std::endl;

 delete p;
}

int _tmain(int argc, _TCHAR* argv[])
{
 std::cout << "###########" <<std::endl;
 test1();
 std::cout << "###########" <<std::endl;
 test2();
 std::cout << "###########" <<std::endl;
 test3();
 std::cout << "###########" <<std::endl;

 return 0;
}
-----------------------------------------------------------------------------
###########
<- test1() 함수: 잘된다...
o_1()
o_2()
o_3()
-----------
~o_3()
~o_2()
~o_1()
-----------
~o_3()
~o_2()
~o_1()
########### <- test2() 함수: 무엇인가 이상하다???
o_1()
o_2()
o_3()
----------- <- p->~o_1 (); 호출 부분... 부모 클래스 파괴자를 호출한다.
~o_3()
~o_2()
~o_1()
----------- <- delete p; 가 이상하다 = _=??? 무엇일까...
~o_1()
########### <- test3() 함수:
o_1()
o_2()
o_3()
-----------
<- //p->~o_1 ();
-----------   
주석처리 했더니 delete p; 가 제대로 동작한다.
~o_3()
~o_2()
~o_1()
###########
계속하려면 아무 키나 누르십시오 . . .
-----------------------------------------------------------------------------
디버깅을 해보았다.

p->~o_1(); 호출하기전 __vfptr(virtual fucntion pointer) 녀석은 이렇게 가리키고 있었다.

사용자 삽입 이미지

하지만, p->~o_1();을 호출하니 __vfptr 녀석은 이렇게 바뀌어 버렸다.
사용자 삽입 이미지

         test1()역시 p->~o_1();를 수행하면 p의 __vfptr 값도 동일하게 바뀌었다.               


고심끝에 내린 결론은

test1()에서 Stack에 생성된 객체는 파괴될때 가상함수-파괴자를 사용하지 않고 파괴 되므로
위와같은 결과를 얻었고,

test2()에서 Heap에 생성된 객체는 파괴되기전에 직접 p->~o_1(); 호출 하여 __vfptr이
변경됨으로서 delete p;에서 가상함수-파괴자를 이용한 파괴자 호출이 제대로 되지 못하는
것이다.

__vfptr이 변경 되므로 가상함수들이 제대로 동작을 안할 것이라 판단 되었다.
그래서, 소스 코드를 수정해서 다시 테스트 해보았다.
-----------------------------------------------------------------------------
#include <windows.h>
#include <tchar.h>

#include <iostream>

class o_1
{
public:
 o_1 ()         { std::cout << "o_1()"  << std::endl; }
 virtual ~o_1() { std::cout << "~o_1()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_1::show()" << std::endl;
 }

};

class o_2 : public o_1
{
public:
 o_2 () : o_1() { std::cout << "o_2()"  << std::endl; }
 virtual ~o_2() { std::cout << "~o_2()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_2::show()" << std::endl;
 }

};

class o_3 : public o_2
{
public:
 o_3 () : o_2() { std::cout << "o_3()"  << std::endl; }
 virtual ~o_3() { std::cout << "~o_3()" << std::endl; }
public:
 virtual void show (void)
 {
  std::cout << "o_3::show()" << std::endl;
 }

};

void test1 (void)
{
 o_3  o;

 o_1* p = &o;

 std::cout << "-----------" <<std::endl;
 p->show ();
 o.show();
 std::cout << "-----------" <<std::endl;
 p->~o_1 ();
 std::cout << "-----------" <<std::endl;
 p->show ();
 o.show();
 std::cout << "-----------" <<std::endl;
}

void test2 (void)
{
 o_1* p = new o_3 ();

 std::cout << "-----------" <<std::endl;
 p->~o_1 ();
 std::cout << "-----------" <<std::endl;

 delete p;
}

void test3 (void)
{
 o_1* p = new o_3 ();

 std::cout << "-----------" <<std::endl;
 //p->~o_1 ();
 std::cout << "-----------" <<std::endl;

 delete p;
}

int _tmain(int argc, _TCHAR* argv[])
{
 std::cout << "###########" <<std::endl;
 test1();
 std::cout << "###########" <<std::endl;
 test2();
 std::cout << "###########" <<std::endl;
 test3();
 std::cout << "###########" <<std::endl;

 return 0;
}
-----------------------------------------------------------------------------
########### <- test1() 함수: 잘되는게 아니었다.
o_1()
o_2()
o_3()
-----------
o_3::show() <- p->show (); 정상이다.
o_3::show() <- o.show();   정상이다.
-----------
~o_3()
~o_2()
~o_1()
-----------
o_1::show() <- p->show ();      __vfptr이 변경되었으므로 제대로 동작을 못한다.     
o_3::show() <- o.show();
-----------
~o_3()
~o_2()
~o_1()
########### <- test2() 함수:
o_1()
o_2()
o_3()
-----------
~o_3()
~o_2()
~o_1()
-----------
~o_1()
########### <- test3() 함수:
o_1()
o_2()
o_3()
-----------
-----------
~o_3()
~o_2()
~o_1()
###########
계속하려면 아무 키나 누르십시오 . . .

-----------------------------------------------------------------------------
처음에는 컴파일러 버그라고 생각되었지만 곰곰히 따져보니 아닌 것 같다.
설마, 진짜 컴파일러 버그는 아니겠지... = _ =;

[사용 컴파일러]
Microsoft Visual Studio 2005
Version 8.0.50727.762  (SP.050727-7600)
Microsoft .NET Framework
Version 2.0.50727 SP1

Installed Edition: Professional

-----------------------------------------------------------------------------
추가:
데브피아에 올렸보았었는데 오해하실 수 있는 부분 있는거 같아서 추가합니다.

제가 말하고 싶었던것은 소멸자를 직접 호출했을경우 vftable을 가리키는 __vfptr이
변경된다는 걸 말하고 싶었던겁니다.

좀 더 부연설명을 하자면 메모리 풀 같은 걸 만들때 메모리 풀에서 받은 객체를 사용하고 삭제
후 그대로 또 사용했을 경우 일어나는 현상이 어떻게 될것인가 따져보는 의미입니다.

위의 코드는 일종의 toy code입니다.


제가 컴파일러 버그가 아닐까라고 생각한 부분은 직접 파괴자(소멸자)가 호출된다고 해서
메모리에서 실제로 delete가 일어나는 건 아니기 때문에 vftable을 가리키는 __vfptr가
변경되는게 맞는건지 아닌지
잘 판단이 안되었기 때문에 적어 놓은겁니다.


 

Posted by 셈말짓기 :

생성패턴-Builder

2008. 8. 20. 14:21 from 셈말짓기/GoF

-----------------------------------------------------------------------------
[Builder]
-----------------------------------------------------------------------------
복잡한 객체를 생성하는 방법과 표현하는 방법을 정의하는 클래스를 별도로 분리하여 서로 다른
표현이라도 이를 생성할 수 있는 동일한 구축 공정을 제공할 수 있도록 한다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A creational part of GoF's Design Patterns
//
// - Builder
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>

#include <iostream>
#include <memory>



/////////////////////////////////////////////////////////////////////////////
//
// A creational part of GoF's Design Patterns
//
// - Builder
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>

#include <iostream>
#include <memory>


/////////////////////////////////////////////////////////////////////////////
//
// Builder
//
//
/////////////////////////////////////////////////////////////////////////////
class Product
{
public:
 Product() :
  PartA_(0),
  PartB_(0),
  PartC_(0)
 {
 }

 virtual ~Product()
 {
 }

public:
 void SetPartA  (int a) { PartA_= a; }
 void SetPartB  (int b) { PartB_= b; }
 void SetPartC  (int c) { PartC_= c; }

 void Operation (void)
 {
    std::cout << "[Product]" << std::endl
        << "PartA=" << PartA_ << std::endl
        << "PartB=" << PartB_ << std::endl
        << "PartC=" << PartC_ << std::endl
        << std::endl;
 }

private:
 int PartA_;
 int PartB_;
 int PartC_;
};

//// ------------------------------------------------------------------------

class AbstractBuilder
{
public:
 virtual ~AbstractBuilder() {}

public:
 std::auto_ptr<Product> GetResult (void)
 {
  return Product_;
 }
 
 void NewProduct (void)
 {
  Product_.reset ( new Product() );
 }

public:
 virtual void BuildPartA (void)=0;
 virtual void BuildPartB (void)=0;
 virtual void BuildPartC (void)=0;

protected:
 std::auto_ptr<Product> Product_;
};

class ConcreteBuilderA : public AbstractBuilder
{
public:
 virtual void BuildPartA (void) { Product_->SetPartA(1); }
 virtual void BuildPartB (void) { Product_->SetPartB(2); }
 virtual void BuildPartC (void) { Product_->SetPartC(3); }
};

class ConcreteBuilderB : public AbstractBuilder
{
public:
 virtual void BuildPartA (void) { Product_->SetPartA(4); }
 virtual void BuildPartB (void) { Product_->SetPartB(5); }
 virtual void BuildPartC (void) { Product_->SetPartC(6); }
};

//// ------------------------------------------------------------------------

class Director
{
public:
 Director() : Builder_(0) {}
 virtual ~Director()      {}
 
public:
 void SetBuilder (AbstractBuilder* b)
 {
  Builder_ = b;
 }

 void Construct (void)
 {
  Builder_->NewProduct ();
  Builder_->BuildPartA ();
  Builder_->BuildPartB ();
  Builder_->BuildPartC ();
 }

private:
 AbstractBuilder* Builder_;
};


/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
 Director               director;
 ConcreteBuilderA       builder_A;
 ConcreteBuilderB       builder_B;
 std::auto_ptr<Product> product;


 director.SetBuilder (&builder_A);
 director.Construct  ();
 product = builder_A.GetResult();
 product->Operation();

 director.SetBuilder (&builder_B);
 director.Construct  ();
 product = builder_B.GetResult();
 product->Operation();

 return 0;
}

-----------------------------------------------------------------------------
[Product]
PartA=1
PartB=2
PartC=3

[Product]
PartA=4
PartB=5
PartC=6

Posted by 셈말짓기 :

-----------------------------------------------------------------------------
[Abstract Factory]
의도:
구체적 클래스를 정의하지 않고도 서로 관련성이 있거나 독립적인 여러 객체의 군을 생성하기
위한 인터페이스를 제공한다.
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A creational part of GoF's Design Patterns
//
// - Abstract Factory
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>

#include <iostream>
#include <memory>


/////////////////////////////////////////////////////////////////////////////
//
// Abstract Factory
//
//
/////////////////////////////////////////////////////////////////////////////
class AbstractProdcutA
{
public:
 AbstractProdcutA ()         {}
 virtual ~AbstractProdcutA() {}
};

class AbstractProdcutB
{
public:
 AbstractProdcutB ()         {}
 virtual ~AbstractProdcutB() {}
};
 
class AbstractFactory
{
public:
 virtual AbstractProdcutA* CreateProductA (void) = 0;
 virtual AbstractProdcutB* CreateProductB (void) = 0;
};

//// ------------------------------------------------------------------------

class ProdcutA1 : public AbstractProdcutA
{
public:
 ProdcutA1()
 {
  std::cout << "ProdcutA1()" << std::endl;
 }
};
class ProdcutA2 : public AbstractProdcutA
{
public:
 ProdcutA2()
 {
  std::cout << "ProdcutA2()" << std::endl;
 }
};
class ProdcutB1 : public AbstractProdcutB
{
public:
 ProdcutB1()
 {
  std::cout << "ProdcutB1()" << std::endl;
 }
};
class ProdcutB2 : public AbstractProdcutB
{
public:
 ProdcutB2()
 {
  std::cout << "ProdcutB2()" << std::endl;
 }
};

//// ------------------------------------------------------------------------

class ConcreteFactory1 : public AbstractFactory
{
public:
 virtual AbstractProdcutA* CreateProductA (void)
 {
  return new ProdcutA1();
 }
 virtual AbstractProdcutB* CreateProductB (void)
 {
  return new ProdcutB1();
 }
};

class ConcreteFactory2 : public AbstractFactory
{
 virtual AbstractProdcutA* CreateProductA (void)
 {
  return new ProdcutA2();
 }
 virtual AbstractProdcutB* CreateProductB (void)
 {
  return new ProdcutB2();
 }
};

//// ------------------------------------------------------------------------

class Client
{
public:
 void Create (AbstractFactory *f)
 {
  ProdcutA_.reset( f->CreateProductA() );
  ProdcutB_.reset( f->CreateProductB() );
 }

private:
 std::auto_ptr<AbstractProdcutA> ProdcutA_;
 std::auto_ptr<AbstractProdcutB> ProdcutB_;
};



/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
 Client client;


 std::cout << "by ConcreteFactory1" << std::endl;
 client.Create ( &ConcreteFactory1() );

 std::cout << std::endl;

 std::cout << "by ConcreteFactory2" << std::endl;
 client.Create ( &ConcreteFactory2() );

 return 0;
}
-----------------------------------------------------------------------------
by ConcreteFactory1
ProdcutA1()
ProdcutB1()

by ConcreteFactory2
ProdcutA2()
ProdcutB2()

Posted by 셈말짓기 :

구조패턴-Proxy

2008. 8. 19. 16:04 from 셈말짓기/GoF

-----------------------------------------------------------------------------
[Proxy]
의도:
다른 객체에 접근하기 위해 중간 대리 역활을 하는 객체를 둔다.

다른 이름:
Surrogate
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Proxy
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>

#include <iostream>
#include <memory>
#include <map>
#include <string>
#include <list>
#include <algorithm>


#define USE_HANDLE 1


#if (USE_HANDLE==1)
/////////////////////////////////////////////////////////////////////////////
//
// Handle
//
/////////////////////////////////////////////////////////////////////////////
template<typename T>
class CRefCountedInstance
{
public:
 CRefCountedInstance ();

public:
 inline void AddRef       (void);
 inline void Release      (void);
 inline void Assign       (T *p);
 inline bool IsReferenced (void);
 inline T*   GetInstance  (void);

private:
 T   *Instance_;
 int  RefCount_;
};

template<typename T>
CRefCountedInstance<T>::CRefCountedInstance () :
 RefCount_ (0),
 Instance_ (0)
{
}

template<typename T>
void CRefCountedInstance<T>::AddRef (void)
{
 RefCount_++;
}

template<typename T>
void CRefCountedInstance<T>::Release (void)
{
 if (RefCount_>0)
 {
  RefCount_--;
 }

 if (RefCount_==0)
 {
  if (Instance_)
  {
   delete Instance_;
  }

  Instance_ = 0;
 }
}

template<typename T>
void CRefCountedInstance<T>::Assign (T *p)
{
 Instance_ = p;
 AddRef ();
}

template<typename T>
bool CRefCountedInstance<T>::IsReferenced (void)
{
 if (RefCount_==0)
  return false;

 return true;
}

template<typename T>
T* CRefCountedInstance<T>::GetInstance (void)
{
 return Instance_;
}

template<typename T>
class Handle
{
public:
 Handle ();
 explicit Handle (T *p);
 Handle (const Handle<T> &copy);
 virtual ~Handle ();

public:
 Handle<T>& operator = (const Handle<T>& rhs);

public:
 inline T& operator*  () const;
 inline T* operator-> () const;
 inline T* Get    (void) const;

private:
 CRefCountedInstance<T>* Rep_;
};

template<typename T>
Handle<T>::Handle () : Rep_(0)
{
}

template<typename T>
Handle<T>::Handle (T *p)
{
 Rep_ = new CRefCountedInstance<T>();
 Rep_->Assign(p);
}

template<typename T>
Handle<T>::Handle (const Handle<T> &copy)
{
 Rep_ = copy.Rep_;

 if (Rep_)
  Rep_->AddRef ();
}

template<typename T>
Handle<T>::~Handle ()
{
 if (Rep_)
 {
  Rep_->Release ();

  if (!Rep_->IsReferenced())
   delete Rep_;
 }
}

template<typename T>
Handle<T>& Handle<T>::operator = (const Handle<T>& rhs)
{
 if (this == &rhs) return *this;

 if (Rep_)
  Rep_->Release ();

 Rep_ = rhs.Rep_;

 if (Rep_)
  Rep_->AddRef ();

 return *this;
}

template<typename T>
T& Handle<T>::operator*() const
{
 return *(Rep_->GetInstance());
}

template<typename T>
T* Handle<T>::operator -> () const
{
 if (Rep_==0)
  return 0;

 return (Rep_->GetInstance());
}

template<typename T>
T* Handle<T>::Get (void) const
{
 if (Rep_==0)
  return 0;

 return (Rep_->GetInstance());
}
#endif


/////////////////////////////////////////////////////////////////////////////
//
// Proxy
//
/////////////////////////////////////////////////////////////////////////////
class Subject
{
public:
 virtual ~Subject() {}

public:
 virtual void Request (void) = 0;
 virtual void SetData (int ) = 0;
};

class RealSubject : public Subject
{
public:
 explicit RealSubject (int n) :
  Data_ (n)
 {
  std::cout << "RealSubject::RealSubject(" << Data_ << ")" << std::endl;
 }

 virtual ~RealSubject ()
 {
  std::cout << "RealSubject::~RealSubject(" << Data_ << ")" << std::endl;
 }

public:
 virtual void Request (void)
 {
  std::cout << "RealSubject::Request(): Data_ = " << Data_ << std::endl;
 }

 virtual void SetData (int n)
 {
  Data_ = n;
 }

private:
 int Data_;
};


#if (USE_HANDLE==1)
class Proxy :
 public Subject
{
public:
 Proxy() : SubjectData_(0)
 {
 }

 explicit Proxy (int n) :
  SubjectData_ (n)
 {
 }

 Proxy (const Proxy &copy)
 {
  const_cast<Proxy&>(copy).Load();

  SubjectData_ = copy.SubjectData_;
  Subject_     = copy.Subject_;
 }

 virtual ~Proxy () {}

public:
 virtual void Request (void)
 {
  GetSubject()->Request();
 }

 virtual void SetData (int n)
 {
  GetSubject()->SetData(n);
 }

private:
 Subject* GetSubject (void)
 {
  if (Subject_.Get()==0)
  {
   Handle<Subject> s ( new RealSubject(SubjectData_) );
   Subject_ = s;
  }

  return Subject_.Get();
 }

public:
 void Load (void)
 {
  GetSubject();
 }

public:
 Proxy& operator = (const Proxy& rhs)
 {
  if (this == &rhs) return *this;

  const_cast<Proxy&>(rhs).Load();

  SubjectData_ = rhs.SubjectData_;
  Subject_     = rhs.Subject_;

  return *this;
 }

private:
 Handle<Subject>  Subject_;
 int              SubjectData_;
};
#else
class Proxy :
 public Subject
{
public:
 Proxy() :
  SubjectData_(0), 
  Subject_    (0)
 {
 }

 explicit Proxy (int n) :
 SubjectData_ (n),
  Subject_     (0)
 {
 }

 virtual ~Proxy ()
 {
  if (Subject_)
   delete Subject_;
 }

public:
 virtual void Request (void)
 {
  GetSubject()->Request();
 }

 virtual void SetData (int n)
 {
  GetSubject()->SetData(n);
 }

private:
 Subject* GetSubject (void)
 {
  if (Subject_==0)
  {
   Subject_ = new RealSubject(SubjectData_);
  }
  return Subject_;
 }

private:
 Subject         *Subject_;
 int              SubjectData_;
};
#endif


/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
#if (USE_HANDLE==1)
 std::cout << "(USE_HANDLE==1)" << std::endl << std::endl;

 Proxy a(1);
 Proxy b;
 Proxy c;


 std::cout << "a.Load();" << std::endl;
 //a.Load();
 std::cout << std::endl;


 std::cout << "b=a;" << std::endl;
 b=a;
 std::cout << std::endl;


 std::cout << "a.Request ();" << std::endl;
 a.Request ();
 std::cout << std::endl;


 std::cout << "a.SetData (2);" << std::endl;
 a.SetData (2);
 std::cout << std::endl;


 std::cout << "b.Request ();" << std::endl;
 b.Request ();
 std::cout << std::endl;


 std::cout << "c=a" << std::endl;
 c=a;
 std::cout << "c.Request()" << std::endl;
 c.Request ();
 std::cout << std::endl;
#else
 std::cout << "(USE_HANDLE==0)" << std::endl << std::endl;

 Proxy       a(1);
 RealSubject b(2);


 std::cout << std::endl;

 std::cout << "a.Request()" << std::endl;
 a.Request (); // late creating instance
 std::cout << std::endl;

 std::cout << "a.Request()" << std::endl;
 b.Request ();
 std::cout << std::endl;
#endif

 return 0;
}
-----------------------------------------------------------------------------
(USE_HANDLE==1)

a.Load();
RealSubject::RealSubject(1)

b=a;

a.Request ();
RealSubject::Request(): Data_ = 1

a.SetData (2);

b.Request ();
RealSubject::Request(): Data_ = 2

c=a
c.Request()
RealSubject::Request(): Data_ = 2

RealSubject::~RealSubject(2)
-----------------------------------------------------------------------------
(USE_HANDLE==0)

RealSubject::RealSubject(2)

a.Request()
RealSubject::RealSubject(1)
RealSubject::Request(): Data_ = 1

a.Request()
RealSubject::Request(): Data_ = 2

RealSubject::~RealSubject(2)
RealSubject::~RealSubject(1)

Posted by 셈말짓기 :