this指针在父子类中的差别-分析OGRE单例模式遇到的问题

来源:互联网 发布:gif动态截图软件 编辑:程序博客网 时间:2024/05/17 03:32

class   cbase{  
  public:  
  static int   m_i;  

   void Offset()
   {
    int i =0;
   }
  };  
  class   ca:public   cbase  
  {  
  public:  

  void Offset2()
  {
   int i = 0;
  }
  virtual   ~ca(){};  
  };  
  int   main()  
  {  
  ca   a;
  a.Offset();
  a.Offset2();
  //ca*p=&a;  
  //cbase   *pbase= (cbase   *)p;//pbase的值发生了偏移  
  //int offset = (int)(ca*)1 - (int)(cbase*)(ca*)1;
  //pbase = pbase + offset;
  //return   0;  
  }
当运行到Offset函数,和Offset2函数里,我跟踪进去看了一下,得到的this指针如下:

+  this 0x0012ff58 cbase * const

+  this 0x0012ff54 ca * const

注意不同哦,尾数一个是4,一个是8

汇编代码如下:

    ca   a;
0041145D  lea         ecx,[ebp-14h]         // ebp -14
00411460  call        ca::ca (4110C8h)
00411465  mov         dword ptr [ebp-4],0
  a.Offset();
0041146C  lea         ecx,[ebp-10h]         // ebp - 10
0041146F  call        cbase::Offset (411050h)
  a.Offset2();
00411474  lea         ecx,[ebp-14h]         // ebp - 14
00411477  call        ca::Offset2 (411041h)

这是虚函数惹的祸,不信的话,将子类的析构改成非虚的看看,子类和父类的this指针就相等了!

看看下面的singleton模式的写法,

    template <typename T> class Singleton
    {
    protected:

        static T* ms_Singleton;

    public:
        Singleton( void )
        {
            assert( !ms_Singleton );
#if defined( _MSC_VER ) && _MSC_VER < 1200 
            int offset = (int)(T*)1 - (int)(Singleton <T>*)(T*)1;  // 为什么会有这一行呢?这个应该是专门对付有虚函数的类的吧
            ms_Singleton = (T*)((int)this + offset);      // 这样的话不管是有虚函数还是没有虚函数的子类都实用了吧
#else
     ms_Singleton = static_cast< T* >( this );
#endif
        }
        ~Singleton( void )
            {  assert( ms_Singleton );  ms_Singleton = 0;  }
        static T& getSingleton( void )
  { assert( ms_Singleton );  return ( *ms_Singleton ); }
        static T* getSingletonPtr( void )
  { return ms_Singleton; }
    };

 

使用方法:

 接着就可以将任何类转化为singleton,可以按下面步骤:
  1)从Singleton<MyClass>公开派生你的类MyClass;
  2)确保使用前在系统中创建了MyClass的实例。可以设为静态也可以使用new和delete。
  3)调用时使用MyClass::GetSingleton()方法。
  下面是一个例子:
  //定义
  class App: public Singleton <App>
  {
   void Run(){};
  }
  //初始化
  static App app1;
  //访问
  void SomeFunction()
  {
   App::GetSingleton.Run();
   //... ...
  }