代码之家  ›  专栏  ›  技术社区  ›  recursive

虚拟基成员看不到覆盖?

  •  5
  • recursive  · 技术社区  · 15 年前

    我一直以为 base.Something 相当于 ((Parent)this).Something ,但显然不是这样。我认为重写方法消除了调用原始虚拟方法的可能性。

    为什么第三个输出不同?

    void Main() {
        Child child = new Child();
    
        child.Method();             //output "Child here!"
        ((Parent)child).Method();   //output "Child here!"
        child.BaseMethod();         //output "Parent here!"
    }
    
    class Parent {
        public virtual void Method() { 
            Console.WriteLine("Parent here!"); 
        }
    }
    
    class Child : Parent {
        public override void Method() { 
            Console.WriteLine ("Child here!"); 
        }
        public void BaseMethod() { 
            base.Method(); 
        }
    }
    
    6 回复  |  直到 15 年前
        1
  •  5
  •   Fredrik Mörk    15 年前

    BaseMethod 明确地 通过使用 base Method() base.Method() 在班级里。

    base 关键字,它说(除其他外)它可以用来 对已被另一个方法重写的基类调用方法 .

        2
  •  3
  •   dthorpe    15 年前

    ((Parent)this).foo 对于虚拟方法,foo仍然/始终是一个虚拟方法调用。目标地址将从类的虚方法表中查找,该表将始终为对象实例的类型提供最成熟的实现。您可以将其强制转换为parent,但这不会更改用于在运行时调度调用的vtable。

    base 关键字使调用解析为非虚拟调用,以便您可以从子实现中访问祖先实现。运行时没有地址查找,地址在编译时解析。

        3
  •  3
  •   Sergey Teplyakov    15 年前

    C语言规范:

    在编译时, 基本访问 形式基的表达式 基数[E]的计算方法与 他们是这样写的 ((B)这个[E],其中B是基 类中的类或结构的类

    基本访问 参考文献a 虚函数成员(一种方法, 属性或索引器) 确定哪个功能成员 改变。是的函数成员 通过查找 大多数衍生实施(§10.6.3) 函数成员的 这样的运行时类型

    即。基地什么的相当于((父)this)。但仅限于 非虚拟的 成员语义不同。

        4
  •  2
  •   Philip Rieck    15 年前

    我相信你误解了 base.Something() base 具体地调用方法或属性的基类(可能)重写实现。 From MSDN :

    base关键字用于访问 基类的成员 派生类:

    在基类上调用 已被另一个覆盖方法.has已被另一个方法重写。

    请注意 ((Parent)this).Something() 只会影响你使用 new override 虚拟世界。

        5
  •  1
  •   Kendrick    15 年前

    在您调用的BaseMethod中基本方法,这是访问父函数的一种方法(如果需要的话),但是如果您有一个Shape类型的数组,并且数组中有不同的Shape子类,则希望.Draw()方法调用子类而不是超类方法(默认情况下)。