c++ - 处理 CRTP 设计的 protected /私有(private)构造函数/析构函数?

标签 c++ constructor destructor crtp

考虑以下代码:

#include <iostream>
#include <type_traits>

// Abstract base class
template<class Crtp>
class Base
{
    // Lifecycle
    public: // MARKER 1
        Base(const int x) :  _x(x) {}
    protected: // MARKER 2
        ~Base() {}

    // Functions
    public:
        int get() {return _x;}
        Crtp& set(const int x) {_x = x; return static_cast<Crtp&>(*this);}

    // Data members
    protected:
        int _x;
};

// Derived class
class Derived
: public Base<Derived>
{
    // Lifecycle
    public:
        Derived(const int x) : Base<Derived>(x) {}
        ~Derived() {}
};

// Main
int main()
{
    Derived d(5);
    std::cout<<d.set(42).get()<<std::endl;
    return 0;
}

如果我想要从 Base 继承 Derived,并且不想在基类中使用虚拟析构函数,那么最好的关键字是什么Base 的构造函数 (MARKER 1) 和析构函数 (MARKER 2) 以保证不会发生任何坏事?

最佳答案

无论您使用何种编程风格,您总是可以做一些坏事:即使您遵循最好的最佳指导实践。这是它背后的物理现象(并且与减少全局熵的不可能性有关)

也就是说,不要将“经典 OOP”(一种方法论)与 C++(一种语言)、OOP 继承(一种关系)与 C++ 继承(一种聚合机制)以及 OOP 多态性(一种模型)与 C++ 运行时和静态多态性(一种调度机制)。

虽然名称有时匹配,但 C++ 事物不一定非要为 OOP 事物提供服务。

从带有一些非虚拟方法的基类公共(public)继承是正常的。析构函数并不特殊:只是不要在 CRTP 基础上调用 delete。

与经典的 OOP 不同,CRTP 基对于每个派生都有不同的类型,因此拥有“指向基的指针”是毫 headless 绪的,因为没有“指向通用类型的指针”。因此调用“删除 pbase”的风险非常有限。

“protected-dtor paradigm”仅在您通过基于指针的多态性对对象管理(和删除)使用 C++ 继承来编程 OOP 继承时才有效。如果您遵循其他范例,则不应按字面意思对待这些规则。

在你的例子中,proteced-dtor 只是拒绝你创建一个 Base<Derived>在堆栈上并在 Base* 上调用 delete。你永远不会做的事情,因为没有“Dervied”的 Base 没有存在的意义,并且有一个 Base<Derived>*没有意义,因为你可以只有一个 Derived* ,因此同时拥有 public ctor 和 dtor 不会造成特别困惑。

但是你甚至可以做相反的选择来保护 ctor 和 dtor,因为你永远不会构造 Base单独,因为它总是需要一个 Derived 类型才能知道。

由于 CRTP 的特殊构造,所有经典的 OOP 东西都会导致一种“无差异的平衡”,因为不再有“危险的用例”。

您可以使用或不使用它们,但不会发生特别糟糕的事情。如果您按照设计使用对象的方式使用对象,则不会。

关于c++ - 处理 CRTP 设计的 protected /私有(private)构造函数/析构函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14256208/

相关文章:

java - 如何从 Java 中的另一个类调用整个类?

c++ - 如何在具有 protected 析构函数和公共(public)销毁方法的 3 方类上使用 shared_ptr

c++ - 可以使用类的析构函数内部函数来重置值吗?

c++ - 为什么带有析构函数的类不能简单地移动构造?

php - 具有基本数据的类,然后是越来越多的数据 - 部分加载?

c# - 文字字符串赋值会像这样调用 String 构造函数吗?

c++ - gtkmm 绘制单个像素

c++ - 生成所有汉明距离至多为2的无序位串对

c++ - 根据模板函数类型推断变量类型

c++ - FtpFindFirstFile 的问题