了解在堆栈上分配的实例的C++虚拟方法

Jac*_*nds 3 c++

对于以下代码:

#include<iostream>
using namespace std;

class A{
public:
virtual int f(){return 1;}
};
class B : public A{
public:
virtual int f(){return 2;}
};
int main(int argc,char*argv[]){
    A b=B();
    cout<<b.f()<<endl;
}
Run Code Online (Sandbox Code Playgroud)

我希望2打印这个号码.而是程序打印数字1.

有人可以解释为什么会这样吗?

Yip*_*Yay 9

你所做的就是切片.请参阅什么是对象切片?

相反,应该使用指针:

A* b = new B();
Run Code Online (Sandbox Code Playgroud)


Nik*_*sov 6

这是由于切片.运行时多态性仅适用于C++中的指针或引用.您可以使用另一个变量进行虚拟调度:

B b;
A& a = b;
cout << a.f() << endl;
Run Code Online (Sandbox Code Playgroud)

或者您可以直接指定指针,如下所示:

A* aptr = new B;
aptr->f();
delete aptr;
Run Code Online (Sandbox Code Playgroud)

但这里的类B需要一个虚拟析构函数.虽然在第一种情况下并不严格要求,但提供虚拟析构函数是多态类型的一般规则.GCC -Wnon-virtual-dtor标志可以帮助您捕获此错误.


Dav*_*eas 6

问题是变量的类型是A,而不是B.这条线:

A a = B(); 
Run Code Online (Sandbox Code Playgroud)

创建一个临时类型B,然后将其A子部分复制到a类型中A.

要以多态方式使用对象,您需要通过指针或引用来处理它:

int main() {
   B b;
   A &a = b;  // an A reference to the B object
   A *p = &b; // an A pointer to a B object
   a.f();     // will dispatch to B::f
   p->f();    // will dispacth to B::f
}
Run Code Online (Sandbox Code Playgroud)