在 .NET 中,一个类可以有虚拟构造函数吗?

Posted

技术标签:

【中文标题】在 .NET 中,一个类可以有虚拟构造函数吗?【英文标题】:In .NET can a class have virtual constructor? 【发布时间】:2011-04-08 18:11:53 【问题描述】:

类可以有虚拟构造函数吗?

如果是,为什么需要它?

【问题讨论】:

【参考方案1】:

仅供参考,当人们要求虚拟构造函数时,一个非常好的模式是InversionOfControl

在 .NET 中,我们有几个 IoC 容器,例如 ObjectBuilder、Unity、MEF、Spring.NET。在 Java 中(有炫耀我的 Java 无能的风险)有 Spring、Tapestry 和许多其他。

恕我直言,IoC 是 OO 兑现承诺的原因。

【讨论】:

【参考方案2】:

根据定义,虚拟方法是根据接收方的运行时类型分析而不是接收方的编译时静态类型分析来调度的方法

构造函数是在创建特定类型的新实例时调用的方法。

由于新创建对象的运行时类型与其编译时类型总是相同 (*),因此不需要虚拟构造函数:运行时调度总是选择相同的方法作为静态调度,何必费心去改变呢?

(*) 这并不完全正确;在某些涉及 COM 互操作的场景中,构造的运行时类型不是编译时类型。在遗留互操作代码的世界中,很多事情都很奇怪。

【讨论】:

【参考方案3】:

不,类不能有虚拟构造函数。

拥有一个虚拟构造函数是没有意义的。在 C# 中构造对象的顺序是先构造派生类,因此始终调用派生构造函数,因为在构造时要调用的类是众所周知的。

另一件事是,如果你真的把这段代码输入出来,你很快就会发现它毫无意义

如果你有:

public class BaseClass 

    public virtual BaseClass()
    
    

然后

public class InheritedClass : BaseClass

    //overrides baseclass constructor but why would you do this given that the     
    //constructor is always going to be called anyway??
    public override InheritedClass()
    
    

【讨论】:

关于在派生类中调用基类构造函数:不会有一个链到基类正常,例如'public override InheritedClass() : base()'。 @paul ruane:你是对的,但我想说的是重写基类是多余的,因为你要么明确说明它并使用 base( ) 或者你不是,当对象被构造时它会被调用,所以拥有一个虚拟构造函数是没有意义的 拥有虚拟构造函数非常有意义。这就是各种构建器模式在不直接支持它的语言中实现的。 我不同意构造函数的执行顺序,即先Derived,然后Base。在 C# 中,基类构造函数总是在派生类构造函数之前被调用。 维沙尔,你是对的。初始化程序从大多数派生类运行到基类,构造函数从基类运行到最派生类。【参考方案4】:

如果我们查看构造函数和虚拟这个词的定义,我们会得出一个合乎逻辑的结论,即构造函数不能是虚拟的。

【讨论】:

真的吗?在 Delphi 中,虚拟构造函数与 CLASS REFRENCE TYPES(“CLASS OF ”)一起出现。 C 程序员不知道的概念:-)。是的 - 我知道问题是 C#,但虚拟构造函数的概念在所有语言中并不矛盾:-)。 你说得对,关于 Delphi 中的虚拟构造函数,但这是语言规范的结果。您声明一个方法并声明这将是一个构造函数。方法名称与创建什么的类型无关。这是理解为什么虚拟构造函数的概念通常无效的关键。你可以声明一个工厂方法,甚至重写它。所以方式反过来 Delphi 有可以命名为构造函数的虚方法,但它没有像其他 C 语言那样本身是构造函数的结构。【参考方案5】:

不,它是如何工作的?当您从基类派生子类时,必须调用层次结构中的所有构造函数。将构造函数设为虚拟则意味着其他情况。

当您使用工厂模式时,可能会被描述为具有类似虚拟构造函数的行为。想象一下这种情况:

class AnimalFactory

    virtual Animal CreateAnimal( return new Animal("Cow"); );

这个工厂的默认行为是创建奶牛。但是如果我们创建一个派生类:

class DogFactory : AnimnalFactory

    override Animal CreateAnimal( return new Animal("Dog"); );

我们现在正在创造狗。当然这不是真正的虚构造函数(这是不可能的),这是虚构造函数。

【讨论】:

【参考方案6】:

不是直接的,但是经典的四人帮模式工厂方法通过将实例化推迟到子类来实现相当于某种虚拟构造函数。

【讨论】:

【参考方案7】:

声明一些虚拟的东西意味着它可以被当前类的子类覆盖。但是,在实例化类时会调用构造函数。那时您不能创建相关类的子类,因此永远不需要声明构造函数 virtual。

【讨论】:

以上是关于在 .NET 中,一个类可以有虚拟构造函数吗?的主要内容,如果未能解决你的问题,请参考以下文章

我可以从 C# 中同一类的另一个构造函数调用重载构造函数吗?

同一个MFC工程中的两个普通类,为啥一个构造函数打点有反应,一个构造函数打点没反应?是因为设置问题吗

在构造函数中调用类成员的构造函数

java子类可以继承父类的构造方法吗

派生类可以有一个不在 C++ 基类中的构造函数吗?

抽象类可以有构造函数吗?