简体   繁体   中英

Can you copy Derived Class objects from one std::vector<std::unique_ptr<BaseClass>> to another std::vector<std::unique_ptr<BaseClass>>?

I have two vectors. I register derived classes in one vector, then want to make copies and copy them over to the other vector. I am trying to do this to avoid base class slicing, but be able to have "templates" of classes that I use to spawn new objects that I can mutate from those.

How do I clone an object pointed to by unique_ptr and have a new unique_ptr that I can store in a vector ?

The idea shown below is that I could have multiple copies of the class in active , while still having the original object in available . Or, is there a better architecture for trying to make copies of a derived class for storage?

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

class BaseClass {
    virtual void doSomething(){}
};
class DerivedClass1: public BaseClass {
    public:
    float myVar1;
    void doSomething() override { std::cout << "1"; }
};
class DerivedClass2: public BaseClass {
    public:
    int myVar2;
    void doSomething() override { std::cout << "2"; }
};

std::vector<std::unique_ptr<BaseClass>> available;
std::vector<std::unique_ptr<BaseClass>> active;

void registerClass( std::unique_ptr<BaseClass> newAvailable ) {
    available.push_back(std::move(newAvailable));
}
void makeActive() {
    for( auto &toMakeActive : available ) {
//        todo: ?? // active.push_back( available->clone() );
    }
}
int main() {
    std::unique_ptr<DerivedClass1> derived1 = std::make_unique<DerivedClass1>();
    std::unique_ptr<DerivedClass2> derived2 = std::make_unique<DerivedClass2>();
    registerClass( std::move( derived1 ) );
    registerClass( std::move( derived2 ) );

    makeActive();
    makeActive();
    return 0;
} 

How do I clone an object pointed to by unique_ptr and have a new unique_ptr that I can store in a vector ?

C++ has no facility to handle this automatically, you have to implement it manually in each derived class, eg:

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

class BaseClass {
    virtual void doSomething(){}
    virtual std::unique_ptr<BaseClass> clone() = 0;
};

class DerivedClass1: public BaseClass {
public:
    float myVar1;
    void doSomething() override { std::cout << "1"; }
    std::unique_ptr<BaseClass> clone() override { return std::make_unique<DerivedClass1>(*this); }
};

class DerivedClass2: public BaseClass {
public:
    int myVar2;
    void doSomething() override { std::cout << "2"; }
    std::unique_ptr<BaseClass> clone() override { return std::make_unique<DerivedClass2>(*this); }
};

std::vector<std::unique_ptr<BaseClass>> available;
std::vector<std::unique_ptr<BaseClass>> active;

void registerClass( std::unique_ptr<BaseClass> newAvailable ) {
    available.push_back(std::move(newAvailable));
}

/* alternatively:
template<class T>
void registerClass() {
    available.push_back(std::make_unique<T>());
}
*/

void makeActive() {
    for( auto &toMakeActive : available ) {
        active.push_back( available->clone() );
    }
}

int main() {
    registerClass( std::make_unique<DerivedClass1>() );
    registerClass( std::make_unique<DerivedClass2>() );
    /* alternatively:
    registerClass<DerivedClass1>();
    registerClass<DerivedClass2>();
    */

    makeActive();
    makeActive();

    return 0;
}    

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