简体   繁体   中英

How do I cast a templated class

I have an example like the one below in C++ where I receive a pointer to base class, exampleParent , and would like to cast it to a pointer to the inherited class example (in reality I just want to call a function on example ) . The caveat is that the inherited class is templated. In the example below, I know the template is of type int so there is no problem. In general, what would be a good way to do this if I am not aware before hand the type of the template?

class exampleParent{};

template<typename P>
class example: public exampleParent
{
public:
    int do_something() const
    { 
        std::cout<<"I am doing something"<<std::endl;
        return 0;
    }
};

boost::shared_ptr<const exampleParent> getPtr()
{
   return boost::make_shared<const example<int>>();
}

int main()
{
    boost::shared_ptr<const exampleParent> example = getPtr();
    auto example_ptr = boost::dynamic_pointer_cast<const example<int>>(example);
    return example_ptr-> do_something();
}

One solution I propose is to change the code to something like this:

class exampleParent{};
class something_interface: public exampleParent
{
public:
    virtual int do_something() const = 0 ;
};

template<typename P>
class example: public something_interface
{
public:
    int do_something() const override
    { 
        std::cout<<"I am doing something"<<std::end;
        return 0;
    }
};

boost::shared_ptr<const exampleParent> getPtr()
{
   return boost::make_shared<const example<int>>();
}

int main()
{
    boost::shared_ptr<const exampleParent> example = getPtr();
    auto example_ptr = boost::dynamic_cast<const something_interface>(example);
    return example_ptr->do_something();
}

This would work, but it feels a bit of a hack: something_interface should not really exist, as it has no object oriented interpretation in itself.

Any help would be appreciated!

If you can make exampleParent an abstract class (if you can modify that class at all), that would be the best:

class exampleParent
{
public:
    virtual ~exampleParent() = default;
    virtual int do_something() const = 0; 
};
template<typename P>
class example: public exampleParent
{
public:
    int do_something() const override
    { 
        std::cout<<"I am doing something"<<std::endl;
        return 0;
    }
};

Then you don't need a cast to invoke that method.

If you cannot touch this exampleParent class, go on with the intermediate one as you proposed, but remember to actually inherit exampleParent and don't throw exception, just make the method pure virtual:

class intermediate: public exampleParent
{
public:
    ~intermediate() override = default;
    virtual int do_something() const = 0;
};

Otherwise the only way is to do dynamic_pointer_cast for all possible types and check the cast result, because different instances of template class are just different types in general. Of course it doesn't make sense if there is infinite number of possible template parameters P .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM