2012-07-25 47 views
5

Tôi đang tạo thư viện liên quan đến tọa độ 3-D và phát hiện ra rằng có hai tên cho các thành phần của góc 3-D: yaw-pitch-roll và heading- cao-ngân hàngĐiểm thành viên tham chiếu lớp cho thành viên khác trong cùng một lớp

Vì vậy, tôi đã thực hiện như sau (thực hiện trong 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) 
} 

trong đó có các lợi ích của việc giữ tương đương với ký hiệu giữa hai tên đề án. Ví dụ:

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

Tôi đã tự hỏi liệu trình biên dịch có thể tìm ra các tham chiếu không cần thiết hay nếu nó giữ nguyên con trỏ trong cấu trúc.

Ngoài ra, có cách nào tốt hơn để có hai tên cho một thành viên không?

Trả lời

2

tôi đã tự hỏi nếu trình biên dịch sẽ tìm ra những tài liệu tham khảo là không cần thiết, hoặc nếu nó sẽ giữ cho các con trỏ trong cấu trúc.

Trong 99,9% trường hợp, con trỏ sẽ được lưu giữ trong cấu trúc. Tôi không thấy một cách để trình biên dịch loại trừ chúng trên các đơn vị dịch thuật. Esp vì cú pháp của bạn không hợp lệ và bạn phải khởi tạo các tham chiếu trong hàm tạo, điều này rất có thể bị ẩn. Vì vậy, sẽ không có cách nào cho nó để biết tham khảo tài liệu tham khảo mà thành viên.

Cũng có thể có một số chi phí hiệu suất. Ví dụ:

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] 

Thật vậy, nội bộ, tham chiếu hoạt động như con trỏ. Vì vậy, số mov bổ sung bù cho con trỏ đó.

Tôi sẽ không lo lắng về điều đó, thay vào đó, hãy quan tâm đến phong cách. Và có hai thành viên kế toán cho cùng một điều ... chỉ có vẻ sai.

0

Tại sao có quá nhiều biến công khai?

Bạn chỉ có thể làm cho một số getter và setter (giả):

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

Tôi đã cơ bản viết cùng một điều :) Nhưng, bạn không nên trả lại tham chiếu đến thuộc tính thực tế? Nếu không, chúng không thể được sửa đổi thông qua tên thay thế. Trên thực tế, hai phương thức nên được cung cấp: 'const float & yaw() const;' và 'float & yaw();'. Sau đó, nó cũng sẽ làm việc với các tham chiếu đến một 'Góc' liên tục. – betabandido

+0

@betabandido chỉnh sửa mã của tôi đi^_^như tôi đã nói đó là 'pseudocode'. Rõ ràng nó sẽ không hoàn toàn như thế này^_^(và tôi trả lại tài liệu tham khảo btw :-P) – Neal

+0

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

1

Tôi có thể nghĩ đến hai tùy chọn khác nhau. Người đầu tiên sẽ là khá nhiều những gì @Neal đã gợi ý, nhưng trong đó có thực 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; } 
}; 

Tập đầu tiên của phương pháp trả về tài liệu tham khảo không const, vì vậy nó có thể thực sự thay đổi các thuộc tính của struct qua các phương pháp. Ví dụ:

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

Tập thứ hai được sử dụng khi bạn có tham chiếu liên tục đến một góc và bạn chỉ muốn đọc các giá trị trong cấu trúc. Ví dụ:

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

Tôi đã kiểm tra mã lắp ráp do GCC tạo. Cả hai trực tiếp sử dụng thuộc tính struct (ví dụ: a.heading) và sử dụng phương thức bí danh (ví dụ: a.yaw()) tạo cùng một mã assembly, do đó bạn không phải trả bất kỳ hình phạt nào khi sử dụng phương thức bí danh.

Cách thứ hai tôi có thể nghĩ là sử dụng một cách tiếp cận hoàn toàn khác. Một cái gì đó như thế này:

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; 
Các vấn đề liên quan