2017-01-25 1 views
0

In Grafiken sind alle geometrischen Datentypen sehr ähnlich. Um Code-Duplikation zu vermeiden, aber dennoch einen Sinn darin zu haben, empfiehlt der Graphics Codex, eine Vector Klasse mit mehreren Typedefs für Points, Normals und Directions zu verwenden.Typspezifische Typen erzwingen

über die Unterzeichnung So basiert der Normalize Funktion (wie geschrieben steht), weiß man, er mit Directions und nicht Points oder Normals handelt. Natürlich verhindert nichts, dass Sie eine Point oder Normal übergeben, da sie alle Vectors (nur Aliase) sind. Ich frage mich, ob es eine nicht-overhead Möglichkeit gibt, den Programmierer (dh Compiler-Warnstufe 4) zu zwingen, etwas zu übergeben, das explizit Direction deklariert wird (ohne die Struktur Vector mehrfach in verschiedenen Strukturen zu vererben oder mehrmals aus der Struktur Vector zu erben) und wenn nicht, muss der Programmierer eine explizite Besetzung machen (was nur ein Noop ist)? (Haskell zum Beispiel hat diese Funktionalität)

struct Vector { 

    // lots of methods 

    float x, y, z; 
}; 

typedef Vector Point; 
typedef Vector Direction; 
typedef Vector Normal; 

Normal Normalize(const Direction &) { 
    ... 
} 
+1

Schauen Sie sich ** starke typef ** an. – Jarod42

Antwort

1

Der einzige Weg ist eine, die Sie Sie bedeuten nicht mögen, aber hier ist es:

struct Point : Vector {}; 
struct Direction : Vector {}; 
struct Normal : Vector{}; 

gibt es nicht viel Nachteil, abgesehen von zu müssen Definieren und delegieren Sie eventuell vorhandene Konstruktoren.

Für C und unter Verwendung von speziell GCC, hier ist eine vorherige Frage zu diesem Thema: Warn if another typedef'd name of a type is used in an argument list

1

Natürlich können Sie das tun. Sie können dafür die Vererbung verwenden. Solange Sie keine virtuellen Methoden verwenden, erhalten Sie keinen Laufzeitaufwand.

Der Code würde wie folgt aussehen:

struct Vector3d { 
    float x, y, z; 
}; 

struct Direction : 
    public Vector3d { 

}; 

Wenn Sie spezielle constructos haben, dass Sie verwenden möchten, können Sie sie in die Childs mit der Verwendung von Erklärungen enthalten.

2

Sie könnten das tun auch mit Vorlagen, mit dem Vorteil, nicht alle Konstrukteure reimplementieren mit:

template<typename tag> 
struct Vector { 
    ... 
}; 

namespace tags { 
    struct point; 
    struct direction; 
    struct normal; 
} 

typedef Vector<tags::point> Point; 
typedef Vector<tags::direction> Direction; 
typedef Vector<tags::normal> Normal; 

Normal Normalize(const Direction &) { 
    ... 
} 

ist jedoch zu beachten, dass, obwohl es nicht der Laufzeit-Overhead hat, es Codegröße hat mitgehört (die Vorlage, die mit jedem anderen Tag instanziiert wird, sowie Kompilierungszeit-Overhead (Konsolidierung aller schwachen Symbole, die von Instanziierungen in jeder Übersetzungseinheit stammen, in eine einzige Instanz).

Sie können das in gewissem Maße mildern, indem Sie eine nicht-templated Basisklasse bereitstellen, die die "echte Arbeit" ausführt.