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;
}

3 つのテーブル クラスの配列を作成しようとしています。そのためには Base オブジェクトを使用する必要があります。

Base1 * pBase = new table[3];  

私には元気に見えます。しかし、各テーブルにアクセスしようとすると、コンパイラはアクセス違反だと言いました。このコードの何が問題なのかわかりません。ただし、Visual Studio 2010 を使用しています。

4

4 に答える 4

18

C++ では、ポリモーフィズムと配列は混在しません。

一般に、派生クラスのサイズは基本クラスのサイズとは異なるため、ポリモーフィズムとポインター演算はうまく連携しません。配列アクセスにはポインター演算が含まれるため、 などの式pBase[1] は期待どおりに機能しません。

1 つの可能性は、オブジェクトへのポインターの配列を持つことです。おそらく、メモリ管理を簡素化するためのスマート ポインターでさえあります。ただし、 で仮想デストラクタを定義することを忘れないでくださいBase1

于 2012-12-05T07:52:24.933 に答える
6

配列が に静的に型指定されているため、エラーが発生していますBase1。つまり、この行は次のとおりです。

pBase[1].GetRow();

のサイズをBase1バイト単位で追加し、pBaseこれを別のオブジェクトの始まりとして解釈しますが、これは実際には最初のインスタンスBase1の途中のどこかを指しています。table

ポリモーフィック インスタンスの配列が必要な場合は、それらstd::vectorをポインター (またはできればスマート ポインターの何らかの形式) を介して配列 (またはできれば ) に格納する必要があります。

于 2012-12-05T07:57:33.403 に答える
4

アグニューの反応は的を射ていた。もう少し説明しましょう。コードを拡張することにより、オペレーターによって作成された 3 つのオブジェクトのアドレスだけでなく、aBase1と aオブジェクトのサイズも出力します。tabletablenew

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、コンパイラーが に変換pBase[n]するのは 8 バイトの長さであるためpBase + (n * sizeof(Base1))です。

これで、最初の GetRow()方法が機能する理由と、2 番目の方法でクラッシュする理由を正確に理解できるはずです。

于 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 に答える