简体   繁体   English

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

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

If I have something like this: 如果我有这样的事情:

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";
    }
}

and use the following code to call it, 并使用以下代码进行调用,

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

then the Name method of base class gets called. 然后将调用基类的Name方法。 but what would be the actual type of this keyword in the Write method? 但是在Write方法中this关键字的实际类型是什么? if that is of Derived type(as the Program control enters the first if block in Write method) then it is calling the base Name method, and why does the explicit casting, (Derived)this , change the call to the Name method of derived class? 如果那是Derived类型的(由于Program控件在Write方法中输入第一个if块),则它正在调用基本Name方法,为什么显式强制转换(Derived)this ,将对调用的Name方法进行更改类?

this will always be of the derived class type. this将始终是派生类类型。

The reason why in the call this.Name(); 之所以调用this.Name(); calls the base class Name() method is because Name is not defined as a virtual method, thus it is being linked in compile time when the compiler knows nothing about the actual type of this that it will have at this point. 调用基类Name()方法是因为Name没有被定义为一个虚拟的方法,因此它是在编译时被链接时,编译器知道任何关于实际类型的this它将拥有在这一点上。

One more note regarding the code above. 关于以上代码的另一注。 Generally in product code referring to a Derived class from the Base class explicitly is really a bad practice as it breaks one of the OOP principles that the Base class should not be aware about the classes which inherit it. 通常,在产品代码中,显式地引用Base类的Derived类确实是一种不好的做法,因为它违反了OOP原则之一,即,Base类不应该知道继承该类的类。 However, assuming that the code above was just used for C++ investigation then this is of course ok. 但是,假设上面的代码仅用于C ++研究,那当然可以。

You should be using virtual and override if you want to access any overridden members in a derived class: 如果要访问派生类中的所有重写成员,则应使用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";
    }
}

This is all your need. 这就是您的全部需求。 You do not need to and should not be checking the type from the base to handle logic. 您不需要也不应该从基础检查类型来处理逻辑。 Any special logic should be be handled in the derived classes and probably want to mark methods up as virtual in the base and override in the derived classes. 任何特殊的逻辑都应在派生类中处理,并且可能希望在基类中将方法标记为virtual方法,并在派生类中进行override

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

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

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

If you want the actual name of the class in Name() , you just need to call GetType().Name in the base and it will automatically work for any derived classes as GetType() returns you the actual instanced type of the instance. 如果要在Name()中使用该类的实际名称, GetType().Name需要在基类中调用GetType().Name ,它将自动适用于任何派生类,因为GetType()返回您实例的实际实例类型。 Just like GetType() is of the actual instance, this is also your actual instance so any special logic will be of that class' implementation. 就像GetType()是实际实例一样, this也是您的实际实例,因此任何特殊逻辑都将属于该类的实现。

this is actually a redundant call in your base class. this实际上是基类中的多余调用。 Either you specify it or you don't -- you get the same result. 您可以指定它,也可以不指定它,否则会得到相同的结果。 The reason you see mixed results is because you used the new operator. 您看到混合结果的原因是因为您使用了new运算符。 new only works when you are working with that explicit type. 仅当使用该显式类型时, new才有效。 It basically hides other implementations in the chain. 它基本上隐藏了链中的其他实现。 And so, this being in the context of Base is going to give your Base.Name() where as if you had overridden, Derived.Name() would have been used instead. 因此,在Base上下文中, this将为您提供Base.Name() ,就像您已被覆盖一样,将使用Derived.Name()代替。

MSDN: Knowing when to use override and new keywords MSDN:知道何时使用替代和新关键字

Here is an excellent answer about new -- Why does calling a method in my derived class call the base class method? 这是关于new一个很好的答案- 为什么在派生类中调用方法会调用基类方法?

By casting ((Derived)this).Name() , you are explicitly setting it to the derived class. 通过强制转换((Derived)this).Name() ,可以将其显式设置为派生类。 Since you have Write defined in the base class, this will point method calls to it. 由于您在基类中定义了Write ,因此这将指向方法调用。 This behavior occurs because you have not overridden the base method and you are calling it from the base class. 发生此现象的原因在于,您没有重写基方法,而是从基类中调用它。

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

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