¿Es un "constructor de objetos" un nombre más corto para una "función con el nombre` object` que devuelve el tipo `object`"?

9

Quiero decir, es una cuestión de elegir palabras más que cualquier diferencia entre la función y la llamada al constructor. La cosa que se llama "constructor de un objeto" también se puede llamar "función con objecttipo de retorno de nombre object".

Se podría argumentar que C ++ no permite que uno tenga la misma función y nombre de tipo; Sin embargo, hay una solución para hacerlo. C ++ tiene un azúcar sintáctico especial (que se denomina constructor) con el que puede crear una función con el objecttipo de retorno de nombre object. Así que creo que un constructor se puede ver y usar como una función independiente.

¿Hay algunas diferencias semánticas importantes que me estoy perdiendo aquí?

usuario3123061
fuente
1
Tenga en cuenta que el hecho de que los constructores se nombren por su tipo está lejos de ser universal: PHP los llama __construir, Object Pascal / Delphi los llama Crear, y parece recordar que en ese caso es solo una convención, y la verdadera distinción es que ellos tener la palabra clave "constructor" delante de su definición.
IMSoP
Nota: Los constructores en C ++ no devuelven nada (y, por lo tanto, no tienen ningún tipo de retorno).
el.pescado
Los factores son meta-métodos, no métodos. no envía un mensaje ctors a una instancia de una clase, lo envía a la clase, en realidad al objeto de clase, que es el metaobjeto de la clase. y los controladores definitivamente no son funciones, ya que tienen efectos secundarios: cada vez obtienes un resultado diferente.

Respuestas:

17

Un constructor es básicamente un método, sí, pero es un método especial.

Por ejemplo, en C ++ un constructor no es simplemente una función que devuelve una nueva instancia de ese tipo. Si lo fuera, la herencia no funcionaría. No se podía llamar a los constructores base, porque también devolverían una nueva instancia. Terminaría con una nueva instancia de A, que luego se devuelve al constructor de B que crea una nueva instancia de B, que luego se devuelve al constructor de C, etc.

En cambio, un constructor es más un método de inicialización que el asignador de instancias llama automáticamente. Cuando, por ejemplo, llama a "nuevo" para hacer un objeto en el montón, asigna la memoria para el tipo que solicitó (usando un asignador de memoria, como malloc), luego llama al método del constructor. El compilador tiene reglas especiales sobre cómo, y en qué orden, ese constructor puede llamar a los otros constructores. Por ejemplo, en C #, si no llama explícitamente a un constructor base, el compilador agregará una llamada al constructor predeterminado base.

Son esas reglas acerca de cómo el compilador maneja los constructores lo que lo hace diferente de "una función llamada .ctor que devuelve una instancia del tipo".

Kevin Fee
fuente
3
Tampoco se suele utilizar newpara construir objetos en C ++, ya que tiene variables automáticas.
Quentin
6

No, un constructor de objectes muy diferente de una función llamada objecty que regresa object. Un constructor no tiene nombre, pero eso es en gran medida un tecnicismo. Las diferencias más importantes son que un constructor no tiene tipo de retorno y que no se puede llamar directamente.

Un constructor no devuelve nada porque se le asigna un bloque de memoria y opera en esa memoria en el lugar. Podría ayudar si olvida el nombre "constructor" por un momento y piensa en él como un inicializador . El propósito del constructor no es construir un objeto "de la nada". Su propósito es inicializar un objeto en el lugar preciso de la memoria donde debe estar.

Si un constructor devolviera un objeto, ese objeto devuelto (el valor de retorno) tendría que vivir en algún lugar (probablemente en la pila), y allí, tendría que inicializarse de alguna manera , estamos corriendo en un bucle aquí.

Esto va de la mano con el hecho de que un constructor nunca puede ser llamado directamente. Si tiene una clase objecty usa una expresión en object()alguna parte, no tiene la semántica de "llamar al constructor de object". Tiene la semántica de "crear un objeto de tipo temporal object". El compilador traduce esto en la asignación de un lugar para que el temporal viva (probablemente / comúnmente en la pila), y llama al constructor para construir (= inicializar) un objeto en ese lugar.

El mismo principio se aplica cuando se usa new object(). Esta es una nueva expresión, que hace dos cosas:

  1. Llame a una función de asignación operator new(que devuelve a void*) para asignar memoria sin procesar para el objeto.
  2. Emita una llamada de constructor en esta memoria sin formato para construir (= inicializar) un objeto en ese fragmento de memoria sin formato.

Pensando en un constructor de objectcomo una función como esta:

static object object();

Está Mal. En todo caso, la forma en que funciona un constructor está más cerca de esto:

static void object(object &place_to_work_in);

Con la excepción de que nunca puedes llamarlo directamente. Está siempre sólo se llama cuando especificado por una construcción del lenguaje diferente. Incluso la colocación nueva (también conocida como el truco "llamar a un constructor aquí") new (&place_for_object) object()no llama al constructor directamente. Se traduce en una llamada a la forma de colocación nueva, operator newque devuelve su argumento, seguido de una llamada al constructor (como cualquier otra expresión nueva).

Angew ya no está orgulloso de SO
fuente
Confieso que no participo mucho en esta pila, por lo que es posible que no esté familiarizado con la cultura y los estándares esperados aquí. Si hay algo que puedo mejorar en esta respuesta, por favor avíseme además de la votación negativa, para que pueda solucionarlo.
Angew ya no está orgulloso de SO
+1 No se preocupe por ese voto negativo, su respuesta es excelente :) Por alguna razón, casi todas las respuestas aquí tienen un voto negativo.
amon
1

Su intento de volver a redactar es incorrecto.

Aunque un constructor parece una función miembro con un nombre igual al nombre de la clase, el hecho es que un constructor realmente no tiene un nombre. Esto se establece explícitamente en el estándar C ++ (sección [class.ctor] / 1):

Los constructores no tienen nombres.

En cuanto a: "Creo que un constructor se puede ver y usar como una función independiente" va ... bueno, no estoy muy seguro de lo que quieres decir. Una función libre ciertamente no puede ser un constructor, un constructor debe ser miembro de una clase. Al mismo tiempo, ciertamente puede definir una función libre que crea un objeto y devuelve una instancia de ese objeto. Esa función libre puede incluso (más o menos) tener el mismo nombre que el tipo de objeto que crea, si lo desea lo suficiente. Por ejemplo, podría definir la clase dentro de un espacio de nombres, luego definir una función fuera del espacio de nombres:

namespace foo { 
    class bar {};
}

foo::bar bar() { return foo::bar(); }

Este no es realmente el mismo nombre (la función es justa bary la clase es foo::bar), pero dependiendo de su punto de vista, podría mirarlos de esa manera de todos modos.

Sin embargo, una función libre de este tipo no tendría las otras características clave de un constructor. La invocación de un constructor puede ser completamente implícita. Por ejemplo, si tengo una clase como:

class foo {
public:
   foo (int) {}
   foo operator+(foo const &other) {}
};

... luego código como:

foo f(1);

foo h(0);
h = f + 1;

... puede crear un objeto foo temporal a partir del 1para que pueda pasar ese objeto foo a foo::operator+. Eso simplemente no sucederá con una función libre, incluso si esa función libre se definió para tomar el tipo de parámetro correcto y devolver el tipo de resultado requerido. Para una conversión tan implícita, se requiere un constructor.

Jerry Coffin
fuente
1

Quiero decir, es una cuestión de elegir palabras más que cualquier diferencia entre la función y la llamada al constructor. La cosa que se llama "constructor de un objeto" también se puede llamar "función con objeto de nombre que devuelve objeto de tipo".

Primero, los constructores no devuelven nada y, como consecuencia, no tienen tipos de retorno.

En segundo lugar, los constructores son diferentes en el sentido de que no se puede llamar al constructor directamente de la misma manera que se llaman funciones. En cambio, si declara una variable, el tiempo de ejecución llamará a los constructores apropiados.

Tercero, en caso de herencia, las funciones regulares en las subclases anulan las funciones en las clases primarias. Constructores, por otro lado, los constructores de cascada - clase primaria se llaman primero, luego los constructores de subclase.

Cuarto, los constructores pueden tener listas de inicialización, mientras que la función "normal" no.

el.pescado
fuente