【More Effective C++ 条款3】最好不要以多态方式处理数组

1.在数组与多态混用的情况下,数组元素的访问会出现不可预期的结果(因为数组元素的访问会使用到下标运算)

将一个子类对象数组传递给一个父类对象数组声明的函数,编译器会允许这个行为,但是由于子类对象和父类对象的内存结构不同,会导致运行结果异常,因为在这种情况下,编译器仍然假设每一个元素的大小是父类对象元素的大小,但此时实际上每一个元素的大小是子类对象元素的大小

复制代码
#include<bits/stdc++.h>
using namespace std;

class BST
{
public:
    char c;
};

class balancedBST:public BST//公有继承
{
public:
    int x;
};

void printBSTArray(ostream& s,const BST array[],int numElements)//打印基类数组,注意数组的类型为基类!
{
    for(int i=0;i<numElements;i++)
        s<<array[i].c;
    s<<endl;
}

int main()
{
    BST array[3];
    for(int i=0;i<3;i++)
        array[i].c='A'+i;

    printBSTArray(cout,array,3);//传递进入函数的是基类数组,打印正常

    balancedBST barray[3];
    for(int i=0;i<3;i++)
    {
        barray[i].x=i+1;
        barray[i].c='a'+i;
    }

    printBSTArray(cout,barray,3);//传递进入函数的是子类数组,打印异常!
    /*
    异常的原因:
    因为函数定义的时候该对象的数组定义的是为基类类型,所以编译器在后续的操作中,
    无论传入函数的是基类对象数组还是子类对象数组,都将视为基类对象数组
    而基类对象的内存结构和子类对象的内存结构是不一样的
    这样,通过下标访问到的东西,其实不是你想访问的东西

    array[i] *(array+i)
    array[0]和array[i] 之间相隔 i*sizeof(BST)

    函数是按照i*sizeof(BST)算的,而如果你传入的是基类对象数组,也按照这样算的话,肯定是访问不到你想要的东西的
    */


}

/*
运行结果:
ABC
ai
*/
复制代码

2.在多态与数组混用的情况下,数组元素的删除也存在问题,会使用到没有定义的操作(通过基类指针来删除子类对象数组的行为在C++中是未定义的!)

复制代码
#include<bits/stdc++.h>
using namespace std;

class BST
{
public:
    char c;
};

class balancedBST:public BST//公有继承
{
public:
    int x;
};

void deleteArray(ostream& logStream,BST array[])
{
    logStream<<"Deleting array at adress: "<<static_cast<void*>(array)<<endl;
    delete [] array;//该操作的底层其实使用了下标,如果传入的是子类对象数组,那么通过基类指针来删除子类对象数组的行为在C++中是未定义的!
}

int main()
{
    BST *array =new BST[3];
    balancedBST *barray =new balancedBST[3];

    deleteArray(cout,array);//传入的是基类对象

    deleteArray(cout,barray);//传入的是子类对象,存在问题,底层使用了未定义的操作
}
复制代码


总结:那么如何避免上述两种问题呢?

第一个办法是避免采用多态方式来处理数组

第二个方法是避免让一共具体类继承自另外一个具体类



posted @   西*风  阅读(262)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示