2012-07-25 17 views
5

Estoy creando una biblioteca que implica coordenadas tridimensionales, y descubrí que hay dos nombres para los componentes de un ángulo tridimensional: cabeceo y cabeceo elevación del bancoMiembro de referencia de clase apunta a otro miembro de la misma clase

Así que me hizo el siguiente (hecho en 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) 
} 

que tiene la ventaja de mantener el equivalente notación entre los dos nombres-esquemas. Por ejemplo:

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

Me preguntaba si el compilador se daría cuenta de las referencias eran innecesarias, o si sería mantener los punteros en la estructura.

Además, ¿hay una mejor manera de tener dos nombres para un miembro?

Respuesta

2

Me preguntaba si el compilador se daría cuenta de las referencias eran innecesarias, o si sería mantener los punteros en la estructura.

En el 99.9% de los casos, los punteros se mantendrán en la estructura. No veo una forma para que el compilador los excluya en unidades de traducción. Esp puesto que su sintaxis es inválida, y usted tendría que inicializar las referencias en el constructor, que muy bien podrían estar ocultas. Entonces no habría forma de que sepa qué referencia hace referencia a qué miembro.

También puede haber algunos gastos generales de rendimiento. Por ejemplo:

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] 

De hecho, internamente, las referencias actúan como punteros. Por lo tanto, el mov adicional compensa la desreferenciación de ese puntero.

Sin embargo, no me preocuparía, sino que me preocuparía el estilo. Y tener dos miembros contabilizando lo mismo ... simplemente parece estar mal.

0

¿Por qué hacer tantas variables públicas?

puede simplemente hacer algunos captadores y definidores (pseudocódigo):

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

Básicamente estaba escribiendo lo mismo :) Pero, ¿no deberías devolver referencias a los atributos reales? De lo contrario, no se pueden modificar con el nombre alternativo. En realidad, se deben proporcionar dos conjuntos de métodos: 'const float & yaw() const;' y 'float & yaw();'. Entonces también funcionará con referencias a un 'Ángulo 'constante. – betabandido

+0

@betabandido edito mi código lejos^_^como dije es 'pseudocode'. Obviamente, no sería completamente así^_^(y devuelvo referencias por cierto :-P) – Neal

+0

@LuchianGrigore ahhh! ** pseudocódigo ** ___pseudocódigo___ _pseudocódigo_. – Neal

1

Puedo pensar en dos opciones diferentes. La primera de ellas sería más o menos lo @Neal ya se ha sugerido, pero incluyendo bienes código C++:

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; } 
}; 

el primer conjunto de métodos devuelve referencias no constante, por lo que es posible modificar realmente los atributos de la estructura mediante estos métodos. Por ejemplo:

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

La segunda serie se utiliza cuando se tiene una referencia constante a un ángulo y lo que desea es leer los valores en la estructura. Por ejemplo:

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

He comprobado el código de ensamblaje generado por GCC. Tanto el uso directo de un atributo de estructura (por ejemplo, a.heading) como el uso de un método de alias (por ejemplo, a.yaw()) generan el mismo código de ensamblaje, por lo que no paga ninguna penalización por usar el método de alias.

La segunda forma en que puedo pensar sería usar un enfoque totalmente diferente. Algo como esto:

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; 
Cuestiones relacionadas