Domanda

Ho una piccola confusione riguardo le situazioni in cui l'attuazione (compilatore) non sarà fornire il costruttore di copia e l'operatore di assegnazione di copia.

  1. Quando si dichiara la ctor copia e / o copia operatore di assegnazione nella nostra classe.
  2. Alcuni dice che quando deriviamo da una classe che ha una copia ctor privato e / o copiare operatore di assegnazione.

Sono un po 'confuso circa la seconda situazione, è la seconda situazione è proprio.
a) L'implementazione non li dichiarerà per voi, in modo da otterrete un errore di tempo di compilazione.
O
b) L'implementazione dichiarerà e definirli, ma quando il compilatore definito tentativi di implementazione per trovare il metodo della classe base, che otterrà un errore di compilazione.

Ho avuto un colloquio di ieri, ho detto la sua (b) che sta accadendo, ma non è d'accordo le intervistatore, dice la sua (a).

ho provato a compilare il seguente codice in Microsoft C / C ++ 14.00 e gcc 4.4.5

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

struct B : A
{
};


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

  return 0;
}

output del compilatore 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 &)'

uscita compilatore 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 

Quindi penso che, l'attuazione dichiarerà e definirlo, ma quando il compilatore definito tentativi di implementazione per trovare il metodo della classe base, si otterrà un errore di compilazione. Correggetemi se sbaglio.

È stato utile?

Soluzione

Per quanto riguarda il costruttore di copia, questo è ciò che dice lo standard (12,8 / 7):

  

Un programma è illformed se la classe   per i quali un costruttore di copia è    implicitamente definito ha:

     
      
  • un membro di dati non statica di tipo classe (o array di esso) con un   copia inaccessibili o ambigue   costruttore, o
  •   
  • una classe base con una copia inaccessibile o ambigue   costruttore .
  •   

Per quanto riguarda l'operatore di assegnamento per copia (12,8 / 12):

  

Un programma è illformed se la classe   per cui un operatore di assegnamento copia   è implicitamente definito ha:

     
      
  • un membro di dati non statico di tipo const o
  •   
  • un membro di dati non statica di tipo di riferimento, o
  •   
  • un membro di dati non statica di tipo classe (o array di esso) con un   inaccessibile copia operatore di assegnazione,   o
  •   
  • una classe base con un operatore di assegnamento per copia inaccessibile.
  •   

Come il compilatore segnala l'errore, o come in realtà scende in esso, è praticamente irrilevante dal mio punto di vista.

Tuttavia, credo che la risposta (b) è probabilmente più corretto: l'assegnazione copia classe base è dichiarato, ed è inaccessibile. La classe derivata ha un implicito ha dichiarato Copia incarico che il compilatore cercherà di definire se utilizzato , rendendo così il programma di mal-formata.

Altri suggerimenti

Una classe avrà un costruttore di copia e un operatore di assegnamento per copia implicitamente ha dichiarato se non c'è nessun utente dichiarato versione di entrambi. Questo accade sempre.

Semplificando, l'attuazione implicitamente definire questi solo se sono realmente utilizzati. Se, quando l'implementazione cerca di definirli, la definizione implicita sarebbe mal formato (ad esempio per la copia assegnazione della classe contiene un membro di riferimento o di un membro const o per il costruttore di copia di una base di membro dispone costruttore di copia privata) allora il programma è mal formati.

Un programma può essere ancora valido se contiene le classi che hanno implicitamente ha dichiarato Copia costruttori e copiare gli operatori di assegnazione che non può essere definito in modo implicito finché non provoca questi effettivamente essere definite utilizzandoli o causare loro di essere utilizzati.

Il tuo caso (b) è più accurata.

C ++ 03 standard 12.8p10

  

Se la definizione della classe non dichiara esplicitamente un operatore di assegnamento per copia, uno è dichiarata implicitamente .

E 12.8p12

  

Un operatore di assegnamento per copia implicitamente dichiarata è implicitamente definito quando un oggetto di questo tipo di classe è assegnato un valore del suo tipo di classe o un valore di un tipo classe derivata dalla sua tipo di classe. Un programma viene mal formati se la classe per la quale un operatore di assegnamento per copia è implicitamente definito ha:

  • un membro di dati non statico di tipo const, o
  • un membro di dati non statica di tipo di riferimento, o
  • un membro di dati non statica di tipo classe (o array di esso) con inaccessibile operatore di assegnazione copia o
  • una classe base con un operatore di assegnamento per copia inaccessibile.

I requisiti corrispondenti per i costruttori implicitamente definiti copia, costruttori di default, e distruttori hanno formulazioni simili.

Come specificare che i metodi esistono, anche se le loro definizioni saranno chiarisce illegali alcune cose su risoluzione di sovraccarico. Ad esempio,

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

è illegale perché il B::operator=(const B&) implicitamente dichiarata è il sovraccarico di meglio, ma la definizione implicita è mal-formata. Senza questa dichiarazione, si potrebbe pensare che il compilatore deve convertire implicitamente b2 a int e quindi assegnare quello a b1.

Credo che la distinzione tra i due dipende dai dettagli dell'implementazione specifica (e non fa molta differenza). Per quel che vale, Comeau dà questo:

"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".

Quindi, su questo compilatore, rileva l'errore "durante" l'implicita generazione di operatore di assegnazione di B. In altre parole, si tenta di generare essa, e trova che non può. Sia che si rileva come è scriverlo fuori, o cercando in A direttamente, non importa.

Questo è ciò che accade:

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

L'operatore di default = tenta di chiamare A :: operator =, che è privato.

La norma sembra essere d'accordo con te. Citando l'attuale progetto:

§12.8 / 8:

  

Se la definizione di classe non lo fa   dichiarare in modo esplicito un costruttore di copia   e non v'è alcun movimento user-dichiarata   costruttore, un costruttore di copia è   implicitamente dichiarata in default   (8.4).

§12.8 / 12:

  

Un default costruttore di copia / spostamento per   una classe X è definito come eliminato   (8.4.3) se X ha: [...]

     
      
  • una classe base diretta o virtuale B che non può essere copiato / spostato a causa   la risoluzione di sovraccarico (13.3), come applicata   corrispondente al costruttore di B,   Risultati in un'ambiguità o una funzione   che viene eliminata o inaccessibile   il costruttore di default [...]
  •   

Quindi, il costruttore di copia sintetizzata è dichiarata e definita, ma definito come cancellato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top