2009-02-06 41 views
6
#include "iostream" 

    class A { 
     private: 
     int a; 
     public : 

     A(): a(-1) {} 
     int getA() { 
      return a; 
     } 

    }; 

    class A; 

    class B : public A { 
     private: 
     int b; 
     public: 

     B() : b(-1) {} 

     int getB() { 
      return b; 
     } 

    }; 

    int main() { 
     std::auto_ptr<A> a = new A(); 

     std::auto_ptr<B> b = dynamic_cast<std::auto_ptr<B> > (a); 

     return 0; 

    } 

LỖI: Không thể dynamic_cast `(& a) -> std :: auto_ptr < _Tp> :: get() constTại sao dynamic_cast này của auto_ptr không thành công?

+0

nơi khai báo cho :: get()? – cbrulak

Trả lời

11

Vâng, std::auto_ptr<B> không có nguồn gốc từ std::auto_ptr<A>. Nhưng B có nguồn gốc từ A. Các auto_ptr không biết về điều đó (nó không phải là thông minh). Có vẻ như bạn muốn sử dụng con trỏ quyền sở hữu được chia sẻ. boost::shared_ptr là lý tưởng, nó cũng cung cấp một dynamic_pointer_cast:

boost::shared_ptr<A> a = new A(); 
boost::shared_ptr<B> b = dynamic_pointer_cast<B> (a); 

Đối auto_ptr, một điều như vậy có thể không thực sự làm việc. Vì quyền sở hữu sẽ chuyển sang b. Nhưng nếu diễn viên thất bại, b không thể có quyền sở hữu. Nó không rõ ràng phải làm gì với tôi. Bạn có lẽ sẽ phải nói nếu diễn viên thất bại, một người sẽ tiếp tục có quyền sở hữu - có vẻ như nó sẽ gây ra rắc rối nghiêm trọng. Bắt đầu tốt nhất bằng cách sử dụng shared_ptr. Cả hai ab sau đó sẽ trỏ đến cùng một đối tượng - nhưng B như một shared_ptr<B>a như một shared_ptr<A>

1

Lý do là auto_ptr mà không thực sự là một con trỏ. Đó là một con trỏ thông minh mà là một trình bao bọc con trỏ nhưng không thực sự là một con trỏ. Loại được chuyển dưới dạng đối số kiểu mẫu thành dynamic_cast phải là loại con trỏ (hoặc tham chiếu) thực sự.

http://msdn.microsoft.com/en-us/library/cby9kycs(VS.80).aspx

5

cast động không hoạt động theo cách đó. A : public B không bao hàm auto_ptr<A> : public auto_ptr<B>. Đây là lý do tại sao số shared_ptr của boost cung cấp shared_dynamic_cast. Bạn có thể viết một diễn viên năng động auto_ptr mặc dù:

template<typename R, typename T> 
std::auto_ptr<R> auto_ptr_dynamic_cast(std::auto_ptr<T>& in) { 
    auto_ptr<R> rv; 
    R* p; 
    if(p = dynamic_cast<R*>(in.get())) { 
     in.release(); 
     rv = p; 
    } 
    return rv; 

}

Chỉ cần lưu ý những gì xảy ra ở đây. Kể từ khi auto_ptr s có ngữ nghĩa quyền sở hữu, một downcast thành công có nghĩa là bản gốc thường được nhập, auto_ptr không còn có quyền sở hữu nữa.

0

Bạn đang cố gắng truyền A* (trả lại a.get()) thành std::auto_ptr<B> và vì thứ hai thậm chí không phải là loại con trỏ, điều này không thành công. Có lẽ bạn chỉ muốn bỏ nó vào B*:

std::auto_ptr<A> a(new A()); 
std::auto_ptr<B> b(dynamic_cast<B*>(a.get())); 

này sẽ vẫn không biên dịch, vì AB không loại đa hình. A cần có chức năng ảo để làm cho các loại đa hình. Điều này sẽ biên dịch, nhưng các diễn viên sẽ chỉ ném std::bad_cast, vì nó không thực sự là một B*.

Và thậm chí nếu nó là một B*, nó sẽ thất bại theo những cách khủng khiếp nếu bạn cố gắng sử dụng nó. Cả hai std::auto_ptr s ab sẽ giả sử chúng sở hữu đối tượng và giải phóng nó sau này, dẫn đến tất cả các loại tham nhũng bộ nhớ. Bạn có thể muốn sử dụng a.release() sau khi dàn diễn viên thành công.

0

Tôi nghĩ cửa hàng C++ RTTI (thông tin loại thời gian chạy) trong vtable. Do đó sử dụng dynamic_cast <> với một đối tượng thể hiện, đối tượng cần có 'vtable'. C++ tạo vtable chỉ khi ít nhất một hàm được khai báo 'virtual' trong lớp.

Lớp A và Lớp B không có chức năng ảo. Đây có thể là lý do cho sự thất bại dynamic_cast. Hãy thử khai báo một destructor ảo trong lớp cơ sở.

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