在多态性方面,引用和指针是否相等?

49

我总是认为在多态方面必须使用指针。以经典的例子为例:

DrawEngine::render(Shape *shape)
{
    shape->draw();
    shape->visible(true);
}

如果传递指向各种Shape派生类的指针,那么使用引用是否也可以工作?

DrawEngine::render(Shape &shape)
{
     shape.draw();
     shape.visible(true);
}

这样做甚至有效吗:

engine.render(myTriangle); // myTriangle instance of class derived from Shape
如果这个方法起作用了,那么这两种情况之间有什么区别吗?我试图在 Stroustrup 找到相关信息,但没有发现任何内容。 我重新打开这个问题是因为我想再探索一下。 所以至少有一个区别是 dynamic_cast。对我来说,多态性包括使用 dynamic_cast。 我可以走了吗?
Rhomboid & r = dynamic_cast<Rhomboid &>(shape);

如果强制类型转换失败会发生什么?这与其他情况有何不同?

Rhomboid * r = dynamic_cast<Rhomboid*>(&shape);
3个回答

54

关于多态性,引用与指针的工作方式相同。


4
当然可以直接进行类型转换,但是有不同的方面。例如,dynamic_cast在进行错误的类型转换时会抛出异常而不是返回空指针。 - GManNickG
3
我认为dynamic_cast的例子是指针和引用之间的基本区别:指针可以合法地为NULL,而引用则不行。我理解这个问题的核心在于引用在虚表方面的行为是否与指针相同。因此给出了简要回答。 - Alex Emelianov
2
在我看来,引用似乎只是指针上的一些语法糖。 - Etienne de Martel
@Etienne,对我遇到的每个编译器来说这确实是正确的。但是我不怎么出门。 - Mark Ransom
9
@Etienne:C++只是在机器码的基础上添加了语法糖 :-). - pm100

10

关于dynamic_cast,在使用指针时,失败的类型转换会产生一个空指针,并在使用引用时抛出bad_cast异常(如果我没记错的话)。

其中一个原因是不存在有效的空引用。

还有可能是另一个原因(但这可能只是一个无意中有用的特性),有时需要异常,有时需要易于检查的空指针,在手头有引用或指针时,无论哪种情况都只需要最多进行一次解引用或取地址操作即可得到所需的行为。

祝好!


-1
指针在其他方面也有帮助。例如,在函数中将字符串作为char*参数传递并接受它。
考虑反转字符串的旧例子:
void reversestring(char* myString)
{
int firstPos=0;
int lastPos=myString.length - 1;
while (firstPos < lastPos)
{
  char temp=myString[firstPos];
  myString[firstPos]=myString[lastPos];
  myString[lastPos]=temp;
  firstPos++;
  lastPos--;
}
}

编写像这样使用引用的字符串操作代码并不那么简单。


1
myString.length?那是C++吗? - The Light Spark
2
@TheLightSpark 如果 myString 是一个 std::string,那么这是有效的,但我认为对于原始的 C 字符串来说是无效的。此外,length 应该是一个函数调用,但这只是小题大作。 - Justin Time - Reinstate Monica
如果它是std::string,它可以是一个引用。在现代C++中,您可以使用std::array代替char*,或者更好地使用std::string。 - Jonathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接