我有2个班级:
class Base
{
public:
virtual int Foo(int n);
virtual void Goo() = 0;
virtual ~Base() ;
};
class Derived : public Base
{
public:
int Add4Bytes;
void Goo();
int Foo(int n);
};
int Test(Base* b)
{
for (int i=0;i<5;++i)
{
b->Foo(i);
++b;
}
return 0;
}
void Test2(Base arr[])
{
for (int i=0;i<5;++i)
{
arr[i].Foo(i);
}
}
void main
{
Base* b = new Derived[5];
Test(b);
}
所以,当我调用Test时,在第二个循环之后会出现内存viloation异常。
我有两个问题:
和更重要的问题
p.s - 请不要告诉我阅读迈耶斯的书,这就是我提出这个问题的确切原因。 :)
由于
答案 0 :(得分:4)
参数类型之间没有区别,数组参数被调整为函数声明中的指针。
虽然您可以将指向Derived
的指针转换为指向Base
的指针,但您无法将Derived
数组视为Base
的数组,它们是不相关的类型。这是因为在Derived
数组中,Base
类是Derived
的子对象,而不是Base
数组的一部分。当您执行指针算法时,就好像它是Base
数组的一部分,您将获得未定义的行为,您可能会构造一个Base
指针,该指针不会指向{{1}的开头。 1}}对象。
答案 1 :(得分:3)
由于对象切片,数组不能很好地处理多态类型作为内容。数组元素具有固定大小,如果派生对象的大小大于基数,则基础对象数组实际上不能保存派生对象。
即使函数参数可能会衰减为指针,对该指针执行的指针算法也将基于数组类型的元素大小。
要处理多态类型的数组,您需要添加另一级别的间接并处理指向对象的数组(或其他容器)。
在我将Base转换为纯抽象类
后,Test2无法编译
您不能拥有抽象类型的数组,因为您不能拥有抽象类型的实例(只有指针或对它们的引用)。
答案 2 :(得分:1)
您的Test
函数会逐步查看Base
个对象,即步幅为sizeof( Base )
,但需要sizeof( Derived )
。您可能希望将其声明为:
int Test( const std::vector<Base*>& );
答案 3 :(得分:0)
您可以在C ++ FAQ Lite问题21.4中找到有关基类和派生类数组的其他信息:Is an array of Derived
a kind-of array of Base
?