为什么基类对象必须是调用派生虚函数的引用?
#include<iostream>
using namespace std;
class A {
public:
virtual void print() { cout << "Hello 1" << endl; }
};
class B : public A {
public:
int x;
void print() { cout << "Hello " << x << endl; }
};
void main(){
B obj1;
A &obj2 = obj1;
A obj3 = obj1; // Why it is different from obj2
obj1.x = 2;
obj1.print();
obj2.print();
obj3.print(); // ?
}
答案 0 :(得分:5)
当您将派生对象分配给基础变量时,它会将“sliced”转换为基类的实例;它不再是派生的实例。这是必要的,因为基本变量只有足够的空间保留给基类的实例;派生类的实例及其附加数据将不适合。
使用引用时,不必将对象复制到较小的空间中,因此不会发生切片。
答案 1 :(得分:3)
A obj3 = obj1; // Why it is different from obj2
通过复制构建obj3。在这种情况下,obj1向上转换为A类型,其中obj3由obj1的“A”参数构成。这种现象称为slicing。
A &obj2 = obj1;
此行将引用obj2绑定到obj1的实例。你已经通过将obj2指向它来将obj1提升为“A”。请记住,在C ++中,引用实际上只是一个别名。您刚刚给obj1一个不同的名称,该名称绑定到基类类型。
所以A obj3
在堆栈上分配和构造一个全新的对象,而A &obj2
只为已经存在的其他东西创建一个引用/别名。