2013-02-19 34 views
5
class Interface 
{ 
}; 

class Class : public Interface 
{ 
}; 

class Foo 
{ 
public: 
    std::vector<std::shared_ptr<Interface>>& GetInterfaces() 
    { 
     return *(std::vector<std::shared_ptr<Interface>>*)(&m_data); 
     //return m_data; 
    } 

private: 
    std::vector<std::shared_ptr<Class>> m_data; 
}; 

Điều này hoạt động nhưng rất xấu và đáng sợ. Có cách nào tốt hơn/an toàn hơn để làm điều đó không? Tôi không muốn tạo m_data loại std::vector<std::shared_ptr<Interface>> vì mô-đun Foo thuộc về các tác phẩm hoàn toàn với Class, Interface (và Foo::GetInterfaces()) được triển khai để tương tác với một mô-đun riêng biệt chỉ biết về chức năng Interface.Cách truyền véc tơ của shared_ptrs của một lớp dẫn xuất đến một véc tơ của share_ptrs của một lớp cơ sở

Hãy cho tôi biết nếu bất kỳ điều gì ở đây không rõ ràng, điều đó hợp lý với tôi nhưng tôi đã đập đầu vào vấn đề này một lúc.

Trả lời

7

Đúc không chính xác, chúng là các loại riêng biệt; Tôi khá chắc chắn bạn đang gọi hành vi không xác định.

Bạn cần tạo một vectơ mới và trả về giá trị theo giá trị.

std::vector<std::shared_ptr<Interface>> b (m_data.begin(), m_data.end()); 
return b; 

Điều này sẽ vẫn khá rẻ (1 phân bổ).

+0

gì con trỏ chia sẻ sẽ làm gì trong tình huống đó? Tôi không chắc chắn nó sẽ muốn chia sẻ con trỏ giữa hai loại khác nhau của con trỏ chia sẻ! –

+0

@MichaelKohne không có gì là tốt. – 111111

+0

Ahh, di chuyển ngữ nghĩa cho chiến thắng! nên làm cho trở về bởi giá trị ok. –

4

Bên cạnh đó điều này là không thể với việc thực hiện vector, vấn đề cũng là tham chiếu không chuyển đổi. Mã của bạn thậm chí còn tồi tệ hơn và là hành vi không xác định.

Việc bạn có thể làm là cung cấp giao diện hiển thị phạm vi hoặc begin/end thay vì chính vùng chứa đó. Nếu bạn kết hợp điều đó với transform_iterator thực hiện chuyển đổi, bạn nên đặt.

Mẫu mã:

class Interface { 
    virtual ~Interface(); 
}; 

class X : public Interface {}; 

class C { 

private: 
    typedef std::shared_ptr<Interface> iptr_type; 
    typedef std::shared_ptr<Class> ptr_type; 
    std::vector<ptr_type> v_; 

    struct F { 
    iptr_type 
    operator()(ptr_type p) { return iptr_type(p); } 
    }; 

    typedef boost::transform_iterator< 
    F, std::vector<ptr_type>::iterator> iiterator; 

public: 
    iiterator 
    begin() 
    { 
    return boost::make_transform_iterator(
     begin(v_), F()); 
    } 

    iiterator 
    end() 
    { 
    return boost::make_transform_iterator(
     end(v_), F()); 
    } 
}; 
+0

Nếu nó có ý nghĩa trong trường hợp sử dụng của bạn, sau đó lộ ra một ' .begin() 'và' .end() 'giao diện trình lặp là một lựa chọn tốt. – 111111

+0

@ 111111 Chắc chắn, điều đó là tốt. Nhưng tôi đoán phạm vi là điều hip hơn. – pmr

+0

nhận xét của tôi là một nhận xét hỗ trợ ý tưởng của bạn :) – 111111

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