【问题标题】:Using pointer to base class as array parameter使用指向基类的指针作为数组参数
【发布时间】:2011-01-09 16:48:44
【问题描述】:

我有 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 时,在第二个循环之后会出现内存违规异常。

我有两个问题:

  1. Test 和 Test2 中的函数参数有什么区别? (在我将 Base 转换为纯抽象类后,Test2 无法编译)。

还有更重要的问题

  1. 如何防止该异常,以及如何将派生类数组传递给假设获取基类数组的函数。 (我无法在编译时告诉我将传递哪个派生类)

p.s - 请不要告诉我读 Meyers 的书,这就是我问这个问题的确切原因。 :)

谢谢

【问题讨论】:

    标签: c++ class inheritance pointers polymorphism


    【解决方案1】:

    参数类型没有区别,数组参数在函数声明中调整为指针。

    虽然您可以将指向Derived 的指针转换为指向Base 的指针,但不能将Derived 的数组视为Base 的数组,它们不是相关类型。这是因为在Derived 的数组中,Base 类是Derived 的子对象,而不是Base 数组的一部分。当您执行指针运算时,就好像它是 Base 数组的一部分一样,您会得到未定义的行为,您可能会构造一个 Base 指针,它并不完全指向 Base 对象的开头。

    【讨论】:

      【解决方案2】:

      由于对象切片,数组不能很好地处理多态类型作为内容。数组元素具有固定大小,如果派生对象的大小大于基对象,则基对象数组实际上无法容纳派生对象。

      即使函数参数可能衰减为指针,对指针进行的指针运算仍将基于数组类型的元素大小。

      要处理多态类型的数组,您需要添加另一个间接级别并处理指向对象的指针数组(或其他容器)。

      将 Base 转换为纯抽象类后,Test2 无法编译

      你不能有抽象类型的数组,因为你不能有抽象类型的实例(只有指针或对它们的引用)。

      【讨论】:

        【解决方案3】:

        您的Test 函数遍历Base 对象数组,即步幅为sizeof( Base ),而它必须为sizeof( Derived )。您可能希望将其声明为:

        int Test( const std::vector&lt;Base*&gt;&amp; );

        【讨论】:

          【解决方案4】:

          您可以在 C++ FAQ Lite 问题 21.4 中找到有关基类和派生类数组的更多信息:Is an array of Derived a kind-of array of Base?

          【讨论】:

            猜你喜欢
            • 2015-06-17
            • 1970-01-01
            • 2016-03-19
            • 2023-03-22
            • 1970-01-01
            • 2020-09-06
            • 2011-05-10
            • 2021-12-10
            • 1970-01-01
            相关资源
            最近更新 更多