基类的指针数组;每次项目启动我都有不同的结果

Array of pointers of base class; every program launch I have different results

本文关键字:结果 启动 项目 数组 指针 基类      更新时间:2023-10-16

我有一项任务要创建四个类——一个基类、两个派生类和一个可以存储派生对象的动态数组。基类应该存储名称(一些字符串),派生类应该有其唯一的voice()函数。我的代码是:

#include <iostream>
class Pet
{
public:
    char* name_;
    virtual void voice(){}
};
class Dog : virtual public Pet
{
public:
    Dog(char* str)
    {
        name_ = new char[strlen(str)];
        for(int i=0; str[i] != 0; ++i)
        {
            name_[i] = str[i];
        }
    }
    virtual void voice()
    {
        std::cout<<"I'm a dog! My name is "<<this->name_<<std::endl;
    }
};
class Cat : virtual public Pet
{
public:
    Cat(char* str)
    {
        name_ = new char[strlen(str)];
        for(int i=0; str[i] != 0; ++i)
        {
            name_[i] = str[i];
        }
    }
    virtual void voice()
    {
        std::cout<<"I'm a cat! My name is "<<this->name_<<std::endl;
    }
};
class Pack
{
private:
    Pet** pack_;
    int num;
public:
    Pack()
    {
        pack_ = new Pet*[0];
        num = 0;
    }
    void add(Pet* a)
    {
        Pet** newpack = new Pet*[num+1];
        for (int i = 0; i<num; ++i)
            newpack[i] = pack_[i];
        newpack[num] = a;
        ++num;
        for (int i = 0; i<num; ++i)
            pack_[i] = newpack[i];
        delete [] newpack;
    }
    void voiceall()
    {
        for (int i=0; i<num; ++i)
            pack_[i]->voice();
    }
};
int main() {
    Pack pack;
    for (int i=0; i<6; ++i)
    {
        char* str;
        std::cin.getline(str, 100);
        if (i%2 == 0)
        {
            Dog* a = new Dog(str);
            pack.add(a);
        }
        else
        {
            Cat* a = new Cat(str);
            pack.add(a);
        }
    }
    pack.voiceall();
    return 0;
}

这段代码似乎有效,但令我惊讶的是,并不是每次启动它。使用相同输入的三分之一-一半的启动会导致错误(EXC_BAD_ACCESS),通常发生在pack_[i]->voice();Pack类的voiceall()函数中。我对这个从基派生的指针太陌生了,不明白哪里出了问题。

UPD:伙计们,我真的不能使用STL,因为我的老师教东西的方式很痛苦。

pack_ = new Pet*[0];

CCD_ 4指向大小为CCD_。

++num;

num递增到大于0的数字。

for (int i = 0; i<num; ++i)
        pack_[i] = newpack[i];

您对数组的访问超出了范围。这导致了不明确的行为。

要解决此问题,请不要访问超出其边界的数组。您可能打算分配一个大小为num的数组,并将pack_指向该数组。好吧,你确实分配了一个数组,但你永远不会更新pack_,所以它的大小永远不会改变,然后你会删除新的更大的数组。我建议使用std::vector来避免这样的错误(作为奖励,它也比你正在做的更高效)。

顺便说一下,您有许多内存泄漏。避免手动分配动态内存,使用std::stringstd::vector可以轻松修复它们。

一个直接的崩溃源是您没有为输入分配任何内存——您正在读取一个未初始化的指针。

更换

char* str;

带有

char str[100];

您的名称数组也有一个元素太小;使用

name_ = new char[strlen(str) + 1];
strcpy(name_, str);

add会立即删除需要存储所有元素的数组。
您还可以在旧数组的边界之外进行写入。

它应该更像这样:

void add(Pet* a)
{
    Pet** newpack = new Pet*[num+1];
    // Copy the old array to the new.
    for (int i = 0; i<num; ++i)
        newpack[i] = pack_[i];
    // Add the new element to the new array.
    newpack[num] = a;
    ++num;
    delete [] pack_;  // Delete the old array...
    pack_ = newpack;  // ... and use the new one instead.
}