Konstante Elementfunktionen

9

Nachdem ich dies gelesen habe, ist es nach meinem Verständnis eine Deklaration einer Methode als const , die verhindert, dass die Klasse versehentlich geändert wird Mitgliedsvariablen.

  • Sind const Methoden häufig verwendet?
  • Sollten sie für alles verwendet werden, das keine Membervariablen ändern sollte?
Maxpm 14.01.2011, 13:03
quelle

8 Antworten

14

Ja, const sollte bei Bedarf immer verwendet werden.

Es ermöglicht Ihrem Compiler, Ihre Anwendungslogik zu überprüfen und statisch const-correctness zu bestätigen frei!

Einige Leute sagen sogar, dass const der Standard sein sollte, und Sie sollten gezwungen sein, mutable für das zu verwenden, was nicht konstant ist.

    
peoro 14.01.2011, 13:04
quelle
6

Ich benutze const ausgiebig, um die Konstruktionsabsicht zu kommunizieren. Wenn ich beabsichtigte, dass eine Methode eine reine Abfrage und keine Modifikationsfunktion war, würde ich beides erzwingen und sie mit einem 'const' in der Signatur kommunizieren.

Ich ermutige Sie, Meyers Gedanken zur Frage der Nebenwirkungen-freien Funktionen und der Implikationen, die das Testen ermöglichen, zu betrachten.

    
gap 14.01.2011 13:06
quelle
4

Nur mein Zeugnis.

Vor einigen Jahren war ich immer noch gegen die Verwendung von const, nur wegen der Einschränkungen in Design und Schreiben längerer Funktionssignaturen ... und so weiter ...

Aber einer meiner Projektleiter bestand immer darauf, mich daran zu erinnern: "Du solltest const-Funktion verwenden, es vermeidet Unfälle und macht Unsinn".

Und eines Tages war ich mit einem unmöglichen Bug konfrontiert. Tage nach Tagen nach Tagen ... Ein Albtraum. Das Design war zu groß für mich, um es in seiner Gesamtheit zu erfassen. Ich suchte vergeblich, bis ich entschied, dass ich verloren war.

Dann habe ich zwei Tage damit verbracht, ALLE Funktionen neu zu definieren, die const sein sollten . Ich meine es, zwei Tage. (Neukompilierungen waren lange, da es sich um ein Projekt mit 5 Millionen Zeilen Code handelte).

Und dann: ich habe einfach den Bug gefunden ... eher der Compiler hat den Bug für mich gefunden: In einer getterartigen Methode, die mir die bevorzugte Größe eines GUI-Controls hätte geben sollen, berechnete der Code tatsächlich die Größe , aber es hat auch seine Größe zwischengespeichert und seine Größe aktualisiert ... So modifiziert das Objekt.

Jetzt vergesse ich manchmal, const zu setzen. Aber wenn ich es bemerke, korrigiere ich es.

    
Stephane Rolland 14.01.2011 13:23
quelle
1

Das Hinzufügen von const zu einer Member-Funktion ermöglicht den Aufruf von const-Referenzen auf ein Objekt, da es garantiert, dass die Instanzvariablen nicht geändert werden. Const-Referenzen treten an verschiedenen Stellen in der STL auf, daher ist es sinnvoll, Member-Funktionen als const zu markieren, wobei die Funktion nicht den Zustand eines Objekts ändern will.

Hinweis: Es ist möglich, bestimmte Instanzvariablen als mutable zu markieren, so dass sie auch durch const-Funktionen geändert werden können. Dies ist beispielsweise nützlich, um Nachschlag-Caches zu implementieren.

    
Frederik Slijkerman 14.01.2011 13:09
quelle
1

Deklaration einer Methode, die keine Membervariablen ändern soll:

  1. Versichert, dass das, was Sie denken, geschieht, d. h. dass Sie nicht versehentlich eine Variable irgendwo ändern.
  2. Erklärt den Aufrufern der Funktion, dass diese Methode die Membervariablen nicht ändert, wodurch die Notwendigkeit entfällt, den Code zu lesen oder sich auf die Dokumentation zu verlassen, die dies sagt.

Also ja, benutze const wo immer es Sinn macht. Sie sind nicht so weit verbreitet, wie ich es gerne sehen würde, wahrscheinlich weil die meisten Entwickler den großen Vorteil nicht sehen.

    
marcog 14.01.2011 13:10
quelle
1

Wenn Sie vergessen, einen Accessor als const zu markieren, erlaubt der Compiler nicht, dass die Methode für const -Objekte oder Referenzen auf const -Objekte aufgerufen wird. Also ja, Accessoren als const zu markieren ist wichtig.

    
fredoverflow 14.01.2011 13:10
quelle
1

Wenn Sie eine const-Referenz oder einen Zeiger (d. h. Zeiger auf const) eines Klassenobjekts haben, können Sie NUR Const-Member-Methoden der Klasse aufrufen.

Wenn also jemand "vergessen" würde, eine "get" -Methode const zu machen, wäre es nicht möglich, sie mit einer const-Referenz aufzurufen (Es gibt eine Problemumgehung mit const_cast, aber wir wollen das nicht benutzen!).

Also, wenn die Klasse nicht durch die Methode modifiziert wird, sollte sie const sein.

Hinweis: Es gibt Situationen, in denen Sie eine Variable als "Implementierungsdetail" ändern möchten, z. B. Lazy-Laden oder Sperren eines Mutex. In einem solchen Fall können Sie die Methode const immer noch machen, aber diese Membervariable "veränderbar" machen.

Wenn Sie eine virtuelle Methode schreiben, sollte sie const sein, wenn keine abgeleitete Klasse benötigt wird, um veränderbar zu sein.

    
CashCow 14.01.2011 13:12
quelle
1

Wenn möglich, sollten Sie das Schlüsselwort const verwenden.

Es verhindert Sie vor den Fehlern im Code.

Es erhöht die Lesbarkeit des Codes sehr. Jeder, der die Kopfzeile liest und const-Schlüsselwörter sieht, kann sofort verstehen, dass eine const-Methode den Zustand eines Objekts nicht ändert und ohne Angst verwendet werden kann, dass er das Objekt zum Beispiel ändert

    
Andrew 14.01.2011 13:14
quelle

Tags und Links

Django: Verwenden von Annotate, Count und Distinct in einem Queryset ___ answer1863513 ___

Die Antwort lautet einfach: "Wirf dich nicht in deinem Agent-Code an GameState!".

Alternativ kannst du das GameState-Material als privat deklarieren. Oder wenn Sie von einigen wenigen anderen Klassen darauf zugreifen müssen, deklarieren Sie es als paketgeschützt.

    
___ qstntxt ___

Ich habe den Code eines einfachen Spiels, in dem ein AgentInterface implementiert werden muss, um einen Agenten-Controller für einen der Charaktere im Spiel zu erstellen. GameState ist eine Klasse, die das GameStateInterface implementiert, und ein Objekt, das diese Schnittstelle implementiert, kann an den Agenten übergeben werden, sodass der Agent die Daten aus dem Spielzustand lesen und analysieren kann und der Agent die entsprechende Aktion (als int zurückgegeben) zurückgeben muss der Charakter sollte nehmen.

Dies ist das AgentInterface, das Agents implementieren müssen:

%Vor%

Ausführen des Spiels mit einem Agenten namens MyAgent:

%Vor%

Aber es gibt einige Informationen in GameState, auf die der Agent NICHT zugreifen darf, da dies den Controller betrügen würde. Eine Cast-Konvertierung von GameStateInterface in GameState würde es dem Agenten jedoch ermöglichen, auf Informationen zuzugreifen, die nicht im GameStateInterface definiert sind:

%Vor%

Meine Frage wäre, ist es möglich, eine Cast-Conversion zu blockieren? Ich weiß, dass Polymorphie eines der Hauptmerkmale von Java und objektorientierten Programmiersprachen ist, aber in solchen Fällen möchte ich Umwandlungen vermeiden.

Ich weiß, dass dies auf viele andere Arten gelöst werden kann, aber ich war neugierig zu wissen, ob es möglich ist, dies zu tun.

Vielen Dank im Voraus.

    
___ answer1863512 ___

Es ist nicht möglich, einen Cast zu blockieren. Sie können Ihren Spielstatus jedoch so definieren, dass er nur von einem bestimmten Ort aus erstellt werden kann. Eine Sache, die Ihnen in den Sinn kommt, wäre eine private innere Klasse, die die Schnittstelle implementiert, oder eine Factory, die eine private innere Klasseninstanz zurückgibt

    
___ answer1863510 ___

Soweit ich weiß, ist es nicht möglich, eine Typumwandlung abzufangen und zu leugnen (z. B. durch eine ClassCastException).

Aber anstatt zu versuchen, das Typecase zu leugnen, kannst du einfach das Proxymuster verwenden, um den Zugriff auf den eigentlichen GameState zu kontrollieren Objekt. Implementiere einfach eine Proxy-Klasse, die nur das GameStateInterface implementiert und es alle Methodenaufrufe an das GameState-Objekt weiterleiten lässt. Anstatt den tatsächlichen GameState-Objektverweis an die Aktionsmethode zu übergeben, übergeben Sie ihn nun von einer Instanz Ihrer Proxyklasse umschlossen.

    
___ answer1863519 ___

Wenn Sie Bedenken haben, dass der Spielstatus von einem Agenten geändert wird, erstellen Sie eine Bean-Kopie des Status und übergeben Sie diese an den Agenten und nicht an das echte GameState-Objekt.

Es ist nicht möglich, einen Cast zu verbieten (es ist wahrscheinlich eine nicht sperrbare JVM-Sprachspezifikation), oder ich habe noch nie davon gehört.

    
___ answer1863520 ___

Im Allgemeinen können Sie nicht verhindern, dass ein Objekt in Java umgewandelt wird. Der Code, der einen Verweis auf Ihre %code% erhält, kann eine nicht private, nicht geschützte Methode für dieses Objekt aufrufen. Selbst wenn Sie Casting verhindern könnten, könnte es immer noch Reflexion verwenden.

Wenn der %code% -Code unter Ihrer Kontrolle steht, halten Sie die Dinge einfach und werfen Sie sie nicht um. Wenn andere %code% -Klassen schreiben, könnten Sie eine Proxy-Klasse erstellen, die ein GameState-Objekt übernimmt und nur die Methoden von GameStateInterface implementiert.

%Vor%

Dann könnten Sie einen Proxy erstellen und es so übergeben:

%Vor%

Der Code, der ein %code% erhält, hätte nur Zugriff auf die Methoden in %code% .

    
___ answer5108831 ___

Ich habe ein gesichertes schreibgeschütztes Objekt implementiert. Wenn Sie eine schreibgeschützte Schnittstelle (keine Setter) erstellen, können Sie immer noch Methoden des reinen Objekts typisieren und darauf zugreifen. ZB Interface haben nur ein get und das Kind dieses Interface hat das Set. Wenn Sie das Objekt an die Schnittstelle übergeben, haben Sie nur den get. ABER Sie können immer noch dieses Objekt typisieren und auf alles zugreifen: (

Um dies zu vermeiden, können Sie eine Zusammensetzung erstellen, die NUR dem Ersteller der Klasse gehört. Hier ist ein Beispiel:

%Vor%

Auf diese Weise geben Sie Folgendes ein:

%Vor%

Er hat also Zugriff auf das Item-Objekt (die innere Klasse kann auf private Methoden zugreifen :)) Wenn Sie nur lesenden Zugriff auf dieses Objekt haben wollen:

%Vor%

Nun ist es absolut NICHT möglich, zu tippen, weil sie nicht vom selben Typ sind!

Hoffe, das kann jemandem helfen! (Ich würde gerne, wenn Sie Quelle nennen: P)

    
___ answer1863560 ___

Was wir tun, ist ein Jar mit "Stubs", gegen den Sie kompilieren können, aber es enthält keine Implementierung. Wenn das tatsächliche Produkt ausgeführt wird, ersetzen wir die Stubs durch ein echtes Glas.

Aber in unserem Fall kontrollieren wir, wo es läuft.

Auch in unserem Fall machen wir genau das, was Sie verlangen. Jede Klasse muss (zur Laufzeit) Zugriff auf andere Klassen anfordern. Ich glaube, das ist alles eine benutzerdefinierte Implementierung und ich bin mir nicht sicher, ob es auf einer JVM läuft.

Sie können versuchen, den Quellcode für das Zeug, an dem ich gerade arbeite, zu finden / anzufordern. Es gibt eine Referenzimplementierung, wenn Sie angeben, dass Sie an der Entwicklung von Kabelboxen interessiert sind, die Sie möglicherweise erhalten können. Es heißt die "tru2way" oder "OCAP" Referenz-Stack-Implementierung und ich denke, das Projekt ist irgendwo auf der Java-Site verfügbar. Könnte ein bisschen googlen - und ich bin mir ziemlich sicher, dass Sie alles in einem speziellen Klassenlader oder SecurityManager finden.

EDIT: Ich denke, ich könnte falsch liegen. Wir erstellen "Berechtigungen" mit dem Sicherheitsmanager basierend auf dem Namen der Klasse, auf die zugegriffen wird. Wenn ein Thread versucht, eine Methode für die Klasse aufzurufen, testen wir zuerst seine Berechtigungen (wir schreiben den Code innerhalb der Klasse "protected") und wenn der aktuelle Thread nicht über die Berechtigung verfügt, die durch den Namen der Klasse identifiziert wird, löst er ein Ausnahme.

Gleicher Effekt wie später, aber langsamer und ausführlicher. Aber dann müssen wir verhindern, dass Kinder pr0n anschauen.

Bearbeiten 2: (Entschuldigung !!)

Wenn ich auf solche Berechtigungsbeschreibungen schaue, glaube ich, dass es zumindest teilweise möglich ist:

Dadurch wird Codeberechtigung für die Abfrage einer Klasse für ihre öffentlichen, geschützten, standardmäßigen (Paket-) Zugriffs- und privaten Felder und / oder Methoden erteilt. Obwohl der Code Zugriff auf die privaten und geschützten Feld- und Methodennamen hätte, hätte er keinen Zugriff auf die Daten des privaten / geschützten Felds und könnte keine privaten Methoden aufrufen. Dennoch kann bösartiger Code diese Informationen verwenden, um einen Angriff besser zu zielen. Darüber hinaus kann es beliebige öffentliche Methoden aufrufen und / oder auf öffentliche Felder in der Klasse zugreifen. Dies könnte gefährlich sein, wenn der Code normalerweise nicht in der Lage wäre, diese Methoden aufzurufen und / oder auf die Felder zuzugreifen, da er das Objekt nicht mit diesen Methoden und Feldern an die Klasse / Schnittstelle übergeben kann.

Sonst könnten Applets daran gehindert werden, beliebige JVM-Klassen zu instanziieren und darauf zuzugreifen? Es ist möglich, dass die "Gefährlichen" Pfade auf die gleiche Art und Weise blockiert werden, wie wir unsere Sachen blockieren - indem wir die Berechtigungen jedes Mal lesen, wenn sie aufgerufen werden - aber das obige Zitat lässt den Eindruck entstehen, dass mehr verfügbar ist und die meisten Klassen komplett blockiert sind Standard.

Das hat mich eine Weile interessiert, aber ich habe mich nie wirklich darum gekümmert.

    
___ answer1863505 ___

Nein, es gibt keine Möglichkeit, dies zu tun.

Beste Wünsche,
Fabian

    
___ answer1863687 ___

Man kann nur auf einen zugänglichen Typ umwandeln. Indem Sie GameState privat, paketgeschützt oder geschützt machen, können Sie einschränken, wer darauf casten darf.

Wenn Sie nicht vertrauenswürdigen Code ausführen, müssen Sie einen Sicherheitsmanager installieren, da die Reflektion dazu verwendet werden kann, Zugriffsmodifizierer in der Datei absensce zu umgehen (siehe Feld.setAccessible )

    
___ tag123java ___ Java (nicht zu verwechseln mit JavaScript oder JScript oder JS) ist eine universelle objektorientierte Programmiersprache, die für die Verwendung in Verbindung mit der Java Virtual Machine (JVM) entwickelt wurde. "Java-Plattform" ist der Name für ein Computersystem, auf dem Tools zum Entwickeln und Ausführen von Java-Programmen installiert sind. Verwenden Sie dieses Tag für Fragen, die sich auf die Java-Programmiersprache oder Java-Plattform-Tools beziehen. ___ tag123casting ___ Casting ist ein Prozess, bei dem ein Objekttyp explizit in einen anderen Typ konvertiert wird, wenn die Konvertierung zulässig ist. Dieser Prozess könnte zu einer Wertänderung führen. ___ answer1863507 ___

Ich weiß nicht, ob das, was Sie beschreiben, in Java möglich ist. In anderen Sprachen können Sie typecast-Operatoren überlasten und sie eine Exception oder etwas auslösen lassen, aber das ist in Java nicht möglich. Ihre beste Wette ist wahrscheinlich, es auf eine der "vielen anderen Arten" zu tun, über die Sie gesprochen haben.

    
___