之所以不能将多态性与值一起使用,而是使用引用和指针

时间:2013-07-08 19:19:38

标签: c++ polymorphism

我在帖子下面找到了 C++ polymorphism without pointers 解释为具有多态性特征C ++必须使用指针或引用类型。

我研究了一些进一步的资源,所有人都说同样但原因。

使用值来支持多态性是否存在技术上的困难,或者C ++已经决定不提供这种能力?

4 个答案:

答案 0 :(得分:10)

多态处理值的问题可归结为object slicing问题:由于派生对象可能使用的内存多于其基类,因此在自动存储中(即在堆栈上)声明值会导致仅分配内存对于基础,而不是对于派生对象。因此,可以切掉属于派生类的对象的部分。这就是为什么C ++设计者有意识地决定将虚拟成员函数重新路由到基类中的实现,而基类中的实现不能触及派生类的数据成员。

答案 1 :(得分:4)

困难来自这样一个事实:你所谓的对象被分配在自动内存中(在堆栈上),并且必须在编译时知道大小。

指针的大小在编译时是已知的,无论它们指向什么,并且引用被实现为引擎盖下的指针,所以不用担心。

考虑对象:

BaseObject obj = ObjectFactory::createDerived();

如果obj有条件地返回派生对象,应为createDerived()分配多少内存?为了解决这个问题,返回的对象是切片和“转换为* BaseObject,其大小已知。

这一切都源于“为你所用的付出”的心态。

答案 2 :(得分:1)

简短的回答是因为标准指定了它。但允许它有任何不可逾越的技术障碍吗?

C ++数据结构已知大小。多态性通常要求数据结构的大小可以变化。通常,您不能在较小类型的存储中存储不同(较大)的类型,因此通常不可能在父类的存储中存储具有额外变量(或其他更大的原因)的子类。

现在,我们可以解决这个问题。我们可以创建一个大于存储父类所需的缓冲区,并在该缓冲区中构造子类:但在这种情况下,通过引用接触所述实例,并且您将仔细包装该类。

这类似于boost::anyboost::variantstd::string的许多实现所使用的称为“小对象优化”的技术,其中我们将(通过值)对象存储在缓冲区中在课堂上并手动管理他们的生活。

还有一个问题,Derived指向实例的指针可能具有与实例的Base指针不同的值:C ++中的对象的值实例被假定存在于实例的存储开始的位置通过大多数实现。

所以理论上,如果我们将多态实例限制为可以存储在相同内存占用中的派生类,那么C ++可以允许多态实例,DerivedBase具有相同的“指针”值,但这将是一个非常狭窄的极端情况,并且可以减少编译器几乎在每种情况下可以对类的值实例进行的优化和假设! (现在,编译器可以假设类C的值实例具有virtual方法,这些方法在其他地方没有被覆盖,作为示例)这对于非常小的边际收益来说是非常重要的。

此外,如果我们真的需要,我们能够使用C ++语言使用现有的语言功能(放置新的,引用和手动销毁)来模拟这个角落的情况,而不会强加上述成本。

答案 3 :(得分:1)

“多态与值”并不是很清楚你的意思。在C ++中,当您拥有类型为A的对象时,它始终表现为A类型的对象。这是完全正常和合理的事情。我不知道它是如何以任何其他方式表现的。因此,目前尚不清楚某人决定“不提供”你所谈论的“能力”。

C ++中的多态性意味着一件事:通过具有多态类型的表达式进行的虚拟函数调用将根据该表达式的 dynamic 类型进行解析(而不是< 非虚拟函数的em> static 类型。这就是它的全部内容。

C ++中的多态性始终按照上述规则运行。它通过指针工作。它通过引用以这种方式工作。它通过直接对象(你称之为“值”)的方式工作。因此,说C ++中的多态性仅适用于指针和引用并不正确。它也适用于“价值观”。如上所述,它们都遵循相同的规则。

但是,对于直接对象(“值”),其动态类型始终与静态类型相同。因此,即使多态性对于直接值起作用,它也不会证明任何真正的“多态”。具有多态性的直接对象的行为与没有多态性的行为相同。因此,直接对象的多态性是简并的,微不足道的多态性。它只存在于概念上。这也是完全合乎逻辑的:类型A的对象应该表现为A类型的对象。它还有什么其他表现?

为了观察实际的非简并多态性,需要一个静态类型与其动态类型不同的表达式。当静态类型A的表达式(关于虚函数调用)表现为不同类型B的对象时,会观察到非平凡的多态性。为此,静态类型A的表达式实际上必须引用类型为B的对象。这只能通过指针或引用来实现。在表达式的静态和动态类型之间创建差异的唯一方法是使用指针或引用。

换句话说,说C ++中的多态只能通过指针或引用工作是不正确的。这是正确的说,使用指针或引用,多态性变得可观察且非平凡。