无需显式向下转型访问子类成员的C++技术咨询
不用显式向下转型的解决办法
方案一:给基类添加虚接口
在Base类中定义纯虚函数封装val的设置逻辑,让拥有val的子类A、B实现该函数,通过基类指针直接调用即可完成赋值,无需转型。
修改后的代码:
struct Base { virtual void set_val(int v) = 0; // 纯虚函数,强制子类实现 virtual ~Base() = default; // 基类必须加虚析构,避免内存泄漏 }; struct A : public Base { int val; void set_val(int v) override { val = v; } }; struct B : public Base { int val; void set_val(int v) override { val = v; } }; struct C : public Base { // 若C不需要set_val功能,可给Base的set_val设默认空实现,这里就不用重写 void set_val(int v) override {} }; void bar(bool x, int value) { std::unique_ptr<Base> ptr; if (x) { ptr = std::make_unique<A>(); } else { ptr = std::make_unique<B>(); } ptr->set_val(value); // 正常调用,无报错 }
注:如果C不需要set_val功能,建议把Base中的set_val改为非纯虚函数并提供空默认实现,避免C强制重写。
方案二:提取中间接口类
新增一个继承自Base的ValHolder类,专门封装val成员,让A、B继承ValHolder,C直接继承Base。由于bar只处理带val的A、B,可以直接用ValHolder类型的指针管理对象,直接访问val。
示例代码:
struct Base { virtual ~Base() = default; }; struct ValHolder : public Base { int val; }; struct A : public ValHolder { // 自动继承ValHolder的val }; struct B : public ValHolder { // 自动继承ValHolder的val }; struct C : public Base { // 无val }; void bar(bool x, int value) { std::unique_ptr<ValHolder> ptr; if (x) { ptr = std::make_unique<A>(); } else { ptr = std::make_unique<B>(); } ptr->val = value; // 直接访问成员,无需转型 }
方案三:初始化对象时直接赋值
给A、B添加带参数的构造函数,在创建对象时直接完成val的赋值,跳过后续通过基类指针访问成员的步骤。
示例代码:
struct Base { virtual ~Base() = default; }; struct A : public Base { int val; explicit A(int v) : val(v) {} // 带参数的构造函数 }; struct B : public Base { int val; explicit B(int v) : val(v) {} }; struct C : public Base { // 无val }; void bar(bool x, int value) { std::unique_ptr<Base> ptr; if (x) { ptr = std::make_unique<A>(value); // 创建时直接赋值 } else { ptr = std::make_unique<B>(value); } // 无需后续赋值操作 }
内容的提问来源于stack exchange,提问作者xyf
相关产品推荐
相关产品推荐

