7


例如,我有两个“接口”和类类型:

class IPlugin
{
  public:
    virtual void Load(void) = 0;
    virtual void Free(void) = 0;
};

class IFoo
{
  public:
    virtual void Foo(void) = 0;
};


class Tester: public IPlugin, public IFoo
{
   public:
           Tester() {};
          ~Tester() {};

           virtual void Load()
           {
              // Some code here
           }

           virtual void Free()
           {
              // Some code here
           }

           virtual void Foo(void)
           {
              // Some code here
           }
 };

vtab 实际上具有什么结构,例如 type Tester?以及 表达式中的dynamic_cast操作员行为(我的意思是dynamic_cast操作员如何扫描 vtab 以进行有效的引用类型转换):

Tester* t = new Tester();
IPlugin* plg = dynamic_cast<IPlugin*>(t);
IFoo* f = dynamic_cast<IFoo*>(plg);  

提前致谢!

4

4 回答 4

18

C++ 中的虚拟表是一个实现细节。下图显示了一种可能的实现方式。

虚拟表图

存在类的两个实例(A 和 B)。每个实例都有两个 vtbl 指针,而 vtbl 包含指向实际代码的指针。

在您的示例中,没有实例数据,但出于说明目的,我假设每个类都包含一些实例数据。

当指针Tester被转换为指针时IFoo,指针被调整,如图所示。它不是指向实例数据的开始,而是指向实例数据的IFoo一部分。

巧妙的是,使用IFoo指针的调用者对类部分周围的数据一无所知IFoo。对于使用IPlugin指针的调用者也可以这样说。该指针恰好指向实例数据的开头,也由Tester指针指向,但只有使用Tester指针的调用者知道实例数据的整个布局。

使用dynamic_cast需要未在图表中的 RTTI(运行时类型信息)。vtbl 将包含附加类型信息,这些信息给定一个IFoo指向实例的 say 指针,Tester允许代码在运行时发现指针指向的对象的实际类型,并使用它来向下转换指针。

于 2011-05-03T12:16:56.593 回答
6

vtab 实际上具有什么样的结构,例如 Tester 类型?

虚拟调度的机制是实现定义的。vtable 和 vptr 不是 C++ 标准所要求的,程序员在 C++ 中编程甚至不需要这些知识,因为您无法访问虚拟表(即使您的编译器实现了这一点);它由编译器生成并添加到您的代码中,就像它在将代码转换为机器代码之前对您的代码做了很多事情一样。


Tester* t = new Tester();
IPlugin* plg = dynamic_cast<IPlugin*>(t);
IFoo* f = dynamic_cast<IFoo*>(plg);  

dynamic_cast第二行不需要这里。以下内容就足够了:

Tester* t = new Tester();
IPlugin* plg = t;                 //upcast          - dynamic_cast not needed
IFoo* f=dynamic_cast<IFoo*>(plg); //horizontal-cast - dynamic_cast needed

dynamic_castupcast 中不需要;仅在向下投射和水平投射时需要。

Tester* tester1 = dynamic_cast<Tester*>(plg); //downcast - dynamic_cast needed
Tester* tester2 = dynamic_cast<Tester*>(f);   //downcast - dynamic_cast needed
于 2011-05-03T11:10:21.057 回答
6

ISO/IEC 14882 第二版 2003-10-15中不存在 vptr、虚拟表等术语,因此完全取决于编译器实现者。

关于 impl 的信息。在微软的视觉 C++ 中: http ://www.openrce.org/articles/files/jangrayhood.pdf

关于 impl 的文章。g++ 中的虚拟表:http: //phpcompiler.org/articles/virtualinheritance.html

于 2015-06-20T00:01:25.043 回答
3

C++ 标准没有定义虚拟机制(Virtual Pointer & Virtual Table)。编译器无需以自己选择的方式实现该机制。它是编译器的实现细节。鉴于此,编译器将如何实现虚拟机制的细节从用户那里抽象出来。重要的是虚拟机制中预期的行为。

在你的情况下:

Tester* t = new Tester(); 
IPlugin* plg = dynamic_cast<IPlugin*>(t); 
IFoo* f = dynamic_cast<IFoo*>(plg);   

plg&f都将指向它们各自类型的有效对象,因为tis 派生自它们两者。

当然,这并不能回答您提出的具体问题,而只是想清楚有关虚拟机制的细节是编译器的实现细节。

于 2011-05-03T11:12:29.507 回答