Is it OK để kế thừa từ các C ++ 11 thông minh con trỏ và ghi đè lên các nhà khai thác tương đối?


0 Phiếu
Đã hỏi 26/4/2016 bởi Useless (350 điểm)
Theo cppreference.com , std::shared_ptr cung cấp một bộ đầy đủ của nhà điều hành tương đối (==,! =, <,...), nhưng ngữ nghĩa so sánh không quy định. Tôi giả sử họ so sánh các con trỏ nguyên tiềm ẩn cho các đối tượng tham chiếu, và std::weak_ptr và std::unique_ptr làm như vậy. Cho một số mục đích, tôi thích để có nhà khai thác tương đối để các con trỏ thông minh dựa trên so sánh các đối tượng tham chiếu (chứ không phải là gợi ý cho họ). Điều này đã là một cái gì đó tôi làm rất nhiều, nhưng với riêng tôi gợi ý"ngớ ngẩn" mà hành xử chủ yếu như nguyên con trỏ ngoại trừ các nhà khai thác tương đối. Tôi muốn làm điều tương tự với các tiêu chuẩn C ++ 11 thông minh con trỏ quá. Vì vậy...
  1. là nó OK để kế thừa từ các C ++ 11 thông minh con trỏ (shared_ptr, weak_ptr và unique_ptr) và ghi đè lên các nhà khai thác tương đối?
  2. có bất kỳ vấn đề lén lút tôi cần phải tìm ra cho? Ví dụ, là có bất kỳ phương pháp khác mà tôi cần phải thực hiện hoặc sử dụng using để đảm bảo những điều làm việc một cách chính xác?
  3. cho cuối cùng trong sự lười biếng, là có một library mẫu có sẵn mà sẽ làm cho tôi tự động?
tôi hy vọng điều này là một "tất nhiên bạn có thể làm điều đó, thằng ngốc!" loại điều, nhưng tôi là một chút không chắc chắn vì có một số lớp học trong library tiêu chuẩn (container như std::map ít) mà cậu không nên thừa hưởng từ.

2 Câu trả lời

–1 Phiếu
Đã trả lời 13/5/2016 bởi NotedBe (520 điểm)
được bình chọn là câu trả lời hay nhất 14/5/2016 bởi Pbz_Sane
 
Câu trả lời hay nhất
Lần đầu tiên, như những người khác đã đã chỉ ra là inheritance đó không phải là con đường để đi. Nhưng thay vì các wrapper phức tạp do câu trả lời chấp nhận đề nghị, tôi sẽ làm một cái gì đó đơn giản hơn nhiều: thực hiện của riêng bạn so sánh với loại riêng của bạn:
namespace myns {
struct mytype {
   int value;
};
bool operator<( mytype const& lhs, mytype const& rhs ) {
   return lhs.value < rhs.value;
}
bool operator<( std::shared_ptr<mytype> const & lhs, std::shared_ptr<mytype> const & rhs )
{
   // Handle the possibility that the pointers might be NULL!!!
   // ... then ...
   return *lhs < *rhs;
}
}
ma thuật , mà không phải là thực sự ma thuật ở tất cả là đối số tra cứu phụ thuộc (aka. Tra cứu Koening hoặc ADL). Khi compiler gặp một cuộc gọi function nó sẽ thêm namespace các đối số để tra cứu. Nếu các đối tượng là instantiation một khuôn mẫu, sau đó compiler cũng sẽ thêm không gian tên loại được sử dụng để nhanh chóng các mẫu. Vì vậy, trong: int main() { std::shared_ptr<myns::mytype> a, b; if ( a < b ) { // [1] std::cout << "less\\n"; } else { std::cout << "more\\n"; } } [1], và bởi vì ab là các đối tượng người dùng quy định loại ADL (*) sẽ kick và nó sẽ thêm cả hai stdmyns vào bộ tra cứu. Sau đó nó sẽ tìm thấy tiêu chuẩn định nghĩa của operator< cho std::shared_ptr đó là: template<class T, class U> bool std::operator<(shared_ptr<T> const& a, shared_ptr<U> const& b) noexcept; và nó cũng sẽ thêm myns và thêm: bool myns::operator<( mytype const& lhs, mytype const& rhs ); sau đó, sau khi tra cứu kết thúc, độ phân giải overload khai mạc và nó sẽ xác định rằng myns::operator< là một kết hợp tốt hơn so với std::operator< cho cuộc gọi, vì nó là một kết hợp hoàn hảo và trong đó không case -mẫu có sở thích. Nó sau đó sẽ gọi cho mình operator< thay vì một trong những tiêu chuẩn. Điều này sẽ trở thành hơn một chút phức tạp nếu type của bạn là thực sự là một bản mẫu, nếu nó là, thả một bình luận và tôi sẽ mở rộng các câu trả lời. (*) đây là một đơn giản hóa nhẹ. Bởi vì operator< có thể được thực hiện cả hai như là một function member hoặc một chức năng miễn phí, compiler sẽ kiểm tra bên trong std::shared_ptr<> cho member operator< (không có trong các tiêu chuẩn) và bạn bè. Nó cũng sẽ nhìn bên trong mytype cho các friend chức năng... và như vậy. Nhưng lúc đầu, nó sẽ tìm thấy một trong những quyền.
Đã bình luận 14/5/2016 bởi Pbz_Sane (256,960 điểm)
Nói chung, nó không phải là an toàn để kế thừa từ bất cứ điều gì người đã hủy không phải là năng động. Nó có thể và _is_ thực hiện phổ biến, bạn chỉ có thể _really_ cẩn thận.
0 Phiếu
Đã trả lời 05/5/2016 bởi qvqverda (160 điểm)
Nói chung, nó không phải là an toàn để kế thừa từ bất cứ điều gì người đã hủy không phải là năng động. Nó có thể và được thực hiện thường, bạn chỉ có thể thực sự cẩn thận. Thay vì kế thừa từ các con trỏ, tôi chỉ muốn sử dụng thành phần, đặc biệt là kể từ khi số lượng thành viên tương đối nhỏ. Bạn có thể có thể làm cho một mẫu class cho
template<class pointer_type>
class relative_ptr {
public:
    typedef typename std::pointer_traits<pointer_type>::pointer pointer;
    typedef typename std::pointer_traits<pointer_type>::element_type element_type;
    relative_ptr():ptr() {}
    template<class U>
    relative_ptr(U&& u):ptr(std::forward<U>(u)) {}
    relative_ptr(relative_ptr<pointer>&& rhs):ptr(std::move(rhs.ptr)) {}
    relative_ptr(const relative_ptr<pointer>& rhs):ptr(std::move(rhs.ptr)) {}
    void swap (relative_ptr<pointer>& rhs) {ptr.swap(rhs.ptr);}
    pointer release() {return ptr.release();}
    void reset(pointer p = pointer()) {ptr.reset(p);}
    pointer get() const {return ptr.get();}
    element_type& operator*() const {return *ptr;}
    const pointer_type& operator->() const {return ptr;}
    friend bool operator< (const relative_ptr& khs, const relative_ptr& rhs) const 
    {return std::less<element>(*lhs,*rhs);}
    friend bool operator<=(const relative_ptr& khs, const relative_ptr& rhs) const 
    {return std::less_equal<element>(*lhs,*rhs);}
    friend bool operator> (const relative_ptr& khs, const relative_ptr& rhs) const 
    {return std::greater<element>(*lhs,*rhs);}
    friend bool operator>=(const relative_ptr& khs, const relative_ptr& rhs) const 
    {return std::greater_equal<element>(*lhs,*rhs);}
    friend bool operator==(const relative_ptr& khs, const relative_ptr& rhs) const 
    {return *lhs==*rhs;}
    friend bool operator!=(const relative_ptr& khs, const relative_ptr& rhs) const 
    {return *lhs!=*rhs;}
protected:
    pointer_type ptr;
};
này rõ ràng là sự đơn giản của các wrapper, reduces, bạn đến các mẫu số chung thấp nhất cho các con trỏ thông minh, nhưng bất cứ điều gì. Họ đang phức tạp không chính xác, bạn có thể làm cho một cho mỗi lớp học thông minh pointer . Tôi sẽ cung cấp một cảnh báo rằng tôi không giống như các công trình == way, kể từ khi nó có thể trở về true cho hai con trỏ đối tượng khác nhau. Nhưng bất cứ điều gì. Tôi cũng chưa kiểm tra các mã, nó có thể không cho một số tác vụ, như cố gắng sao chép khi nó có chứa một unique_ptr.

ToughDev Q&A là gì?

Trang web hỏi đáp cho các bạn đam mê lập trình, phát triển phần mềm và các vấn đề kỹ thuật khác. Với sự giúp đỡ của bạn, chúng tôi hy vọng sẽ xây dựng thành công một thư viện đầy đủ các câu hỏi và trả lời về tất cả các vấn đề có liên quan đến lập trình!







...