如何覆盖从构造函数调用的基类方法

Posted

技术标签:

【中文标题】如何覆盖从构造函数调用的基类方法【英文标题】:how to override a base class method called from a constructor 【发布时间】:2011-11-24 15:58:53 【问题描述】:

我可能完全错了..

public class BaseClass

  public string result  get; set; 

  public BaseClass()
  public BaseClass(string x) 
    result = doThing(x);
  
  public virtual string doThing(string x)
  
     return x;
  




public class DerivedClass : BaseClass


  public DerivedClass()
  public DerivedClass(string x):base(x)
  public override string doThing(string x)
  
     return "override" + x;
  

我希望新的 DerivedClass("test") 具有“overridetest”的结果,但它没有:它调用 doThing 的基本方法。我错过了什么吗?我是否需要创建一个 AbstractClass 并让 BaseClass 和 DerivedClass 都继承自它,Derived 类也覆盖方法?

【问题讨论】:

Calling virtual method in base class constructor的可能重复 它并不完全是重复的——这与 ste 的有效性有关,在我的情况下,派生的 doThing 永远不会被调用。 【参考方案1】:

问题是您在构造函数中进行了虚拟调用。此问题的机制和可能的解决方法在here 中有详细说明。

总之,当你进入基类的构造函数时,被覆盖的函数还没有被构造出来,所以调用了基类中的虚函数。

【讨论】:

在发布的代码中,由于静态编译器绑定,当控件位于基类的构造函数中时,重写的函数可用。派生类的方法不会被调用,因为您无法从基类访问任何派生类的非静态成员。【参考方案2】:

您不能从基类访问子类的实例成员。

它调用基类的doThing 方法,因为就基类而言,这是唯一可用的doThing 方法。如果您想要每个类的实例调用它自己的 doThing 方法,请在您的子类中替换:

public DerivedClass(string x):base(x)

与:

public DerivedClass(string x)

    doThing(x);

【讨论】:

【参考方案3】:

从设计的角度来看,在构造函数调用期间,您应该始终警惕“做事”。构造函数的目的仅仅是使类的实例进入有效状态以供将来使用;它不应该尝试“做”任何其他事情或产生任何其他副作用。如果您的对象构造是一件复杂的事情,您可能希望使用 Builder 或 Factory 模式来屏蔽调用代码的复杂性。

【讨论】:

【参考方案4】:

这是因为您的DerivedClass 使用基本构造函数并将result 设置为base.doThing("test"),即“测试”。

所以您可以将您的 DerivedClass 更改为:

public class DerivedClass : BaseClass


  public DerivedClass()
  public DerivedClass(string x):base(x)
  
     result="override"+x; 
     //or as result already be set as x, you can use: result="override" + result;
  


或者如你所说,

需要创建一个 AbstractClass 并同时具有 BaseClass 和 DerivedClass 继承自那个,Derived 类也重写方法?

【讨论】:

以上是关于如何覆盖从构造函数调用的基类方法的主要内容,如果未能解决你的问题,请参考以下文章

如何从 CPP 中的基类继承构造函数?

在派生构造函数中的某些代码块之后调用派生类中的基类构造函数[重复]

这个设计模式有名字吗? (具有仅调用构造函数的实现的基类)

如何继承构造函数?

从子类中的基类添加构造函数

C++中如何在子类的构造函数中调用基类的构造函数来初始化基类成员变量