我在哪里可以找到C ++有状态虚拟基础的一个很好的解释?

时间:2012-05-30 15:51:13

标签: c++

我在哪里可以找到对C ++有状态虚拟基础的一个很好的解释?

我查看了JSF C++ Coding Standard并阅读了他们的解释,但正在寻找其他信息。

感谢您提供的任何其他详细信息。

2 个答案:

答案 0 :(得分:3)

Stanley Lippman的书"Inside the C++ Object Model"对这个主题进行了很好的介绍(尽管已过时但仍然有效)。

答案 1 :(得分:2)

虚拟是关于间接的。让我们开始简单:

struct Foo { void bar(int, bool) {} } x;
x.bar(12, false);

此处,Foo::bar()对实例x的调用在编译时是完全已知的并且是静态解析的:一个固定函数,它给出了实例引用和函数参数。功能名称,调用,完成。到目前为止没问题。

继续前进:

struct Boo { virtual void bar(char, float) = 0; };
extern Boo * foreign_function();

Boo * p = foreign_function();
p->bar('a', -1.5);

这次,在编译时无法知道bar()调用应该去哪里。解决此问题的唯一方法是添加一个间接级别,允许您查找此成员函数的所有可能覆盖,并在运行时选择正确的覆盖,具体取决于*p的动态类型。这次我们从函数名开始,在运行时执行查找,然后进行调用。这种模式应该仍然相当熟悉。

这里的要点是,足以知道*p的动态类型是(非虚拟)基础Boo的子类型,因此我们只需一次查找即可实现此类型(例如,指向与Boo的表兼容的表的vtable指针。)

现在开始大鱼:

struct Voo { virtual void doo(double, void *) = 0; };
struct Left  : virtual Voo { virtual void doo(double, void *); } };
struct Right : virtual Voo { virtual void doo(double, void *); } };
struct Most : Left, Right  { virtual void doo(double, void *); } };

Left * p = /* address of a Most object, say */;
p->doo(0.1, nullptr);

我们已经知道我们不知道doo()应该去哪里,我们必须在运行时查找它。但是,不再可能实现简单的一步间接。即使LeftVoo的子类而Right也是Voo的子类,Voo的实际*p基础子对象却不是实际上是Left - 或Right - 子对象的子对象 - (唯一!)虚拟子对象直接属于Most(或者任何最派生的对象)。在实现方面,单个vtable指针并不好,因为我们不需要Left的vpointer,也不需要Right的vptr。相反,我们想要实际对象所具有的任何vpointer。

所以现在我们发现自己处于熟悉的状态:我们需要查看一些我们只能在运行时知道的东西。而这次我们需要查看的是实际的虚拟基础。所以过程如下:函数名称,在运行时查找虚拟基础,在虚拟基础中查找虚函数,然后进行调用。 (在虚拟化的典型vtable实现中,这通常通过“thunk”或“指针指针”进行额外的查找来完成。)

简而言之,“虚拟”意味着“在运行时确定”。

(这不会强制你的编译器生成运行时代码。如果在编译时可以证明调度的目标,那么调用可能是虚拟化的。但行为你的程序“好像”。)