C ++: Бросать shared_ptr из производного и ловить shared_ptr из базы? - PullRequest
2 голосов
/ 30 марта 2012

Хорошо, мне сказали эту проблему: почему вы можете бросить указатель на производный класс и поймать указатель на его базу ... но вы не можете сделать это с shared_ptrs?

Пример, это работает:

class Base {};
class Derived : public Base {};
int main()
{   
    try 
    {   
        throw new Derived() ;
    }   
    catch( const Base2 * b ) 
    {   
        printf("Received a base" ) ; 
    }   

    return 0 ;
}

Но это не

int main()
{
    try
    {
        throw std::tr1::shared_ptr<Derived>( new Derived() ) ;
    }
    catch( const std::tr1::shared_ptr<Base> & b ) 
    {
        printf("Received a base" ) ;
    }
    return 0 ;
}

Есть идеи?

Ответы [ 2 ]

5 голосов
/ 30 марта 2012

Причина довольно проста: даже когда derived относится к base, shared_ptr<derived> не относится к shared_ptr<base>, поэтому не существует неявного преобразования из одного в другое, если шаблон явно не предоставляет его (ито же самое относится к любому другому шаблону, созданному таким же образом).

Однако, за исключением, я не уверен, какую проблему вы действительно пытаетесь решить.Обычно вы хотите бросить объект (не указатель) и вы хотите перехватить ссылку const.Поскольку у вас нет реальной возможности иметь несколько указателей на один и тот же объект исключения, я не уверен, какую проблему вы решите с помощью shared_ptr<exception_object>.

2 голосов
/ 30 марта 2012

Вы правы, что ваш второй пример не работает.

Обработчик исключений будет перехватывать исключения только очень четко определенными способами. В частности, вы не можете сделать неявное преобразование при отлове. Применяются только преобразования «от базы к базе» и от «указателя к производному к указателю в базу». Поскольку shared_ptr<derived> не является производным от shared_ptr<base> и не является встроенным указателем, он не совпадает.

Если вы хотите поймать shared_ptr<base>, тогда конвертируйте в shared_ptr<base> перед броском.

...