5

我用第二人称写作只是因为它对你来说很容易。

您正在使用游戏引擎,并且真的希望特定的引擎类有一个新的方法来执行“bla”。但是您不希望将“游戏”代码传播到“引擎”代码中。

所以你可以用你的一个新方法从中派生一个新类,并将该代码放在你的“游戏”源目录中,但也许还有另一种选择?

所以这在 C++ 语言中可能是完全非法的,但你起初认为,“也许我可以通过我自己的头文件向现有类添加一个新方法,其中包括‘父’头文件和一些特殊语法。这在工作时是可能的例如,带有命名空间..."

假设您不能跨多个标头声明一个类的方法(并且您非常确定您不能),那么支持“中间件/引擎/库”和“应用程序”之间明确划分的其他选项是什么,您想知道?

4

8 回答 8

8

我对您的唯一问题是,“您添加的功能是否需要成为成员功能,还是可以是免费功能?” 如果你想做的事情可以使用类的现有接口来解决,那么唯一的区别是语法,你应该使用一个自由函数(如果你认为那是“丑陋的”,那么......吸干它并继续前进, C++ 不是为猴子补丁设计的)。

如果您试图了解类的内部内容,这可能表明原始类缺乏灵活性(它没有公开足够的信息让您从公共接口中做您想做的事情)。如果是这样的话,也许原来的类可以“完成”,然后你又要在它上面放一个自由函数。

如果这些都不起作用,并且您只需要一个成员函数(例如,原始类提供了您想要获取的受保护成员,并且您没有修改原始接口的自由)......只有然后才诉诸继承和成员函数实现。

如需深入讨论(以及std::string' 的解构),请查看本周大师“Monolith”类文章

于 2008-10-23T04:29:22.380 回答
1

听起来像是“作用于”关系,不适合继承(谨慎使用!)。

一种选择是组合实用程序类,它通过使用指向它的指针来实例化“引擎”的某个实例。

于 2008-10-23T03:22:54.543 回答
1
  • 继承(如您所指出的),或
  • 使用函数而不是方法,或者
  • 更改引擎代码本身,但使用 quilt 或 Mercurial/MQ 等补丁管理器隔离和管理更改

不过,我看不出在这种情况下继承有什么问题。

于 2008-10-23T03:41:19.450 回答
1

如果新方法将使用现有的公共接口实现,那么可以说它更加面向对象,因为它是一个单独的函数而不是一个方法。至少,斯科特迈耶斯认为它是。

为什么?因为它提供了更好的封装。IIRC 的论点是类接口应该定义对象所做的事情。Helper 风格的函数是可以用/对对象完成的事情,而不是对象必须自己做的事情。所以他们不属于这个班级。如果他们在类中,他们可以不必要地访问私有成员,从而扩大该成员的隐藏范围,因此如果私有成员发生任何变化,则需要触及的代码行数。

当然,如果你想访问受保护的成员,那么你必须继承。如果您想要的方法需要每个实例的状态,但不能访问受保护的成员,那么您可以根据口味继承或组合 - 前者通常更简洁,但如果关系不是真的“是”,则具有某些缺点.

于 2008-10-23T04:11:40.887 回答
0

听起来你想要Ruby mixins。不确定 C++ 中有什么接近的东西。我认为您必须进行继承。

编辑:您也许可以放入一个朋友方法并像混合一样使用它,但我认为您会开始以一种不好的方式破坏您的封装。

于 2008-10-23T03:17:52.790 回答
0

您可以做一些类似 COM 的事情,其中​​基类支持 QueryInterface() 方法,该方法允许您请求具有该方法的接口。这在 C++ 中实现相当简单,您不需要 COM 本身。

您还可以“假装”成为一种更动态的语言,并将一组回调作为“方法”,并使用模板或宏来调用它们,并将“this”推入堆栈,然后再将其余参数推入堆栈。但这将是疯狂的:)

于 2008-10-23T03:31:20.267 回答
0

或Objective C中的类别。

有一些概念方法可以在 C++ 中扩展类架构(不是单个类),但这不是随意的行为,需要提前计划。对不起。

于 2008-10-23T03:39:04.260 回答
0

对我来说,这听起来像是一个经典的继承问题。除非我将代码放在“引擎增强”目录中,并将该概念包含在您的架构中。

于 2008-10-23T03:46:10.300 回答