FStructA 和 FStructB 共享一个共同成员 Key,因此不妨考虑将其移至它们都派生自的基类。
在处理多态类型时,基类几乎总是需要virtual 析构函数,以便在通过基类指针销毁对象时正确调用派生构造函数。这在使用智能指针时尤其重要,例如在多态对象的容器中,正如这段代码所做的那样。
struct 成员默认为public,struct 派生自另一个struct,默认使用public 继承,因此明确声明FStructA 和FStructB 从@ 继承publicly 987654333@ 是多余的。
使用override 时,无需再次指定virtual。 override 就其本质而言意味着 virtual。
避免将new 与智能指针构造函数一起使用。请改用 std::make_...() 函数 - std::make_unique() 用于 std::unique_ptr,std::make_shared() 用于 std::shared_ptr()。
重载的Add() 方法可以合并为一个模板方法。
emplace_back() 在处理(智能)指针时与push_back() 相同,尤其是对于必须在容器外部构造的多态类型。仅当容器本身能够直接构造元素时,使用emplace_back() 而不是push_back() 才有意义,然后您只需给emplace_back() 构造函数参数。但在这段代码中并非如此。
在您的range-for 循环中,您将获取DataElement 按值,这将在DataElements 中复制每个shared_ptr,从而随着它们的引用计数递增和递减进入和离开范围。虽然这很好,但这是不必要的开销。您应该参考DataElement。事实上,在迭代任何容器时,您通常应该使用引用,除非您确实需要副本,或者制作副本的开销可以忽略不计(即,对于普通类型)。
在声明变量时尽可能考虑使用auto,尤其是在处理模板类型时。这在range-for 循环中特别有用。
不要将static_cast 与shared_ptr 的原始指针一起使用,而是使用static_pointer_cast 来维护正确的共享所有权语义。
不要不必要地复制对象。您正在取消引用 static_cast 的结果,然后制作对象的副本,然后您正在处理副本,而不是原始文件。这有时很有用,但这段代码不是其中之一。使用指针或引用来避免复制。
除非确实需要,否则不要将基类转换为派生类。如果你有多态类型(就像这段代码一样),尽可能使用多态行为(即虚方法)。正确的多态处理逻辑不应该关心它在操作什么类型。
当std::unique_ptr 足够时不要使用std::shared_ptr。 std::shared_ptr 有std::unique_ptr 没有的开销(引用计数、控制块等)。共享所有权有其用途,但此代码没有展示它们。
话虽如此,请尝试更多类似的东西:
struct IStruct
{
std::string Key;
virtual ~IStruct() = default;
//virtual bool GetType() const = 0;
virtual void Process() = 0;
};
struct FStructA : IStruct
{
int IntData;
/*
bool GetType() const override
{
return true;
}
*/
void Process() override
{
// Process A
}
};
struct FStructB : IStruct
{
float FloatData;
/*
bool GetType() const override
{
return false;
}
*/
void Process() override
{
// Process B
}
};
class SomeSystem
{
public:
template<typename T, typename... Args>
void Add(Args&&... args)
{
DataElements.push_back(/*std::make_shared*/std::make_unique<T>(std::forward<Args>(args)...));
}
void Process()
{
for (auto &DataElement : DataElements)
{
/*
if (DataElement->GetType())
{
auto StructA = static_pointer_cast<FStructA>(DataElement);
// Process A
}
else
{
auto StructB = static_pointer_cast<FStructB>(DataElement);
// Process B
}
*/
DataElement->Process();
}
}
private:
std::vector</*std::shared_ptr*/std::unique_ptr<IStruct>> DataElements;
};
int main()
{
SomeSystem system;
system.Add<FStructA>(...params as needed...);
system.Add<FStructB>(...params as needed...);
system.Process();
}