2010-02-05 30 views
12

Tôi muốn xác định toán tử nhị phân trong không gian tên chung. Toán tử hoạt động trên một lớp được xác định trong một không gian tên khác và toán tử sẽ nhận được quyền truy cập vào các thành viên riêng tư của lớp đó. Vấn đề tôi có là tôi không biết cách phạm vi toán tử toàn cục đó khi biến nó thành một người bạn trong định nghĩa lớp.Làm cách nào để xác định bạn bè trong không gian tên chung trong một không gian tên C++ khác?

tôi đã cố gắng một cái gì đó như:

namespace NAME 
{ 
    class A { 
     public: 
      friend A ::operator * (double lhs, const A& rhs); 
     private: 
      int private_var; 
    }; 
} 

A operator * (double lhs, const A& rhs) 
{ 
    double x = rhs.private_var; 
    ... 
} 

Trình biên dịch (g ++ 4.4) không biết phải làm gì với nó. Dường như dòng

friend A ::operator *() 

được đánh giá là một cái gì đó tương tự (pseudo-code)

(A::operator) 

thay vì

(A) (::operator) 

Nếu tôi bỏ qua :: trong việc kê khai của điều hành các công việc biên dịch nhưng toán tử sau đó nằm trong không gian tên NAME và không nằm trong không gian tên chung.

Làm cách nào để tôi có thể đủ điều kiện cho không gian tên chung trong tình huống như vậy?

Trả lời

15

Đầu tiên, lưu ý rằng tuyên bố điều hành của bạn còn thiếu một bằng cấp không gian tên cho A:

NAME::A operator * (double lhs, const NAME::A& rhs) 

và sau đó lừa quyết định là thêm dấu ngoặc đơn để kê khai người bạn như thế này, cũng giống như bạn đề xuất trong "pseudo của bạn -code"

friend A (::operator *) (double lhs, const A& rhs); 

Để làm cho nó tất cả các biên dịch, sau đó bạn cần một số tờ khai về phía trước, đến lúc này:

namespace NAME 
{ 
    class A; 
} 

NAME::A operator * (double lhs, const NAME::A& rhs); 

namespace NAME 
{ 
    class A { 
     public: 
      friend A (::operator *) (double lhs, const A& rhs); 
     private: 
      int private_var; 
    }; 
} 

NAME::A operator * (double lhs, const NAME::A& rhs) 
{ 
    double x = rhs.private_var; 
} 

Alexander là đúng, mặc dù - bạn có lẽ nên khai báo toán tử trong cùng một không gian tên như các tham số của nó.

+0

Đó là 3 câu trả lời gần như giống hệt nhau ngay bây giờ :-) – finnw

+0

Chắc chắn, ý bạn là * chỉ * ba :) –

3

Tôi không biết câu trả lời chính xác cho câu hỏi của bạn.

Nhưng đó là ý tưởng tồi tệ để xác định toán tử bên ngoài không gian tên của các tham số của nó (bây giờ bạn cắt tìm kiếm đối số phụ thuộc rất dễ sử dụng cho toán tử).

+2

+1. Trong khi câu trả lời này cắt xuống gốc của vấn đề, một nitpick nhẹ: nếu op * ở phạm vi toàn cầu, thì bạn không cần ADL, vì hàm luôn sẵn sàng. (Tôi không chắc chắn, nhưng có lẽ OP không hiểu ADL và do đó đã đưa ra điều này?) –

4

Biên dịch này, tôi giả định mà không thử nghiệm rằng nó cũng hoạt động. Lưu ý việc sử dụng dấu ngoặc đơn:

namespace NAME {class A; } 
NAME::A operator * (double lhs, const NAME::A& rhs); 

namespace NAME 
{ 
    class A { 
     public: 
      friend A (::operator *) (double lhs, const A& rhs); 
     private: 
      int private_var; 
    }; 
} 

NAME::A operator * (double lhs, const NAME::A& rhs) 
{ 
    double x = rhs.private_var; 
    return rhs; 
} 

int main() {} 

Vì Alexander đề cập, câu hỏi của bạn không giải thích tại sao toán tử không nằm trong không gian tên NAME. Dù bằng cách nào, nó có thể được gọi là 1.0 * some_A_instance. Vì vậy, bạn có thể tạo ra rắc rối không cần thiết cho chính mình.

+0

Darn, bạn đánh bại tôi với nó khoảng 20 giây. Hầu như mã giống hệt nhau. – finnw

+0

Điều đó làm cho chúng ta ba giờ, tôi đoán ... –

+0

Tuyệt vời, bạn đã cứu ngày của tôi. Tôi không biết thực tế là nhà điều hành có thể cư trú trong NAME và vẫn hoạt động theo cách tôi muốn. – Andreas

2

Có thể - bạn có thể kèm theo declarator trong ngoặc đơn: friend A (::operator * (double lhs, const A& rhs));

Bạn cũng cần để chuyển tiếp-tuyên bố cả hai lớp và hàm.

namespace NAME {class A;} 
NAME::A operator *(double lhs, const NAME::A& rhs); 

// ... 

namespace NAME 
{ 
    class A { 
     public: 
      friend A (::operator * (double lhs, const A& rhs)); 
     private: 
      int private_var; 
    }; 
} 

NAME::A operator *(double lhs, const NAME::A& rhs) { 
    //... 
} 

Nhưng tôi đồng ý với Andreas rằng sẽ tốt hơn nếu xác định cả hai trong cùng một không gian tên nếu có thể.

Các vấn đề liên quan