假设我有一个基类和一些派生类:
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 {/*...*/}
};
和管理我的派生对象的地方:
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());
我可以做update:
bm1.update();
最后我必须在程序退出时释放资源:
bm1.clear();
上面的场景很好,但下一个不是:
问题是当我添加另一个基类并扩展我的派生类时:
注:根据这个答案:在c++中为什么要避免多重继承?,第3点和第4点,我的Base1
和Base2
是不同的概念,所以多重继承在这里应该没问题。
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 {/*...*/}
};
也想象有一个新的Base2Manager
,基本上和Base1Manager
一样。
最后我的问题是,如何适当地释放资源?
显然我不能做两次释放:
bm1.clear();
bm2.clear();
我只能选择一个管理器,让它来做这件事,但是这两个管理器是分开制作的,彼此不认识,怎么处理才合适呢?
智能指针有帮助吗?我是否应该添加一个像addButNotRelase(Base2* p)
这样的API,以便我可以操纵p
,但不拥有p
(如将p
放在objs
以外的vector
中)?
std::shared_ptr
在这里有帮助,因为两个管理器都拥有(可能相同的)指针。
在您的第一个示例中,只有一个管理器,您可能已经将std::shared_ptr
替换为std::unique_ptr
。
如果其他类必须拥有该对象以控制生命周期,则可以在管理器中使用简单指针。
用法如下:
// 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);