2015-06-03 12 views
5

Tôi đã cố gắng thực hiện một số toán tử quá tải (* và +) trên một lớp được bọc trong con trỏ thông minh.Quá tải của nhà điều hành của lớp được bọc trong con trỏ thông minh

auto p = std::make_unique<Polynomial<T>>(); 

Khi tôi cố gắng quá tải bằng cách sử dụng quá tải bình thường, rõ ràng là sẽ yêu cầu loại con trỏ thông minh.

Chỉnh sửa, vì vậy:

std::unique_ptr<Polynomial<T>> operator+(const std::unique_ptr<Polynomial<T>>& right); 

template<class T>std::unique_ptr<Polynomial<T>> Polynomial<T>::operator+(const std::unique_ptr<Polynomial<T>>& right) { 
    //Do stuff 
} 

Và các lỗi:

Error from trying to use the + operator

Vậy làm thế nào để bạn đi về quá tải các nhà khai thác bình thường khi lớp được gói gọn trong một smartpointer?

+1

"Khi tôi cố gắng quá tải nó sử dụng quá tải bình thường, nó rõ ràng là yêu cầu cho các loại con trỏ thông minh." -- Gì. – Shoe

+0

Tại sao các lớp học này lại được bao bọc trong các con trỏ thông minh? Tại sao bạn không thể sử dụng chúng làm loại giá trị? –

Trả lời

11

Không.

Chạy những hoạt động trên pointees, không phải trên con trỏ:

*p = *p + *p 

Nó sẽ là rất khó hiểu cho người sử dụng mã của bạn nếu đột nhiên con trỏ có ngữ nghĩa hoàn toàn khác nhau và bất ngờ.

Nó cũng sẽ gây nhầm lẫn cho bạn.

2

So how do you go about overloading the normal operators when the class is encapsulated in a smartpointer?

Chỉ cần khai báo như thường lệ:

template<typename T> 
Polynomial<T> operator*(Polynomial<T> lhs, Polynomial<T> rhs) { ... } 

template<typename T> 
Polynomial<T> operator+(Polynomial<T> lhs, Polynomial<T> rhs) { ... } 

và sau đó đưa ra một cái gì đó như:

auto p = std::make_unique<Polynomial<int>>(); 
auto q = std::make_unique<Polynomial<int>>(); 

chỉ cần gọi:

auto x = (*p) * (*q); 
auto y = (*q) + (*p); 

Live demo


Các lỗi mà bạn cung cấp:

enter image description here

là do thực tế rằng nhà điều hành của bạn quá tải:

std::unique_ptr<Polynomial<T>> operator+(const std::unique_ptr<Polynomial<T>>& right); 

đang quá tải unaryoperator+ cho các biểu thức như +x.

Và khác:

template<class T> 
std::unique_ptr<Polynomial<T>> Polynomial<T>::operator+(const std::unique_ptr<Polynomial<T>>& right) { 
    //Do stuff 
} 

đang quá tải operator+ cho toán hạng kiểu Polynomial<T>std::unique_ptr<Polynomial<T>>.

Do đó đưa hai unique_ptr<Polynomial<T>>, cụ thể là xy, biểu thức sau đây:

x + y 

không tìm thấy một giải pháp quá tải cho operator+.

Tôi cũng không khuyến khích quá tải các toán tử đối với các loại thư viện chuẩn.

2

Để có câu trả lời trực tiếp cho câu hỏi của bạn, tôi đồng ý với @LightnessRacesinOrbit: Chỉ cần không. Nhưng lý do để viết một câu trả lời khác là câu hỏi mà bạn đang hỏi có vẻ giống như một số XY-problem với tôi.

Bạn có một lớp học Polynomial<T> nhưng bạn mong đợi người dùng quấn nó trong một con trỏ thông minh? Đây là một thiết kế lành mạnh, hy vọng người dùng có thể làm việc trực tiếp với Polynomial, do đó cung cấp các toán tử bình thường hoạt động trực tiếp trên loại đó.

Quay lại một bước và suy nghĩ về lý do bạn cho rằng con trỏ thông minh sẽ được sử dụng/cần thiết/hữu ích. Thông thường, điều này được thực hiện vì lý do hiệu quả được cho là đúng không? Nhưng điều đó chỉ có nghĩa là bạn nên suy nghĩ lại cách bạn tự thực hiện Polynomial. Hãy xem xét những điều sau:

  • Polynomial có di chuyển-xây dựng và-khớp? Nếu không, hãy thực hiện nó.
  • Còn dữ liệu được lưu trữ thì sao? Có lẽ bộ nhớ trong phải được quản lý bởi một con trỏ thông minh. Cùng với di chuyển-ngữ nghĩa, điều này có thể dẫn đến hoạt động rất hiệu quả.
  • Để quá tải nhà điều hành, hãy thực hiện a+=b;, sử dụng thư viện để tạo a+b được tạo cho bạn. Kiểm tra Boost.Operators hoặc df.operators của tôi, cái sau cũng di chuyển.

Với việc thực hiện đúng, các yêu cầu để sử dụng std::unique_ptr<Polynomial<T>> nên đi :)

+0

'mẫu friend Toán tử đa thức + (Lhs && lhs, Rhs && rhs) {Đa thức ret = std :: forward (lhs); ret + = std :: forward (rhs); return ret; } '- tại sao bạn cần một thư viện cho điều đó? Tôi đoán bạn có thể đoán trước sự giao hoán, và có điều kiện sử dụng trái hoặc phải trong trường hợp đó cho 'ret' ban đầu? Và tôi thử nghiệm SFINAE. Và một số công việc để tránh xung đột 'nhà điều hành +' mơ hồ. – Yakk

+0

@Yakk Một số người không đồng ý với cách tiếp cận của tôi, nhưng với tình trạng quá tải cho thời gian, bạn có thể tối ưu hóa thêm bằng cách trả về tham chiếu rvalue thay vì một đối tượng mới trong một số trường hợp. "Di chuyển-nhận thức" có nghĩa là nhiều hơn với tôi hơn thực hiện của bạn. Đặc biệt đối với các lớp mà các thời gian bổ sung có chi phí đáng kể và 'Đa thức ' trông giống hệt như một trong những trường hợp đó. –

+1

Không bao giờ, bao giờ trả về một tham chiếu rvalue (bên ngoài các biểu thức truyền): nó có nghĩa là phần mở rộng tham chiếu trọn đời không hoạt động. Một cái gì đó đơn giản như 'for (coeff x: a + b)' sẽ không hoạt động! Và cái gì là tốt! – Yakk

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