Đó chỉ là một cảnh báo về khía cạnh phức tạp của ngôn ngữ. Khi bạn khai báo một hàm friend
, nó không phải là thành viên của lớp khai báo. Bạn có thể định nghĩa nó ở đó để thuận tiện, nhưng nó thực sự thuộc về không gian tên.
Khai báo hàm bạn bè không phải là mẫu, bên trong mẫu lớp, vẫn khai báo hàm không phải mẫu trong không gian tên. Nó không phải là một thành viên của lớp, cũng không phải là một khuôn mẫu. Tuy nhiên, đó là đã tạo ra theo mẫu lớp học.
Tạo các chức năng không phải mẫu từ một mẫu có chút mơ hồ. Ví dụ: bạn không thể thêm tuyên bố cho hàm đó bên ngoài khối class
. Vì vậy, bạn phải định nghĩa nó bên trong khối class
, điều này có ý nghĩa bởi vì mẫu lớp sẽ tạo ra nó.
Một điều khó khăn khác về bạn bè là việc khai báo bên trong class Float {}
không khai báo hàm trong không gian tên. Bạn chỉ có thể tìm thấy nó thông qua độ phân giải quá tải phụ thuộc vào ý nghĩa của đối số, tức là chỉ định một đối số có loại Float
(hoặc một tham chiếu hoặc con trỏ). Đây không phải là một vấn đề cho operator+
, vì nó có khả năng bị quá tải dù sao, và nó sẽ không bao giờ được gọi ngoại trừ với các loại do người dùng định nghĩa.
Ví dụ về một vấn đề tiềm ẩn, hãy tưởng tượng bạn có một hàm tạo chuyển đổi Float::Float(Bignum const&)
. Nhưng Bignum
không có operator+
. (Xin lỗi, ví dụ giả tạo.) Bạn muốn dựa vào operator+(Float const&, Float const&)
để thêm Bignum
. Bây giờ my_bignum + 3
sẽ không biên dịch vì toán hạng không phải là Float
để nó không thể tìm thấy hàm friend
.
Có thể, bạn không có gì phải lo lắng, miễn là hàm được đề cập là operator
.
Hoặc bạn cũng có thể thay đổi friend
làm mẫu. Trong trường hợp đó, nó phải được xác định bên ngoài khối class {}
và được khai báo trước đó, thay vì cần được khai báo và xác định bên trong.
template<int E, int F> // now this is a template!
Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs);
template<int E, int F>
class Float
{
// deduce arguments E and F - this names operator+< E, F >.
friend Float<E, F> operator+<> (const Float<E, F> &lhs, const Float<E, F> &rhs);
};
Bạn có thể muốn đọc http://www.parashift.com/c++-faq-lite/templates.html#faq-35.16 – UncleBens