2012-07-25 9 views
5

Ich mache eine Bibliothek, die 3D-Koordinaten enthält, und entdeckte, dass es zwei Namen für die Komponenten eines 3D-Winkels gibt: Gier-Pitch-Roll und Heading- Elevation-BankKlassenreferenzelement zeigt auf ein anderes Element in derselben Klasse

Also habe ich die folgende (done in C++ 11):

struct Angle { 
    float heading; 
    float elevation; 
    float bank; 
    float &yaw = heading; 
    float &pitch = elevation; 
    float &roll = bank; 

    // Some Constructors (copy and assignment have to be made manually) 
} 

die den Vorteil der Beibehaltung der Schreibweise gleichwertig zwischen den beiden Namensschemata hat. Zum Beispiel:

Angle angle; 
rotate(angle.yaw); // this is equivalent to rotate(angle.heading) 

Ich frage mich, ob der Compiler die Referenzen waren unnötig herausfinden würde, oder wenn es wäre die Zeiger in der Struktur zu halten.

Gibt es auch eine bessere Möglichkeit, zwei Namen für ein Mitglied zu haben?

Antwort

2

ich mich gefragt, ob der Compiler die Referenzen waren unnötig herausfinden würde, oder wenn es die Zeiger in der Struktur halten würde.

In 99,9% der Fälle werden die Zeiger in der Struktur beibehalten. Ich sehe keine Möglichkeit für den Compiler, sie über Übersetzungseinheiten auszuschließen. Esp, da Ihre Syntax ungültig ist und Sie die Referenzen im Konstruktor initialisieren müssen, die sehr gut versteckt werden könnten. Es gäbe also keine Möglichkeit zu wissen, welche Referenz auf welches Mitglied Bezug nimmt.

Es könnte auch etwas Leistungs Overhead sein. Zum Beispiel:

float x = a.elevation; 
013F13E0 fld   dword ptr [ebp-18h] 
013F13E3 fstp  dword ptr [x] 
    float y = a.pitch; 
013F13E6 mov   eax,dword ptr [ebp-0Ch] 
013F13E9 fld   dword ptr [eax] 
013F13EB fstp  dword ptr [y] 

In der Tat, Referenzen funktionieren wie Zeiger. Das Extra mov gleicht den Dereferenzieren dieses Zeigers aus.

Ich würde mir keine Sorgen machen, würde sich stattdessen um den Stil kümmern. Und zwei Mitglieder für dasselbe zu haben ... scheint einfach falsch zu sein.

0

Warum so viele öffentliche Variablen?

Sie können nur einige Getter und Setter (Pseudo-Code) machen:

struct Angle { 
    float heading; 
    float elevation; 
    float bank; 

    float& yaw() const { 
     return heading; 
    } 
    float& pitch() const { 
     return elevation; 
    } 
    float& roll() const { 
     return bank; 
    } 

    //etc... 

    // Some Constructors (copy and assignment have to be made manually) 
} 
+0

Ich schrieb im Grunde die gleiche Sache :) Aber, sollten Sie nicht Verweise auf die tatsächlichen Attribute zurückgeben? Andernfalls können sie nicht über den alternativen Namen geändert werden. Eigentlich sollten zwei Methoden zur Verfügung gestellt werden: 'const float & gier() const;' und 'float & gier();'. Dann wird es auch mit Referenzen auf einen konstanten "Winkel" arbeiten. – betabandido

+0

@betabandido bearbeite meinen Code weg^_^wie ich schon sagte es ist 'Pseudocode'. Offensichtlich wäre es nicht vollständig wie dieses^_^(und ich gebe Referenzen zurück btw :-P) – Neal

+0

@LuchianGrigore ahhh! ** Pseudocode ** ___pseudocode___ _pseudocode_. – Neal

1

Ich kann mir zwei verschiedene Möglichkeiten vorstellen. Die erste wäre so ziemlich das, was @Neal hat bereits vorgeschlagen, aber einschließlich Echt C++ Code:

struct Angle { 
    float heading; 
    float elevation; 
    float bank; 

    float& yaw() { return heading; } 
    float& pitch() { return elevation; } 
    float& roll() { return bank; } 

    const float& yaw() const { return heading; } 
    const float& pitch() const { return elevation; } 
    const float& roll() const { return bank; } 
}; 

Der erste Satz von Methoden gibt nicht konstante Referenzen, so ist es möglich, tatsächlich die Attribute durch diesen die Struktur zu ändern Methoden. Zum Beispiel:

Angle a{60, 45, 0}; 
a.roll() = 15; 

Der zweite Satz wird verwendet, wenn Sie einen konstanten Verweis auf einen Winkel haben, und Sie wollen nur die Werte in der Struktur zu lesen. Zum Beispiel:

void print_yaw(const Angle& a) { 
    std::cout << "yaw=" << a.yaw() << std::endl; 
} 

Ich habe den Assembler-Code überprüft, der von GCC generiert wurde. Beide, die direkt ein struct-Attribut (z. B. a.heading) verwenden und eine Alias-Methode (z. B. a.yaw()) verwenden, generieren denselben Assemblierungscode, sodass Sie keine Strafe für die Verwendung der Alias-Methode zahlen.

Die zweite Möglichkeit, die ich denken kann wäre einen völlig anderen Ansatz zu verwenden. Etwas wie dieses:

enum Accessors { HEADING=0, ELEVATION, BANK }; 
enum AliasedAccessors { YAW=0, PITCH, ROLL }; 
typedef float Angle[3]; 

Angle a{60, 45, 0}; 
std::cout << a[HEADING] << " must be equal to " << a[YAW] << std::endl; 
Verwandte Themen