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

如何通过抽象类智能指针访问子类的受保护成员变量?

解决方案:通过抽象基类智能指针访问子类专属成员

要通过unique_ptr<Writer>访问youngWriter中的pencil成员,核心问题是基类Writer没有定义getPencil方法,直接调用会编译失败。这里提供两种可行方案:

方案一:使用dynamic_cast向下转型

dynamic_cast可以在运行时检查类型转换的合法性,只有当智能指针实际指向youngWriter对象时,转换才会成功。

修正后的完整代码示例

#include <memory>
#include <string>

class Pen{
public:
    Pen(std::string _color): color(_color){} // 修正构造函数名大小写,补充std::命名空间
    std::string getColor(){return color;} // 补充返回类型
protected:
    std::string color;
};

class Pencil{}; // 补充Pencil类定义

// 统一基类名大小写为Writer
class Writer{
public: 
    Writer() {}
    virtual void changeColor(std::string color) = 0; // 补充返回类型void
};

class oldWriter: public Writer{
protected:
    Pen *pen;
public:
    // 修正构造函数参数:传入Pen指针而非string
    oldWriter(Pen* _pen): pen(_pen){}
    virtual void changeColor(std::string color){ pen->color = color;} // 补充返回类型
};

class youngWriter: public Writer{
protected:
    Pen *pen;
    Pencil pencil;
public:
    youngWriter(Pen* _pen): pen(_pen){}
    virtual void changeColor(std::string color){ pen->color = color;}
    Pencil& getPencil(){return pencil;} // 返回引用避免不必要拷贝
};

int main(){
    // 创建youngWriter对象并赋值给基类智能指针
    std::unique_ptr<Writer> artist = std::make_unique<youngWriter>(new Pen("blue"));
    
    // 用dynamic_cast向下转型,先获取裸指针判断
    if (auto* young_artist = dynamic_cast<youngWriter*>(artist.get())) {
        Pencil& pencil = young_artist->getPencil();
        // 在此操作pencil
    } else {
        // 转换失败,说明artist指向的不是youngWriter对象
    }

    // 也可以直接转换智能指针
    auto young_artist_ptr = std::dynamic_pointer_cast<youngWriter>(artist);
    if (young_artist_ptr) {
        Pencil& pencil = young_artist_ptr->getPencil();
        // 操作pencil
    }
}

注意事项

  • dynamic_cast要求基类包含至少一个虚函数(你的代码中Writer已有纯虚函数changeColor,满足要求)。
  • 转换后必须检查结果是否为空,避免空指针访问。

方案二:在基类添加虚方法

在Writer中定义一个返回Pencil指针的虚函数,子类按需重写,无需显式转型即可调用。

代码修改示例

class Writer{
public: 
    Writer() {}
    virtual void changeColor(std::string color) = 0;
    // 添加默认返回nullptr的虚方法
    virtual Pencil* getPencil() { return nullptr; }
};

class youngWriter: public Writer{
    // ... 其他代码不变
public:
    // 重写基类方法,返回自身pencil的地址
    Pencil* getPencil() override { return &pencil; }
};

int main(){
    std::unique_ptr<Writer> artist = std::make_unique<youngWriter>(new Pen("blue"));
    
    Pencil* pencil = artist->getPencil();
    if (pencil) {
        // 操作*pencil
    }
}

优缺点

  • 优点:代码更简洁,无需显式转型。
  • 缺点:基类引入了子类专属的方法,可能破坏基类的抽象性,适合子类专属成员是通用业务场景的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 01:40:37