error: cannot dynamic_cast ... (target is not pointer or reference)

26,765

Solution 1

dynamic_cast can only cast to a pointer value or reference, which is exactly what the error is telling you.

From $5.2.7/1 of the C++ Standard.

The result of the expression dynamic_cast< T >(v) is the result of converting the expression v to type T. T shall be a pointer or reference to a complete class type, or “pointer to cv void.”

In order for dynamic_cast to throw an exception when the object cannot be converted you need to cast to a reference. Change it to the following:

dynamic_cast<AA&>(a).aa();
//           ^^^ cast to reference.

As Johnsyweb pointed out dynamic_cast will always throw std::bad_cast when the conversion fails. Although std::bad_cast is derived from std::exception it is always a good idea to use the exception which best fits the expected fail condition. This prevents inadvertently interpreting other errors as an unsuccessful cast.

To apply this to your example it might look like the code below.

#include <iostream>
#include <typeinfo> // std::bad_cast

class A
{
public:
    virtual void f(void){}
};

class AA:public A
{
public:
    void aa(void){};
};

int main(void)
{
    A a;

    try
    {
        dynamic_cast<AA&>(a).aa();
    }
    catch(const std::bad_cast& ex)
    {
        std::cout << "["<<ex.what()<<"]" << std::endl;
    }
    return 0;
}

[Note, doing things like using namespace std; is strongly discouraged as it can cause conflicts with identifiers in the global namespace. I have removed it in the example above.]

Solution 2

Your problem is not with exception handling, but with your dynamic cast:

'AA' is not a reference or pointer

dynamic_cast safely converts pointers and references to classes and not instances.

So you could do:

dynamic_cast<AA&>(a).aa();

...which will always fail and throw a std::bad_cast exception.

You should catch the most-specific type of exception that you are expecting and since the recommended way to catch is by reference, you should prefer:

catch (std::bad_cast const& ex)

Further reading: dynamic_cast conversion on cppreference.com.

Solution 3

You are getting a compiler error because your dynamic_cast is not on pointer or reference.
Change it to:

dynamic_cast<AA&>(a).aa();

... and you get the proper exception thrown.

On side note: Smart compilers like g++ would warn as well:
warning: dynamic_cast on an object (here a) can never succeed.

So it's better to limit such code for toying around. In production quality code, the dynamic_cast should be performed only on pointer/reference.

Solution 4

I just dealt with the same error, but in my case I was going from a pointer to a pointer, so the other answers here did not apply. My error message was slightly different, however: error: cannot dynamic_cast 'f()' (of type 'class B*') to type 'class A*' (target is not pointer or reference to complete type).

The root cause in my case was much more simple and mundane.

Notice the addition of to complete type at the end. This caused me to remember that I did not include the header file for my class which I was using. It was not an unknown symbol because A* was forward declared with class A; in the header file, causing it to exist but not be complete, hence the error.

The solution in my case was to include the header file for the class I was casting to.

This is not the question asker's problem above, but as can be seen by my case can generate the same type of error.

Share:
26,765
focusHard
Author by

focusHard

Updated on July 09, 2022

Comments

  • focusHard
    focusHard almost 2 years

    I'm learning exception handling in C++ and run into a problem. Here's the code:

    #include<iostream>
    #include<exception>
    
    using namespace std;
    
    class A
    {
    public:
        virtual void f(void){}
    };
    
    class AA:public A
    {
    public:
        void aa(void){};
    
    };
    
    int main(void)
    {
    
        A a;
        try
        {
            dynamic_cast<AA>(a).aa();
        }
        catch(exception ex)
        {
            cout<<"["<<ex.what()<<"]"<<endl;
        }
        return 0;
    }
    

    So I thought the try catch will allow the function to execute and show me the content of the exception, but my compiler does not compile it. I'm using codeblock with GNU GCC. Please help me and show me what I need to do to get the code run as I intended. thanks a lot.