2012-02-06 26 views
7

Tôi đang gặp khó khăn trong việc đặt câu hỏi về những gì tôi đang cố hỏi để tôi cung cấp cho bạn một ví dụ:Cú pháp quá tải của toán tử cơ bản trong C++

Giả sử chúng tôi đang làm việc trên hệ thống 3D xác định một lớp vectơ, Vec3. Chúng ta quá tải một số toán tử số học cho các resons rõ ràng. Trong số này chúng ta quá tải toán tử * sao cho nó sẽ trả về dấu chấm của hai vectơ. Bây giờ mã của chúng tôi nên tìm một cái gì đó như thế này:

class Vec3{ 
private: 
    float x, y, z; 
public: 
    float operator*(const Vec3&) const; //dot product 
. 
. 
. 

Bây giờ nói rằng chúng tôi muốn để có thể mở rộng vector của chúng tôi bằng cách sử dụng các nhà điều hành * với một cái gì đó, nói một phao. Điều này có thể được thực hiện bằng cách tuyên bố như sau:

Vec3 operator*(const float) const; 
    friend Vec3 operator*(const float, const Vec3&); 

này yeilds hai quá tải và Tôi tự hỏi nếu có một cách để làm điều đó chỉ với một cú, tức là nói chúng ta khai báo này thay cho hai dòng trên:

friend Vec3 operator*(const Vec3&, const Vec3&); 

và sau đó thêm giá trị mặc định cho Vec3 ctor để xử lý chuyển đổi từ phao.

ví dụ cuối cùng này sẽ làm việc cho:

Vec3 someVec3 = 1.0 * otherVec3; //through friend Vec3 operator*(const float, const Vec3&) 

tuy nhiên không cho điều này:

Vec3 someVec3 = otherVec3 * 1.0; 

như trình biên dịch sẽ không biết được của hai sử dụng:

friend Vec3 operator*(const float, const Vec3&); //the one we want to use 
or 
    float operator*(const Vec3&) const; //the one for the dot product 

Mọi đề xuất?

Cảm ơn bạn!

+3

Có gì sai với hai lần quá tải? Khi bạn chỉ ra, một sự mơ hồ khá khó chịu được tạo ra khi bạn cố gắng đơn giản hóa nó ... –

+2

Điều duy nhất tôi sẽ làm khác đi, là tạo ra cả hai phiên bản của vô hướng các hàm bạn bè thay vì một thành viên, để mã sẽ có cùng tính đối xứng với chính nó. –

+0

Sẽ không hiệu quả khi xây dựng một véc tơ chỉ để vượt qua một phao. Đây sẽ là một thời gian chạy không hiệu quả nhưng một chức năng quá tải thêm có thể được inlined. – QuentinUK

Trả lời

5

Trong trường hợp này tôi ban đầu sẽ tham mưu chống khai thác quá tải, vì thế nào là người sử dụng của bạn để biết nếu * đại diện cho dấu chấm hoặc chéo sản phẩm (cả hai đều là ý nghĩa hợp lý tùy thuộc vào dự kiến ​​sử dụng của khách hàng). Tôi thực sự khuyên bạn không nên hỗ trợ operator* và làm điều đó với các thành viên dot, crossscale. Sau đó, bạn không phải lo lắng về nhiều tình trạng quá tải và nó rõ ràng cho người dùng của bạn những gì họ đang nhận được.

Tuy nhiên, nếu bạn muốn tiếp tục với các nhà khai thác, không có gì sai khi có hai tình trạng quá tải. Tạo ra một giả Vec3 để làm rộng không chỉ là ngữ nghĩa sai, nó sẽ thêm một lượng nhỏ chi phí không cần thiết.

1

Không có gì sai trong một vài quá tải, đặc biệt là không nếu họ có thể dễ dàng được thực hiện trong điều kiện của nhau là:

Vec3 operator*(const float scale, const Vec3& vec) 
{ return vec * scale; } 

Thật khó để có được nó đơn giản hơn thế!

2

Boost.Operators có thể thực hiện hầu hết công việc nồi hơi cho bạn. Ví dụ .:

class Vec3 
    : boost::multipliable2<Vec3, float> 
{ 
public: 
    // ... 

    Vec3 operator*=(float); 
    // Vec3 operator*(Vec3, const float&) and 
    // Vec3 operator*(const float&, Vec3) auto-generated 
    // by multipliable. 
}; 
Các vấn đề liên quan