Интересный вопрос.Иногда мы сталкиваемся с такой ситуацией в обслуживании устаревших кодов, о которых мы не знаем, кто написал.
Есть ли недостатки наличия двух векторов в MyClass…?
Я думаю, что нет никаких механических (или эксплуатационных) недостатков. Если мы изо всех сил пытаемся уложиться в сроки выпуска, у нас нет иного выбора, кроме как выбрать такой простой способ.Тем не менее, сохранение одинаковых векторов в два раза фактически снижает удобство сопровождения, и мы должны рассмотреть возможность его улучшения в будущем.
- std :: dynamic_pointer_cast (или boost :: dynamic_pointer_cast) [Демо]
Если вам нужно dynamic_pointer_cast
для реализации таких функций, как @ Caleth push_back
/ remove
, как насчет удаления only_derived1
и неохотно применяя только один dynamic_pointer_cast
в 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();
}
}
}
Объявление виртуальной функции BaseObject::additionalMethod()
и реализация
void DerivedObject2::additionalMethod()
{
/* nothing to do */
}
, после чего вы можете снова удалить only_derived1
.В этом методе вы должны реализовать DerivedObject3::additionalMethod()
, только если определен DerivedObject3.
Но, хотя это зависит от кода вашего конструктора или установщика, если следующий случай также произойдет
everything; ->derived2
only_derived1; ->derived1
thisметод все еще недостаточен.
В идеале, мы не должны использовать публичное наследование для реализации объектов внутри "IS-ALMOST-A "отношения, как говорит Херб Саттер. Отношение между BaseObject
, DerivedObject1
и DerivedObject2
выглядит следующим образом. Поскольку я не знаю весь код вашего приложения, я могу ошибаться, но этоСтоит рассмотреть возможность извлечения DerivedObject1::additionalMethod()
в качестве другого класса или указателя функции и помещения его вектора в MyClass в качестве закрытого члена.