7
class Base1
{
    private:
     int testInput; 
    public:
       Base1();
       virtual int GetRow(void) = 0;
 };

 Base1::Base1()
 {
   testInput = 0;
 }

class table : public Base1
{
   private:
    int row;    
   public:  
     table();
     virtual int GetRow(void);
};

table::table()
{   
  //Contructor
  row = 5;
}

int table::GetRow()
{
  return row;
}

int main ()
{
  Base1* pBase = new table[3];
  pBase[0].GetRow();
  pBase[1].GetRow();   //when i get to  this line, the compiler keep saying access
                           // violation.
  pBase[2].GetRow();

  return 0;
}

I'm trying to create an array of 3 table class. The requirement is I have to use Base object to do that.

Base1 * pBase = new table[3];  

look fine to me. But when I tried to access each table, the compiler said it's access violation. I don't know what wrong with this code. I'm using Visual Studio 2010 though.

4

4 回答 4

18

在 C++ 中,多态性和数组不会混合使用。

由于通常派生类的大小与基类的大小不同,因此多态性和指针算术不能很好地结合使用。由于数组访问涉及指针运算,因此诸如此类的表达式pBase[1] 无法按预期工作。

一种可能性是拥有一个指向对象的指针数组,甚至可能是智能指针来简化内存管理。但是不要忘记在Base1.

于 2012-12-05T07:52:24.933 回答
6

您收到错误是因为该数组是静态类型为Base1. 这意味着这一行:

pBase[1].GetRow();

Base1以字节为单位添加大小并将其pBase解释为另一个Base1对象的开头,但这实际上指向第一个table实例中间的某个地方。

如果你需要一个多态实例数组,你必须std::vector通过指针(或者最好是某种形式的智能指针)将它们存储在数组中(或者最好是在 a 中)。

于 2012-12-05T07:57:33.403 回答
4

阿格纽的反应很到位。让我再解释一下。通过扩充您的代码,我打印出一个Base1和一个table对象的大小以及三个table对象的地址,因为它们是由new操作员创建的:

A Base1 object is 8 bytes
A table object is 12 bytes
A table object is being constructed at 0x002977C0
A table object is being constructed at 0x002977CC
A table object is being constructed at 0x002977D8

如您所见,这些对象在内存中彼此间隔 12 个字节。

现在,让我们打印出 pBase[0]、pBase[1] 和 pBase[2] 给出的地址:

pBase[0] is at 0x002977C0
pBase[1] is at 0x002977C8
pBase[2] is at 0x002977D0

现在看看会发生什么:我们返回的指针相隔 8 个字节。这是因为指针运算是在一个指针上完成的,它的类型是Base1并且因为Base1是 8 字节长,编译器所做的就是翻译pBase[n]pBase + (n * sizeof(Base1)).

现在您应该能够准确理解第一个 GetRow()工作的原因以及第二个崩溃的原因。

于 2012-12-05T08:07:53.407 回答
2

您需要创建(使用new)所有这些数组元素,这样做:

for(int i = 0; i < 3; ++i)
    pBase[i] = new table();
于 2012-12-05T07:56:18.130 回答