在C ++中使用多态性通常需要动态分配,使用工厂模式等。这不是真实的陈述吗?当然,如果我真的尝试过的话,我可以在堆栈上实例化派生类型,但这是每天的代码还是一次学术练习?
其他一些面向对象的语言在堆上分配每个用户创建的类型。但是,使用C ++进行的任何分配都可能引起与同行之间有关性能的争论。
那么,如何在保持最小分配的同时使用多态呢?
此外,我们是否真的在使用多态性而没有任何动态分配的同时编写了真实的代码?我们会忘记我们曾经学习过工厂模式吗?
编辑:
在我的问答中,我们似乎确定了在编译时知道类型还是不知道类型的情况之间的区别。
有人提出,使用流是没有动态分配的多态性的一个例子。但是,在使用流时,在键入程序时就会知道所需的类型。
另一方面,在某些情况下,您在编译时不知道类型。这是我到达(并且被教导要到达)工厂模式的地方。给定一些输入,确定要实例化的具体类型。我没有其他选择。有一个吗?
-
让我们尝试使用真实代码中出现的场景。
让我们假设一个股票交易系统。 您的工作是存储从客户通过网络到达的订单。
自然,我想出了类似这样的内容,出于示例目的,对域进行了超级简化:
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
};
但是,我们只是放弃了多态性,而我认为这完全是好的面向对象原则。我们仍然很可能会分配它们并在它们进入时将它们存储起来。除非我们要为它们声明一个静态大小的容器并标记元素已使用或未使用。...(还有C)
是否存在一些我不知道的替代方案?
答案 0 :(得分:2)
在C ++中使用多态通常需要动态分配,使用 工厂模式等。这不是真实的陈述吗?我当然可以 如果我真的尝试过,则实例化堆栈上的派生类型,但这是 每天的代码或学术练习?
“通常”是没有意义的;这是一个模糊比较,没有任何指标可以生成统计数据。是否可以在没有动态分配的情况下使用多态?是的,微不足道。考虑这种情况:
struct A{};
struct B : A;
void foo(A& a) {};
void foo(A* a) {};
void bar() {
B b;
foo(b);
foo(&b);
}
并且不使用动态内存。
答案 1 :(得分:1)
首先,在C ++中,人们经常区分编译时和运行时多态,我认为,您的问题是关于运行时多态行为的。
是的,有多种方法可以享受多态而不使用动态分配。 STL中的流就是一个很好的例子。 (尽管很多人质疑他们的设计,但这并不重要。
有些人说,除非您有一个容器(指向)不同动态类型的多态对象,否则确实不需要运行时多态,并且模板会更好地工作-但由于模板是自费的,有时运行时多态性更适合。