C+多态性+;vs Java
我将一些java代码转换成C++,我希望保持类结构相似。然而,我遇到了以下问题,我不知道如何解决; 我用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
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();
}
创建派生对象时,它首先调用基的构造函数