使用指向基类的指针作为数组参数

时间:2010-01-26 21:02:40

标签: c++ class inheritance pointers polymorphism

我有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异常。

我有两个问题:

  1. Test和Test2中的函数参数有什么区别? (在我将Base转换为纯抽象类之后,Test2不会编译)。
  2. 和更重要的问题

    1. 我如何防止该异常,以及如何将派生类数组传递给假定获取基类数组的函数。 (我无法在编译时告诉哪个派生类我将通过该功能)
    2. p.s - 请不要告诉我阅读迈耶斯的书,这就是我提出这个问题的确切原因。 :)

      由于

4 个答案:

答案 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?