c++ - 派生类的切片是如何发生的?
问题描述
我无法理解切片是如何发生的?例如,在这段代码中:
class A {
public:
virtual h() {
cout << "type A" << endl;
}
};
class B : public A {
public:
virtual h() override {
cout << "type B" << endl;
}
};
void f(A a) {
a.h();
}
void g(A& a) {
a.h();
}
int main() {
A a1 = B(); // a1 is A and doesn't recognize any B properties
A *a = new B();
f(*a);
g(*a);
}
我注意到:
变量 a1 不知道它是 B,但变量 a 确实知道。我指的是这种情况正在发生,因为在变量 a1 中,对 B 的赋值是按值分配的,与变量 a 相反,我在其中创建了一个指向 B 的指针。
当我将变量 a 传递给不同的函数时,也会发生同样的事情——当我通过值传递时,它认为它是 A,但是当我通过引用传递时,它认为它是 B。
如果有人能给我更广泛和更深入的解释,我会很高兴。先感谢您!
解决方案
- 变量 a1 不知道它是 B
更准确地说:变量 a1 被声明为 A,所以它是 A。它不是 B,也从来不是 B。这与变量“知道”什么无关;这是关于变量的类型。a1 通过“切片”基本子对象的副本从 B 初始化。
如果有人能给我更广泛和更深入的解释,我会很高兴。
运行时多态需要间接。A 类型的对象始终是 A 类型,没有其他类型。这就是语言中的类型。原因之一是编译器必须知道对象需要多少内存。如果编译器为 A 保留内存,那么可能更大的派生实例如何适合保留的内存?
但是指向 A 的指针(或引用)既可以指向不同的 A 对象,也可以指向从 A 派生的类的基本子对象。无论完整对象有多大,指针无论如何都可以指向对象的一部分,这不会影响指针本身的大小。
派生类的切片是如何发生的?
每当您将派生对象转换为基本类型时,就会发生切片。转换复制基类子对象。请注意,当您将派生值转换为对基的引用时,不会发生切片 - 除非您使用该引用来初始化基类型的对象。
推荐阅读
- java - 将来自 JSON 的多个属性附加到 thymeleaf 中的 Anchor 标记
- php - 如何将控制器中不存在的函数重定向到索引函数?
- java - 有人能告诉我我对 IntelliJ 做错了什么吗
- netcdf - 使用 NCO 连接全局层 netCDF 数据失败
- unity3d - 有没有办法让 Unity TextMeshPro 下拉选项的字体与列表中的其他字体不同?
- apache-spark - 如何用 Apache Spark 数据框中的前一个或下一个值替换 None 或 null?
- angular - CombineLatest,在所有 observables 完成后只执行一次
- jquery - 如何将 jquery、ajax 集成到 JSP & JSF 中
- html - 下拉菜单和输入不应该是透明的
- javascript - 如何在 JSON 中创建一个函数,该函数将更改位于数组内部的对象内部的属性