2012-07-25 18 views
5

3次元座標を含むライブラリを作成していて、3次元の角度のコンポーネントに2つの名前があることがわかりました:yaw-pitch-rollとheading-標高バンククラス参照メンバが同じクラスの他のメンバを指している

だから私は(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) 
} 

2名、制度間の表記と同等を維持するという利点を有しています。たとえば:コンパイラが参照が不要でした見つけ出すかどうか、それは構造内のポインタを維持するかどう

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

私は思っていました。

また、1人のメンバーに2つの名前を付けるより良い方法はありますか?

答えて

2

コンパイラが参照が不要でした見つけ出すかどうか、それが構造にポインタを続けるならば、私は思っていました。

ケースの99.9%において、ポインタは構造内に保持されます。コンパイラが翻訳単位を超えて除外する方法はありません。あなたの構文が無効で、あなたがコンストラクタ内の参照を初期化しなければならないので、非常に隠れる可能性があります。だからどの参照がどのメンバーを参照しているかを知る方法はありません。

パフォーマンスのオーバーヘッドもある可能性があります。例:

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] 

実際、内部的には、参照はポインタのように動作します。したがって、余分なmovは、そのポインタの逆参照を補完します。

私はそれについて心配しないであろうが、代わりにスタイルを気にするだろう。 2人のメンバーが同じことを説明しているのは間違っているようです。

0

なぜ多くの公開変数を作成するのですか?

あなただけのいくつかのゲッターとセッター(擬似コード)を作ることができます。

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

私は基本的に同じことを書いていました:)しかし、実際の属性への参照を返すべきではありませんか?それ以外の場合は、代替名で変更することはできません。実際には、 'const float&yaw()const;'と 'float&yaw();'の2つのメソッドセットを用意する必要があります。次に、一定の 'Angle'への参照でも動作します。 – betabandido

+0

@betabandido編集私のコード離れて^ _ ^私はそれが '擬似コード'だと言った。明らかに、これは完全にこのようなものではないでしょう^ _ ^(そして、私は参考文献btw:-Pを返します) – Neal

+0

@LuchianGrigoreああ! **擬似コード** ___擬似コード_ _擬似コード。 – Neal

1

私は2つの異なるオプションが考えられます。一つ目は@Nealが既に提案しているものはかなりあることが、実際の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; } 
}; 

方法の第1のセットは非const参照を返すので、実際にこれらを通じて構造体の属性を変更することが可能であるがメソッド。例:

2番目のセットは、角度の定数参照があり、構造体の値を読みたい場合に使用します。例:

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

GCCで生成されたアセンブリコードを確認しました。構造体属性(例:a.heading)を直接使用し、エイリアスメソッド(例:a.yaw())を使用すると、同じアセンブリコードが生成されるため、エイリアスメソッドを使用する場合のペナルティはありません。

私が考えることのできる第2の方法は、全く異なるアプローチを使用することです。このようなもの:

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; 
関連する問題