c++ - 启用可重写 init 函数的优雅方式

标签 c++ c++11

由于一旦无法在基类构造函数中调用派生类覆盖函数,我想模拟这种行为(类似于C#、Java...在幕后正在做什么)。

我能想到的最优雅的(从签名的角度来看)如下:

class Base {
protected:
    virtual void init() {
    }

    template <typename T, typename ...U>
    T internal_create(U&& u) {
        T instance(std::forward<U>(u)...);
        instance.init();
        return instance;
    }
};

class Derived : public Base {
protected:
    Derived() = default;
    virtual void init() override {
    }
public:
    static Derived create() {
        return internal_create<Derived>();
    }


};

其中 create 可以替代构造函数(从 public 的角度来看),并且是实例化对象的唯一方法。 问题是这是否可以更简单地实现,因为现在每个派生类都必须实现 create

最佳答案

我看不到你的代码可以编译。我看不出虚拟 init 方法的意义,尽管它确实建议两阶段构建。这就是邪恶,您可以通过阅读 Bjarne Stroustrup 的 appendix E to “The C++ Programming Language” 来了解更多信息。 ,尤其是 E3.5 节。

FAQ 中概述了在基类构造函数中进行派生类初始化的常用方法。 。由于我曾经说服 Marshall 添加该常见问题解答项目,因此我也可以随时将您引导至我自己的 blog .

以后,请记住,首先查看常见问题解答通常是一个好主意。


哦,我忘了。关于构造期间动态类型的 C++ 规则的要点是提供类型安全构造。在 Java 和 C# 中,您可以很容易地在访问派生类的某些未初始化成员时引入错误,但在 C++ 中则不然。

两阶段构造抛弃了类型安全,并使编写异常安全使用代码变得困难,以换取 1990 年代早期编译器干净编码的能力(但实际上,谁需要这种能力)。

其他常见的解决方案旨在保持类型安全。

关于c++ - 启用可重写 init 函数的优雅方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12505161/

相关文章:

c++ - boost::variant 和 STL 容器 - 我做错了吗?

c++ - 是否有用于 C 字符串的标准 C++ 迭代器?

c++ - 将即时任务添加到 `CFRunLoop` 的最简单方法?

c++ - 为什么一个文件没有错误而其他文件有错误 - "Non Static Member Reference mush be relative to specific object"

c++ - 在 C++ 中使用 "super"

c++ - 包装的 unique_ptr 的模板化 move 构造函数

c++ - 从 C++11 中的 std::exception 派生时的异常规范

c++ strage 编译报错的解决方法

c++ - 使用成员函数时使用 std::result_of 编译失败

c++ - 推导和模板化使用之间有什么区别? (请看上下文)