C+多态性+;vs Java

C+多态性+;vs Java,java,c++,polymorphism,factory,Java,C++,Polymorphism,Factory,我将一些java代码转换成C++,我希望保持类结构相似。然而,我遇到了以下问题,我不知道如何解决; 我用Java实现这一点: public class Mother { protected Father make; public Mother(){ make = maker(); make.print(); }; public Father maker(){ return

我将一些java代码转换成C++,我希望保持类结构相似。然而,我遇到了以下问题,我不知道如何解决; 我用Java实现这一点:

public class Mother {   
    protected Father make;  
    public  Mother(){       
        make = maker();         
        make.print(); };    
    public Father maker(){ 
        return new Father();};}

public class Daughter extends Mother {
    public Daughter(){
        super();}
    @Override
    public Father maker(){
        return new Son();};}

public class Father {
    public void print(){
        System.out.println("I am the Father!\n");}}

public class Son extends Father {
    @Override
    public void print(){
        System.out.println("I am the son!\n");};}

public static void main(String[] args) {
    Daughter dot  = new Daughter();
}
将产生:我是儿子 而:

班长{
公众:
虚拟空打印(){

STD::CUT< P> <代码>子< /COD>构造函数调用<代码>母亲< /C>构造函数,调用<代码>()/代码>。在C++中,至少该对象仅被认为是<代码>母亲<代码>,因为子< /COD>结构不完整。因此<代码>母亲::MAKER()调用了
,因此这样做是正确的。然而,在构造过程中调用虚拟函数通常被认为是一种强烈的代码气味——正是出于这些原因


在Java中,显然总是调用子类重写,即使在构造过程中也是如此,因此Java中的构造函数永远不应该调用可重写的方法。这样做会导致未定义的行为。对此有一个很好的解释。

子类的构造函数调用
母类的构造函数,该构造函数调用(C++),至少在C++中,对象仅被认为是<代码>母亲<代码>,因为<代码>女儿< /C>结构不完整。因此<代码>母亲::调用了
,因此这样做是正确的。然而,在构造过程中调用虚拟函数通常被认为是一种强烈的代码气味——正是出于这些原因


在Java中,显然总是调用子类重写,即使在构造过程中也是如此,因此Java中的构造函数永远不应该调用可重写的方法。这样做可能会导致未定义的行为。对此有一个很好的解释。

AFAIK在Java中,调用(非最终)是唯一不好的风格构造函数中的方法,即在派生类中可以重写的方法。C++总是调用实际类的版本,而不是重写的。
您可以通过将对象传递给构造函数来实现这一点吗?

< p> AFAIK,在java中,调用构造函数中的(非最终)方法是一种坏的方式,即在派生类中可以重写的方法。C++总是调用实际的类的版本,而不是重写的。

您可以通过将对象传递给构造函数来绕过这个问题吗?在C++中,

< p>从基本构造函数调用虚函数不调用更多派生的实现。de>DERIVED
。因此,虚拟函数表仍在构造中,直到
DERIVED
构造函数完成执行后,才会指向更派生的实现

java(和C ^)不同于C++,这里可以从基本构造函数调用虚函数,它将调用最派生的实现。但是,由于最派生的构造函数还没有运行,所以对象可能处于未定义状态,这就是为什么不建议从构造函数调用虚函数的原因。


至于如何绕过它,您可以添加一个
initialize
方法,在创建实例后调用该方法。由于此时将完全构造对象,因此它将调用正确的虚拟函数(所有语言)在C++中,从基本构造函数调用虚函数不调用派生的实现。这是因为,对于构造函数来说,类型< <代码>基< /C> >,即使构造函数是从派生类调用的,也就是代码>派生< /COD>。正在构造错误,并且在
派生的
构造函数完成执行之前不会指向更派生的实现

java(和C ^)不同于C++,这里可以从基本构造函数调用虚函数,它将调用最派生的实现。但是,由于最派生的构造函数还没有运行,所以对象可能处于未定义状态,这就是为什么不建议从构造函数调用虚函数的原因。


至于如何绕过它,您可以添加一个
initialize
方法,在创建实例后调用该方法。由于此时将完全构造对象,因此它将调用正确的虚拟函数(所有语言).

您不应该从基类构造函数调用虚拟函数-派生类“vtable”还没有链接到,因此您将始终结束对基类函数的调用。您也不应该在Java中真正这样做,因为虽然它将调用正确的函数,但最派生的类还没有实例化-这可能是错误的最终,由于不同的原因,这两种语言都是错误的

解决此问题的一种方法是让派生类将虚拟调用的结果传递给基类:

daughter(): mother(new son) { }
以便:

mother() : make(new father) { make->print(); }
mother(father * m) : make(m) { make->print(); }
通过委派构造函数,这变得更容易:

mother()
: mother(new father)
{ }

mother(father* m)
: make(m)
{
    make->print();
}

您不应该从基类构造函数调用虚拟函数-派生类“vtable”尚未链接到,因此您将始终结束对基类函数的调用。您也不应该在Java中真正这样做,因为虽然它将调用正确的函数,但最派生的类尚未实例化-这可能导致最终,由于不同的原因,这两种语言都是错误的

解决此问题的一种方法是让派生类将虚拟调用的结果传递给基类:

daughter(): mother(new son) { }
以便:

mother() : make(new father) { make->print(); }
mother(father * m) : make(m) { make->print(); }
通过委派构造函数,这变得更容易:

mother()
: mother(new father)
{ }

mother(father* m)
: make(m)
{
    make->print();
}

创建派生对象时,它首先调用基的构造函数