2013-03-21 28 views
8

Tôi có một đối tượng (Z) xuất phát từ hai đối tượng khác (A và B).Thừa kế đôi của enable_shared_from_this

A và B có nguồn gốc từ enable_shared_from_this<>, tương ứng enable_shared_from_this<A>enable_shared_from_this<B>.

Tất nhiên tôi gọi shared_from_this() trên Z. Và tất nhiên trình biên dịch báo cáo điều này là mơ hồ.

Câu hỏi của tôi là:

  • là nó an toàn để thừa hưởng hai lần từ enable_shared_from_this<> hoặc nó sẽ tạo ra hai tội tham khảo tách
  • Nếu không an toàn, làm thế nào để giải quyết việc này (xấu!)?

Lưu ý: Tôi đã tìm thấy câu hỏi khác bad weak pointer when base and derived class both inherit from boost::enable_shared_from_this nhưng nó không thực sự trả lời. Tôi có nên sử dụng thủ thuật virtual không?

+0

bản sao có thể có của [tăng chia sẻ \ _từ \ _này và nhiều thừa kế] (http://stackoverflow.com/questions/14939190/boost-shared-from-this-and-multiple-inheritance) – user

Trả lời

11

Vâng, theo giải pháp bad weak pointer when base and derived class both inherit from boost::enable_shared_from_this là sử dụng thừa kế ảo. Dưới đây là một thực hiện cho các tiêu chuẩn C++ 11 shared_ptr (không Boost):

#include <memory> 

struct virtual_enable_shared_from_this_base: 
    std::enable_shared_from_this<virtual_enable_shared_from_this_base> { 
    virtual ~virtual_enable_shared_from_this_base() {} 
}; 
template<typename T> 
struct virtual_enable_shared_from_this: 
virtual virtual_enable_shared_from_this_base { 
    std::shared_ptr<T> shared_from_this() { 
     return std::dynamic_pointer_cast<T>(
     virtual_enable_shared_from_this_base::shared_from_this()); 
    } 
}; 

struct A: virtual_enable_shared_from_this<A> {}; 
struct B: virtual_enable_shared_from_this<B> {}; 
struct Z: A, B { }; 
int main() { 
    std::shared_ptr<Z> z = std::make_shared<Z>(); 
    std::shared_ptr<B> b = z->B::shared_from_this(); 
} 

Đây không phải là một phần của việc thực hiện mặc định, có lẽ vì sự cần thiết của việc thừa kế ảo.

+0

Tôi nghĩ tốt hơn nên sử dụng 'static_pointer_cast' tại đây – kassak

+0

@kassak' static_pointer_cast' sẽ không hoạt động; đây là thừa kế ảo nên cần có một diễn viên động. – ecatmur

+0

nhưng đó là downcasting đơn giản từ 'virtual_enable_shared_from_this_base' thành' T', bắt nguồn từ nó. Trình biên dịch than phiền? – kassak

1

Yep, lớp học của bạn sẽ được bắt nguồn từ hai lớp riêng biệt enable_shared_from_this<A>enable_shared_from_this<B>, và có hai khác nhau yếu ref của

Lừa từ câu trả lời cho phép để có một lớp cơ sở, vì thừa kế ảo

+0

Tại sao không phải là điều này lừa được tích hợp trong 'enable_shared_from_this' theo mặc định? – Offirmo

+0

@LucDanton Nó không thể đối phó, bởi vì cả hai instatiations của cho phép chia sẻ từ đây là các lớp học riêng biệt. Đó là lý do tại sao ngay cả thừa kế đều được thừa hưởng riêng biệt. Cách duy nhất là có một lớp ảo, kế thừa nó với bất kỳ đối số kiểu nào, và sau đó sử dụng lớp ảo đó làm cơ sở. Vấn đề duy nhất có thể, trong 'make_shared' nhưng tôi không chắc chắn – kassak

+0

@LucDanton nghĩ về nó, sử dụng thủ thuật" ảo "buộc đối tượng dẫn xuất có một bảng ảo, do đó làm cho nó lớn hơn. Vì triết lý C++ là "bạn chỉ trả tiền cho những gì bạn yêu cầu", thủ thuật ảo không nên được sử dụng theo mặc định. – Offirmo