【发布时间】:2010-11-30 16:57:36
【问题描述】:
好的,我们开始吧。我正在尝试使用CRTP 模板来消除我的应用程序对多态性的需求。我使用像下面这样的方法
template <RealType> class Base
{
void doSomething()
{
static_cast<RealType>(this)->doSomethingImpl()
}
class Derived1 : public Base
{
void doSomethingImpl()
{
/* do something, for real */
}
}
class Derived2 : public Base
{
void doSomethingImpl()
{
/* do something else */
}
}
如果我理解正确,这种方法允许我的类没有 vtable,因此函数调用是直接的,不需要额外的间接。
现在假设我想将我所有的 Derived# 类存储在一个容器中。让我们说一个向量。
第一种方法:我可以创建一个非模板 SuperBase 类,Base 从中继承并将其存储在容器中。
但在我看来,如果我想这样做,我将不得不在 SuperBase 中将 doSomething 设为虚拟。而我的目标主要是没有vtable。
第二种方法:我使用类型擦除,即类似 boost::any 的东西将我的元素存储在 Vector 中。 但是,我看不到可以迭代元素并在它们上调用 doSomething 的方法,因为要“使用” boost::any,我需要在迭代时知道对象的真实类型。
你认为我想做的事有可能吗?
在我看来,这是因为 doSomething() 是 Base 的一部分,但除了使用继承之外,我看不到这样做的方法......
【问题讨论】:
-
从以下两个答案中总结一点,以后可能还会有更多:您说,“我的目标主要是没有 vtable”。什么?正常的目标是,“我想编写一些有效的代码”,或者“我想编写一些有效且运行速度快的代码”。 vtables 是一个实现细节,一种提供动态多态性的方式,听起来您的主要目标是拥有动态多态性。
-
谢谢大家!好吧,避免 vtables 的重点确实是性能,因为这段代码将用于低级函数(即经常调用)。一般来说,我对 vtables 没有特别的仇恨:)。另一件事是我读了很多关于静态多态性的文章,我很好奇它是否可能!显然不是。谢谢大家的回答!
-
多态是一种可以在某些对象的确切类型可能取决于运行时事件时使用的工具。如果你需要这个,那么多态是一个非常好的工具。为了解决甚至未被证明存在的性能问题而放弃它以支持更钝的工具似乎是一个真正可怕的错误。如果您的对象的类型只能在运行时确定,那么您需要运行时多态。如果你不使用内置的,你需要自己破解。即使在非常特殊的情况下,这非常很难做到正确并且比内置的更快。
标签: c++ metaprogramming type-erasure