第三章里面《六大关键技术之仿真》frame2范例中
BOOL CMyWinApp::InitInstance()
{
    cout << "CMyWinApp::InitInstance \n";
    m_pMainWnd = new CMyFrameWnd;  //调用CMyFrameWnd构造函数
    return TRUE;
}CMyFrameWnd::CMyFrameWnd()
{
    cout << "CMyFrameWnd::CMyFrameWnd \n";
    Create();  //CMyFrameWnd无重写Create(),调用父类CFrameWnd的Create()
}BOOL CFrameWnd::Create()
{
  cout << "CFrameWnd::Create \n";
  CreateEx(); //CreateEx不是虚函数,CFrameWnd未重写它,调用父类CWnd的CreateEx()
  return TRUE;
}
BOOL CWnd::CreateEx()
{
  cout << "CWnd::CreateEx \n";
  PreCreateWindow(); //这是一个虚函数,CWnd中有定义,CFrameWnd也重写了它,那你认为这里是调用
                     //CWnd::PreCreateWindow,还是CFrameWnd::PreCreateWindow?
  return TRUE;
}侯先生解释是调用CFrameWnd::PreCreateWindow,因为“第2章的「Object slicing 与虚拟函数」
一节所说提「虚拟函数的一个极重要的行为模式」”,实际运行结果也是如此。1、可我觉得跟object slicing无关,Object slicing是把派生类对象强制转化成父类对象使用,但这个例子里,并不存在子类强制转化为父类使用的情况(或者是我没看明白?)
2、这里如果说是一个多态性的典型应用的话,按我的理解,应该有一个父类指针指向子类实例化对象的过程,但是我也没看到这个过程,难道是通过this指针传递和隐性转换的?于是我糊涂了,高手请解惑。 

解决方案 »

  1.   

    BOOL CWnd::CreateEx()
    {
      cout < < "CWnd::CreateEx \n";
      this->PreCreateWindow(); //这是一个虚函数,CWnd中有定义,CFrameWnd也重写了它,那你认为这里是调用
                        //CWnd::PreCreateWindow,还是CFrameWnd::PreCreateWindow?
      return TRUE;

    这里的this肯定是CWnd了,如果重写的话当然调用CFrameWnd::PreCreateWindow了,你的理解是对滴
      

  2.   

    我问你
    m_pMainWnd = new CMyFrameWnd
    这个m_pMainWnd是什么类型?
    如果是CWnd*  不就解释了.
      

  3.   


    确实是CWnd*,如下定义
    class CWinApp : public CWinThread
    {
    public:
      CWinApp* m_pCurrentWinApp;
      CWnd* m_pMainWnd;
    。。
    }
    但是没明白为什么解释了?
    我换成
    BOOL CMyWinApp::InitInstance() 

        cout < < "CMyWinApp::InitInstance \n";
        //pMainWnd = new CMyFrameWnd;  //调用CMyFrameWnd构造函数 
        CMyFrameWnd* m_pFrameWnd;
        m_pFrameWnd = new CMyFrameWnd;
        return TRUE; 
    } 结果一样。
      

  4.   

    看了一天的书,总算有点明白了,在这个多层调用过程中,this指针始终指向的是new CMyFrameWnd实例化出来的对象,但指针类型却跟随调用成员函数所属的不同类不同而被隐性转换为不同的类指针了,所以调用CWnd的成员函数时,this指针的类型转成了CWnd*,但值却是实例化的子类对象地址,正好符合虚函数的要求(父类型指针指向子类实例化对象),由于该函数是虚函数且被重写了,所以就动态调用子类CFrameWnd的PreCreateWindow函数了(假如CMyFrameWnd也重写了PreCreateWindow,那就调用的是CMyFrameWnd的),跟object slicing确实是风马牛不相及
    以上理解如有不对之处,请指正,但请不要教训人,什么样才叫学好了呢?谢谢!
      

  5.   

    1 没看出来8楼所说的话是教训lz
    2 不管什么叫学好,至少你现在没学好
    3 俺看不懂object slicing是什么意思,就拿lz的解释来用吧,“Object slicing是把派生类对象强制转化成父类对象使用”,那么“指针类型却跟随调用成员函数所属的不同类不同而被隐性转换为不同的类指针”,是不是存在你所说的object slicing,难道非要自己写代码 Parent *a = child,才算是object slicing么?
      

  6.   

    其实楼主你本身的理解就是正确的,其实就是Object Slicing的一种特殊表现形式罢了,不过比平常使用多态的方式(子类指针强制转换成父类指针)要隐蔽而已,主要就是因为this指针的隐含作用。
      

  7.   

    我刚看到这儿,也糊涂了,这应该是和编译器如何实现this指针有关。
    类成员函数会被替换成如下形式
    void  function( class *this, ...)但是从m_pMainWnd=new CMyFrameWnd 开始,实际的对象是CMyFrameWnd,然后如楼主
     “指针类型却跟随调用成员函数所属的不同类不同而被隐性转换为不同的类指针了”其实我觉得侯捷在这边强调的应该不是object slice,这是up_cast才会发生的事情。因为他那句话有歧义,推理看来是强调多态的。只不过,这里this指针被编译器偷换类型概念了。
      

  8.   

    是不是由于虚函数表中对应的地址指向改写后的PreCreatWindow