c++ - 为什么我们不能在没有基类指针或引用的情况下在 C++ 中实现多态性?

标签 c++ oop compiler-theory



首先看看下面的代码(这段代码中shape是基类,line是派生类)

void drawshapes(shape sarray[],int size)
{
    for(int i=0;i< size; i++)
        sarray[i].draw();
}

main()
{
   line larray[10];
   larray[0]=line(p1,p2);//assuming that we have a point class
   larray[1]=line(p2,p3);
   ..........
   drawshapes(larray,10);
}


当我们编译这个程序时,首先会调用 shape 的 draw 方法,然后程序终止。为什么它终止?为什么我们不能在没有基类指针或引用的情况下实现多态性这是什么技术原因?如果我们试图用对象数组实现多态性,编译器会做什么?请以易于理解的方式举例说明。我将非常感激。

最佳答案

您提出一个问题并提供了一个失败的代码示例,但原因不同。从你的问题的措辞来看:

为什么多态需要引用/指针?

struct base {
   virtual void f();
};
struct derived : public base {
   virtual void f();
};
void call1( base b ) {
   b.f(); // base::f
}
void call2( base &b ) {
   b.f(); // derived::f
}
int main() {
   derived d;
   call1(d);
   call2(d);
}

当您使用按值传递语义(或将派生元素存储在基础容器中)时,您正在创建 derived 类型元素的 base 类型拷贝。这称为切片,因为它类似于您有一个派生 对象并且您切片/剪切基础 从它的子对象。在示例中,call1 不适用于 main 中的对象 d,而是使用类型为 base 的临时对象,并且 base::f 被调用。

call2 方法中,您将传递对 base 对象的引用。当编译器在 main 中看到 call2(d) 时,它将在 d 中创建对 base 子对象的引用并将其传递给函数。该函数对指向类型derived 的对象的base 类型的引用执行操作,并将调用derived::f。指针也是如此,当您将 base * 放入 derived 对象时,该对象仍然是 derived

为什么我不能将 derived 指针容器传递给采用 base 指针容器的函数?

_很明显,如果derivedbase,则derived 的容器 base< 的容器.

没有。 derived 的容器不是base 的容器。那会破坏类型系统。下面是使用 derived 容器作为打破类型系统的 base 对象容器的最简单示例。

void f( std::vector<base*> & v )
{
   v.push_back( new base );
   v.push_back( new another_derived );
}
int main() {
   std::vector<derived*> v;
   f( v ); // error!!!
}

如果语言允许标有错误的行,那么它将允许应用程序将非 derived* 类型的元素插入到容器中,这将意味着很多麻烦。 ..

但问题是关于值类型的容器......

当您拥有值类型的容器时,元素会被复制到容器中。将 derived 类型的元素插入到 base 类型的容器中,将在 derived< 中复制 base 类型的子对象 对象。这与上面的切片相同。除了作为一种语言限制之外,它还有一个很好的理由,当你有一个 base 对象的容器时,你有空间只容纳 base 元素。您不能将更大的对象存储到同一个容器中。否则编译器甚至不知道为每个元素保留多少空间(如果我们稍后扩展一个更大的类型会怎样?)。

在其他语言中,这似乎实际上是允许的(Java),但事实并非如此。唯一的变化是语法。当您在 Java 中使用 String array[] 时,您实际上是在编写 C++ 中的 string *array[] 的等价物。所有非基本类型在语言中都是引用,您不在语法中添加 * 并不意味着容器包含 String 的实例,容器将 引用 保存到字符串中,与 c++ 指针的关系比与 c++ 引用的关系更密切。

关于c++ - 为什么我们不能在没有基类指针或引用的情况下在 C++ 中实现多态性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2190455/

相关文章:

c++ - 将两个大数的和与另一个进行比较

c++ - Fortran Do 循环的上限

java - 强制两个相似的类表现得好像它们在 Java 中是多态的

graph-theory - 寄存器分配和溢出,简单的方法?

C++为void指针分配一个字符串

c# - 如何使用 C++ 静态库编译 C# 应用程序?

python - 如何在 Python 中告诉类创建一个球体?

PHP 面向对象 : Avoid Singleton/Static Methods in Domain Model Pattern

compiler-theory - 是否可以将低级语言转换为高级语言?

c++ - 重复文字和硬编码