3

私は C++ Primer Plus の本の第 13 章まで読んでいました。動的メモリ割り当て、コピー コンストラクター、および = 演算子のオーバーロードで継承を使用する例がありました。

呼び出される基本クラスには、コンストラクターbaseDMAで使用するプライベート char へのポインターがあります。new

class baseDMA
{
private:
   char * label;

...
};

baseDMA::baseDMA(const char * l)
{
    label = new char[std::strlen(l) + 1];
    std::strcpy(label, l);
    ...
}

=演算子をオーバーロードするときはlabel pointer、新しい値に割り当て、新しい場所を指すため、を削除します。それを削除しないと、ポインターが別のものを指し、このポインターが指していた古い場所は削除されず、現在は何も指されていないため、後で削除することはできません (これは著者が別の章でそれを説明する方法です)

これは=、基本クラスのオーバーロードされた演算子です。

baseDMA & baseDMA::operator=(const baseDMA & rs)
{
   if (this == &rs)
      return *this;
   delete [] label;
   label = new char[std::strlen(rs.label) + 1];
   std::strcpy(label, rs.label);
   return *this;
}

次に、作成者は hasDMA と呼ばれる派生クラスを定義します。これは、次のように定義するnewforも使用します。pointer-to-char

class hasDMA :public baseDMA
{
private:
    char * style;
    ...
};

hasDMA::hasDMA(const char * s, const char * l)
: baseDMA(l)
{
    style = new char[std::strlen(s) + 1];
    std::strcpy(style, s);
}

ここで少し混乱するのは、作成者が派生クラスの演算子をオーバーロードするとき、基本クラスから行ったように、新しい値を与える前=にそうしないように見えることです。これは、作成者が派生クラスのオーバーロードされた演算子を実行した方法です。delete [] stylelabel=

hasDMA & hasDMA::operator=(const hasDMA & hs)
{
    if (this == &hs)
       return *this;
    baseDMA::operator=(hs); // copy base portion
    //no delete [] style
    style = new char[std::strlen(hs.style) + 1];
    std::strcpy(style, hs.style);
    return *this;
} 

新しい値を割り当てる前に基底クラスから がstyle指すメモリを解放したのと同じように、 が指すメモリを解放しない理由は何ですか?label

前もって感謝します

4

1 に答える 1

6

理由は作者のミスです。これは、自分の記憶を管理してはならない方法の優れた例です。彼はstd::vector自分の記憶を管理するために使用する必要があります。彼はそうしませんでした。その結果、彼のコードは非常に間違っていました。彼を真似た場合、あなたのコードはまさにそのようになります。

さらに、彼は非常に時代遅れの自己割り当てチェックを使用しており、もはやイディオムではなく、コピー アンド スワップも使用していません。

要するに、新しい本を入手してください。これはすべて悪いです。

于 2013-02-23T19:06:09.323 に答える