class B {
public:
  virtual void foo() {
      cout << "B" << a;
  }
  int a = 1;
};
class D : public B{
public:
  D() {
    a = 2;
  }
  virtual void foo() {
      cout << "D" << a;
  }
};
B x = D();  // 请务必仔细看这一行
x.foo();
	这段代码输出什么?
                                        这里最重要的概念是对象切片。当我们写:
B x = D();
这里发生的是:创建一个D的临时对象,然后用这个临时对象来初始化x。由于x的类型是B,而不是B*或B&,所以这里会发生切片——即D对象中属于B的部分会被复制到x中,而D特有的部分会被“切掉”。
  这意味着:
 1.x是一个B类型的对象,不是一个D类型的对象。
 2.D的构造函数会被调用(因为先创建D的临时对象),但x最终只是一个B。 
虚函数的动态绑定(即多态)只在通过指针或引用调用时生效。在这里,x是一个对象,不是指针或引用。因此,x.foo()的调用会在编译时就确定调用B::foo(),因为x的静态类型是B。
在D的构造函数中,a被设置为2。但由于x是一个B对象,它只会包含B的子对象。D的构造函数确实会被调用(因为先创建D的临时对象),但a的设置是在D的构造函数中进行的。然而,x是B类型,所以a的值取决于B的部分。
  实际上,当D的临时对象被创建时:
 1. 首先调用B的构造函数(隐式默认构造函数),将a初始化为1。
 2. 然后调用D的构造函数,将a改为2。
 3. 然后这个D对象被切片,复制其B部分到x中。因此x.a会是2(因为D的构造函数已经运行,将a改为2)。 
让我们一步步验证:
1. 创建D的临时对象:
2. 用临时对象初始化x(B x = D();):
3. 调用x.foo():
因此,输出是:
B2
如果改为指针或引用,行为会不同:
D d; B* ptr = &d; ptr->foo(); // 输出 D2,因为多态生效 B& ref = d; ref.foo(); // 输出 D2,因为多态生效
但原问题中是对象,所以不会多态。
输出:
B2