虚方法仅适用于基类指针

时间:2014-01-11 22:29:47

标签: c++ virtual-functions

下面是C ++中虚拟函数最简单的例子:

#include <iostream>

class A {
public:
    virtual void f() {
        std::cout << "A";
    }
};

class B : public A {
public:
    void f() {
        std::cout << "B";
    }
};


int main() {
    {
        // calls f() in derived class
        A* a = new B();
        a->f();
    }
    {
        // calls f() in base class
        A a = B();
        a.f();
    }
}

此程序的输出为BA。我希望它是BB,即在任何情况下调用基类。 为什么使用基类指针会有所不同? 我没有在标准中找到解释。

3 个答案:

答案 0 :(得分:7)

这称为slicingA a = B();创建一个A类型的副本。有关其来源B的所有信息都被遗忘了。利用多态的唯一方法是通过引用或指针(或允许编译时多态的机制,例如模板或函数重载)。

答案 1 :(得分:3)

多态性与指针一起使用,因为在指针(或引用)的情况下,您可以区分指针的类型和对象的类型。现在在以下代码中:

A a = B();
a.f();

发生的事情称为切片。即对象B()被切片,其基础A()被分配给。

不要忘记让析构函数虚拟化!

答案 2 :(得分:0)

A a = B()的情况下,函数调用的顺序是:

  1. 调用B类的默认构造函数。
    • 在堆栈上创建类型B的临时对象。
  2. 调用从B到A的转换运算符。
    • 在堆栈上创建A类临时对象。
  3. 使用前一个对象的地址作为参数调用类A的复制构造函数。
    • 在堆栈上创建A类型的非临时对象。
    • 此对象将保留在堆栈中,直到函数返回。
    • 它是A类型的对象,因此您打印的是“A”而不是“B”。
  4. 总结一下,这是上面一行的“完整版”:A(B()->operator A())