Reputation: 3035
Say I have a base class and some derived classes:
class Base1
{
public:
virtual ~Base1() {}
virtual void update() = 0;
};
class Derive1 : public Base1
{
public:
void update() override {/*...*/}
};
class Derive2 : public Base1
{
public:
void update() override {/*...*/}
};
and somewhere to manage my derived objects:
class Base1Manager
{
public:
void add(Base1* p)
{
objs.push_back(p);
}
void update()
{
std::for_each(objs.begin(), objs.end(), [](Base1* p) { p->update(); });
}
void clear()
{
std::for_each(objs.begin(), objs.end(), [](Base1* p) { delete p; });
objs.clear();
}
std::vector<Base1*> objs;
};
Base1Manager bm1;
bm1.add(new Derive1());
bm1.add(new Derive2());
I can do update:
bm1.update();
finally I have to release the resources upon program exit:
bm1.clear();
The above scenario is fine, but the next is not:
The problem is when I add another base class and expand my derived classes:
NOTE: According to this answer:
[Why should I avoid multiple inheritance in C++?, Point 3 and 4, my Base1
and Base2
are different concepts so the multiple inheritance should be fine here.
class Base1
{
public:
virtual ~Base1() {}
virtual void update() = 0;
};
class Base2
{
public:
virtual ~Base2() {}
virtual void do_different_thing() = 0;
};
class Derive1 : public Base1, public Base2
{
public:
void update() override {/*...*/}
void do_different_thing() override {/*...*/}
};
class Derive2 : public Base1, public Base2
{
public:
void update() override {/*...*/}
void do_different_thing() override {/*...*/}
};
Also imagine there is a new Base2Manager
, basically the same as Base1Manager
.
Finally my question is, how to properly release the resources?
Apparently I can not do the release twice:
bm1.clear();
bm2.clear();
I have to choose only 1 manager and let it do the job, but these 2 managers are made separately and does not know each other, so what's the proper way to handle it?
Would smart pointer help? Should I add an API like addButNotRelase(Base2* p)
so that I can manipulate p
but not own p
(like put p
in a vector
other than objs
?
Upvotes: 0
Views: 127
Reputation: 217275
std::shared_ptr
helps here as both managers own the (potentially same) pointer.
In your first example, with only one manager, you may have replaced std::shared_ptr
by std::unique_ptr
.
If an other class have to own the object to control lifetime, then you may use simple pointer in your manager.
The usage should look like:
// The container
std::vector<std::shared_ptr<Base1>> base1s;
std::vector<std::shared_ptr<Base2>> base2s;
// The objects
std::shared_ptr<Derive1> d1 = std::make_shared<Derive1>();
std::shared_ptr<Derive2> d2 = std::make_shared<Derive2>();
// Feed the containers
base1s.push_back(d1);
base1s.push_back(d2);
base2s.push_back(d1);
base2s.push_back(d2);
Upvotes: 1