Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

09.07.2014, 12:29

Überladene Funktion Reihenfolge

Guten Tag,
ich habe folgendes Problem.
Ich habe einen Header, in dem ich ein paar freie Funktionen definiert habe, welche alle Templates sind.
Manche der Funktionen haben eine genauere Definition der übergebenen Parameter, als andere.

Hier mal 2 Beispiele:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
template<class T>
std::set<PointF> intersections(const LineBase<T>& first, const LineBase<T>& other)
{
    // ...
}

template <class Geo1, class Geo2>
std::set<PointF> intersections(const Geo1& first, const Geo2& second)
{
    //...
}


LineBase ist die Basisklasse meiner Lines, welche einen Templateparameter des zu haltenden Datentyps (int, float, etc.) erwartet. An die Funktion werden allerdings nur ausdefinierte Childklassen übergeben.
Die 2. Überladung erwartet 2 Typen von egal welcher Geometrie Klasse (also, Line, Rechteck, Parallelogramm, etc.).
Ich mache also folgendes:

C-/C++-Quelltext

1
2
3
GEOMETRY::Line line1(p1, p2);
GEOMETRY::Line line2(4, 1, 5, 7);
auto& p : GEOMETRY::intersections(line1, line2);

Ich erstelle mir 2 Linien, und prüfe ob sie sich überschneiden, und wenn ja, wo (Schnittpunkte werden im set zurück geliefert).
Und hier kommen wir zum eigentlichen Problem.
Es wird jetzt Überladung 2 aufgerufen, obwohl ich eigentlich möchte, das Überladung 1 aufgerufen wird.
Das ist auch soweit logisch, dass das so geschieht, nur wie löse ich nun das Problem?
Es ist zwingend notwendig, das für spezielle Typen, spezielle Überladungen aufgerufen werden. Da es aber für jede Geometrie 2 abgeleitete Klassen gibt (Von LineBase erbt Line und LineF, wobei LineF die float Variante ist) würde ich das ganz gerne über die Basisklasse regeln, um eben Redundanzen zu vermeiden.

Meine Überlegung war daraufhin, für alle Geometrieklassen eine Grundlegende Basisklasse zu schaffen, sodass ich hier besser unterscheiden kann.

Welche Möglichkeiten habe ich denn jetzt, oder kann mir jemand ein besseres Design vorschlagen, auf welches ich nicht komme?

mfg

2

09.07.2014, 13:11

Was genau macht denn die zweite Überladung?

Falls alle Geometrie-Klassen von derselben Basisklasse abgeleitet sind, könntest du das doch mit Polymorphie lösen:

C-/C++-Quelltext

1
2
3
4
std::set<PointF> intersections(const GeometryBase& first, const GeometryBase& second)
{
    //...
}

Dann brauchst du dafür kein Template.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

3

09.07.2014, 13:45

Das wäre dann allerdings dynamische Polymorphie statt statische. Ich würde es so machen, denn das ist OOP. Aber C++ ist ja immer etwas eigen mit seiner statischen Polymorphie - aus scheinbaren Performance-Gründen (zumindest hier gibt es außer dem wohl keinen schlüssigen Grund keine Klassen-Hierarchie zu haben).
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

09.07.2014, 14:05

Das Problem ist wohl, dass beides Funktionstemplates sind und die erste Variante eine implizite Konvertierung der Parameter benötigt, weshalb die zweite Variante nach den Overload Resolution Rules der bessere Match ist. Ich weiß nicht, wie genau das mit deiner LineBase<T> etc. funktioniert und mich wundert ein wenig, wieso genau diese Basisklasse benötigt wird bzw. wieso du deine Funktionsparameter hier in Form von Basisreferenzen haben musst, aber ich rate einfach mal ins Blaue und schlage vor, anstatt dem Template

C-/C++-Quelltext

1
2
3
4
5
template<class T>
std::set<PointF> intersections(const LineBase<T>& first, const LineBase<T>& other)
{
    // ...
}

eine Friend Function Definition in LineBase<T> zu machen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
template<class T>
class LineBase
{
  // ...

  friend std::set<PointF> intersections(const LineBase& first, const LineBase& other)
  {
    // ...
  }
};


Dies führt dazu, dass intersections(const LineBase&, const LineBase&) kein Template mehr ist, sondern für jede Instanz von LineBase<T> eine Funktion generiert wird, welche gegenüber dem allgemeinen Template dann bevorzugt wird.

EDIT: Wieso returned intersections() von zwei LineBase<T> eigentlich einen PointF und keinen Point<T>?

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »dot« (09.07.2014, 14:11)


5

09.07.2014, 16:46

Ok, erstmal danke für die Antworten.
Wie bereits geschrieben, hatte ich auch die Idee, eine generelle Basisklasse für alle Figuren zu nutzen, das funktioniert aber leider nicht (Bzw. funktioniert schon, nur bringt mir das dann herzlich wenig, da ich manche Methoden auf Grund ihres Rückgabewertes nicht überschreiben kann).
Ich habe mir für jede Klasse einen Iterator geschrieben, mit welchem ich auf alle Lines zugreifen kann, hier wäre natürlich die Möglichkeit vorhanden, ein end und begin Iterator zu übergeben. Halte ich prinzipiell gar nicht mal für eine schlechte Methode.

Eine friend Funktion kannte ich bisher gar nicht, werde da mal mit rumspielen, danke für den Hinweis ;)

Warum ich einen PointF returne? Die Schnittpunkte liegen ja eher selten direkt auf einer ganzen Koordinate, sondern eher dazwischen. Ich möchte einfach die Möglichkeit bieten, selbst zu entscheiden, ob man die Nachkommastellen nutzt, oder wie man damit verfahren möchte, ohne das von vorneherein in einen anderen Datentyp casten zu müssen.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »anti-freak« (09.07.2014, 17:01)


Werbeanzeige