Item3 不要对数组使用多态

类继承的最重要的特性是你可以通过基类指针或引用来操作派生类。这样的指针或引用具有行为的多态性,就好像它们同时具有多种形态。C++允许你通过基类指针和引用来操作派生类数组。不过这根本就不是一个特性,因为这样的代码几乎从不如你所愿地那样运行。

现在我们定义一个基类和派生类:sizeof(CBase) = 4,sizeof(CDerived) = 8;

class CBase{
public:
    int x;
public:
    CBase(int a) : x(a){}
};
class CDerived : public CBase{
public:
    int y;
public:
    CDerived(int a, int b) : CBase(a), y(b){}
};

一个打印基类对象数据的函数:

void DispBaseArr(const CBase arrObj[], int iCnt)
{
    for(int i = 0; i < iCnt; i++){
        cout << arrObj[i].x << endl;
    }
}

当我们传入符合要求的参数【基类对象数组】,输出就能达到我们预期的效果:1,2,3,4,5

CBase arrBase[5] = {1, 2, 3, 4, 5};
DispBaseArr(arrBase, sizeof(arrBase)/sizeof(CBase));

当我们传入不符合要求的参数【派生对象的数组】,输出的序列将会是这样的:1,10,2,20,3

CDerived arrDerived[5] = {CDerived(1,10), CDerived(2,20), CDerived(3,30), CDerived(4,40), CDerived(5,50)};
DispBaseArr(arrDerived, sizeof(arrDerived)/sizeof(CDerived));

如果你把一个含有 CDerived 对象的数组变量传递给 DispBaseArr函数,你的编译器就会犯错误。在这种情况下,编译器原先已经假设数组中元素与 CBase 对象的大小一致,但是现在数组中每一个对象大小却与 CDerived 一致。派生类的长度通常都比基类要长。我们料想 CDerived 对象长度的比 CBase长。如果如此的话,DispBaseArr函数生成的指针算法将是错误的, 没有人知道如果用 CDerived 数组来执行 DispBaseArr函数将会发生什么样的后果。不论是什么后果都是令人不愉快的。

完整示例代码如下:

#include<iostream>
#include<iomanip>
#include<string>
using namespace std;

//不要对数组使用多态
class CBase{
public:
	int x;
public:
	CBase(int a) : x(a){}
};
class CDerived : public CBase{
public:
	int y;
public:
	CDerived(int a, int b) : CBase(a), y(b){}
};

void DispBaseArr(const CBase arrObj[], int iCnt)
{
	for(int i = 0; i < iCnt; i++){
		cout << arrObj[i].x << endl;
	}
}
void main()
{
	CBase arrBase[5] = {1, 2, 3, 4, 5};
	DispBaseArr(arrBase, sizeof(arrBase)/sizeof(CBase));
	CDerived arrDerived[5] = {CDerived(1,10), CDerived(2,20), CDerived(3,30), CDerived(4,40), CDerived(5,50)};
	DispBaseArr(arrDerived, sizeof(arrDerived)/sizeof(CDerived));
}

猜你喜欢

转载自blog.csdn.net/CherishPrecious/article/details/81707322
今日推荐