![]() ![]() |
|
MoreEffectiveC++:不使用多态性数组 | |
作者:佚名 文章来源:不详 点击数 更新时间:2008/3/1 11:02:39 文章录入:杜斌 责任编辑:杜斌 | |
|
|
假设你有一个类BST(比如是搜索树对象)和继承自BST类的派生类BalancedBST: class BST { ... }; class BalancedBST: public BST { ... }; 在一个真实的程序里,这样的类应该是模板类,但是在这个例子里并不重要,加上模板只会使得代码更难阅读。为了便于讨论,我们假设BST和BalancedBST只包含int类型数据。 有这样一个函数,它能打印出BST类数组中每一个BST对象的内容: void printBSTArray(ostream& s, const BST array[], int numElements) { for (int i = 0; i < numElements; ) { s << array[i]; //假设BST类 } //重载了操作符<< } 当你传递给该函数一个含有BST对象的数组变量时,它能够正常运行: BST BSTArray[10]; ... printBSTArray(cout, BSTArray, 10); // 运行正常 然而,请考虑一下,当你把含有BalancedBST对象的数组变量传递给printBSTArray函数时,会产生什么样的后果: BalancedBST bBSTArray[10]; ... printBSTArray(cout, bBSTArray, 10); // 还会运行正常么? 你的编译器将会毫无警告地编译这个函数,但是再看一下这个函数的循环代码: for (int i = 0; i < numElements; ) { s << array[i]; } 这里的array[I]只是一个指针算法的缩写:它所代表的是*(array)。我们知道array是一个指向数组起始地址的指针,但是array中各元素内存地址与数组的起始地址的间隔究竟有多大呢?它们的间隔是i*sizeof(一个在数组里的对象),因为在array数组[0]到[I]间有I个对象。编译器为了建立正确遍历数组的执行代码,它必须能够确定数组中对象的大小,这对编译器来说是很容易做到的。参数array被声明为BST类型,所以array数组中每一个元素都是BST类型,因此每个元素与数组起始地址的间隔是be i*sizeof(BST)。 至少你的编译器是这么认为的。但是如果你把一个含有BalancedBST对象的数组变量传递给printBSTArray函数,你的编译器就会犯错误。在这种情况下,编译器原先已经假设数组中元素与BST对象的大小一致,但是现在数组中每一个对象大小却与BalancedBST一致。派生类的长度通常都比基类要长。我们料想BalancedBST对象长度的比BST长。如果如此的话,printBSTArray函数生成的指针算法将是错误的,没有人知道如果用BalancedBST数组来执行printBSTArray函数将会发生什么样的后果。不论是什么后果都是令人不愉快的。 |
|
![]() ![]() |