Frage

Ich arbeite an Code, die Nearest-Neighbor-Abfragen. Es gibt zwei einfache Ideen, die zu Grunde liegen, wie ein Benutzer Daten in einer Suchabfrage können:

  • am nächsten N Punkte zu einem bestimmten Punkt im Raum.
  • alle Punkte innerhalb einer bestimmten Entfernung.

In meinem Code, werden Punkte in einen Punktliste setzen, und die Punktliste ist ein Container die Aufgabe, die Verfolgung der Punkte hat, die bei der Suche gefunden wurde.

Im Moment meiner Punktliste Objekt hat einen Konstruktor:

PointList( unsigned int maxvals ); // #1

Die nächsten beiden Konstrukteure, die Ich mag würde hinzufügen, sind diese:

PointList( float maxdist ); // #2
PointList( unsigned int maxvals, float maxdist ); // #3

Meine Frage ist: Wie kann ich sicherstellen, dass meine Benutzer und der C ++ Compiler das Recht generieren Konstruktor für die Punktliste und unterscheidet zwischen Konstruktoren 1 und 2? Soll ich implementieren gerade # 3 und Konstanten zur Verfügung stellen, die großen willkürlich definieren Werte für maxvals und maxdist? Eine weitere Alternative könnte ein anderes System von leichten Gegenständen zu schreiben, die die Logik für das Hinzufügen von Punkten in die Liste regieren, aber das fühlt sich an wie viel des Guten für eine so einfache Idee.

Ich versuche wirklich für meine Benutzer transparent zu machen, die vor allem Wissenschaftler, die C ++ gelernt haben, manchmal ohne den Nutzen der formalen Bildung. Dank!

War es hilfreich?

Lösung

Die Überladungsauflösung für Integer-Typen passiert auf zwei Kategorien, die sehr grob zusammengefasst werden können

  • Promotion: Dies ist eine Konvertierung von Typen kleiner als int int oder unsigned int, je nachdem, ob int alle Werte des Quelltypen speichern kann.
  • Konvertierung. Dies ist eine Konvertierung von beliebigen ganzzahligen Typ in einen anderen Typ Integer

ähnliche, Konvertierung für Punkttypen Floating passiert auf zwei Kategorien

  • Promotion: Dies ist eine Umwandlung von float zu double
  • Konvertierung: Dies ist eine Konvertierung von jedem Gleitkomma-Typ in einer anderen Gleitkommatyps

Und es gibt eine Umwandlung von Integer in Schwimm- oder zurück. Dies wird als eine Umwandlung gewählt, anstatt eine Förderung. Eine Förderung ist auf Platz besser als eine Umwandlung, und wo nur eine Förderung benötigt wird, wird dieser Fall bevorzugt werden. So können Sie die folgenden Konstrukteure verwenden

PointList( int maxVals );
PointList( unsigned int maxVals );
PointList( long maxVals );
PointList( unsigned long maxVals );

PointList( double maxDist );
PointList( long double maxDist );

Für jeden Integer-Typen, soll dies die erste Gruppe von Konstruktor wählen. Und für jeden Punkt schwebenden, soll dies die zweite Gruppe von Konstrukteuren wählen. Ihre ursprünglichen zwei Konstrukteuren leicht in einer Mehrdeutigkeit zwischen float und unsigned int führen kann, wenn Sie eine int passieren, zum Beispiel. Für den anderen zwei Argumente Konstruktor, können Sie mit Ihrer Lösung gehen, wenn Sie wollen.


Das heißt, ich auch eine Fabrik-Funktion verwenden würde, weil von der Art des Parameters die Bedeutung der Entscheidung ziemlich zerbrechlich ist, denke ich. Die meisten Menschen würden erwarten, dass das folgende Ergebnis gleich

PointList p(floor(1.5));
PointList u((int)1.5);

Aber es in einem anderen Zustand führen würde.

Andere Tipps

Warum Factory-Methoden nicht statt Konstrukteure verwenden? Factory-Methoden haben den Vorteil, anpassbare Namen.


static PointList createNearestValues(unsigned int maxvals) {}
static PointList createByDistance(float maxdist) {}

Erwägen Sie wahr typedefs . Es ist ein wenig mehr Aufwand seitens des Client-Code, aber Sie sind garantiert Richtigkeit.

Anrufpunktliste (10) für die erste und die Punktliste (10f) für den zweiten.

Für die zweite, können Sie auch 10.0 verwenden.

Wenn Konstrukteure # 1 und # 2 vorhanden ist, der richtige Konstruktor wird aufgerufen, wenn der Wert, den Sie einfügen von float oder int und keine Umwandlung stattfinden soll. So sicher nur, dass Sie die Art der Zahlen machen Sie explizit aufrufen verwenden, um (das heißt 1f und 1). Constructor # 3 scheint nicht viel von einer Option zu sein, da es nicht wirklich notwendig ist, und würde nur Benutzer Ihres Codes verwirren. Wenn Sie die Standardwerte für die beiden Nummer benötigen könnten Sie

PointList(int max, float max=VALUE)

und

PointList(float max, int max=VALUE)

Auch hier: das scheint mehr Schaden dann Code in Bezug auf die Lesbarkeit des Codes zu tun

.

Dies fordert eine gute Lektüre auf Überladungsauflösung .

Ich würde auf jeden Fall verwenden expliziten Konstrukteure. Im Beispiel ist die ganze Zahl ohne Vorzeichen konvertiert nicht implizit.

class A
{
public:
    explicit A(float f){}
    explicit A(int i){}
};

void test(){
    unsigned int uinteger(0);
    A a1(uinteger);        //Fails, does not allow implicit conversions

    A a2((float)uinteger); //OK, explicit conversion

    float f(0.0);
    A a3(f);               //OK

    int integer(0);
    A a4(integer);         //OK
}

Die Fehlermeldung ist leicht genug, um zu verstehen:

: error C2668: 'A::A' : ambiguous call to overloaded function
: could be 'A::A(int)'
: or       'A::A(float)'
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top