Domanda

Tipicamente la dichiarazione 'using' viene utilizzata per includere nell'ambito alcune funzioni membro delle classi base che altrimenti rimarrebbero nascoste.Da questo punto di vista si tratta solo di un meccanismo per rendere le informazioni accessibili più comode da usare.
Tuttavia:la dichiarazione 'using' può essere utilizzata anche per modificare i vincoli di accesso (non solo per le funzioni ma anche per gli attributi).Per esempio:

class C{
public:
  int a;
  void g(){ cout << "C:g()\n"; }
  C() : a(0){}
};

class D : public C{
private:
  using C::a;
  using C::g;
public:
  D() { a = 1; }
};

int main(void){
  D d;
  cout << d.a << endl;  //error: a is inaccessible
  C *cp = &d;
  cout << cp->a << endl; //works
  d.g();  //error: g is inaccessible
  cp->g();  //works
  return 0;
}

Penso che questa limitazione di accesso nella classe derivata sia in realtà inutile, perché puoi sempre accedere a g() e a da un puntatore alla classe base.Quindi non dovrebbe esserci almeno una sorta di avviso del compilatore?O non sarebbe ancora meglio vietare tale limitazione di accesso da parte di una classe derivata?La dichiarazione using non è l'unica possibilità per aggiungere vincoli all'accesso.Potrebbe anche essere fatto sovrascrivendo la funzione di una classe base e posizionandola in una sezione con più vincoli di accesso.Esistono esempi ragionevoli in cui è effettivamente necessario limitare l'accesso in questo modo?Altrimenti non vedo perché dovrebbe essere consentito.

E un'altra cosa:almeno con g++ lo stesso codice viene compilato bene senza la parola "usando".Ciò significa per l'esempio sopra:è possibile scrivere C::a;e C::g;invece di usare C::a;utilizzando C::g;La prima è solo una scorciatoia per la seconda oppure ci sono delle sottili differenze?

//MODIFICARE:
quindi dalla discussione e dalle risposte di seguito la mia conclusione sarebbe:
- è consentito limitare i vincoli di accesso nelle classi derivate con ereditarietà pubblica
- ci sono esempi utili in cui potrebbe essere utilizzato
- il suo utilizzo potrebbe causare problemi in combinazione con i modelli (ad es.una classe derivata non potrebbe più essere un parametro valido per alcune classi/funzioni modello, sebbene la sua base lo sia)
- una progettazione del linguaggio più pulita non dovrebbe consentire tale utilizzo
- il compilatore potrebbe almeno emettere una sorta di avviso

È stato utile?

Soluzione

Per quanto riguarda la tua dichiarazione senza using:Queste sono chiamate "dichiarazioni di accesso" e sono deprecate.Ecco il testo dello Standard, da 11.3/1:

L'accesso di un membro di una classe di base può essere modificato nella classe derivata menzionando il suo ID qualificato nella dichiarazione di classe derivata.Tale menzione è chiamata dichiarazione di accesso.L'effetto di una dichiarazione di accesso qualified-id; è definito equivalente alla dichiarazione usingqualified-id; [Nota:Le dichiarazioni di accesso sono deprecate;membro using-dichiarazioni (7.3.3) forniscono mezzi migliori per fare le stesse cose.Nelle versioni precedenti del linguaggio C++, le dichiarazioni di accesso erano più limitate;furono generalizzati e resi equivalenti using-dichiarazioni - nota finale]

Direi che il più delle volte non è bene cambiare pubblico membri a privato O protetto membri della classe derivata, perché ciò violerebbe il principio di sostituzione:Sai che una classe base ha alcune funzioni e se esegui il cast su una classe derivata, allora tu aspettarsi anche quelle funzioni devono essere richiamabili, perché la classe derivata è un base.E come hai già detto, questa invariante è già applicata comunque dal linguaggio che consente di convertire (che funziona implicitamente!) In un riferimento alla classe base, o qualificando il nome della funzione, e quindi chiamando la funzione (quindi pubblica).

Se vuoi vietare a qualcuno di chiamare un insieme di funzioni della base, allora penso che questo suggerisca che il contenimento (o in rari casi, l'ereditarietà privata) sia un'idea migliore.

Altri suggerimenti

Mentre la dichiarazione utilizzando hai mostrato fornisce un meccanismo per modificare il livello di accesso (ma solo verso il basso), che non è l'uso primario di esso in un tale contesto. Un contesto usando v'è principalmente destinato a consentire l'accesso a funzioni che altrimenti sarebbero in ombra dalla classe di base a causa della meccanica lingua. Per es.

class A {
public:
   void A();
   void B();
};

class B {
public:
   using A::B;
   void B(int); //This would shadow A::B if not for a using declaration
};

La dichiarazione

using C::a

porta "a" al campo di applicazione di denominazione locale in modo che in seguito sarà possibile utilizzare "a" a Riferirsi ai "C :: un"; dal momento che, "C :: a" e "a" sono intercambiabili finché non si dichiara una variabile locale con il nome "a".

La dichiarazione non modifica i diritti di accesso; è possibile accedere a "a" nella sottoclasse solo perché "a" non è privata.

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