我有一个创建四个类的任务 - 一个基类,两个派生类和一个可以存储派生对象的动态数组。基类应存储名称(某些字符串),派生应具有其唯一的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),通常在行voiceall()
中的Pack
类pack_[i]->voice();
函数中。我在这个基础派生指针的东西上太新了,无法理解什么是错的。
UPD:伙计们,我不能真正使用STL,因为我的老师有非常痛苦的教学方式。
答案 0 :(得分:1)
pack_ = new Pet*[0];
pack
指向大小为0
的数组。
++num;
您将num
增加到大于0
的数字。
for (int i = 0; i<num; ++i)
pack_[i] = newpack[i];
您可以访问数组越界。这导致了不确定的行为。
要解决这个问题,请不要使用它的界限来访问阵列。您可能打算为此分配一个大小为num
且指向pack_
的数组。好吧,你确实分配了一个数组,但你永远不会更新pack_
所以它的大小永远不会改变,你以后会删除新的更大的数组。我建议使用std::vector
来避免这样的错误(作为奖励,它也比你正在做的更有效)。
作为旁注,你有很多内存泄漏。避免手动分配动态内存,并使用std::string
和std::vector
轻松修复它们。
答案 1 :(得分:0)
即时崩溃源是您没有为输入分配任何内存 - 您正在读取未初始化的指针。
替换
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.
}