Ena*_*aid 7 c++ shared-ptr c++03
我有一个基类,BaseObject和两个派生类DerivedObject1和DerivedObject2.他们有共同的行为和方法,但DerivedObject1还有一个额外的方法.我的主类MyClass存储(in std::vector)boost::shared_ptr这些类的实例.MyClass需要调用commonMethod()所有BaseObject,有时需要调用additionalMethod()所有DerivedObject1.
class BaseObject
{
virtual void commonMethod();
}
Class DerivedObject1 : public BaseObject
{
void commonMethod();
void additionalMethod();
}
Class DerivedObject2 : public BaseObject
{
void commonMethod();
}
Run Code Online (Sandbox Code Playgroud)
有两个向量的缺点MyClass,一个存储所有指针的DerivedObject1和DerivedObject2,另一个向量只存储指针DerivedObject1?意思是我会有DerivedObject1两次所有的指针.但我认为对不同方法的要求至少是明确的.
class MyClass
{
typedef std::vector<std::shared_ptr<BaseObject>> BaseObjectVector;
typedef std::vector<std::shared_ptr<DerivedObject1>> DerivedObject1Vector;
BaseObjectVector everything;
DerivedObject1Vector only_derived1;
void doSomething()
{
for (BaseObjectVector::iterator iter = everything.begin(); iter != everything.end(); ++iter)
{
(*iter)->commonMethod();
}
}
void doSomethingForDerivedObject1()
{
for (DerivedObject1Vector::iterator iter = only_derived1.begin(); iter != only_derived1.end(); ++iter)
{
(*iter)->additionalMethod();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我可以想到其他方法,主要有一个向量DerivedObject1和一个向量DerivedObject2,但要调用commonMethod(),我将不得不迭代两个向量.我的原始解决方案对我来说似乎是最好的,除了一些指针存储两次.这有什么缺点?
有趣的问题.我们有时会遇到维护遗留代码的情况,我们不知道谁编写了这些代码.
在MyClass中有两个向量有什么缺点吗?
我认为没有机械(或性能)缺点. 如果我们努力满足发布截止日期,我们别无选择,只能选择这么简单的方式.但是,两次存储相同的向量实际上会降低可维护性,我们应该考虑在将来对其进行改进.
如果你需要dynamic_pointer_cast实现像@Caleth 's push_back/ 这样的函数remove,那么如何从一开始only_derived1就删除和不情愿地应用一个dynamic_pointer_castin doSomethingForDerivedObject1()如下?它将使MyClass更简单.如果将来定义DerivedObject3,则所需的修改不会很复杂.
void MyClass::doSomethingForDerivedObject1()
{
for (const auto& obj_i : everything)
{
if (auto derived1 = std::dynamic_pointer_cast<DerivedObject1>(obj_i))
{
derived1->additionalMethod();
}
}
}
void MyClass::doSomethingForDerivedObject3()
{
for (const auto& obj_i : everything)
{
if (auto derived3 = std::dynamic_pointer_cast<DerivedObject3>(obj_i))
{
derived3->additionalMethod();
}
}
}
Run Code Online (Sandbox Code Playgroud)
声明虚函数BaseObject::additionalMethod()并实现
void DerivedObject2::additionalMethod()
{
/* nothing to do */
}
Run Code Online (Sandbox Code Playgroud)
然后你可以再次删除only_derived1.在此方法中,DerivedObject3::additionalMethod()只有在定义了DerivedObject3时才必须实现.
但是,虽然它取决于您的构造函数或setter代码,但是如果还会发生以下情况
everything; ->derived2
only_derived1; ->derived1
Run Code Online (Sandbox Code Playgroud)
这种方法还不够.
理想情况下,我们不应该用公有继承来实现中的对象"IS-ALMOST-A"关系,如香草萨特说,之间的关系BaseObject,DerivedObject1以及DerivedObject2看起来像这一个.因为我不知道你的应用程序的整个代码可能是我错误,但值得考虑提取DerivedObject1::additionalMethod()为另一个类或函数指针,并将其向量作为私有成员放在MyClass中.