C++ 虚拟方法:我必须在父类中为子级和父级不共享的每个方法创建一个虚拟方法吗?

Posted

技术标签:

【中文标题】C++ 虚拟方法:我必须在父类中为子级和父级不共享的每个方法创建一个虚拟方法吗?【英文标题】:C++ Virtual Methods: Must I create a virtual method in the parent class for every method that the child and parent do not share? 【发布时间】:2014-08-04 22:06:05 【问题描述】:

我有几个多边形类型的对象,它们只定义了形状,我想将它们存储在一个包含多边形的向量中。 Polygon 有几个通用方法,例如 getArea() 等,但它是一个纯粹的抽象类。

如果我有一个名为 Circle 的 Polygon 子节点,使用 getRadius() 方法,如果它存储在向量中,我是否需要在 Polygon 中创建一个虚拟方法来访问该方法?

如果我扩展为越来越多的形状,在 Polygon 声明中创建所有这些虚拟方法(与子声明中的关联子方法)会不会是多余的并且浪费空间?

是否有另一种方法可以通知编译器我在可用子方法的多边形向量中创建的(子类型)对象而不使用虚拟方法?或者这就是虚方法的全部意义所在?

我了解如何使用子级和父级共享的虚拟方法,我只是询问父级没有我想从子级访问的方法的情况。

【问题讨论】:

如果父类需要共享​​>来自潜在子类的方法,它应该是虚拟的。如果子类只需要使用基类中的方法,则该方法不需要在基类中是虚拟的。 如果您发现自己想要创建一个只对一个子类有意义的虚拟方法,那么您的设计可能是错误的(即您可能滥用了多态性)。 我相信比我知识渊博的人很快就会给出答案,但在我看来,如果您有需要在 Circles 上操作的代码,它应该只接受 Circle 对象。如果它可以处理任何多边形,它不应该使用子类特定的功能 另外,“我有一个 Polygon 的孩子,叫做 Circle”——什么?听起来你的父类应该叫做 Shape。 你是正确的命名,石油查尔斯沃思。绝对应该是形状。 【参考方案1】:

虚拟方法的重点是允许不同子级以不同方式实现的方法在运行时以正确的实现方式调用。

如果你有一个特定于一个子类的方法,那么父类应该有一个虚拟方法。

如果您尝试调用特定于Circle 的方法,那么您应该使用Circle* 而不是Polygon*

【讨论】:

好吧,我所使用的理论是,我想创建一个向量来包含我的所有多边形,并为所有多边形提供一些共享方法和特定于每个子类的一些方法。我应该尝试放弃这种设计吗?我注意到我对子类中特定方法的需求正在增加。我希望能够遍历向量,检查它是哪种多边形(即圆形、矩形、三角形)并对它们应用效果。有没有更好的方法,因为我希望能够动态创建不同样式的多边形。 @user3908267,一种可能性是您可以创建一个名为applyEffects 的虚拟方法,每个孩子将通过调用特定于孩子的方法来实现不同的方法。然后,当您迭代 vector 时,您只需在每个多边形上调用 applyEffects,对象本身就会知道要执行的正确行为。 哦,好的!那是一个好主意。是的,我真的不认为父级中的一堆挂起的虚拟方法无论如何都是一件好事。 非常感谢,我只是在面向对象编程方面让自己焕然一新。我整天在汇编中编程,所以我有点生疏了。 @user3908267,不用担心。我很高兴你发现这个讨论很有用。 :)【参考方案2】:

如果非共享方法对父类没有意义,那么你根本不想把它放在父类中。事实上,在这种情况下,多态性不适用,因为您不能让不同的运行时实例在该方法上表现出不同的行为:该方法对某些子类的实例没有意义,而对其他一些子类的实例则有意义。因此,您可能想要创建一个新类,它 (1) 将成为前面提到的父类的子类,(2) 将有一个在其他类之间共享的虚拟方法,(3) 将由这些类扩展类。

一般来说,如果您想调用特定类的特定方法,您需要将您的对象转换为该类或其声明该方法的祖先之一(虚拟或非虚拟)。

【讨论】:

谢谢!我同意我确实没有正确使用多态性。感谢您的帖子。【参考方案3】:

我想您想对将分别调用单个多边形的向量进行一次 getRadius 调用。那么基类显然是有意义的。

只需为所有子类实现单独的 GetRadius 方法,并具有一个默认虚函数以确保一致性。

既然你是说有多个形状,这意味着有多个类,也就是多个 GetRadius 实现。

虚函数将简化您的调用过程。

【讨论】:

以上是关于C++ 虚拟方法:我必须在父类中为子级和父级不共享的每个方法创建一个虚拟方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 Laravel 中为父级和子级创建活动类

nHibernate 保存一对多

React 父/子状态更改设计问题

在父类中为多个孩子定义方法

Django 模板扩展:子级不覆盖父级

如果父级不调用 wait(),则同一父级的两个子级不使用管道进行通信