扩展现有的 C 类

新手上路,请多包涵

我想在不更改现有类的情况下添加额外的功能。

说,

 class base{
public:
    int i;
    base(){i = 1;}
    virtual void do_work(){ /*Do some work*/ }
};

如果我想添加 serialization 成员函数,我将简单地创建一个派生类

class derived : public base{
public:
    void serialize();
};

void derived::serialize(){
    cout << "derived class" << endl;
}

我确实需要处理现有的 base 对象,例如

int main(){
    base a;
    derived & b = static_cast<derived &>(a);

    b.serialize();
}

此示例运行没有问题。但我确实知道 downcaststatic_cast 通常是要避免的。

但是我想知道 downcast 对于这个特殊用例是否可以被认为是安全的,因为 derived 类只有一个额外的成员函数。访问 vtable 是否会有一些潜在的未定义行为?

原文由 Mike Jiang 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 305
1 个回答

您扩展的方式 Base 您没有使用 vtable 因为您没有 virtual 方法。可能更容易将其视为 Derived has A Base ;您创建了一个包含 Base 成员变量的新类。

我的建议。

模板功能

我个人会使用模板功能。您可以保留原始问题中的所有工作,并避免向您的班级添加 virtual 调用。

 template<typename T>
void serialize_object(T& t)
{
  t.serialize()
}

然后根据你的例子。

 Derivied d;
serialize_object(d);

最大的好处是您没有在此处添加运行时强制转换。如果您传递的对象没有方法 serialize ,编译器会通知您。

虚拟化

如果您真的想通过虚拟接口处理此问题,请执行此操作。

 struct Serializable{
 virtual void serialize()=0;
 virtual ~Serializable(){}
}

class Derived : public Serializable {
  public:
   void serialize() override;
}

void Derivied::serialize()
{
 std::cout << "Yah\n";
}

然后在你的代码中。

 Derivied d;
Serializable& s = dynamic_cast<Serializable&>(d);

但是,这里最大的问题是你的基类的所有者是谁?他们提供了虚拟 dtor 吗?如果没有,那么使用 std::unique_ptrstd::shared_ptr 可能会导致您无法直接处理接口。

原文由 Freddy 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题