1️⃣ 继承

  • 继承的最重要性质就是:可以通过“指向base class objects”的 pointersreferences,来操作 derived class objects。如此的pointersreferences,我们说其行为是多态的。

2️⃣ 问题

  • C++允许你通过base classpointersreferences来操作“derived class objects“所形成的数组。

3️⃣ 例子

1
2
class BST { ... };
class BalanceBST : BST { ... };
1
2
3
4
5
6
void printBSTArray(ostream& s, const BST array[], int numElements)
{
for (int i = O; i < numElements; ++i) {
s << array[i]; // 假设 BST objects 有一个 operator<< 可用。
}
}

🔹 当给这个函数传递一个由 BST 对象组成的数组,代码不会产生问题。

1
2
3
BST BSTArray[10];
...
printBSTArray(cout , BSTArray, 10);

🔸 当给这个函数传递一个由 BalanceBST 对象组成的数组,编译器不会发生报错,但是代码并不是我们想象的那样。

1
2
3
BalnaceBST bBSTArray[10];
...
printBSTArray(cout, bBSTArray, 10);

4️⃣ 解析

  • array[i] 等价于*(array+i)array是个指针,指向数组起始处。
  • array所指内存和array+i所指内存两者相距多远?答案是i*sizeof(数组中的对象)。因为array[0]array[i]之间有i个对象。
  • 为了让编译器所产生的代码能够正确走访整个数组,编译器必须决定数组中的对象大小。由于参数array被声明成“类型为BST”的数组吗?所以数组中的每个元素必然都是BST对象,所以arrayarray+i之间的距离一定是i*sizeof(BST)
  • 但如果交给printBSTArray函数一个由BalancedBST对象组成的数组,编译器就会被误导。这种情况下它仍假设数组中每一元素的大小是BST的大小,但其实每一元素的大小是BalancedBST的大小。由于 derived classes通常比base classes大,因此,我们可以合理地预期一个BalancedBSTobject比一个BSTobject大。如果是这样,编译器为printBSTArray函数所产生的指针算术表达式,对于 BalancedBST objects所组成的数组而言就是错误的。