No estoy de acuerdo con @sechastain
.
Inline está lejos de ser automático. Independientemente de si el método se define o no en el lugar o se utiliza una sugerencia (inline
palabra clave o __forceinline
), el compilador es el único que decide si la alineación realmente tendrá lugar y usa heurística complicada para hacerlo. Sin embargo, un caso particular es que no debe alinear una llamada cuando se invoca un método virtual utilizando el despacho en tiempo de ejecución, precisamente porque el despacho en tiempo de ejecución y la alineación no son compatibles.
Para comprender la precisión de "utilizar el envío en tiempo de ejecución":
IClassInterface* i = /**/;
i->LOL(); // runtime dispatch
i->QueueClass::LOL(); // compile time dispatch, inline is possible
@0xDEAD BEEF
: Encuentro su diseño frágil para decir lo menos.
El uso de C-Style arroja aquí está mal:
QueueClass* p = /**/;
IClassInterface* q = p;
assert(((void*)p) == ((void*)q)); // may fire or not...
Fundamentalmente no hay garantía de que las 2 direcciones son iguales: es la aplicación definida, y es improbable que se resisten al cambio.
les deseo ser capaz de lanzar con seguridad el puntero void*
a un puntero IClassInterface*
entonces usted necesita para crear desde una IClassInterface*
originalmente para que el compilador de C++ puede realizar la aritmética de punteros correcta dependiendo de la disposición de los objetos.
Por supuesto, también destacaré que el uso de variables globales ... probablemente usted lo sepa.
¿Cuál es el motivo de la ausencia? Honestamente, no veo nada aparte de un error en el compilador/enlazador. He visto la definición en línea de virtual
funciones varias veces (más específicamente, el método clone
) y nunca causó problemas.
EDITAR: Ya que "la aritmética de punteros correcta" no fue tan bien entendido, aquí es un ejemplo
struct Base1 { char mDum1; };
struct Base2 { char mDum2; };
struct Derived: Base1, Base2 {};
int main(int argc, char* argv[])
{
Derived d;
Base1* b1 = &d;
Base2* b2 = &d;
std::cout << "Base1: " << b1
<< "\nBase2: " << b2
<< "\nDerived: " << &d << std::endl;
return 0;
}
Y aquí es lo que estaba impreso:
Base1: 0x7fbfffee60
Base2: 0x7fbfffee61
Derived: 0x7fbfffee60
No es la diferencia entre el valor de b2
y &d
, aunque se refieran a una entidad. Esto se puede entender si uno piensa en el diseño de la memoria del objeto.
Derived
Base1 Base2
+-------+-------+
| mDum1 | mDum2 |
+-------+-------+
Al convertir de Derived*
a Base2*
, el compilador llevará a cabo el ajuste necesario (en este caso, incremente la dirección del puntero por un byte) de manera que el puntero termina señalando de manera efectiva a la parte Base2
de Derived
y no a la Base1
parte interpretada erróneamente como un objeto Base2
(que sería desagradable).
Es por esto que el uso de C-Style arroja que hay que evitar cuando downcasting. Aquí, si tiene un puntero Base2
, no puede reinterpretarlo como un puntero Derived
. En su lugar, deberá usar static_cast<Derived*>(b2)
, que disminuirá el puntero en un byte para que apunte correctamente al comienzo del objeto Derived
.
punteros Manipular que normalmente se conoce como la aritmética de punteros. Aquí el compilador realizará automáticamente el ajuste correcto ... a condición de conocer el tipo.
Lamentablemente, el compilador no puede realizarlos al convertir desde un void*
, por lo tanto, depende del desarrollador asegurarse de que maneja correctamente esto. La regla general es la siguiente: T* -> void* -> T*
con el mismo tipo que aparece en ambos lados.
Por lo tanto, usted debe (simplemente) corregir su código declarando: IClassInterface* globalMember
y que no tendría ningún problema de portabilidad. Probablemente aún tengas problemas de mantenimiento, pero ese es el problema de usar C con código OO: C no tiene conocimiento de que haya nada orientado a objetos.
¿Qué pasa con cualquier otra función virtual no en línea en 'QueueClass' (si hay alguna)? ¿Funcionan? En otras palabras, ¿está el problema con 'LOL' local en la entrada de' 'VOL de' 'LOL'' o si la tabla completa está vacía o falta? – AnT
¿por qué heredar de forma privada IClassInterface? –
¿Por qué la función 'get ...' devuelve 'void *' en lugar de 'IClassInterface *'? – AnT