c++ - 提高克隆模式的安全性

标签 c++ design-patterns crtp cloneable

如果想在 C++ 中实现 Clone 模式,他可能不确定安全性,因为派生类可能会忘记覆盖它:

struct A {
    virtual A* Clone() const {
        return new A(*this);
    }
}

struct B : A {
    int value;
};

int main() {
   B b;
   // oops
   auto b_clone = b.Clone();
   delete b_clone;
}

在这方面改进 C++ 中的 Clone 模式有哪些可能的方法?

有人问了一个更一般的问题: Forcing a derived class to overload a virtual method in a non-abstract base class

但是,在 C++ 中没有好的解决方案似乎过于笼统——讨论是关于强制方法覆盖的可能方法。我更感兴趣的是发现一种有用的模式,这可能有助于在使用 Cloneable 模式的确切情况下提供帮助。

最佳答案

这是对其中一个答案的阐述,建议使用 typeid 进行运行时检查: Forcing a derived class to overload a virtual method in a non-abstract base class

使用 CRTP,可以得出以下基本思想:

创建类 Cloneable<Derived> , 它管理 Derived 的克隆,并添加所有需要的运行时检查(似乎即使使用 CRTP 也无法进行编译时检查)。

然而,这并不简单,还必须通过 Cloneable 管理继承。 ,如所述:

#include <memory>
#include <cassert>
#include <type_traits>
#include <typeinfo>

class CloneableInterface {
public:
    virtual std::unique_ptr<CloneableInterface> Clone() const = 0;
};

template <class... inherit_from>
struct InheritFrom : public inherit_from... {
};

template <class Derived, class AnotherBase = void, bool base_is_cloneable = std::is_base_of_v<CloneableInterface, AnotherBase>>
class Cloneable;

// three identical implementations, only the inheritance is different

// "no base is defined" case
template <class Derived>
class Cloneable<Derived, void, false> : public CloneableInterface {
public:
    std::unique_ptr<CloneableInterface> Clone() const override {
        assert(typeid(*this) == typeid(Derived));
    return std::make_unique<Derived>(static_cast<const Derived&>(*this));
    }
};

// Base is defined, and already provides CloneableInterface
template <class Derived, class AnotherBase>
class Cloneable<Derived, AnotherBase, true> : public AnotherBase {
   ...
};

// Base is defined, but has no CloneableInterface
template <class Derived, class AnotherBase>
class Cloneable<Derived, AnotherBase, false> : public AnotherBase, public CloneableInterface {
    ...
};

使用示例:

class Base : public Cloneable<Base> {
};

// Just some struct to test multiple inheritance
struct Other {
};

struct Derived : Cloneable<Derived, InheritFrom<Base, Other>> {
};

struct OtherBase {
};

struct OtherDerived : Cloneable<OtherDerived, InheritFrom<OtherBase>> {
};

int main() {
    // compiles and runs
    auto base_ptr = std::make_unique<Base>();
    auto derived_ptr = std::make_unique<Derived>();
    auto base_clone = base_ptr->Clone();
    auto derived_clone = derived_ptr->Clone();

    auto otherderived_ptr = std::make_unique<OtherDerived>();
    auto otherderived_clone = otherderived_ptr->Clone();
}

欢迎任何批评和改进建议!

关于c++ - 提高克隆模式的安全性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56977929/

相关文章:

c++ - 如果使用 CRTP,如何在存在的情况下调用派生函数,否则使用默认值?

c++ - 继承通用成员函数

c++ - CRTP + enable_if 的好友功能不起作用?

c++ - 在 lambda 捕获中创建一个数组

c++ - vector 拆分/移位元素

c# - 实例化时存在对象依赖,如何实现Singleton?

java - robocode引擎: how to design (write) the runtime engine -- the robot world

c# - MVVM 中的什么使它对托管 WPF 和 Silverlight 特别有吸引力,但对 native C++ 却没有吸引力?

c++ - DrawText 和文本裁剪

c# - 将 System::String^(C# 字符串)转换为 C++ std::string