Frage

In der Regel wird die "Verwendung" -DEklaration verwendet, um einige Mitgliederfunktionen von Basisklassen in den Umfang zu bringen, die sonst versteckt wären. Aus dieser Sicht ist es nur ein Mechanismus, um zugängliche Informationen bequemer zu verwenden.
Die Deklaration "Verwenden" kann jedoch auch verwendet werden, um Zugriffsbeschränkungen zu ändern (nicht nur für Funktionen, sondern auch für Attribute). Zum Beispiel:

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

Ich denke, diese Einschränkung des Zugriffs in der abgeleiteten Klasse nützt eigentlich keine Nutzung, da Sie immer auf G () und A von einem Zeiger auf die Basisklasse zugreifen können. Sollte es also nicht zumindest eine Art Compiler -Warnung geben? Oder wäre es nicht noch besser, eine solche Einschränkung des Zugangs durch eine abgeleitete Klasse zu verbieten? Die Verwendung von Deklarationen ist nicht die einzige Möglichkeit, um Zugriffsbeschränkungen hinzuzufügen. Es könnte auch durchgeführt werden, indem eine Basisklassenfunktion überschrieben wird und sie in einem Abschnitt mit mehr Zugriffsbeschränkungen platziert. Gibt es einige angemessene Beispiele, bei denen es in der Tat Nessecary ist, den Zugang auf solche Weise zu begrenzen? Wenn nicht, verstehe ich nicht, warum es erlaubt sein sollte.

Und eine andere Sache: Zumindest mit G ++ kompiliert der gleiche Code gut ohne das Wort "Verwenden". Das heißt für das obige Beispiel: Es ist möglich, C :: a zu schreiben; und c :: g; anstatt C :: a zu verwenden; Verwenden von C :: G; Ist die erste nur eine Abkürzung für letztere oder gibt es einige subtile Unterschiede?

//BEARBEITEN:
Aus der Diskussion und den Antworten nach unten wäre meine Schlussfolgerung:
- Es darf die Zugriffsbeschränkungen in abgeleiteten Klassen mit öffentlichem Erbe einschränken
- Es gibt nützliche Beispiele, bei denen es verwendet werden kann
- Die Verwendung kann ein Problem in Kombination mit Vorlagen verursachen (z. B. eine abgeleitete Klasse könnte kein gültiger Parameter für eine Vorlagenklasse/Funktion mehr sein, obwohl es sich um Basis handelt.
- Ein sauberer Sprachdesign sollte eine solche Verwendung nicht zulassen
- Compiler könnte zumindest eine Art Warnung ausstellen

War es hilfreich?

Lösung

In Bezug auf Ihre Erklärung ohne using: Diese werden als "Zugangserklärungen" bezeichnet und werden veraltet. Hier ist der Text aus dem Standard, von 11.3/1:

Der Zugang eines Mitglieds einer Basisklasse kann in der abgeleiteten Klasse geändert werden, indem in der abgeleiteten Klassenerklärung erwähnt wird. Diese Erwähnung wird als Zugangserklärung bezeichnet. Die Auswirkung einer Zugangserklärung qualified-id; ist definiert als gleichwertig der Erklärung usingqualified-id; Fußnote: Zugangserklärungen sind veraltet; Mitglied Verwenden von Deklarationen (7.3.3) bieten ein besseres Mittel, um die gleichen Dinge zu tun. In früheren Versionen der C ++ - Sprache waren die Zugriffserklärungen eingeschränkter; Sie wurden verallgemeinert und gleichwertig gemacht zu Verwenden von Deklarationen - Ende Fußnote

Ich würde sagen, dass es meistens nicht gut ist, sich zu ändern Öffentlichkeit Mitglieder zu Privatgelände oder geschützt Mitglieder in der abgeleiteten Klasse, da dies gegen das Substitutionsprinzip verstößt: Sie wissen erwarten von Diese Funktionen sind auch aufrufbar, weil die abgeleitete Klasse ist ein Base. Und wie Sie bereits erwähnt haben, wird diese Invariante ohnehin bereits von der Sprache erzwungen, die es ermöglicht, (die implizit funktionieren!) In eine Basisklassenreferenz umzuwandeln oder den Funktionsnamen zu qualifizieren und dann die (dann öffentliche) Funktion aufzurufen.

Wenn Sie jemandem verbieten möchten, der eine Reihe von Funktionen der Basis anruft, ist dies eine bessere Idee, dass die Eindämmung (oder in seltenen Fällen private Erbe) eine bessere Idee ist.

Andere Tipps

Während die von Ihnen gezeigte Verwendung von Deklarationen einen Mechanismus zur Änderung des Zugangsniveaus (aber nur nach unten) bietet, ist dies in einem solchen Kontext nicht die primäre Verwendung. Eine Verwendung von Kontext ist in erster Linie beabsichtigt, den Zugriff auf Funktionen zu ermöglichen, die ansonsten aufgrund der Sprachmechanik aus der Basisklasse schatten würden. Z.B

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

Die Erklärung

using C::a

Bringt "a" in den lokalen Namenszahlenbereich, damit Sie später "A" zu Schiedsrichter zu "C :: a" verwenden können; Da das "C :: a" und "a" austauschbar sind, solange Sie keine lokale Variable mit dem Namen "a" deklarieren.

Die Erklärung ändert keine Zugriffsrechte. Sie können nur in der Unterklasse auf "A" zugreifen, weil "a" nicht privat ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top