如何在C++中创建一个具有多态性的数组?

Le *_*anh 7 c++ arrays polymorphism virtual inheritance

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;
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试创建一个3表类的数组.要求是我必须使用Base对象来做到这一点.

Base1 * pBase = new table[3];  
Run Code Online (Sandbox Code Playgroud)

看起来很好.但是当我试图访问每个表时,编译器说它是访问冲突.我不知道这段代码有什么问题.我正在使用Visual Studio 2010.

NPE*_*NPE 14

在C++中,多态和数组不会混合.

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

一种可能性是拥有指向对象的指针数组,甚至可能是智能指针以简化内存管理.但是不要忘记在中定义一个虚拟析构函数Base1.


Rei*_*ica 6

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

pBase[1].GetRow();
Run Code Online (Sandbox Code Playgroud)

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

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


Nik*_*lis 5

阿格纽的回应非常到位。让我再解释一下。Base1通过扩充您的代码,我打印出 a和 a对象的大小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
Run Code Online (Sandbox Code Playgroud)

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

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

pBase[0] is at 0x002977C0
pBase[1] is at 0x002977C8
pBase[2] is at 0x002977D0
Run Code Online (Sandbox Code Playgroud)

现在看看会发生什么:我们返回的指针间隔 8 个字节。Base1这是因为指针算术是在类型为 8 字节长的指针上完成的,Base1编译器所做的就是将其转换pBase[n]pBase + (n * sizeof(Base1)).

现在您应该能够准确理解为什么第一个 GetRow()有效以及为什么在第二个上崩溃。