Frage

Ich habe eine Klasse Mitglied MyMember , die ein ist myType Zeiger. Ich möchte dieses Element in einer Funktion zuweisen, die als const deklariert wird. Ich mache wie folgt:

void func() const
{
     ...
     const_cast<myType*>(myMember) = new myType();
     ...
}

Des Tun funktioniert gut in VC ++, aber GCC gibt einen Fehler mit der Meldung „L-Wert als linker Operand Zuordnung erforderlich“.

Making the member wandelbar erlauben Sie mir einfach die const_cast zu entfernen und den Wert zuweisen. Allerdings bin ich nicht ganz sicher, dass das kommt mit anderen Nebenwirkungen.

Kann ich mein Mitglied zuweisen, ohne das Element wandelbar machen zu müssen? Wie? Gibt es Nebenwirkungen bei der Herstellung von Mitgliedern wandelbar?

War es hilfreich?

Lösung

Der Code würde nicht wirklich Arbeit in VC ++ - Sie nicht den Wert zu aktualisieren (oder zumindest es sollte nicht), also die Warnung von GCC. Korrekter Code ist

const_cast<myType*&>(myMember) = new myType();

oder [von anderer Antwort, danke: P]:

const_cast<ThisType*>(this)->myMember = new myType();

Machen Mutable es effektiv bedeutet, dass Sie impliziten const_casts in const Member-Funktionen zu erhalten, die in der Regel ist das, was Sie Lenkung sein soll, wenn Sie finden sich viele const_casts auf this tun. Es gibt keine ‚Nebenwirkungen mit wandelbar‘ andere als das.

Wie Sie aus den heftigen Debatten kreisen diese Frage sehen können, nolens volens Nutzung von mutable und viele const_casts kann definitiv Symptome schlecht riecht in Ihrem Code. Aus konzeptioneller Sicht Wegwerfen Konstantheit oder mutable verwenden, können viel größere Auswirkungen haben. In einigen Fällen das Verfahren auf nicht-const, das heißt, die richtige Sache zu tun sein kann auf die Tatsache, besitzt bis zu ändern, dass sie Zustand zu ändern.

Es hängt alles davon ab, wie viel const-Korrektheit Angelegenheiten in Ihrem Kontext - Sie möchten nicht nur sprinking mutable herum wie Feenstaub zu machen Sachen Arbeit beenden, aber mutable ist für den Gebrauch bestimmt, wenn das Mitglied ist nicht Teil des beobachtbaren Zustand des Objekts. Die strengste Ansicht von const-Korrektheit halten würde, dass kein einziges Bit den Zustand des Objekts kann geändert werden (zB dies von entscheidender Bedeutung sein könnte, wenn Sie beispielsweise in einem ROM ist ...) - in diesen Fällen müssen Sie nicht jede Konstantheit wollen verloren sein. In anderen Fällen können Sie einige externen Zustand gespeichert irgendwo ouside des Objekts haben - beispielsweise eine Thread-spezifische Cache, der auch in Betracht gezogen werden muss, bei der Entscheidung, ob es angemessen ist,

.

Andere Tipps

Dieses Szenario - eine gekapselte interne Zustandsänderung, die keinen externen Zustand auswirkt (z Caching Ergebnisse.) - ist genau das, was das mutable Schlüsselwort ist für

const_cast ist fast immer ein Zeichen von Design Versagen. In Ihrem Beispiel entweder func() nicht const sein sollte, oder myMember sollte mutable sein.

Ein Anrufer von func() wird erwarten, dass sie nicht zu ändern Objekt; Das aber bedeutet, „nicht zu ändern in einer Weise, die sie wahrnehmen kann“; das ist nicht seine externen Zustand zu ändern. Wenn myMember ändert nicht das externe Statusobjekt ändern, ist das, was das mutable Schlüsselwort ist für; andernfalls func() nicht const sein sollte, weil Sie Ihre Funktion garantiert verraten würden.

Beachten Sie, dass mutable ist kein Mechanismus circunvent const-Korrektheit; es ist ein Mechanismus, um es zu verbessern.

class Class{
int value;
void func()const{
const_cast<Class*>(this)->value=123;
}
};

Wie Steve Gilham schrieb, ist mutable die korrekte (und kurz) Antwort auf Ihre Frage. Ich möchte nur einen Hinweis in eine andere Richtung geben. Vielleicht ist es möglich, in Ihrem szenario Verwendung einer (oder mehr) Schnittstelle zu machen? Vielleicht können Sie es aus dem folgenden Beispiel grok:

class IRestrictedWriter // may change only some members
{
public:
  virtual void func() = 0; 
}

class MyClass : virtual public IRestrictedWriter
{
public:
  virtual void func()
  {
    mValueToBeWrittenFromEverybody = 123; 
  }

  void otherFunctionNotAccessibleViaIRestrictedWriter()
  {
    mOtherValue1 = 123;
    mOtherValue2 = 345;
  }

  ...   
}

Also, wenn Sie zu irgendeiner Funktion eines IRestrictedReader * anstelle einem const MyClass * passieren kann es func nennen und damit Veränderung mValueToBeWrittenFromEverybody während mOtherValue1 Art „const“ ist.

. Ich mutable immer ein bisschen wie ein Hack finden (aber verwende es manchmal).

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