Pregunta

En primer lugar, quiero quedado claro que entiendo que no hay noción de vtables y vptrs en el C ++ estándar . Sin embargo, creo que prácticamente todas las implementaciones de implementar el mecanismo de despacho virtual en más o menos la misma manera (me corrija si estoy equivocado, pero esta no es la cuestión principal). Además, creo que Sé lo virtual de funciones de trabajo , que es, siempre puedo decir qué función se llama, sólo necesito los detalles de implementación.

Supongamos que alguien me hizo la siguiente:
"Tienes base de clase B con funciones virtuales v1, v2, v3 y derivado de clase D:. B, que anula las funciones V1 y V3 y V4 agrega una función virtual explicar cómo funciona despacho virtual".

Yo respondería así:
Para cada clase con funciones virtuales (en este caso B y D) tenemos una matriz separada de punteros a funciones llamadas vtable.
La viable para B contendría

&B::v1
&B::v2
&B::v3

la viable para D contendría

&D::v1
&B::v2
&D::v3
&D::v4 

Ahora la clase B contiene un puntero VPTR miembro. D hereda de forma natural y, por tanto, contiene también. En el constructor y el destructor de B B conjuntos VPTR a punto de vtable de B. En el constructor y el destructor de D D ajustarlo en el punto a D's vtable.
Cualquier llamada a una función virtual f en un objeto x de la clase X polimórfico se interpreta como una llamada a x.vptr [posición de f en vtables]

Las preguntas son:
1. ¿Tengo algún error en la descripción anterior?
2. ¿Cómo funciona el compilador posición conocimientos de f en vtable (en detalle, por favor)
3. ¿Esto quiere decir que si una clase tiene dos bases entonces tiene dos vptrs? Lo que sucede en este caso? (Tratar de describir de una manera similar a como lo hice, con el mayor detalle posible)
4. ¿Qué pasa en una jerarquía de diamante con A en la parte superior B, C en el medio y D en la parte inferior? (A es una clase base virtual de B y C)

Gracias de antemano.

¿Fue útil?

Solución

1. ¿Tengo que cualquier error en la descripción anterior?

Todo bien. : -)

2. ¿Cómo funciona el compilador posición conocimientos de f en vtable

Cada proveedor tendrá su propia manera de hacer esto, pero yo siempre pienso en la viable como mapa de la función de miembro de la firma de memoria de correcciones. Por lo que el compilador simplemente mantiene esta lista.

3. ¿Esto quiere decir que si una clase tiene dos bases entonces tiene dos vptrs? Lo que está ocurriendo en este caso?

Típicamente, los compiladores componen un new vtable que consiste en todos los vtables de las bases virtuales adjuntas juntos en el orden en que se especifican, junto con el puntero vtable de la base virtual. Siguen esta vtable con las funciones de la clase derivada. Este es muy específica del proveedor, pero para class D : B1, B2, por lo general ver D._vptr[0] == B1._vptr.

herencia múltiple

Esa imagen es en realidad para la composición de los campos miembros de un objeto, pero vtables puede estar compuesto por el compilador en la exacta misma manera (por lo que yo entiendo).

4. Qué pasa en una jerarquía de diamante con A en la parte superior B, C en el medio y D en la parte inferior? (A es una clase base virtual de B y C)

La respuesta corta? un infierno. ¿Se hereda prácticamente tanto las bases? Sólo uno de ellos? ¿Ninguno de ellos? En última instancia, se utilizan las mismas técnicas de la composición de un vtable para la clase, pero ¿cómo se hace esto varía de manera violentamente, ya que ¿Cómo que debe hacerse no es del todo de piedra. Hay una explicación decente de resolver el problema de diamante jerarquía aquí , pero, como la mayoría de las esto, es bastante específica del proveedor.

Otros consejos

  1. Se ve bien para mí
  2. específico de la implementación, pero la mayoría son sólo con el fin código fuente - es decir, el orden en que aparecen en la clase - a partir de la clase base, a continuación, la adición de nuevas funciones virtuales a partir de la derivada. Mientras el compilador tiene una forma determinista de hacer esto, entonces cualquier cosa que quiere hacer es fina. Sin embargo, en Windows, para crear las tablas V-COM compatibles, que tiene que ser con el fin fuente

  3. (no estoy seguro)

  4. (conjetura) Un diamante sólo significa que usted podría tener dos copias de una clase base B. herencia virtual se fusionarán en una sola instancia. Así que si se establece a través de un miembro de D1, se puede leer a través de D2. (Con C deriva de D1, D2, cada uno de ellos derivan de B). Creo que en ambos casos, los vtables serían idénticos, como los punteros de función son los mismos - la memoria de los miembros de datos es lo que se fusionó
  5. .

Comentarios:

  • No creo que los destructores entran en él!

  • una llamada tal como por ejemplo D d; d.v1(); probablemente no se implementa a través de la viable, ya que el compilador puede resolver la dirección en función de compilación / enlace a tiempo.

  • El compilador sabe la posición de f porque puso ahí!

  • Sí, una clase con múltiples clases base tendrá típicamente múltiples vptrs (suponiendo funciones virtuales en cada clase base).

  • Scott Meyers' 'efectiva C ++' libros explican la herencia múltiple y diamantes mejor que yo; Me gustaría recomendar la lectura de ellos para esto (y muchas otras) razones. Considerarlas una lectura esencial!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top