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

在GoogleTest中结合继承正确使用unique_ptr的方法

问题分析与解决方案

直接代码错误

你的测试代码存在空指针解引用的严重问题:
当执行C myC = C(move(myA));时,myA的所有权被完全转移给myC的pA成员变量,此时myA变成空指针。后续调用myA->getSmtInA()会触发未定义行为,大概率导致程序崩溃。

设计逻辑混淆

代码同时使用了**继承(C is-a A)和组合(C has-a A)**两种关系,这通常是设计意图不清晰导致的。需要先明确需求方向:

  • 是让C作为A的子类,重写A的方法并维护自身状态?
  • 还是让C作为A的包装类(装饰器模式),内部封装一个A实例并代理其操作?

场景1:C作为A的子类(重写方法)

如果需求是让C继承A的行为并扩展,直接重写A的虚方法即可,无需持有额外的A指针:

修正后的类实现

// 基类A补充成员变量与方法实现
class A {
public:
    A() : smtInA(0) {}
    virtual ~A() {}

    virtual void setSmtInA(int setSmt);
    virtual int getSmtInA(void);

private:
    int smtInA; // 存储数据的成员变量,原代码缺失
};

void A::setSmtInA(int setSmt) {
    smtInA = setSmt;
}

int A::getSmtInA(void) {
    return smtInA;
}

// 子类C:继承A并重写/扩展方法
class C : public A {
public:
    C() : smtInC(0) {}
    virtual ~C() {}

    // 重写A的方法,操作子类自身成员
    void setSmtInA(int setSmt) override {
        smtInC = setSmt;
    }

    int getSmtInA(void) override {
        return smtInC;
    }

    // 子类自定义方法
    void setSmtInC(int setSmt) {
        smtInC = setSmt;
    }

    int getSmtInC(void) {
        return smtInC;
    }

private:
    int smtInC;
};

对应的GoogleTest测试代码

TEST(Some_Tests, Test1) {
    C myC;

    myC.setSmtInC(15);
    // 直接调用继承自A的方法,已被C重写
    int temp = myC.getSmtInA();
    
    EXPECT_EQ(15, temp);
}

场景2:C作为A的包装类(装饰器模式)

如果需求是让C封装一个A实例,通过组合扩展功能,需要调整类接口以正确访问内部A实例:

修正后的类实现

// 基类A补充成员变量与方法实现(同场景1)
class A {
public:
    A() : smtInA(0) {}
    virtual ~A() {}

    virtual void setSmtInA(int setSmt);
    virtual int getSmtInA(void);

private:
    int smtInA;
};

void A::setSmtInA(int setSmt) {
    smtInA = setSmt;
}

int A::getSmtInA(void) {
    return smtInA;
}

// 包装类C:继承A并持有A实例(装饰器)
class C : public A {
public:
    C(unique_ptr<A> upA) : pA(move(upA)) {}
    virtual ~C() {}

    // 子类自定义方法:操作内部封装的A实例
    void setSmtInC(int setSmt) {
        pA->setSmtInA(setSmt);
    }

    int getSmtInC(void) {
        return pA->getSmtInA();
    }

    // 提供访问内部A实例的接口(供测试或外部使用)
    A& getInnerA() {
        return *pA;
    }

private:
    unique_ptr<A> pA;
};

对应的GoogleTest测试代码

TEST(Some_Tests, Test1) {
    unique_ptr<A> myA = make_unique<A>();
    C myC = C(move(myA));

    myC.setSmtInC(15);
    // 通过C提供的接口访问内部A实例,避免使用已失效的原指针
    int temp = myC.getInnerA().getSmtInA();
    
    EXPECT_EQ(15, temp);
}

关键注意点

  • std::unique_ptr的所有权转移:使用move后,原指针会被置空,绝对不能再访问。
  • 继承与组合的选择:is-a关系用继承,has-a关系用组合,避免同时混用导致逻辑混乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 02:05:20