2

実装 (コンパイラ) がコピー コンストラクターとコピー代入演算子を提供しない状況について、少し混乱しています。

  1. クラスでコピーctorおよび/またはコピー代入演算子を宣言するとき。
  2. プライベートコピーctorおよび/またはコピー代入演算子を持つクラスから派生すると言う人もいます。

私は2番目の状況について少し混乱しています.2番目の状況はまさにそうです.
a) 実装では宣言されないため、コンパイル時にエラーが発生します。
または
b) 実装はそれらを宣言および定義しますが、コンパイラ定義の実装が基本クラスのメソッドを見つけようとすると、コンパイル時エラーが発生します。

私は昨日インタビューを受けました、私はその(b)が起こっていると言いましたが、インタビュアーは同意しません、彼は(a)と言いました。

Microsoft C/C++ 14.00 と gcc 4.4.5 の両方で次のコードをコンパイルしようとしました。

struct A
{
private:
  A& operator = ( const A& );
};

struct B : A
{
};


int main()
{
  B b1;
  B b2;
  b1 = b2;

  return 0;
}

Microsoft コンパイラの出力

ctor01.cpp(9) : error C2248: 'A::operator =' : cannot access private member declared in class 'A'
ctor01.cpp(4) : see declaration of 'A::operator ='
ctor01.cpp(2) : see declaration of 'A'
This diagnostic occurred in the compiler generated function 'B &B::operator =(const B &)'

gcc コンパイラ出力

Ctor01.cpp: In member function ‘B& B::operator=(const B&)’:
Ctor01.cpp:4: error: ‘A& A::operator=(const A&)’ is private
Ctor01.cpp:8: error: within this context
Ctor01.cpp: In function ‘int main()’:
Ctor01.cpp:15: note: synthesized method ‘B& B::operator=(const B&)’ first required here 

したがって、実装はそれを宣言して定義すると思いますが、コンパイラ定義の実装が基本クラスのメソッドを見つけようとすると、コンパイル時エラーが発生します。私が間違っている場合は修正してください。

4

6 に答える 6

7

コピーコンストラクターに関して、これは標準が言うことです (12.8/7) :

コピー コンストラクターが暗黙的に定義されているクラスが次の場合、プログラムは不正な形式です 。

  • アクセスできないかあいまいなコピー コンストラクターを持つクラス型 (またはその配列) の非静的データ メンバー、または
  • アクセスできないかあいまいなコピー コンストラクターを持つ基本クラス

コピー代入演算子について (12.8/12) :

コピー代入演算子が暗黙的に定義されているクラスが次の場合、プログラムは不正な形式です。

  • const 型の非静的データ メンバー、または
  • 参照型の非静的データ メンバー、または
  • アクセスできないコピー代入演算子を持つクラス型 (またはその配列) の非静的データ メンバー、または
  • アクセスできないコピー代入演算子を持つ基本クラス。

コンパイラがエラーを報告する方法、または実際にエラーが発生する方法は私の観点からはほとんど無関係です。

ただし、答え (b) の方がおそらくより正しいと思います。基本クラスのコピー代入が宣言されており、アクセスできません。派生クラスには、暗黙的に宣言されたコピー割り当てがあり、使用されている場合はコンパイラが定義 しようとするため、プログラムの形式が正しくありません。

于 2010-12-02T18:03:23.147 に答える
3

クラスには、ユーザーが宣言したバージョンがない場合、暗黙的に宣言されたコピー コンストラクターとコピー代入演算子があります。これは常に起こります。

簡単に言えば、実装は、実際に使用される場合にのみこれらを暗黙的に定義します。実装がそれらを定義しようとしたときに、暗黙的な定義が不適切な場合 (たとえば、コピー代入の場合、クラスに参照メンバーまたは const メンバーが含まれているか、コピー コンストラクターの場合、ベースまたはメンバーにプライベート コピー コンストラクターがある場合)、プログラムは不正です。

暗黙的に宣言されたコピー コンストラクターと、暗黙的に定義できないコピー代入演算子を持つクラスがプログラムに含まれている場合でも、プログラムは、それらを使用または使用することによって実際に定義されない限り、有効である可能性があります。

于 2010-12-02T18:06:20.133 に答える
2

あなたのケース(b)はより正確です。

C++03標準12.8p10

クラス定義でコピー代入演算子が明示的に宣言されていない場合は、暗黙的に宣言されます。

そして12.8p12

暗黙的に宣言されたコピー代入演算子は、そのクラス型のオブジェクトにそのクラス型の値またはそのクラス型から派生したクラス型の値が割り当てられたときに暗黙的に定義されます。コピー代入演算子が暗黙的に定義されているクラスが次の場合、プログラムの形式は正しくありません。

  • タイプの非静的データメンバーconst、または
  • 参照型の非静的データメンバー、または
  • アクセスできないコピー代入演算子を持つクラスタイプ(またはその配列)の非静的データメンバー、または
  • アクセスできないコピー代入演算子を持つ基本クラス。

暗黙的に定義されたコピーコンストラクタ、デフォルトコンストラクタ、およびデストラクタの対応する要件には、同様の表現があります。

定義が違法であってもメソッドが存在することを指定すると、過負荷の解決に関するいくつかのことが明らかになります。例えば、

class A {
private:
  A& operator=(const A&);
};

class B : public A {
public:
  operator int() const;
  B& operator=(int);
};

void f(B& b1, const B& b2)
{ b1 = b2; }

B::operator=(const B&)暗黙的に宣言された方が過負荷になりますが、暗黙的な定義の形式が正しくないため、は違法です。b2その宣言がないと、コンパイラは暗黙的にに変換してからint、に割り当てる必要があると思うかもしれませんb1

于 2010-12-02T18:36:45.623 に答える
1

2つの違いは、特定の実装の詳細に依存すると思います(大きな違いはありません)。それが価値があるものとして、コモーはこれを与えます:

"ComeauTest.c", line 7: error: "A &A::operator=(const A &)" (declared at line 4) is
          inaccessible
  struct B : A
             ^
          detected during implicit generation of "B &B::operator=(const B &)"
                    at line 16

1 error detected in the compilation of "ComeauTest.c".

そのため、そのコンパイラでは、B の代入演算子の暗黙的な生成「中」にエラーが検出されます。つまり、生成しようとして、生成できないことがわかります。書き出すときにそれを検出するか、A直接見ることによって検出するかは、実際には問題ではありません。

于 2010-12-02T18:03:07.840 に答える
0

これが起こることです:

struct A
{
private:
  A& operator = ( const A& );
};

struct B : A
{
  B& operator = ( const B& other )
  {
    A::operator=( other );
    return *this;
  }
};


int main()
{
  B b1;
  B b2;
  b1 = b2;

  return 0;
}

デフォルトの operator= は、非公開の A::operator= を呼び出そうとします。

于 2010-12-02T17:59:53.907 に答える
0

基準はあなたと一致しているようです。現在のドラフトからの引用:

§12.8/8:

クラス定義でコピー コンストラクターが明示的に宣言されておらず、ユーザーが宣言した移動コンストラクターがない場合、コピー コンストラクターは暗黙的にデフォルトとして宣言されます (8.4)。

§12.8/12:

クラス X のデフォルトのコピー/移動コンストラクターは、X が次の場合に削除済み (8.4.3) として定義されます: […]

  • オーバーロード解決 (13.3) が B の対応するコンストラクターに適用されるため、コピー/移動できない直接または仮想基本クラス B は、あいまいさ、またはデフォルトのコンストラクターから削除またはアクセスできない関数をもたらす […]

したがって、合成されたコピー コンストラクターは宣言および定義されますが、削除済みとして定義されます。

于 2010-12-02T18:04:12.713 に答える