2009-06-29 7 views

Antwort

73

Wenn eine Klasse eine abstrakte Klasse ist (beabsichtigt), ist ein geschützter Konstruktor genau richtig. In diesem Fall möchten Sie nicht, dass Objekte aus der Klasse instanziiert werden, sondern nur, um von ihnen zu erben.

Es gibt andere Anwendungsfälle, beispielsweise wenn ein bestimmter Satz von Konstruktionsparametern auf abgeleitete Klassen beschränkt werden soll.

+7

+1 Aber das muss nicht unbedingt eine abstrakte Klasse sein. Es ist jedoch oft der Fall. – ralphtheninja

+4

Reicht es nicht aus, eine Funktion für die Definition einer Basisklasse als rein virtuell zu deklarieren? Oder das obige ist in Abwesenheit von rein virtueller Funktion. Was ist ein Erstellungsereignis für eine abgeleitete Klasse einer solchen abstrakten Klasse? –

+0

@Henk Holterman Es tut sicherlich - siehe Abschnitt 10.4 des C++ Standards mit dem Titel "Abstract Classes" –

11

einmaliger Gebrauch könnte Fabrik-Muster seine

6

Eine geschützte Konstruktor bedeutet, dass nur Mitglieder abgeleitete Instanzen der Klasse konstruieren können (und abgeleitete Instanzen), den Konstruktor. Das klingt ein bisschen nach Hühnchen und Ei, ist aber manchmal nützlich, wenn Klassenfabriken implementiert werden.

+3

Technisch gilt dies nur, wenn ALLE ctors geschützt sind. – MSalters

+1

Freund Klassen können auch den geschützten Konstruktor aufrufen (nicht nur abgeleitete Klassen). –

+0

...und eine Verwendung einer Friend-Klasse, die den geschützten Konstruktor aufruft, wäre im Falle eines Objekts, das über Member verfügt, die konstant sind (vom Konstruktor festgelegt), aber öffentlich sein müssen, aber niemals durch einen anderen öffentlichen Zugriff gesetzt werden Das Objekt wird nicht woanders erstellt und die Daten werden daher auch nirgendwo anders verändert. – osirisgothra

3

Um eine Unterklasse einen Konstruktor verwenden zu lassen, der für einen Instanziierer nicht direkt zugänglich sein soll.

3

Sie können es verwenden, um die Klassen zu begrenzen, die es schaffen könnte, zum Beispiel:

class Level 
{ 
private: 

Level(); 
¨Level(); 

friend class LevelManager; 
}; 

die einzige Klasse, die eine Instanz davon erstellen kann, ist die Levelmanager-Klasse, so dass Sie immer wissen, dass die Stufe Instanz wird im LevelManager erstellt.

+0

Wenn das stimmt, ist das ein privater Konstruktor, der nicht geschützt ist. – David

+0

ahaha sorry, ich lese falsch. Soll ich meinen Beitrag löschen? –

7

Nicht öffentliche Konstruktoren sind nützlich, wenn Konstruktionsanforderungen bestehen, die nicht allein vom Konstrukteur garantiert werden können. Wenn beispielsweise eine Initialisierungsmethode direkt nach dem Konstruktor aufgerufen werden muss oder wenn das Objekt sich selbst bei einem Container/Manager-Objekt registrieren muss, muss dies außerhalb des Konstruktors erfolgen. Indem Sie den Zugriff auf den Konstruktor beschränken und nur eine Factory-Methode bereitstellen, können Sie sicherstellen, dass jede Instanz, die ein Benutzer erhält, alle seine Garantien erfüllt. Dies wird auch häufig verwendet, um ein Singleton zu implementieren, was wirklich nur eine weitere Garantie der Klasse ist (dass es nur eine einzige Instanz geben wird).

Der Grund dafür, dass der Konstruktor nicht privat, sondern geschützt ist, ist derselbe, als ob eine andere Methode oder ein anderes Feld geschützt statt privat wäre: so dass er von Kindern geerbt werden kann. Vielleicht möchten Sie eine öffentliche, nicht virtuelle Factory-Methode in der Basisklasse, die Referenzen auf Instanzen der abgeleiteten Klassen zurückgibt; Die abgeleiteten Klassen möchten natürlich Zugriff auf die übergeordneten Konstruktoren, möchten diese jedoch nicht außerhalb der Factory erstellen.

2

Für Fabrikmethoden mit Nebenwirkungen.

Dies erstellt Instanzen der Klasse und garantiert, dass jede von ihnen eine eindeutige inkrementierende Integer-ID hat. Beachten Sie, dass Sie den Standard auch ausblenden müssen, wenn der Konstruktor, den Sie verwenden möchten, nicht der Standard ist.

5

Ein geschützter Konstruktor kann verwendet werden, um eine Klasse effektiv abstrakt zu machen, wenn keine der Methoden rein virtuell ist.

Es ist nicht im C++ Sinne ziemlich abstrakt, da Freundesklassen es immer noch verwenden können, ohne zu überschreiben, aber dann müssten Sie diese deklarieren.