2009-05-22 4 views
1

Was ist eine gute Faustregel, ob der Rückgabewert einer const Member-Funktion const sein sollte oder nicht? Hier ist, was ich tendiere zu tun, aber ich kämpfe mit mehrdeutigen Szenarien.Konstanz des zurückgegebenen Objekts (s) aus einer const Member-Funktion

class foo 
{ 
    public: 
     // if the returned object is conceptually 
     // (and therefore usually literally but not even necessarily) 
     // owned by *this*, 
     // then a const ptr should be returned 
     const ownedByFoo *getOwnedByFoo() const { return m_ownedByFoo; } 
     ownedByFoo *getOwnedByFoo() { return m_ownedByFoo; } 

     // what's a poor boy to do here? 
     // veryRelatedToFoo might be a conceptual contemporary or parent 
     // of Foo. Note naming the function "find..." instead of "get.." 
     // since *get* implies the object holds it as a data member but 
     // that may not even be the case here. There could be a 
     // standalone container that associates foo and veryRelatedToFoo. 
     // Should constness be symmetrical here? 
     const veryRelatedToFoo *findVeryRelatedToFoo() const; 
     veryRelatedToFoo *findVeryRelatedToFoo(); 

     // If the returned object is only (conceptually) 
     // peripherally related to *this*, 
     // the returned object probably shoudn't be const, even if 
     // foo happens to have one of these as a direct data member, 
     // since we don't want to give away the implementation details of 
     // Foo and it may hold peripherallyRelatedToFoo simply for performance 
     // reasons, etc. 
     peripherallyRelatedToFoo *findPeripherallyRelatedToFoo() const 

    ... 
}; 

Ein weiterer Hinweis ist, dass, sobald Sie asymmetrische Konstantheit haben, Sie Ein konstantes Objekt fragen konnte Objekt B zurück, dann Objekt B fragen Objekt A zurückzukehren, und dann haben Sie es geschafft, die dazu bestimmt umgehen Beschaffenheit des Objektes A.

Antwort

1

Etwas Konstanz zu haben ist mehr als man in vielen Sprachen findet!

Sobald Sie (wie Sie haben) den Unterschied zwischen "physisch const" und "logisch const" verstehen, bleiben die "zweideutigen" Szenarien genau das: Thema der Debatte. Bedenken Sie zum Beispiel, dass das Schlüsselwort mutable existiert.

Ich glaube Ihnen, die richtige allgemeine Idee haben, und darüber hinaus, dass es alles strittig und subjektiv und variiert entsprechend dem speziellen Problem und Einschränkungen usw.

Ich neige dazu, ‚keine Ausnahmen von der Regel‘ zu bevorzugen, so dass ich würde es vermeiden, einen Zeiger auf nicht const von einer const-Methode zurückzugeben; aber ich denke, ich kann mir einige Szenarien vorstellen, in denen ich versucht werden könnte ... obwohl ich mich eher dafür entscheiden könnte, die Methode nicht-konstant zu machen.

1

(Ich bin die Tatsache ignorieren, dass Sie Objektzustand direkt wie das zurückkommen, was in der Regel eine schlechte Idee, weil es Verkapselung bricht - ich dies als „Beispielcode“ suchen)

Es ist keine Beziehung zwischen den beiden. Eine const Elementfunktion ist ein Element, das das zugrunde liegende Objekt nicht ändert - "während es ausgeführt wird". Es gibt keine Zusage oder Anforderung, dass der Rückgabewert const ist oder nicht. Der const -ness-Vertrag ist "over", sobald die Methode zurückkehrt. Ich denke, du wirst verwirrt, weil du versuchst, den Rückgabewert mit der Methode zu verbinden, die ihn erzeugt hat.

Ob der zurückgegebene Wert const oder nicht const ist, hängt ausschließlich von der Art des zurückgegebenen Werts und der Semantik ab, die Sie der Methode zuweisen möchten.

In Ihrem spezifischen ersten Fall sollten die beiden Methoden dieselbe const -ness zurückgeben. Die const Überladung ist wahrscheinlich nicht das, was Sie verwenden möchten. Wenn Sie die beiden Variationen wollen, würde ich wahrscheinlich es explizit machen, wie solche:

const ownedByFoo *getOwnedByFoo() const { return m_ownedByFoo; } 
ownedByFoo *getOwnedByFooForEdit() { return m_ownedByFoo; } 

Auf diese Weise gibt es keine Zweideutigkeit ist und keine geheimnisvolle Bindung der beiden. Beachten Sie, dass ich das zweite nicht-const gemacht habe, weil wir wahrscheinlich nicht möchten, dass Client-Code m_ownedByFoo für ein const-Objekt ändert. Das ist eine Anforderung, die aus der Semantik der Methode ("gibt den internen Zustand" zurück), nicht aus einer Verknüpfung zwischen der constness der Methode und der const -ness des Rückgabewerts. Wenn der zurückgegebene Wert nicht Teil des Objektstatus ist, würde ich wahrscheinlich etwas anderes tun.

+1

Technisch gesehen haben Sie Recht mit dem Const-ness-Vertrag, aber das ist eine übermäßig wörtliche Interpretation. Wenn Sie ein Objekt unschuldig (wie in const) bitten, ein Stück von sich selbst zu übergeben, und erhalten Sie (eine geladene Waffe in Form von) ein nicht-konstantes Objekt, das Sie dann nach Herzenslust modifizieren können? Diese Methode ist ein trojanisches Pferd in dein Objekt. Ihre 2nd pt ist gut. Ich denke, die Leute sind im Allgemeinen an die überladene Signatur gewöhnt, weil sie die gleiche get-Methode überall in const und non-const verwenden können, ohne darüber nachzudenken, aber den Anrufer darüber nachzudenken, ist oft eine gute Sache –

+0

@ No-Op, Sicher, ich stimme zu und ich finde, dass die wörtliche Interpretation Verwirrung verhindert. Es kann argumentiert werden, dass Sie in diese Falle gegangen sind, indem Sie zunächst eine geladene Waffe zur Verfügung gestellt haben (einen Zeiger auf einen Nicht-Konstanten Ihres Zustands). Ich könnte entweder vorschlagen: a) Betrachte immer eine const * (mach das zu deiner Semantik). b) Überlegen Sie, ob Sie eine Kopie des tatsächlichen Zustands bereitstellen; Geben Sie das in Ihrer Semantik an und zahlen Sie die entsprechenden Kopierkosten. c) Überlegen Sie, ob die Konstante const privat ist, damit die Methode nicht für ein const-Objekt aufgerufen werden kann. –

+0

... Ich persönlich finde es zu dunkel, dass die Konstanz des Rückgabewerts von der Beschaffenheit Ihres Objekts abhängt. YMMV. –

0

Geben Sie keinen nichtkonstanten Zeiger oder Verweis auf Elementdaten von einer Konst-Methode zurück.

0

Wenn die zurückgegebene Referenz const ist, machen Sie die Funktion const, wenn nicht, tun Sie es nicht. Sie sollten versuchen, die Rückgabe einer nichtkonstanten Referenz an die Member-Daten zu vermeiden, da dadurch die Kapselung unterbrochen wird, es sei denn, die Klasse ist in erster Linie eine Art von Containerklasse.

0

Wenn die Rückgabe eines nichtkonstanten Verweises/Zeigers dem Aufrufer erlauben würde, eine Invariante zu annullieren, die die Klasse beibehalten soll, geben Sie diesen nichtkonstanten Verweis/Zeiger nicht zurück. (Es sollte const sein.)

Verwandte Themen