通过引用传递总是避免切片问题吗?

时间:2011-11-26 13:30:13

标签: c++ polymorphism pass-by-reference

这让我感到很惊讶,但我正在玩一些代码并发现,至少在我的计算机上,当一个函数通过引用接受一个父类并且你传递一个子实例时,切片问题没有不会发生。举例说明:

#include <iostream>

class Parent
{
public:
    virtual void doSomething()
    {
        using namespace std;
        cout << "Parent::DoSomething" << endl;
    }
};

class Child : public Parent
{
public:
    virtual void doSomething()
    {
        using namespace std;
        cout << "Child::DoSomething" << endl;
    }
};

void performSomething(Parent& parent)
{
    parent.doSomething();
}

int main(int argc, char** argv)
{
    Child myChild;

    performSomething(myChild);

    return 0;
}

打印出Child::DoSomething

像我说的那样,我有点惊讶。我的意思是,我知道通过引用传递就像传递指针一样(但在我的理解中更安全),但我不知道在这样做时我仍然要保持多态性。

我只是想确定,这是应该发生还是其中一个“它适用于我的机器”类型的实例?

4 个答案:

答案 0 :(得分:11)

“切片”是指基本拷贝构造函数无法区分精确类型匹配与派生类。调用切片的唯一方法是调用基本拷贝构造函数。通常,当按值传递参数时会发生这种情况,但可以设计其他情况:

class Base { };
class Derived : public Base { };

void foo(Base);

int main()
{
  Derived x;

  Base y = x;   // flagrant slicing
  foo(x);       // slicing by passing by value
}

你永远不会做任何这样的事情,所以你不会遇到任何切片情况。

答案 1 :(得分:9)

您看到的行为是正确的。这就是它应该如何工作。引用就像指针一样工作。

答案 2 :(得分:3)

应该发生这种情况。通过引用传递完全像传递指针 - 它在引擎盖下做同样的事情。这没有魔力;多态对象的每个实例都有一个与之关联的虚函数表。只要你不复制任何东西,你就不会丢失那些信息,你的虚拟函数调用将按照你期望的方式工作。

在传递值时遇到问题的原因是它将使用您在函数签名中指定的类型的复制构造函数,因此最终会得到一个全新的超类实例。

答案 3 :(得分:2)

是的,绑定到引用可启用动态绑定。这是由对象的动态类型与其静态类型的差异引起的。

如果按值获取参数,它将变为Parent类。虽然如果通过引用或指针传递某些内容并调用虚函数,运行时将查找正在引用的实际对象的dynamic typemost-derived type