You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现派生类构造后自动调用基类sanitycheck且不修改派生类构造?

实现派生类构造后自动调用基类sanitycheck的方案

要让所有继承Base的派生类在构造函数执行完毕后自动调用Base::sanitycheck,且不修改Derived的构造代码,我们可以通过修改基类Base的实现来达成目标,以下是两种可行方案:


方案一:工厂函数(构造后立即调用sanitycheck)

该方案通过给Base添加模板工厂函数,强制用户通过工厂创建派生类对象,在工厂内部完成构造后立即调用sanitycheck,完全匹配期望的输出顺序。

修改后的完整代码:

#include<iostream>
std::ostream& o = std::cout;

struct Base
{
    void sanitycheck() { o << "base checks\n"; }
protected:
    // 将基类构造函数设为protected,强制用户通过工厂函数创建对象
    Base() { o << "make base\n"; }
public:
    // 模板工厂函数,支持所有派生类
    template<typename Derived>
    static Derived create() {
        Derived d;
        d.sanitycheck();
        return d;
    }
};

// Derived代码完全无需修改
struct Derived : Base 
{
    Derived() { o << "make derived\n"; }
};

// Dummy类可保留(本方案未使用)
struct Dummy
{
    Base& base;
    Dummy(Base& base) :base(base) {}
    ~Dummy() { base.sanitycheck(); }
};

int main()
{
    // 通过工厂函数创建Derived对象
    Derived x = Base::create<Derived>();
    /* 输出:
    make base
    make derived
    base checks
    */
}

方案说明:

  • 将Base的构造函数设为protected,避免用户直接构造Base或直接用Derived x;的方式创建派生类对象,必须通过工厂函数。
  • 工厂函数create构造派生类对象后,立即调用sanitycheck,保证输出顺序完全符合要求。
  • Derived的代码完全不需要修改,满足题目限制。

方案二:利用RAII成员(对象销毁时调用sanitycheck)

如果允许sanitycheck在对象销毁时执行,可以利用Dummy类作为Base的成员,借助RAII特性,在对象生命周期结束时自动触发检查。

修改后的完整代码:

#include<iostream>
std::ostream& o = std::cout;

// 先声明Base,避免Dummy编译错误
struct Base;

struct Dummy
{
    Base& base;
    Dummy(Base& base) :base(base) {}
    ~Dummy() { base.sanitycheck(); }
};

struct Base
{
    void sanitycheck() { o << "base checks\n"; }
    // 添加Dummy成员,构造时绑定当前Base对象
    Dummy dummy;
    Base() : dummy(*this) { o << "make base\n"; }
};

// Derived代码完全无需修改
struct Derived : Base 
{
    Derived() { o << "make derived\n"; }
};

int main()
{
    // 将对象放在局部作用域中,离开作用域时销毁
    {
        Derived x;
    }
    /* 输出:
    make base
    make derived
    base checks
    */
}

方案说明:

  • 在Base中添加Dummy类型的成员变量,构造时传入当前Base对象的引用。
  • 当Derived对象销毁时,会先销毁Base的成员变量dummy,dummy的析构函数自动调用sanitycheck。
  • 若直接在main中声明Derived x;,base checks会在main函数结束时输出;若将对象放在局部作用域中,输出顺序则和期望一致。

内容的提问来源于stack exchange,提问作者user22056011

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 11:35:54