2012-05-09 24 views
5

Tôi có một lớp cơ sở trừu tượng (ví dụ: VectorWrapperBase) làm giá trị và điều này cho phép tôi ánh xạ chuỗi thành các loại vectơ khác nhau.Đối tượng ánh xạ có chứa ptr_map của lớp cơ sở trừu tượng

boost::ptr_map<std::string, VectorWrapperBase> memory_map; 
//... 
memory_map.insert(str_key, new VectorWrapper<T>()); 

Điều này có vẻ hiệu quả. Tuy nhiên, khi tôi có memory_map là thành viên của một lớp khác và cố gắng lưu trữ lớp đó trong một std::map, việc biên dịch không thành công.

class AgentMemory { 
    //... 
    private: 
    boost::ptr_map<std::string, VectorWrapperBase> memory_map; 
}; 

std::map<std::string, AgentMemory> agent_map; 
//... 
agent_map.insert(std::pair<std::string, AgentMemory>(agent_name, AgentMemory())); 

Dòng cuối cùng không thành công với:

/SOMEPATH/boost_1_48_0/boost/ptr_container/clone_allocator.hpp:34 
    error: cannot allocate an object of abstract type ‘xyz::VectorWrapperBase’ 

Là mới đến C++, đây là khó hiểu.

I nghi ngờ lỗi xảy ra với việc sao chép bản đồ đối tượng AgentMemory liên quan đến nhân bản ptr_map. Và kể từ khi đối tượng VectorWrapper của tôi không phải là cloneable, lỗi được nâng lên.

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

  • Tại sao tôi nhận lỗi? (Có phải sự nghi ngờ của tôi thậm chí gần với những gì đang xảy ra không?)
  • Làm cách nào để giải quyết vấn đề này?

Để giải quyết những lỗi biên dịch, tôi đã xem xét những điều sau đây, nhưng không có nhiều kinh nghiệm với C++ không thể quyết định là thích hợp hơn:

  1. Tháo specifier tinh khiết (= 0) để VectorWrapperBase là không còn trừu tượng
    • này cảm thấy giống như một hack từ VectorWrapperBase không bao giờ nên được instantiated
  2. Tận dụng tối VectorWrappers cloneable
    • This seems to work, nhưng trong trường hợp sử dụng của tôi chỉ các vùng chứa trống được gán cho bản đồ cấp cao nhất để VectorWrappers bên trong ptr_map bên trong không bao giờ được nhân bản. Các cloneability do đó sẽ có chỉ để xoa dịu trình biên dịch và không phản ánh việc sử dụng thực tế.
  3. Quên ptr_map và sử dụng std::mapshared_ptr thay thế.
    • Tôi ít quan tâm đến giải pháp này vì tôi muốn tuổi thọ của trình bao bọc véc tơ được liên kết với bản đồ của bản đồ. Tôi cũng quan tâm một chút (có lẽ không cần thiết như vậy?) Về chi phí tiềm năng của việc sử dụng rộng rãi shared_ptr trong một ứng dụng nhiều luồng.
+0

Lớp Tóm tắt Cơ sở của bạn có trình phá hủy ảo không? – TemplateRex

+0

Có. .. –

Trả lời

0

Tuyên bố

agent_map.insert(std::pair<std::string, AgentMemory>(agent_name, AgentMemory())); 

sẽ gọi constructor mặc định của AgentMemory, mà lần lượt sẽ gọi constructor mặc định của boost::ptr_map<std::string, VectorWrapperBase>, mà sẽ cố gắng để gọi các nhà xây dựng không tồn tại cho trừu tượng lớp cơ sở VectorWrapperBase.

Vì vậy, bạn phải đảm bảo rằng mọi người xây dựng các kiểu gói hoặc kế thừa VectorWrapperBase phải luôn luôn xây dựng một lớp dẫn xuất cụ thể. Trong trường hợp của bạn, tùy chọn 3 (một bản đồ các con trỏ được chia sẻ cho các lớp dẫn xuất) có thể là hợp lý, nhưng điều đó phụ thuộc vào ngữ cảnh lớn hơn của mã của bạn.

+0

Cảm ơn lời giải thích. Điều gì làm tôi bối rối là 'ptr_map' bắt đầu rỗng vì vậy tại sao có cần phải gọi hàm tạo cho' VectorWrapperBase'? –

+0

@ShawnChin Như tôi đã giải thích trong câu trả lời của tôi, lệnh 'insert()' với đối số 'AgentMemory()' sẽ tạo ra lời gọi hàm tạo. – TemplateRex

+0

Có lẽ tôi đã hiểu lầm, nhưng 'VectorWrapperBase' không phải là một thành viên của' AgentMemory' và vì vậy tôi không thấy lý do tại sao một thể hiện của nó nên được tạo ra. Điều đó nói rằng, bây giờ tôi đánh giá cao thực tế là 'VectorWrapperBase' cần phải được cloneable vì' ptr_map' cần phải được sao chép bởi constructor sao chép của lớp đóng gói. –