3 Stimmen

Teil einer öffentlichen verschachtelten Klasse nur für die umgebende Klasse sichtbar halten

Ich habe eine verschachtelte Klasse in c++, die öffentlich sein muss. Aber ich möchte, dass einige ihrer Methoden für die äußere Welt sichtbar sind und der Rest nur für die verschachtelte Klasse sichtbar ist. Das heißt:

class set {
public:
    class iterator {
        innerMethod();
    public:
        outerMethod();
    }
}

Ich möchte in der Lage sein, eine Methode für die Klasse set zu schreiben, die innerMethod() verwendet. Wenn ich sie öffentlich mache, kann ich auch von außen darauf zugreifen, was etwas ist, das ich auf jeden Fall nicht möchte. Gibt es einen Weg, dies zu tun, ohne die Sache mit "friend class set" zu machen?

Vielen Dank im Voraus!

2voto

Nawaz Punkte 339767

Es gibt KEINE GUTE MÖGLICHKEIT, dies zu tun, ohne das Schlüsselwort friend zu verwenden.

In dem Kommentar, den Sie gemacht haben:

In der Programmierklasse, die ich gerade besuche, wurde gesagt, dass die Verwendung von 'friend' nicht ratsam sei und im Allgemeinen als "schlechtes Programmieren" angesehen wird, es sei denn, es gibt wirklich keine andere Möglichkeit. Also versuche ich, es so weit wie möglich zu vermeiden.

friend bricht die Kapselung, vielleicht ist das der Grund, warum Ihr Klassenlehrer gesagt hat, dass es schlechtes Programmieren ist. Aber auch Member-Funktionen brechen die Kapselung, also warum verwenden Sie sie? Warum vermeiden Sie sie nicht auch? friend bricht die Kapselung auf die gleiche Weise wie Member-Funktionen; also wenn Sie sich wohl dabei fühlen, Member-Funktionen zu verwenden, wenn sie benötigt werden, sollten Sie auch damit zurechtkommen, friend zu verwenden wenn sie benötigt werden. Beide existieren in C++ aus einem bestimmten Grund!

class set {
public:
 class iterator 
 {
  friend class set; //<---- das ermöglicht es Ihrer Klasse set, auf innere Methoden zuzugreifen!

  void innerMethod(){}
 public:
  void outerMethod(){}
 };
 iterator it;

 void fun()
 {
  it.innerMethod();
  it.outerMethod();
 }
};

Sehen Sie hier: Wie Nicht-Member-Funktionen die Kapselung verbessern

1voto

peoro Punkte 24751

Nein, ich denke nicht, dass es andere nicht-hacky Methoden gibt, außer die Verwendung der friend-Direktive.

friend existiert genau für solche Zwecke, warum würdest du es vermeiden?

1voto

peenut Punkte 3255

Versuchen Sie zu fragen: Gibt es eine Möglichkeit, zwei Zahlen zu addieren, ohne sie zu addieren? Entschuldigung, wenn ich hart bin, aber befreundete Klasse ist genau dafür da...

1voto

Matthieu M. Punkte 266317

Ja, das stimmt.

Ich versuche seit geraumer Zeit, die Methode zu befürworten, die grundlegende Idee besteht darin, eine Key-Klasse zu verwenden.

Obwohl dies den Gebrauch von friend tatsächlich nicht entfernt, reduziert es den Satz von offengelegten Implementierungsdetails.

Klasse setzen;

// 1. Definieren Sie die Schlüsselklasse
Klasse set_key: unvererbbar { Freundesklasse setzen; set_key() {} ~set_key() {} };

Klasse festlegen
{

  // 2. Definieren Sie den Iterator
  Klasse iterator
  {
  Öffentlich:
    void öffentliche_methode();

    void eingeschränkte_methode(set_key&);

  }; // Klasse iterator

}; // Klasse setzen

Jetzt ist eingeschränkte_methode öffentlich, sodass set keinen speziellen Zugriff auf iterator benötigt. Die Verwendung davon ist jedoch auf diejenigen beschränkt, die in der Lage sind, eine Instanz von set_key zu übergeben... und bequemerweise kann nur set ein solches Objekt erstellen.

Beachten Sie, dass set tatsächlich eine set_key-Objekt an jemanden weitergeben kann, dem es vertraut. Es handelt sich um einen Schlüssel im traditionellen Sinn: Wenn Sie einen Schlüssel Ihrer Wohnung jemandem geben, kann er ihn einer anderen Person anvertrauen. Aufgrund der Semantik der Schlüsselklasse (nicht kopierbar, nur set darf sie erstellen und zerstören) ist dies normalerweise jedoch auf die Dauer des Gültigkeitsbereichs des Key-Objekts beschränkt.

Beachten Sie, dass immer ein böser Hack möglich ist, nämlich *((set_key*)0). Dieses Schema schützt vor Murphy, nicht vor Machiavelli (in C++ ist es sowieso unmöglich).

0voto

Mircea Ispas Punkte 19372

Sie können etwas wie folgt tun:

Klasse setzen

{

public:
    class iterator
    {
        protected:
            iterator(){};
            virtual ~iterator(){};

        public:
            // äußere Methoden...
    };

private:
    class privateIterator : public iterator
    {
        public:
            privateIterator(){};
            ~privateIterator(){}

        // innere Methoden;
    };

public:
    iterator* ErstelleIterator()
    {
        return new privateIterator();// dies wird verwendet, um sicherzustellen, dass nur private Iterator-Instanzen erstellt werden
    }

};

Ich weiß nicht, ob es die richtige Antwort ist, aber es verwendet nun das Schlüsselwort "friend" und versteckt einige der Methoden. Das einzige Problem ist, dass Sie privateIterator nicht deklarieren können und Sie immer ErstelleIterator verwenden müssen, um eine Instanz zu erstellen...

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X