【问题标题】:C++ class hierarchy in which to add functionality with an interface使用接口添加功能的 C++ 类层次结构
【发布时间】:2019-07-24 17:17:17
【问题描述】:

C++。想象一下下面的情况。

从某个基类 A 派生的类有一个类层次结构。 我们不能修改 A 因为它超出了我们的范围。 (由一个库提供,它是一个 MFC CView 类,但在这里应该无关紧要)

所以有 A1、A2 等,它们是从 A 派生并提供特定功能的不同类。

现在假设我们定义了一些新接口 I 来提供一些新功能。

应用程序的具体对象的类将继承自 As 和 I 之一。 我们称他们为 Bs。 (还有好几种,比如 B1 派生自 A1 和 I,B2 派生自 A2 和 I 等)

现在碰巧要实现I的接口,有很多通用代码需要A的功能。 我们如何在不重复太多的情况下组织类层次结构。

例如,如果有一个函数 I::f 需要为所有派生类 Bn 调用 A::f。 为每个 Bn 重新实现 I::f 似乎是浪费。 但显然,我们不能直接从 I::f 调用 A::f,因为它们不相关。

我希望你明白这一点。

在这里可以帮助我们的模式是什么?

【问题讨论】:

  • 听起来您已经将应用程序逻辑捆绑在您的视图类中;任何像这样的共享逻辑都应该真正独立于任何 View 类而存在,考虑研究 Model-View-Presenter 模式以将逻辑从 View 中分离出来。继承CView 的类应该只真正处理它们各自的UI“小部件”的外观和布局,而根本没有任何逻辑。 ——例如按钮单击/事件逻辑或验证或数据库内容等并不真正属于“视图”类,并且可能不希望被与 MFC 相关的问题所污染。
  • @BenCottrell,你可能是对的。但是为了论证,直接忽略CView的信息。或者假装我们实现了额外的外观相关功能。

标签: c++ design-patterns


【解决方案1】:

“从I::f 调用A::f 而不彻底检查所有内容”的直接解决方案是dynamic_cast

struct I {
    void f() {
        dynamic_cast<A *>(this)->f();
    }
};

请注意,这会执行完整的 RTTI 图遍历,以通过对象的未知 Ax 动态类型执行交叉转换,因此它可能会比较慢。

【讨论】:

  • 是的,这就是我们目前所拥有的。但它看起来非常尴尬。毕竟,我不一定是 A。我们考虑实现一个特定的案例,我们确实从 I 派生而不是从 A 派生。
  • @Scrontch dynamic_cast 将在您尝试强制转换为不存在的子对象时正确运行:指针版本将返回 nullptr,您可以检查或断言参考版本 (dynamic_cast&lt;A &amp;&gt;(*this) ) 将抛出std::bad_alloc
猜你喜欢
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
  • 2019-05-10
  • 1970-01-01
  • 1970-01-01
  • 2016-04-12
  • 1970-01-01
  • 2011-08-10
相关资源
最近更新 更多