2008-12-09 6 views
9

Alle Membervariablen und Memberfunktionen in meiner Klasse ClassA sind statisch.Verhindern, dass eine Klasse erstellt wird, deren Memberfunktionen alle statisch sind

Wenn ein Benutzer versucht (versehentlich) ein Objekt dieser Klasse zu erstellen, erhält er eine Warnung: "ClassA, lokale Variable nie referenziert", da alle Funktionen statisch sind, so dass dieses Objekt nie referenziert wird. Also möchte ich verhindern, dass der Benutzer versucht, ein Objekt dieser Klasse zu erstellen.

Wäre es ausreichend, einen privaten Standardkonstruktor (keine Variablen) zu erstellen? Oder muss ich auch privaten Kopierkonstruktor und privaten Zuweisungsoperator erstellen (um die Verwendung der Standardkonstruktoren zu verhindern)? Und wenn ich sie auch erstellen müsste, wäre es vielleicht besser, stattdessen eine rein virtuelle Dummy-Funktion zu erstellen, die den Benutzer daran hindert, ein Objekt zu erstellen?

Vielen Dank

+0

Es ist C++, nicht Java! Warum müssen Sie eine Klasse für statische Funktionen erstellen? mach sie nur global oder unter einem Namespace {} anstelle einer Klasse – hasen

+2

. Wenn du stattdessen einen Namespace verwendest, kannst du private statische Mitglieder nicht haben, um den privaten Status zu halten. –

+0

Sicher kannst du! mache sie statisch und sie werden außerhalb dieser Kompilierungseinheit nicht verfügbar sein. – Ferruccio

Antwort

10

Wie andere gesagt haben, ist ein Namespace, was Sie verwenden sollten. Wenn Sie mit Ihrer Klasse bleiben wollen, eine Klasse erstellen, die einen privaten Konstruktor hat, und leiten daraus, Ihre Absicht klar zu machen:

class NonConstructible { 
    NonConstructible(); 
}; 

class SuperUtils: NonConstructible { 
    static void foo(); 
    // ... 
    static std::vector<int> globalIDs; 
    // ... 
}; 

Ok, jetzt wollen wir den Namensraum schauen, in die das sind eine und einzige Weg, dies zu tun:

namespace SuperUtils { 
    void foo() { 
     // .... 
    } 

    std::vector<int> globalIDs; 
}; 

Sie können, dass SuperUtils::foo(); in beiden Fällen unter Verwendung von nennen, aber der Namensraum hat den Vorteil, dass Sie in einem Bereich der Namespace-Deklaration und Richtlinie bestimmte oder alle Mitglieder können bringen in der aktuelle Umfang, damit Sie sich auf diesen beziehen können em ohne SuperUtils:::

void superFunction() { 
    using namespace SuperUtils; 
    foo(); 
} 

Während im Allgemeinen, dass vermieden werden sollte, kann es hilfreich sein, wenn das Verfahren ausschließlich viel Material von SuperUtils verwenden, die dann die Lesbarkeit des Codes verbessern.

+0

Aber jetzt haben Sie globalIDs öffentlich gemacht, wenn es vorher privat war. Wenn Globals existieren müssen, wie ist es eine Verbesserung für sie von überall zugänglich zu sein? –

+0

Um das Beste aus beiden zu erhalten, könnten Sie die Globals in eine Klasse einfügen und dann mit Nicht-Member-Friend-Funktionen auf sie zugreifen. Oder fügen Sie die Globals und Funktionen in die Klasse ein und verwenden Sie dann Inline-Funktionen in einem Namespace, um sie ohne Angabe des Klassenbereichs aufzurufen. –

+0

"Früher war es privat" - Entschuldigung, ich meine, vorher könnte es privat sein. Fragender hat es nicht gesagt. –

11

Erstellen eines privaten Standardkonstruktors sollte ausreichen. Die beiden anderen Standardkonstrukte (Kopierkonstruktor und -zuweisung) benötigen eine Instanz, damit sie ordnungsgemäß funktionieren. Wenn es keinen Standardkonstruktor gibt, dann gibt es keine Möglichkeit, eine Instanz zu erstellen, daher gibt es keine Möglichkeit, tatsächlich zum Kopierbauteil zu gelangen.

Es würde Ihnen wahrscheinlich ein paar Kopfschmerzen ersparen, alle 3 als privat und nicht implementiert zu definieren.

+0

Noch einmal, da gewählt ... – JaredPar

+2

Das sollte sein: zu deklarieren, aber nicht definieren (implementieren) den Konstruktor. Das sorgt dafür, dass sowohl externer Code versucht, eine Instanz zu erzeugen (Konstruktor ist privat) als auch interner Code fälschlicherweise ein Objekt erzeugt: Linkerfehler als Konstruktor ist nicht definiert. –

3

Um einen Kopierkonstruktor verwenden zu können, muss ein Objekt kopiert werden. Wenn Sie den Standardkonstruktor gesperrt haben, sollten Sie also sicher sein.

20

Anstatt eine Klasse mit allen statischen Methoden zu verwenden, ist es besser, die Methoden in einem separaten Namespace freistehend zu machen. Der Aufruf Syntax wäre das gleiche:

namespace::function() statt classname::function()

und Sie müssen nicht mit jemandem zu tun versuchen, Ihre Klasse zu instanziieren.

+0

Definitiv viel besser als eine Klasse mit allen statischen Methoden. – Naveen

+1

stimme ich überhaupt nicht zu. Ich kann schreiben 'using namespace Xxxx;' und dann muss ich nicht 'Xxxx :: Symbol' schreiben - nur 'Symbol' ist genug. Der statische Klassenansatz zwingt den Programmierer jedes Mal "Class :: Symbol" zu tippen. – xxbbcc

0

Die beste Möglichkeit, die Erstellung von Nicht-Heap-Objekten zu verhindern, besteht darin, den Destruktor privat zu machen. Dann gibt es keine Möglichkeit Compiler kann das Objekt zerstören, wenn es außerhalb des Geltungsbereichs geht und es wird sich beschweren. Dies wird jedoch niemanden daran hindern, Neues zu tun.