当前位置:七道奇文章资讯编程技术VC/C++编程
日期:2011-03-22 13:55:00  来源:本站整理

<b>More Effective C++:不利用多态性数组</b>[VC/C++编程]

赞助商链接



  本文“<b>More Effective C++:不利用多态性数组</b>[VC/C++编程]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

类担当的最重要的特点是你可以通过基类指针或引用来操作派生类.这样的指针或引用具有行为的多态性,就仿佛它们同时具有多种形状.C++答应你通过基类指针和引用来操作派生类数组.不过这根本就不是一个特点,因为这样的代码根本无法如你所愿地那样运行.

假定你有一个类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函数将会发生什么样的后果.不管是什么后果都是令人不高兴的.

假如你试图删除一个含有派生类对象的数组,将会发生各种各样的问题.以下是一种你大概的不精确的做法.

//删除一个数组, 但是首先记录一个删除信息
void deleteArray(ostream& logStream, BST array[])
{
 logStream << "Deleting array at address "
 << static_cast(array) << '
';
 delete [] array;
}
BalancedBST *balTreeArray = // 成立一个BalancedBST对象数组
new BalancedBST[50];
...
deleteArray(cout, balTreeArray); // 记录这个删除操作

这里面也遮盖着你看不到的指针算法.当一个数组被删除时,每一个数组元素的析构函数也会被调用.当编译器碰到这样的代码:

delete [] array;

它必定象这样生成代码:

// 以与构造次序相反的次序来
// 解构array数组里的对象
for ( int i = 数组元素的个数 1; i >= 0;--i)
{
 array[i].BST::~BST(); // 调用 array[i]的
} // 析构函数

因为你所编写的循环语句根本不能正运行,所以当编译成可履行代码后,也不大概正常运行.语言标准中说通过一个基类指针来删除一个含有派生类对象的数组,后果将是不肯定的.这实际意味着履行这样的代码必定不会有什么好后果.多态和指针算法不能混合在一同来用,所以数组与多态也不能用在一同.

值得注意的是假如你不从一个具体类(concrete classes)(比方BST)派生出另一个具体类(比方BalancedBST),那么你就不太大概犯这种利用多态性数组的错误.正如我在背面将介绍的条款33所注释的,不从具体类派生出具体类有很多好处.


  以上是“<b>More Effective C++:不利用多态性数组</b>[VC/C++编程]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • <b>hosts是什么 hosts文件在什么位置 若何改正hosts</b>
  • <b>在 Windows 8 中手动安装语言包</b>
  • <b>五个常见 PHP数据库问题</b>
  • Windows中Alt键的12个高效快速的利用本领介绍
  • <b>MySQL ORDER BY 的实现解析</b>
  • <b>详解MySQL存储历程参数有三种范例(in、out、inout)</b>
  • <b>Win8系统恢复出来经典的开始菜单的办法</b>
  • <b>Win8系统花屏怎么办 Win8系统花屏的办理办法</b>
  • <b>Windows 7系统下无线网卡安装</b>
  • <b>为什么 Linux不需求碎片整理</b>
  • <b>Windows 8中删除账户的几种办法(图)</b>
  • <b>教你如安在win7下配置路由器</b>
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .