Search code examples
c++vectorattributesunique-ptr

Issues about using unique_ptr as type of vector (C++)


I‘m trying to understand a C++ code that uses vector which stores unique_ptr<Base>, where Base is a base class and has a derived class Derivate.

When pushing unique_ptr<Derivate> into this vector, there is no errors and can correctly call the method of derived class.

But when trying to modify a specific attribute of Derivate, there is an error " error: 'class Base' has no member named 'deri_name' ".

The code is as follow:

#include<iostream>
#include<vector>
#include <memory>
using namespace std;

class Base
{
public:
    virtual void test(){
        cout << "this is Base test" << endl;
    }

};

class Derivate :public Base
{
public:
    Derivate(const string& name):deri_name(name){

    }
    virtual void test(){
        cout << "this is Derivate test by " << deri_name << endl;
    }

    string deri_name;
};

int main()
{
    vector<unique_ptr<Base>> vec;
    vec.push_back(make_unique<Derivate>("wayne"));

    vec[0]->test(); // will sprint "this is Derivate test by wayne"

    //vec[0]->deri_name = 'wong';  // will report an error " error: 'class Base' has no member named 'deri_name' "

    return 0;
}

I've tried some methods, but there seems no straightforward way to cast vec[0] from unique_ptr<Base> to unique_ptr<Derivate>

could I possibly modify vec[0]->deri_name without modifying the type of vec?


Solution

  • The vector stores pointers to Base, which has no member named deri_name. If you are certain that vec[0] points to a Derivate object, you can static-cast:

    static_cast<Derivate&>(*vec[0]).deri_name = "wong";
    

    If you don't know for sure, you can dynamic-cast:

    if (auto ptr = dynamic_cast<Derivate*>(vec[0].get()))
        ptr->deri_name = "wong";
    

    Because this kind of thing is typically a pain, consider making your Base class provide virtual methods for operations that derivative classes can opt into. For instance, a set_name method that by default does nothing, but the Derivate class overrides.

    Only you know your requirements, but it's often worth considering ways to avoid polluting code with typecasts, if you can cleanly implement something without it.