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
?
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.