Java与C++在构造函数中调用虚函数时的区别

    别人问了我一个问题:若基类有一个虚函数init(),被构造函数调用,而派生类override了init(),同样在其构造函数中调用之,那么在创建一个派生类对象时,init()显然会依次被基类和派生类的构造函数调用,那么,这两次调用的分别是什么版本的init()?

    我原以为按照OO的思想,在C++和Java中都应该是如下情况:构造函数中的虚函数不是真正的虚函数,而会调用当前版本的函数。

    然而,测试证明我想错了,C++的结果很符合我的预期,而Java的结果让我很是觉得ugly。

    在Java中,在基类的构造函数中,居然调用了派生类版本的init()。

    这结果让我很困惑:难道这不是违背OO的思想么?在基类的构造函数执行过程中,这个对象的所有派生类成分都还未构建,怎么能调用派生类版本的函数呢?

    翻了翻《Thinking in java 4th》,在p301发现了相关文字:


Behavior of polymorphic methods inside constructors

    “if you call a dynamically bound method inside a constructor ,the overridden definition for that method is also used.However , the effect of this call be rather unexpected because the overridden method will be called before the object if fully constructed .This can conceal some
 difficult-to-find bugs."

    "On the other hand, you hsould be pretty horrified at the outcome of this program. You've done a perfectly logical thing,and yet the behavior is mysteriously wrong,with no complaints from the compiler. C++produces more rational behavior in this situation. Bugs like this could easily be buried and take a long time to discover."

    "As a result.......The only safe methods to call inside a constructor are those that are final in the base class(This also applies to private methods,which are automatically final.)


    ........


    Java的这个特性真是Ugly!


    测试代码和结果如下

C++的

#include  < iostream >

using   namespace  std;

class   base
{

public:
  
base()   { init(); }

  
virtual void init(){ cout<<"I am Base "<<endl;}
}
;

class  derived: public   base
{
public:

  derived() 
{ init();}

  
void init() { cout<<"I am Derived "<<endl;}
}
;
import  java.util. * ;

class  Base
{
   
public Base () { init(); }

   
private void init() { System.out.println("Hello,It'Base");}

}


class  Derived  extends  Base
{

   
public Derived() { init();}

   
private void init() { System.out.println("Hello,It's Derived");}

}


public   class  Test
{

    
public static void main (String[] args)
   

        System.out.println(
"in the main");
        Derived d
=new Derived();
   }


}


int  main ()

{

  derived test;
  
return 1;
}



输出结果:

I am Base
I am Derived

java的

import  java.util. * ;

class  Base
{
   
public Base () { init(); }

   
void init() { System.out.println("Hello,It'Base");}

}


class  Derived  extends  Base
{

   
public Derived() { init();}

   
void init() { System.out.println("Hello,It's Derived");}

}


public   class  Test
{

    
public static void main (String[] args)
   
{
        System.out.println(
"in the main");
        Derived d
=new Derived();
   }


}



输出结果

Hello,It's Derived
Hello,It's Derived






  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值