简体   繁体   English

使用 CRTP 时确保安全

[英]Ensure safety while using CRTP

Consider following snippet of code making using of CRTP考虑以下使用 CRTP 的代码片段

#include <iostream>

struct Alone
{
    Alone() { std::cout << "Alone constructor called" << std::endl; }
    int me {10};
};

struct Dependant
{
    explicit Dependant(const Alone& alone)
        : ref_alone(alone)
    { std::cout << "Dependant called with alone's me = " << alone.me << std::endl; }
    const Alone& ref_alone;
    void print() { std::cout << ref_alone.me << std::endl; }
};

template <typename D>
struct Base
{
    Base() { std::cout << "Base constructor called" << std::endl; }

    D* getDerived() { return static_cast<D*>(this); }
    Dependant f { getDerived()->alone };
    void print() { f.print(); }
};

struct Derived : Base <Derived>
{
    Derived() { std::cout << "Derived constructor called "  << std::endl; }
    Alone alone {};
    void print() { Base::print(); };
};

int main()
{
    Derived d;
    d.print();
}

original link http://coliru.stacked-crooked.com/a/79f8ba2d9c38b965原文链接http://coliru.stacked-crooked.com/a/79f8ba2d9c38b965

I have a basic question first我首先有一个基本问题

  • How does memory allocation happen when using inheritance?使用继承时内存分配如何发生? I know the constructors are called from Base to Derived, but it seems that when I do我知道构造函数是从 Base 调用到 Derived 的,但似乎当我这样做时

    Derived d;派生 d;

    memory equivalent to sizeof(D) is allocated, and then constructors are called.分配相当于sizeof(D) 的内存,然后调用构造函数。 Is my understanding correct here?我的理解在这里正确吗? (This would explain printing uninitialised member) (这将解释打印未初始化的成员)

  • Considering the above example in mind, would you suggest/recommend any best practices when it comes to CRTP?考虑到上述示例,您会建议/推荐有关 CRTP 的任何最佳实践吗?

memory equivalent to sizeof(D) is allocated, and then constructors are called分配相当于 sizeof(D) 的内存,然后调用构造函数

How else could it possibly work?否则它怎么可能工作? You can't construct an object in memory that isn't allocated yet.您不能在尚未分配的内存中构造对象。 Memory allocation always comes before object construction.内存分配总是在对象构造之前进行。

Considering the above example in mind, would you suggest/recommend any best practices when it comes to CRTP?考虑到上述示例,您会建议/推荐有关 CRTP 的任何最佳实践吗?

The standard practices for the CRTP: don't call into the CRTP in a constructor/destructor. CRTP 的标准做法:不要在构造函数/析构函数中调用 CRTP。 This is also true of virtual functions.虚函数也是如此。 Virtuals are dynamic polymorphism, while CRTP is static polymorphism. Virtuals 是动态多态性,而 CRTP 是静态多态性。 But they're both using the same basic mechanism: a base class that defines an interface that the derived class must implement.但是它们都使用相同的基本机制:一个定义派生类必须实现的接口的基类。

And just like with virtual functions, trying to call it in constructors/destructors won't do what you mean.就像使用虚函数一样,尝试在构造函数/析构函数中调用它不会达到您的意思。 The only difference is that with virtual functions, the compiler will actually keep you from getting undefined behavior.唯一的区别是对于虚函数,编译器实际上会阻止您获得未定义的行为。 Whereas with the CRTP, you just get breakage.而使用 CRTP,您只会损坏。

Note that this includes default member initializers, which for the purpose of non-aggregates are just shorthand for constructor initialization lists.请注意,这包括默认成员初始化程序,出于非聚合的目的,它们只是构造函数初始化列表的简写。

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

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