Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从派生而不是基调用的虚拟方法_C#_Virtual_Base_Derived Class - Fatal编程技术网

C# 从派生而不是基调用的虚拟方法

C# 从派生而不是基调用的虚拟方法,c#,virtual,base,derived-class,C#,Virtual,Base,Derived Class,有人能向我解释一下,当我将类强制转换为基类时,为什么要调用重写的方法吗 class Base { public virtual void VirtualMethod() { Console.WriteLine("Base virtual method"); } } sealed class Derived : Base { public override void V

有人能向我解释一下,当我将类强制转换为基类时,为什么要调用重写的方法吗

    class Base
    {
        public virtual void VirtualMethod()
        {
            Console.WriteLine("Base virtual method");
        }
    }

    sealed class Derived : Base
    {
        public override void VirtualMethod()
        {
            Console.WriteLine("Overriden method");
        }
    }

    static void Main(String[] args)
    {
        Derived d = new Derived();
        ((Base)d).VirtualMethod();
    }
我的意思是这个代码打印:

Overriden method
而不是

Base virtual method
将来是运行时还是编译时


我知道我可以通过调用
Base.VirtualMethod()
从派生的调用Base的虚拟方法,但是我可以从外部调用它吗?(就像来自
Main
或其他一些类)

方法实现是基于对象的执行时间类型选择的。这是问题的一大部分。任何人都可以使用:

public void Foo(Base b)
{
    b.VirtualMethod();
}
。。。而且不需要知道或关心执行类型是什么,因为多态性将处理它

我知道我可以通过调用Base.VirtualMethod()从派生的调用Base的虚方法,但是我可以从外部调用它吗


不(至少,没有一些骇人听闻的黑客以非虚拟方式调用虚拟方法),这是封装的一部分。覆盖实现已有效地替换了该对象的原始实现。

如果要访问基本实现,则不应使用覆盖,应使用新实现。覆盖覆盖任何父实现,新的“隐藏”父实现,以便您可以通过强制转换为父对象然后调用该方法来访问该实现

internal class Program
{
    private static void Main(string[] args)
    {
        Derived d = new Derived();
        d.VirtualMethod();
        ((Base) d).VirtualMethod();

        Console.ReadLine();
    }

    private class Base
    {
        public virtual void VirtualMethod()
        {
            Console.WriteLine("Base virtual method");
        }
    }

    private sealed class Derived : Base
    {
        public new void VirtualMethod()
        {
            Console.WriteLine("Overriden method");
        }
    }
}
这将输出:

重写方法
基本虚方法


请试着理解@Jon Skeet的回答。他完全正确。设计的原因是几十年的丰富经验和不断探索更好的代码编写方法。“暗箱操作”/“机械原因”在某种程度上是不相关的,因为所有支持OOP的语言和运行时都有相同的行为(至少在涉及虚拟方法时是如此),并且每种语言和运行时的实现都不同。关于第二个问题,请看:+1。注意,行为与C++相反,其中构造函数的虚调用将调用基类的实现。这两种行为都令人困惑,并可能带来令人惊讶的副作用,因此通常不建议从构造函数调用虚拟函数。