简体   繁体   中英

Conversion between C++ vector of base and derived classes

Please have a look at the following code, you can compile it as a single.cpp file but you should imagine base library code in a separate package:

#include <iostream>
#include <memory>
#include <vector>

// Start of classes defined in a base library shared by many projects

class BaseObject
{
    public:

        BaseObject() : value(0) {}

        BaseObject(int val) : value(val) {}

    protected:

        int value;
};

class BaseObjectHandler
{
    public:

        void setVector(std::unique_ptr<std::vector<BaseObject>>&& v)
        {
            vec = std::move(v);
        }

    protected:

        std::unique_ptr<std::vector<BaseObject>> vec;
};

// End of classes defined in a base library shared by many projects

// Start of specific implementation for project A

class SpecificObject : public BaseObject
{
    public:

        SpecificObject() : BaseObject(0) {}
};

class SpecificObjectHandler : public BaseObjectHandler
{
    public:

        void doSomethingOnVector()
        {
            // Do something on vector
        }
};

int main()
{
    SpecificObjectHandler handler;

    handler.setVector(std::make_unique<std::vector<SpecificObject>>());

    handler.doSomethingOnVector();

    exit(0);
}

// End of specific implementation for project A

BaseObjectHandler can share some common operations to its derived handlers, but knows nothing about SpecificObject, because it resides in a separate package base library.

In turn SpecificObjectHandler resides in project A package, knows about SpecificObject of course, and needs the above mentioned common operations that do not act on SpecificObject instances but rely only on BaseObject.

The code obviously does not compile because of error conversion from std::vector<SpecificObject> to std::vector<BaseObject> .

Is there a simple and elegant C++ 14 way to solve this issue? Or do you suggest a completely different pattern for this problem?

I found some answers to similar problems but I need more specific clarification.

Thanks.

Assuming you can edit the base library code, you could define BaseObjectHandler as a template class

// base_class_library.hpp

template<typename ObjectType>
class BaseObjectHandler
{
    public:

        void setVector(std::unique_ptr<std::vector<ObjectType>>&& v)
        {
            vec = std::move(v);
        }

    protected:
        std::unique_ptr<std::vector<ObjectType>> vec;
};

and inherit class SpecificObjectHandler: public BaseObjectHandler<SpecificObject> . Now SpecificObjectHandler has pointer to vector of SpecificObject s and your code would compile.

Of course it may lead to conflicts with other uses of the base library, but whenever you need the old (your) version of BaseObjectHandler you can declare it as BaseObjectHandler<BaseObject> . As a price, you would loose a possibility to upcast SpecificObjectHandler into generic BaseObjectHandler , but maybe that is not important for you.

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