多态性需要分配

Polymorphism Requires Allocation

本文关键字:分配 多态性      更新时间:2023-10-16

在C++中使用多态性通常需要动态分配、使用工厂模式等。这难道不是真实的说法吗?当然,如果我真的尝试,我可以在堆栈上实例化派生类型,但这是每天的代码还是学术练习?

其他一些面向对象的语言在堆上分配每个用户创建的类型。然而,C++我们的任何分配都可能引起同行对绩效的争论。

那么,如何在保持最小分配的同时使用多态性呢?

另外,我们真的在使用多态性而没有任何动态分配的情况下编写真实世界的代码吗?难道我们要忘记我们曾经学过工厂模式吗?


编辑:

在我看来,在这个问答中,我们已经确定了类型在编译时已知或未知的场景之间的差异。

有人提出,使用流是没有动态分配的多态性的一个例子。但是,当您使用流时,您在键入程序时知道所需的类型。

另一方面,在某些情况下,您在编译时不知道类型。这是我达到(并且被教导要达到(工厂模式的地方。给定一些输入,确定要实例化的具体类型。我看不出除此之外还有什么选择。有吗?

--

让我们尝试使用实际代码中出现的场景。

让我们假设一个股票交易系统。 您的工作是存储通过网络从客户到达的订单。

  • 输入的是 JSON 文本。
  • 输出应该是表示订单的数据结构的集合
  • 订单可以是香草股票购买、期权或期货。
  • 在解析 JSON 之前,您不知道客户在订购什么

自然,我会想出这样的东西,为了示例,域而超级简化:

class Order
{
protected:
double   m_price;
unsigned m_size;
};
class Option : public Order
{
protected:
string m_expirationDate;
};
class Future : public Order
{
protected:
string m_expirationDate;
};

然后我想出一些工厂来解析 JSON 并吐出一个订单:

class OrderFactory
{
Order * CreateOrder(const std::string & json);
};

工厂分配。因此,您的同行可能会指出,在每秒接收数百万个订单的系统中,它很慢。

我想我们可以将我们的域转换为一些像怪物一样的 C:

struct Order
{
enum OrderType
{
ORDER_TYPE_VANILLA,
ORDER_TYPE_OPTION,
ORDER_TYPE_FUTURE
}
OrderType   m_type;
double      m_price;
unsigned    m_size;
std::string m_expirationDate;  // empty means it isnt used
int         m_callOrPut        // Encoder rings are great for code!
// -1  - not used
//  0  - Put
//  1  - Call
};

但是我们只是完全抛弃了多态性,以及我认为好的OO原则。我们仍然很可能在它们进来时分配这些并存储它们。除非我们想为它们声明一些静态大小的容器并标记已使用或未使用的元素......(还有更多 C(

是否有一些我不知道的不会分配的替代方案?

在C++中使用多态通常需要动态分配,使用 工厂模式等这难道不是真实的说法吗?当然,我可以 如果我真的尝试,请在堆栈上实例化派生类型,但是是这样吗 每天编程还是学术练习?

"通常"有点毫无意义;这是一个模糊的比较,没有指标来产生统计数据。 是否可以在没有动态分配的情况下使用多态性? 是的,微不足道。 考虑这种情况:

struct A{};
struct B : A;
void foo(A& a) {};
void foo(A* a) {};
void bar() {
B b;
foo(b);
foo(&b);
}

并且未使用动态内存。

首先,C++人们经常区分编译时和运行时多态,我认为,你的问题是关于运行时多态行为的。

是的,有一些方法可以在不使用动态分配的情况下享受多态性。一个很好的例子是STL中的流。(虽然,很多人质疑他们的设计,但这不是重点(。

有人说,除非你有一个不同动态类型的多态对象的容器,否则运行时多态性真的不需要,模板会更好 - 但由于模板需要自付费,有时运行时多态性更适合。