2012-07-13 22 views
6

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.

+0

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') –

+0

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

+0

+1 @ DavidRodríguez-dribeas che apre gli occhi. Ho avuto un'impressione sbagliata per tutto questo tempo. Non solo, ero ** certo ** dell'esatto opposto. –

risposta

0

La mia soluzione preliminare è quello di rendere base 's copia ctor public. Per non consentire la copia delle istanze derived utilizzando il codificatore di copia di base, l'ereditarietà deve essere protected anziché public. Le classi risultanti ora apparire così:

class base { 
protected: 
    base() {} 
public: 
    base (base const &other) {} 
protected: 
    base foo() { 
     base ret; 
     return ret; 
    } 
}; 

class derived : protected base { 
private: 
    derived(base const &b) : base(b) {} 
public: 
    derived() : base() {} 
    derived foo() { 
     derived d(base::foo()); 
     return d; 
    } 
}; 
1

Una soluzione che si potrebbe provare comporterebbe la creazione di un costruttore privato per derivata che costruisce sua base chiamando la funzione di base:

class derived : base { 
    struct from_base_foo {}; 
    derived(from_base_foo) : base(base::foo()) {} 
public; 
    derived foo() { 
     return derived(from_base_foo()); 
    } 
}; 
+0

Provato, l'errore viene quindi emesso per la chiamata al costruttore '' base'' nella nuova ' costruttore 'derivato''. – arne

+0

Oh, giusto si lamenta nella lista di inizializzazione mentre tentava di associare il valore rvalue 'base :: pippo' al constvalore passato come argomento al costruttore di copia' base' ... –

Problemi correlati