如何在CRTP的Base模板类中使用“this”关键字?

huangapple go评论70阅读模式
英文:

How does 'this' keyword in the Base template class of CRTP work?

问题

I understand your request. Here's the translated code:

我一直在研究**CRTP**,但我不理解的是在`main()`函数中,我们创建了一个`Base<Derived>*`类型的对象并调用了`callDerived`方法,为什么'`this`',它是`Base`的一个实例,却拥有`Derived`类的所有信息?我明白`Derived`继承自`Base<Derived>`,但`Derived`只是`Base`的一个模板,但CRTP却像双向继承一样工作:`Derived`继承自`Base`,而`Base`也继承自`Derived`。在这一行中' Base<Derived>* pObjBase = new Base<Derived>();','`Derived`'只是`Base`的一个模板!

我想知道背后发生了什么,以使'`this`'拥有**Derived**的所有信息!

```cpp
#include <iostream>
template <typename T>
class Base {
public:
    virtual ~Base() = default;
    Base()
    {
        std::cout << " Base()\n";
    }
    void callDerived() {
        T& refDerived = static_cast<T&>(*this);
        refDerived.derivedMethod();

        T* pDerived = static_cast<T*>(this);
        pDerived->derivedMethod();

        //T& obj3 = dynamic_cast<T>(*this); //Error
        //T obj4 = dynamic_cast<T>(*this); //Error
        //obj3.derivedMethod();
        //obj4.derivedMethod();
       
    }
};

class Derived : public Base<Derived> {
public:
    Derived() :
        Base()
    {

            std::cout << "Derived() \n";

    }
    void derivedMethod() {
        std::cout << "Derived method gets invoked" << std::endl;
    }
};

int main() {
    Base<Derived>* pObjBase = new Base<Derived>();

    pObjBase ->callDerived(); // 输出:调用Derived方法
    delete pObjBase ;
}
英文:

I have been studying about CRTP and what I don't understand is in the main() where we create an object of type Base&lt;Derived&gt;* and invoke callDerived, how come 'this' which is an instance of Base, has all the information of Derived class too? I understand Derived inherits from Base<Derived> but 'Derived' is juts template for Base but CRTP works like that is a two-way inheritance : Derived is derived from Base and Base is also derived from Derived while in this line ' Base<Derived>* pObjBase = new Base<Derived>();' , 'Derived' is a just template for Base!

I would like to know what is happening behind the scenes that 'this' has all the information of Derived!

  #include &lt;iostream&gt;
template &lt;typename T&gt;
class Base {
public:
virtual ~Base() = default;
Base()
{
std::cout &lt;&lt; &quot; Base()\n&quot;;
}
void callDerived() {
T&amp; refDerived = static_cast&lt;T&amp;&gt;(*this);
refDerived.derivedMethod();
T* pDerived = static_cast&lt;T*&gt;(this);
pDerived-&gt;derivedMethod();
//T&amp; obj3 = dynamic_cast&lt;T&gt;(*this); //Error
//T obj4 = dynamic_cast&lt;T&gt;(*this); //Error
//obj3.derivedMethod();
//obj4.derivedMethod();
}
};
class Derived : public Base&lt;Derived&gt; {
public:
Derived() :
Base()
{
std::cout &lt;&lt; &quot;Derived() \n&quot;;
}
void derivedMethod() {
std::cout &lt;&lt; &quot;Derived method gets invoked&quot; &lt;&lt; std::endl;
}
};
int main() {
Base&lt;Derived&gt;* pObjBase = new Base&lt;Derived&gt;();
pObjBase -&gt;callDerived(); // Output: Derived method called
delete pObjBase ;
}

答案1

得分: 2

It works because you have to make sure that T is the actual type of the object. You don't make a Base&lt;Derived&gt; object, because that's the wrong T and it's broken, as you thought. What you're supposed to do is make a Derived object, which extends from Base&lt;Derived&gt;, and all is fine.

The reason you successfully got the message Derived method gets invoked has nothing to do with templates or CRTP. It is simply because this function in the compiled code doesn't even touch the object at all. Chances are good that you can call this function on null pointers, or pointers to completely unrelated things, and it will still print the message. "It seems to work properly" is an allowed kind of undefined behaviour.

英文:

It works because you have to make sure that T is the actual type of the object. You don't make a Base&lt;Derived&gt; object, because that's the wrong T and it's broken, as you thought. What you're supposed to do is make a Derived object, which extends from Base&lt;Derived&gt;, and all is fine.

The reason you successfully got the message Derived method gets invoked has nothing to do with templates or CRTP. It is simply because this function in the compiled code doesn't even touch the object at all. Chances are good that you can call this function on null pointers, or pointers to completely unrelated things, and it will still print the message. "It seems to work properly" is an allowed kind of undefined behaviour.

huangapple
  • 本文由 发表于 2023年4月1日 01:16:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75901125.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定