Frage

Jemand erzählte mir von einem C ++ Stil Unterschied in ihrem Team. Ich habe meine eigene Sicht auf das Thema, aber ich würde von Vor und cons kommen von allen.

interessiert sein

Also, falls Sie eine Klasse Eigenschaft haben Sie über zwei Getter verfügbar machen möchten, ein Lese- / Schreib, und die andere, nur lesbar (das heißt, es gibt keine festgelegte Methode). Es gibt mindestens zwei Möglichkeiten, es zu tun:

class T ;

class MethodA
{
   public :
      const T & get() const ;
      T & get() ;

      // etc.
} ;

class MethodB
{
   public :
      const T & getAsConst() const ;
      T & get() ;

      // etc.
} ;

Was sind die Vor- und die Nachteile der einzelnen Methoden wäre?

Ich interessiere mich mehr von C ++ technisch / semantischen Gründen, aber Artgründen willkommen sind, auch.

Beachten Sie, dass MethodB einen großen technischen Nachteil (Hinweis: in generischem Code) hat.

War es hilfreich?

Lösung

Nun, für eine Sache, getAsConst muss genannt werden, wenn die ‚this‘ Zeiger const ist - nicht, wenn Sie ein konstantes Objekt erhalten möchten. Also, neben allen anderen Themen, es ist subtil falsch benannt. (Sie können es immer noch an, wenn ‚dies‘ nicht-const ist, aber das ist weder hier noch dort.)

Das Ignorieren, dass getAsConst verdient man nichts, und stellt eine unzumutbare Belastung für die Entwickler der Schnittstelle. Anstatt nur telefonieren „get“ und zu wissen, er bekommt, was er braucht, jetzt muss er wissen, ob oder nicht, dass er zur Zeit eine konstante Variable, und wenn das neue Objekt er erregenden Bedürfnisse const sein. Und später, wenn beiden Objekte nicht-const werden aufgrund eines Refactoring, er hat seinen Ruf wechseln aus.

Andere Tipps

C ++ sollte durchaus in der Lage sein, in fast allen Situationen mit Methode A zu bewältigen. Ich benutze es immer, und ich hatte nie ein Problem.

Methode B ist, meiner Meinung nach, ein Fall der Verletzung von OnceAndOnlyOnce. Und jetzt müssen Sie herausfinden, um zu gehen, ob Sie mit const Referenz zu tun hat, den Code zu schreiben, das erste Mal kompiliert wird.

Ich denke, das eine stilistische Sache ist - technisch sie beide Werke, sondern MethodA macht den Compiler ein wenig härter zu arbeiten. Für mich ist es eine gute Sache.

Ich persönlich ziehe die erste Methode, weil es für eine einheitliche Schnittstelle macht. Auch mir getAsConst () klingt fast so dumm wie getAsInt ().

Auf einer anderen Note, Sie sollten wirklich zweimal überlegen, bevor eine nicht konstante Referenz oder einen nicht konstanten Zeiger auf ein Datenelement der Klasse zurück. Dies ist eine Einladung für Menschen, die das Innenleben Ihrer Klasse zu nutzen, die im Idealfall ausgeblendet werden soll. Mit anderen Worten: es bricht Kapselung. Ich würde einen get () const verwenden und einen Satz () und gebe nur eine nicht konstante Referenz, wenn es keine andere Möglichkeit gibt, oder wenn es wirklich Sinn macht, wie zum Beispiel auf ein Element eines Arrays Lese- / Schreibzugriff geben oder eine Matrix.

den Stil Präzedenzfall durch die Standardbibliothek Given (dh beginnen () und beginnt () const um nur ein Beispiel), sollte es klar sein, dass Verfahren A ist die richtige Wahl. Ich frage die geistige Gesundheit der Person, die Methode B wählt.

So ist der erste Stil ist in der Regel vorzuziehen.

Wir verwenden eine Variation des zweiten Stils ein bisschen in der Codebasis ich derzeit allerdings gerade arbeitete, weil wir einen großen Unterschied zwischen const und nicht-const Nutzung wollen.

In meinem speziellen Beispiel haben wir getTessellation und getMutableTessellation. Es ist mit einem Copy-on-Write-Pointer realisiert. Aus Performance-Gründen wollen wir die const-Version, wo immer möglich verwenden werden, so machen wir den Namen kürzer, und wir machen ihm einen anderen Namen, damit die Leute sowieso nicht versehentlich eine Kopie verursachen, wenn sie schreiben wollten nicht.

Während es Ihre Frage Methode behandelt nur eine erscheint, ich würde gerne meine Eingabe auf Stil geben. Persönlich Artgründen, ziehe ich das erstere. Die meisten IDEs wird die Art Signatur von Funktionen für Sie Pop-up.

Ich würde die erste bevorzugen. Es sieht besser aus in Code, wenn zwei Dinge, die im Wesentlichen die gleiche Sache gleich aussehen tun. Außerdem ist es selten, dass Sie ein nicht-konstantes Objekt haben, aber die konstante Methode aufgerufen werden sollen, so dass nicht viel von einem consern ist (und im schlimmsten Fall, würden Sie brauchen nur ein const_cast <>).

Die erste erlaubt Änderungen der Variablentyp ohne weitere Modifikation des Codes (ob es const ist oder nicht). Natürlich bedeutet dies, dass es keine Benachrichtigung an den Entwickler ist, dass diese von dem beabsichtigten Pfad geändert haben könnten. Es ist also wirklich, ob Sie schnell Refactoring in der Lage zu schätzen, oder die zusätzliche Sicherheitsnetz haben.

Das zweite ist etwas ungarische Notation verwandt, die I persönlich nicht wie so werde ich Stick mit dem ersten Methode.

Ich mag es nicht ungarische Notation, weil es Redundanz hinzufügt, die ich in der Regel in der Programmierung verabscheuen. Es ist nur meine Meinung.

Da Sie die Namen der Klassen verstecken, das zum Nachdenken über Stil kann oder auch nicht gelten:

Ist es sinnvoll, diese beiden Objekte zu sagen, MethodA und MethodB, „get“ oder „getAsConst“? Würden Sie „get“ oder „getAsConst“, wie er Meldungen an das Objekt senden?

So wie ich es sehe, wie der Absender der Nachricht / Aufrufer der Methode, Sie ist derjenige, den Wert bekommen; so in Reaktion auf diese Nachricht „get“, die Sie senden eine Nachricht an MethodA / MethodB, wobei das Ergebnis davon ist der Wert, den Sie benötigen.

. Beispiel: Wenn der Anrufer von MethodA ist, sagen wir, ein Dienst in SOA und MethodA ist ein Repository, dann in den Dienst des get_A (), rufen MethodA.find_A_by_criteria (...)

Der große technologische Nachteil MethodB ich sah, dass, wenn generischen Code darauf anwenden, wir den Code verdoppeln müssen sowohl die const und die nicht-const-Version zu behandeln. Zum Beispiel:

Lassen Sie uns sagen, T ist ein Befehl-able Objekt (dh, wir können auf Objekte vom Typ T Vergleichen mit Operator <), und lassen Sie uns sagen, dass wir die max zwischen zwei MethodA finden möchten (resp. Zwei MethodB).

Für MethodA, alles, was wir brauchen, ist Code:

template <typename T>
T & getMax(T & p_oLeft, T & p_oRight)
{
   if(p_oLeft.get() > p_oRight.get())
   {
      return p_oLeft ;
   }
   else
   {
      return p_oRight ;
   }
}

Dieser Code funktioniert sowohl mit const Objekten und nicht konstanten Objekten vom Typ T:

// Ok
const MethodA oA_C0(), oA_C1() ;
const MethodA & oA_CResult = getMax(oA_C0, oA_C1) ;

// Ok again
MethodA oA_0(), oA_1() ;
MethodA & oA_Result = getMax(oA_0, oA_1) ;

Das Problem kommt, wenn wir diesen einfachen Code, um etwas im Anschluss an die MethodB Konvention anwenden möchten:

// NOT Ok
const MethodB oB_C0(), oB_C1() ;
const MethodB & oB_CResult = getMax(oB_C0, oB_C1) ; // Won't compile

// Ok
MethodA oB_0(), oB_1() ;
MethodA & oB_Result = getMax(oB_0, oB_1) ;

Für die MethodB beide arbeiten auf const und nicht-const-Version, müssen wir beide verwenden die bereits getMax definiert, sondern es die folgende Version von getMax hinzufügen:

template <typename T>
const T & getMax(const T & p_oLeft, const T & p_oRight)
{
   if(p_oLeft.getAsConst() > p_oRight.getAsConst())
   {
      return p_oLeft ;
   }
   else
   {
      return p_oRight ;
   }
}

Fazit, indem sie nicht den Compiler auf const-ness Gebrauch zu vertrauen, wir belasten sie mit der Schaffung von zwei generischen Funktionen, wenn man haben sollte genug gewesen.

Natürlich mit genug Paranoia, die secondth Template-Funktion getMaxAsConst genannt werden sollte ... Und so würde das Problem verbreitet sich durch die gesamten Code ...

- p

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