Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么不能将多态性与值一起使用,而与引用和指针一起使用_C++_Polymorphism - Fatal编程技术网

C++ 为什么不能将多态性与值一起使用,而与引用和指针一起使用

C++ 为什么不能将多态性与值一起使用,而与引用和指针一起使用,c++,polymorphism,C++,Polymorphism,我发现下面的帖子 说明多态性的特点,C++必须使用指针或引用类型。 我调查了一些进一步的资源,他们都说了同样的话,但原因是一样的 是否存在任何技术上的困难来支持多态性,或者是有可能的,但是C++已经决定不提供这种能力了? < p>多态性的处理问题归结为问题:因为派生对象可以使用比基类更多的内存,在自动存储中声明一个值。(即在堆栈上)导致只为基分配内存,而不是为派生对象分配内存。因此,属于派生类的对象的部分可以被切片。这就是为什么C++设计者有意识地将虚拟成员函数重路由到基类中的实现,而不能实现派

我发现下面的帖子 说明多态性的特点,C++必须使用指针或引用类型。 我调查了一些进一步的资源,他们都说了同样的话,但原因是一样的


是否存在任何技术上的困难来支持多态性,或者是有可能的,但是C++已经决定不提供这种能力了?

< p>多态性的处理问题归结为问题:因为派生对象可以使用比基类更多的内存,在自动存储中声明一个值。(即在堆栈上)导致只为基分配内存,而不是为派生对象分配内存。因此,属于派生类的对象的部分可以被切片。这就是为什么C++设计者有意识地将虚拟成员函数重路由到基类中的实现,而不能实现派生类的数据成员的原因。> 困难来自这样一个事实,即您所称的对象是在自动内存(在堆栈上)中分配的,并且大小必须在编译时已知

指针的大小在编译时是已知的,不管它们指向什么,引用都是作为隐藏的指针实现的,所以不用担心

但考虑对象:

BaseObject obj = ObjectFactory::createDerived();
如果
createDerived()
有条件地返回派生对象,则应为
obj
分配多少内存?为了克服这一问题,将返回的对象切片,并“转换*为大小已知的
BaseObject


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

简单的回答是因为标准规定了它。但是,允许它存在任何不可逾越的技术障碍吗

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

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

这类似于
boost::any
boost::variant
std::string
的许多实现所使用的称为“小对象优化”的技术,我们将对象(按值)存储在类内的缓冲区中,并手动管理它们的生存期

<> P>还有一个问题:派生/<代码>实例的指针可以有不同的值,而不是代码> Base< /Cord>指向实例的指针:假定C++中的对象的值实例存在,其中实例的存储由大多数实现开始。 <>理论上,C++可以允许多态性实例,如果我们将它限制在可以存储在同一内存占用的派生类中,用相同的“指针”“派生的<代码>和<代码>基的<代码>都有值,但这将是一个非常狭隘的例子,并且可以减少编译器在几乎所有情况下对类的值实例进行的优化和假设的种类!(现在,编译器可以假设类
C
的值实例有
virtual
方法,例如,这些方法在其他地方没有被覆盖)这是一个非常小的成本,但收益非常小


<> P>更重要的是,如果我们真的需要它,我们可以使用C++语言来模仿现有的语言特征(放置新的、引用和手动破坏),而不必强加上述成本。在C++中,当你有一个类型的对象<代码> a <代码>时,它总是表现为一个类型<代码> > <代码>的对象。这是完全正常和合乎逻辑的。我不知道它可能以任何其他方式来运行。所以,不清楚某人决定“不提供”的“能力”。 在C++中多态性意味着一件事:通过多态表达式的虚函数调用根据该表达式的动态类型(与非虚拟函数的静态类型相反)来解决。这就是它的全部内容。

<>多态在C++中总是按照上述规则工作的,它通过指针工作。它通过引用来工作。它通过直接对象(如你所说的“值”)来工作。因此,C++中的多态性只与指针和引用一起工作并不正确。它与“值”一起工作。同样,它们都遵循同样的规则,如上所述

然而,对于直接对象(“值”),其动态类型始终与静态类型相同。因此,即使多态性适用于直接值,它也不能证明任何真正的“多态性”。具有多态性的直接对象的行为与不具有多态性的直接对象的行为相同。因此,直接对象的多态性是退化的、琐碎的多态性。它仅在概念上存在。这也是完全合乎逻辑的:类型为
A
的对象应表现为类型为
A
的对象。否则它怎么可能存在呢阿维

为了观察实际的非退化多态性,需要一个静态类型与其动态类型不同的表达式。当静态类型
A
的表达式行为时(关于虚拟函数调用),可以观察到非平凡多态性作为不同类型的对象
B
。为此,静态类型
A
的表达式必须实际引用类型
B
的对象。这只能通过指针或引用来实现