Ho una classe (chiamiamolo base
per il momento) che dispone di un'interfaccia protetta, anche i costruttori protette ecc Alcune funzioni di base
ritorno un'istanza di base
per valore:problema di visibilità per la copia costruttore della classe base
class base {
protected:
base() {}
base (base const &other) {} // line 6
base foo() {
base ret;
return ret;
}
};
Queste funzioni sono avvolti nelle classi derivate per restituire il tipo derivato in questo modo:
class derived : public base {
private:
derived(base const &b) : base(b) {}
public:
derived() : base() {}
derived foo() {
derived d(base::foo()); // line 21
return d;
}
};
per facilitare la conversione dal tipo base
ritorno in un derived
tipo restituito, fornisco un costruttore privato in derived
che gestisce questo.
Compilazione questo su CentOS 5.8 con gcc 4.1.2 produce il seguente errore:
test.cpp: In member function ‘derived derived::foo()’:
test.cpp:6: error: ‘base::base(const base&)’ is protected
test.cpp:21: error: within this context
con gcc 4.6.1 e clangore 2.9 su Linux Mint 12, il codice viene compilato file, anche con -Wall -Wextra
, a parte un avviso unused parameter
per il costruttore di copie di base
.
Penso che questo potrebbe essere un bug del compilatore in gcc 4.1.2, ma non sono riuscito a trovare nulla in rete. Qualcuno ha visto questo prima?
Non riesco ad aggiornare il compilatore senza grandi dolori. C'è una soluzione alternativa oltre a rendere pubblico il costruttore di copie della classe base?
EDIT ho aggiunto base b;
prima linea 21 in derived::foo()
. In questo caso, gcc 4.6.1 e gcc 4.1.2 si lamentano che il ctor predefinito di base
è protetto, clang 2.9 compila senza preavviso. Questo è ciò che David Rodríguez - dribeas ha detto nel suo commento - il ctor predefinito non può essere chiamato su un'altra istanza di base
.
EDIT 2 Il paragrafo standard che sembra applicarsi qui è di 11,5 [class.protected]. gcc 4.1.2 sembra essere corretto nel rifiutare il mio codice come errato e mi chiedo perché gcc 4.6.1 e clang lo permettano. Vedi la mia risposta per una soluzione preliminare.
Dal MarkB ha rimosso la sua risposta, mi post il punto principale qui: 'protected' non dà i tipi derivati accedere a quei membri su * qualsiasi * istanza della base genere. È possibile accedere solo ai membri protetti del proprio tipo derivato. Cioè'derived :: foo()' può accedere solo ai membri protetti di 'base' da' this' o qualsiasi altro oggetto 'derivato' (compresi oggetti il cui tipo completo è esso stesso derivato da' derivato') –
Sì, ho letto a riguardo troppo (anche lo ha cercato nello standard), e questa è stata anche la mia prima idea, ma mi chiedo perché sia gcc 4.6.1 sia clang 2.9. compilare questo senza problemi. – arne
+1 @ DavidRodríguez-dribeas che apre gli occhi. Ho avuto un'impressione sbagliata per tutto questo tempo. Non solo, ero ** certo ** dell'esatto opposto. –