繁体   English   中英

当从基类派生类的对象上调用时,“ this”关键字类型

[英]“this” keyword type when called on an object of derived class from base class

如果我有这样的事情:

class Base
{
    public void Write()
    {
     if (this is Derived)
      {
         this.Name();//calls Name Method of Base class i.e. prints Base
        ((Derived)this).Name();//calls Derived Method i.e prints Derived 
      }
     else
      {
        this.Name();
      }
    }

    public void Name()
    {
        return "Base";
    }
}

class Derived : Base
{
    public new void Name()
    {
        return "Derived";
    }
}

并使用以下代码进行调用,

Derived v= new Derived();
v.Write(); // prints Base

然后将调用基类的Name方法。 但是在Write方法中this关键字的实际类型是什么? 如果那是Derived类型的(由于Program控件在Write方法中输入第一个if块),则它正在调用基本Name方法,为什么显式强制转换(Derived)this ,将对调用的Name方法进行更改类?

this将始终是派生类类型。

之所以调用this.Name(); 调用基类Name()方法是因为Name没有被定义为一个虚拟的方法,因此它是在编译时被链接时,编译器知道任何关于实际类型的this它将拥有在这一点上。

关于以上代码的另一注。 通常,在产品代码中,显式地引用Base类的Derived类确实是一种不好的做法,因为它违反了OOP原则之一,即,Base类不应该知道继承该类的类。 但是,假设上面的代码仅用于C ++研究,那当然可以。

如果要访问派生类中的所有重写成员,则应使用virtual和override:

class Base
{
    public void Write()
    {
     if (this is Derived)
      {
         this.Name();//calls Name Method of Base class i.e. prints Base
        ((Derived)this).Name();//calls Derived Method i.e prints Derived 
      }
     else
      {
        this.Name();
      }
    }

    public virtual void Name()
    {
        return "Base";
    }
}

class Derived : Base
{
    public override void Name()
    {
        return "Derived";
    }
}

这就是您的全部需求。 您不需要也不应该从基础检查类型来处理逻辑。 任何特殊的逻辑都应在派生类中处理,并且可能希望在基类中将方法标记为virtual方法,并在派生类中进行override

class Base
{
    public void Write()
    {
        SomeWriteMethod(Name());
    }

    public virtual void Name()
    {
        return "Base";
    }
}

class Derived : Base
{
    public override void Name()
    {
        return "Derived";
    }
}

如果要在Name()中使用该类的实际名称, GetType().Name需要在基类中调用GetType().Name ,它将自动适用于任何派生类,因为GetType()返回您实例的实际实例类型。 就像GetType()是实际实例一样, this也是您的实际实例,因此任何特殊逻辑都将属于该类的实现。

this实际上是基类中的多余调用。 您可以指定它,也可以不指定它,否则会得到相同的结果。 您看到混合结果的原因是因为您使用了new运算符。 仅当使用该显式类型时, new才有效。 它基本上隐藏了链中的其他实现。 因此,在Base上下文中, this将为您提供Base.Name() ,就像您已被覆盖一样,将使用Derived.Name()代替。

MSDN:知道何时使用替代和新关键字

这是关于new一个很好的答案- 为什么在派生类中调用方法会调用基类方法?

通过强制转换((Derived)this).Name() ,可以将其显式设置为派生类。 由于您在基类中定义了Write ,因此这将指向方法调用。 发生此现象的原因在于,您没有重写基方法,而是从基类中调用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM