2009-02-06 1 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; 

    } 

ОШИБКА: не dynamic_cast `(& а) -> станд :: auto_ptr < _Tp> :: получить() ConstПочему этот dynamic_cast auto_ptr не работает?

+0

где декларация для :: get()? – cbrulak

ответ

11

Ну, std::auto_ptr<B> не является производным от std::auto_ptr<A>. Но B происходит от A. Auto_ptr не знает об этом (это не так уж умно). Похоже, вы хотите использовать указатель общего доступа. boost::shared_ptr является идеальным, он также обеспечивает dynamic_pointer_cast:

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

Для auto_ptr, такая вещь не может реально работать. Потому что собственность переместится на b. Но если бросок не удался, b не может получить право собственности. Неясно, что мне тогда делать. Вероятно, вам стоит сказать, что если бросок не сработает, у него останется право собственности - похоже, что это вызовет серьезные проблемы. Лучше всего начать использовать shared_ptr. Оба a и b затем будут указывать на тот же объект - но B как shared_ptr<B> и a как shared_ptr<A>

1

Причина заключается в том, что auto_ptr не на самом деле указатель. Это умный указатель, который является оболочкой указателя, но на самом деле не является указателем. Тип, который передается как аргумент стиля шаблона в dynamic_cast, должен быть истинным типом указателя (или ссылки).

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

5

динамическое приведение не работает таким образом. A : public B не означает auto_ptr<A> : public auto_ptr<B>. Вот почему boost shared_ptr обеспечивает shared_dynamic_cast. Вы могли бы написать auto_ptr динамическое приведение хотя:

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; 

}

Просто надо знать, что здесь происходит. Поскольку auto_ptr s имеют семантику владения, успешный downcast означает, что оригинал более типично типизирован, auto_ptr больше не имеет права собственности.

0

Вы пытаетесь нарисовать A* (возвращено a.get()) на std::auto_ptr<B>, а так как второй не является даже типом указателя, это терпит неудачу. Возможно, вы просто хотите, чтобы бросить его B*:

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

Это еще не обобщать, потому что A и B не являются полиморфными типами. A должен иметь виртуальную функцию, чтобы сделать типы полиморфными. Это будет скомпилировано, но бросок просто выбросит std::bad_cast, так как это не действительно B*.

И даже если бы это было B*, , это провалится ужасно, если вы попытаетесь использовать его. Оба std::auto_ptr s a и b предполагают, что они владеют объектом и освобождают его позже, что приводит к разным повреждениям памяти. Вероятно, вы захотите использовать a.release() после успешной передачи.

0

Я думаю, что C++ хранит RTTI (информацию о типе времени выполнения) в таблице vtable. Следовательно, для использования dynamic_cast <> с объектом экземпляра объект должен иметь «vtable». C++ создает vtable только тогда, когда хотя бы одна функция объявляется «виртуальной» в классе.

В классах A и класса B нет виртуальных функций. Это может быть причиной отказа dynamic_cast. Попробуйте объявить виртуальный деструктор в базовом классе.