Pregunta Asignando objeto de clase derivado a una referencia de clase padre


Siempre me desconcierto cuando veo:

Parent ref = new Child();

donde la clase Child se extiende Parent.

  1. Como funciona el objeto ref parece en la memoria?
  2. ¿Cómo se trata el método virtual? no virtual?
  3. ¿En qué se diferencia de:
Child ref = new Child();

5
2017-12-05 19:49


origen


Respuestas:


¿Cómo se ve el objeto en la memoria?

Tu pregunta no está clara. Hay dos ubicaciones de memoria relevantes. los variable Se asocia con una ubicación de almacenamiento. Esa ubicación de almacenamiento contiene una referencia a otro ubicación de almacenamiento.

La ubicación de almacenamiento de la variable normalmente se realiza como un entero de cuatro u ocho bytes que contiene un "puntero administrado", una dirección de memoria conocida por el recolector de basura.

El diseño de la memoria del objeto también es un detalle de implementación del CLR. El búfer de memoria asociado con el objeto contendrá todos los datos del objeto, todos los valores de los campos y otras cosas. También contiene una referencia a todavía otro ubicación de la memoria, la tabla de funciones virtuales del objeto.

La tabla de funciones virtuales (vtable) contiene incluso más referencias, esta vez las referencias se refieren a los métodos asociados con el tipo más derivado del objeto.

¿Cómo se trata el método virtual? no virtual?

Los métodos virtuales se ejecutan buscando la referencia de objeto de la variable, luego buscando la tabla de variables, luego buscando la forma del método en la tabla de variables y luego invocando ese método.

Los métodos no virtuales no se invocan a través de vtable porque se conocen en tiempo de compilación.

¿En qué se diferencia de ...

Los métodos no virtuales llamados en el objeto llamarán la versión del método en función del tipo de variable. Los métodos virtuales llamados en el objeto llamarán la versión del método en función del tipo de objeto a que se refiere la variable.

Si eso no está todo claro, es posible que desee leer mi artículo que explica cómo "emular" los métodos virtuales en un idioma que no los tiene. Si puede comprender cómo implementar los métodos virtuales en un lenguaje que no los tiene, eso le ayudará a comprender cómo realmente hacer Implementar métodos virtuales.

http://blogs.msdn.com/b/ericlippert/archive/2011/03/17/implementing-the-virtual-method-pattern-in-c-part-one.aspx


6
2017-12-05 23:30



ref es un Child objeto. los métodos virtuales son llamados en Child clase. Sin embargo, los métodos definidos sólo en Child clase no son visibles cuando se asignan a Parent objeto.

Si foo() no era virtual, luego la compilación seleccionará un método basado en el tipo declarado de la variable ref. Si usted tiene Parent ref = new Child(); entonces Parent.foo() sera llamado. Si usted tiene Child ref = new Child(); entonces Child.foo() sera llamado. Por supuesto, en este caso el compilador de C # le pedirá que use new en la declaración de Child.foo() para indicar que quiere ocultar la implementación en Parent.


2
2017-12-05 19:51



Imagino ref sólo contiene la dirección donde el referido Child objeto se puede encontrar. Si llama a un método virtual, el método real invocado depende del tipo dinámico del objeto (Child); Si llama a un método no virtual, depende del tipo estático (Parent) Es diferente de Child ref = ... porque en esa, el tipo estático es Child más bien que Parent.

Y espero que esto no sea tarea :)


0
2017-12-05 20:03



Piénselo de esta manera (suponiendo que Parent no sea una clase abstracta)

Parent ref = new Child();

y

Parent ref = new Parent();

Son en su mayoría los mismos, excepto virtual Los métodos anulados en Child se llamarán en el primero, pero no en el segundo.

los tipo que declare el objeto como determinará qué métodos son disponible en eso. Declarar que un objeto es un tipo menos específico de lo que lo ejemplifica como —el caso anterior—poder afectar a qué métodos se llaman en tiempo de ejecución, pero solo si esos métodos se declaran como abstractos o virtuales.

En cualquier caso, imagina que llamaste a un método. foo en ref. El tiempo de ejecución sería un buen método foo en clase Parent. El tiempo de ejecución entonces vería si foo Era virtual (o abstracto). Si foo no era virtual o abstracto, el tiempo de ejecución llamaría al foo El padre define en ese mismo momento, y listo. Si acaso foo  fueron virtual o abstracto, el tiempo de ejecución verificaría si los ref eran De Verdad instanciado a un tipo más específico que anula foo. Si es así, llamaría ese  foo


0
2017-12-05 20:06