3

スコット・マイヤーズは彼の著書「Effective C ++」で、次のように述べています。

コンパイラによって自動的に提供される機能を禁止するには、対応するメンバー関数をprivateとして宣言し、実装を指定しません。その後、誰かが誤って呼び出した場合、リンク時にエラーが発生します。

スコットが説明しようとしていたことを達成するためのサンプルプログラムを書こうとしました。メンバー関数が宣言されpublic、実装が与えられていない場合でも、同じことを達成できました。私の場合、別のオブジェクトからオブジェクトを初期化しようとしたときにもリンクエラーが発生しました。だから私はスコットが宣言されるメンバー関数の必要性を強調している理由を理解していませんprivateか?

私のサンプルプログラムは以下のとおりです。

#include <iostream>

using namespace std;

class Unique
{
   private:
      int num;

   public:
      Unique(int x)
      {
         num  = x;
      }
      Unique(const Unique &obj);

      Unique& operator =(const Unique &obj);

      void disp(void)
      {
         cout << "num = " << num << "\n";
      }
};

int main()
{
   Unique ob1(3);
   Unique ob2(ob1);

   ob1.disp();
   ob2.disp();

   return 0;
}

次のリンクエラーが発生します:

/tmp/ccXfqSqE.o(.text+0x135):関数main': : undefined reference toUnique :: Unique(Unique const&)'collect2:ldが1つの終了ステータスを返しました

4

3 に答える 3

10

コンパイラエラーは、リンクエラーよりも明確で、より早く発生します(これは、多くのソースファイルからコンパイルされた大きなプロジェクトでより顕著になります)。また、ほとんどの場合、読みやすくなっています。メンバーをプライベートとして宣言するとコンパイルエラーが発生するため、メンバーを未定義のままにして許可しないよりも優先されます。

Baptisteが指摘しているように、C ++ 11には、コンパイラーによって生成されたメンバーを禁止するために使用できるさらに優れたdeleteキーワードがあります。

class A
{
     A(constA&) = delete; // copy construction is not allowed
};
于 2011-11-19T10:13:56.800 に答える
2

スコットは、誰かがコンストラクターを呼び出してリンク時にエラーが発生するのを防ごうとしています。これはまさにあなたが遭遇しているケースです。リンク時よりもコンパイル時に問題を見つける方が安価です。

ちなみに、C ++ 11では、コンパイラーが関数を生成しないようにする公式の方法があることがわかっています。

class Unique{
public:
    Unique() = delete;
}
于 2011-11-19T10:20:10.483 に答える
2

それらをプライベートとして宣言すると、関数が実際に定義されているかどうかに関係なく、誰かがそれらを呼び出そうとしていることを検出するとすぐにコンパイラーは停止します(許可されていないため)。

それらをパブリックと宣言することにより、エラーが発生するまでリンカーステージまで待機する必要があります。これは、正当な呼び出しであるはずですが、定義が欠落しているためです。

于 2011-11-19T10:15:25.010 に答える