1

コピー可能にしたくないクラスがいくつかあります。これらのクラスのいくつかには、ポインター データ メンバーがあります。これらのクラスをコピーできないようにするために、次のクラス テンプレートを個人的に継承します。

template <class T>
class Uncopyable
{
  protected:
    Uncopyable() {}
    virtual ~Uncopyable() {}
  private:
    Uncopyable(const Uncopyable &);
    T & operator=(const T&);
};

私は次のように使用しました:

class Entity : private Uncopyable<Entity> { }

これは問題なく動作しますが、-Weffc++ でコンパイルすると、次の警告が引き続き表示されます。

class Entity has pointer data members
but does not override Entity(const Entity&)
or operator=(const Entity&)

なぜまだこの警告が表示されるのですか?

4

1 に答える 1

8

C++ 言う

ユーザーによって宣言されていない場合、コピー代入演算子はクラスに対して暗黙的に宣言されるため、基本クラスのコピー代入演算子は、派生クラスのコピー代入演算子によって常に隠されます (13.5.3)。派生クラスのコピー代入演算子のパラメーター型である可能性のあるパラメーターの型を持つ代入演算子を基底クラスから取り込む using 宣言 (7.3.3) は、コピー代入演算子の明示的な宣言とは見なされず、派生クラスのコピー代入演算子の暗黙の宣言を抑制しません。using 宣言によって導入された演算子は、派生クラスで暗黙的に宣言されたコピー代入演算子によって隠されます。

コードのバグはoperator=、派生クラスの型の参照を受け入れるように基本クラスが宣言していることです。それは、ベースの operator= の暗黙的な公開宣言を妨げません。したがって、派生クラス基本クラスは引き続き割り当て可能です。コピー不可能なクラスを非テンプレートに変更してみてください。これで十分です。

class Uncopyable
{
  protected:
    Uncopyable() {}
    virtual ~Uncopyable() {}
  private:
    Uncopyable(const Uncopyable &);
    Uncopyable & operator=(const Uncopyable&);
};

そのコードで私が考え出したもう 1 つのこと: Uncopyable virtual のデストラクタを作成しないでください。その理由は、誰も (派生クラス自体を除いて) Uncopyable へのポインターで delete を呼び出すことができないからです (1: デストラクタは保護されているため、2: 非公開で派生するため)。したがって、派生クラスのデストラクタを暗黙的に仮想化することは Uncopyable の関心事ではありません。派生クラスに仮想デストラクタが必要な場合は、代わりにそこに仮想を配置し、Uncopyables のデストラクタを非仮想のままにします。

于 2008-12-27T10:29:00.670 に答える