Perché i costruttori non restituiscono valori?

Per favore dimmi perché il costruttore non restituisce alcun valore. Voglio una ragione tecnica perfetta per spiegare ai miei studenti perché il costruttore non ha alcun tipo di reso.

Ciò che effettivamente accade con il costruttore è che il runtime utilizza i dati di tipo generati dal compilatore per determinare quanto spazio è necessario per memorizzare un’istanza dell’object in memoria, sia essa in pila o nell’heap.

Questo spazio include tutte le variabili dei membri e il vtbl. Dopo che questo spazio è stato allocato, il costruttore viene chiamato come parte interna del processo di istanziazione e inizializzazione per inizializzare il contenuto dei campi.

Quindi, quando il costruttore si chiude, il runtime restituisce l’istanza appena creata. Quindi il motivo per cui il costruttore non restituisce un valore è perché non viene chiamato direttamente dal codice, viene richiamato dall’allocazione di memoria e dal codice di inizializzazione dell’object nel runtime.

Il suo valore di ritorno (se in realtà ne ha uno quando è compilato fino al codice macchina) è opaco per l’utente, quindi non è ansible specificarlo.

Bene, in un modo restituisce l’istanza che è stata appena costruita.

Ad esempio lo si chiama così, ad esempio Java

  Object o = new Something(); 

che sembra proprio come chiamare un metodo “normale” con un valore di ritorno

  Object o = someMethod(); 

(Sono prevenuto verso il C ++, quindi riguardo ad altre lingue, prendi questo con un pizzico di sale.)

Risposta breve: non si desidera controllare esplicitamente il successo per ogni singola costruzione di oggetti nel codice.

Risposta un po ‘più lunga: in C ++, i costruttori sono chiamati dynamicmente così come per gli oggetti allocati globalmente e automaticamente. In questo codice

 void f() { std::string s; } 

non c’è modo per il costruttore di s ( std::string::string() ) di restituire alcun valore. O riesce – allora possiamo usare l’object, o lancia un’eccezione – non abbiamo mai la possibilità di provare ad usarlo.

IMO, è così che dovrebbe essere.

In che modo un costruttore dovrebbe restituire un valore di ritorno? Il new operatore restituisce l’istanza appena creata. Non chiami un ctor, new fa.

 MyClass instance = new MyClass(); 

Se il ctor restituisse un valore, in questo modo:

 public int MyClass() { return 42; } 

Dove riceveresti l’intero?

Quando chiami un costruttore, il valore di ritorno è il nuovo object:

 Point pt = new Point(1,2); 

Ma all’interno del costruttore stesso, non stai effettivamente creando e restituendo l’object; è stato creato prima dell’inizio del codice, stai solo impostando i valori iniziali.

 Point::Point(int x, int y) { this->x = x; this->y = y; } 

La mancanza di un tipo di ritorno riflette il fatto che i costruttori sono usati in modo diverso rispetto ad altre funzioni. Un tipo restituito di null , sebbene tecnicamente accurato, non riflette bene il fatto che il codice viene utilizzato come se restituisse un object. Tuttavia, qualsiasi altro tipo di restituzione indica che il codice dovrebbe return qualcosa alla fine, che è anche errato.

Un costruttore è un metodo chiamato automaticamente quando si inizializza una nuova istanza di un object.

Questo metodo è disponibile se è necessario inizializzare l’object in un determinato stato ed eseguire pochi metodi predefiniti.

In realtà puoi immaginare che il costruttore restituisca sempre l’istanza dell’object creato che sarebbe una buona immagine.

tutte le risposte sono distorte verso C ++ / Java. non c’è motivo per cui un costruttore non restituisca un valore diverso da quello del linguaggio.

guarda un costruttore in senso più ampio: è una funzione che costruisce un nuovo object. puoi scrivere costruttori perfettamente validi in C:

 typedef struct object object; int object_create( object **this ); 

questo è perfetto OOP in C e il costruttore restituisce il valore (questo può anche essere chiamato fabbrica, ma il nome dipende dall’intenzione).

tuttavia, al fine di creare un object automaticamente (per soddisfare alcuni tipi di cast o conversione, ad esempio), devono essere definite alcune regole. in C ++, esiste un costruttore senza argomenti, che viene dedotto dal compilatore se non è definito.


la discussione è più ampia di ciò che pensiamo. La programmazione orientata agli oggetti è un nome che descrive un modo di pensare sulla programmazione. puoi avere OO in quasi tutte le lingue: tutto ciò di cui hai bisogno sono strutture e funzioni. i linguaggi mainstream come C ++ e Java sono così comuni che pensiamo che definiscano “la via”. ora guarda il modello OO in Ada: è lontano dal modello del C ++ ma è ancora OO. sono sicuro che linguaggi come Lisp hanno altri modi di fare OO.

Un punto che non è stato ancora discusso è che il costruttore della class “foo” deve essere utilizzabile non solo quando crea istanze di foo, ma anche quando crea istanze di classi derivate da foo. In assenza di generici (che non erano disponibili quando sono stati progettati Java, C ++ o .net) non sarebbe ansible per il costruttore di foo restituire un object di una class derivata. Pertanto, ciò che deve accadere è che l’object della class derivata venga creato tramite altri mezzi e poi reso disponibile al costruttore di foo (che sarà quindi in grado di utilizzare l’object in questione come foo durante l’inizializzazione).

Anche se l’implementazione VM di un costruttore non restituisce alcun valore, in pratica lo fa di solito: il riferimento del nuovo object. Sarebbe quindi sintatticamente strano e / o confuso essere in grado di memorizzare uno o entrambi il riferimento del nuovo object e un valore di ritorno aggiuntivo in un’istruzione.

Il costruttore non viene chiamato direttamente dal codice dell’utente. Viene chiamato dall’allocazione di memoria e dal codice di inizializzazione dell’object nel tempo di esecuzione. Il suo valore non è visibile all’utente.

In caso di C #, la syntax per dichiarare l’object è:

 classname objectname= new constructor(); 

Secondo questa linea, se stiamo usando l’operatore di assegnazione (=), allora dovrebbe restituire qualche valore. Ma l’objective principale di un costruttore è assegnare valori alle variabili, così quando usiamo una nuova parola chiave crea un’istanza di quella class, e il costruttore assegna i valori alla variabile per quella particolare istanza dell’object, così il costruttore restituisce i valori assegnati per quella esempio.

Non possiamo chiamare autonomamente i costruttori. Invece vengono automaticamente chiamati ogni volta che vengono creati oggetti. Ex:

 MyDate md = new Mydate(22,12,2012); 

Nell’esempio sopra, new restituirà una posizione di memoria che verrà mantenuta da md, e programmaticamente non possiamo restituire più valori in singole istruzioni. Quindi i costruttori non possono restituire nulla.

Da quello che so delle metodologie di progettazione OO, direi quanto segue:

1) Consentendo al costruttore di restituire un valore, lo sviluppatore di framework consente al programma di bloccarsi in un istante in cui il valore restituito non viene gestito. Per mantenere l’integrità del stream di lavoro del programma, non consentire un valore di ritorno dall’inizializzazione di un object è una decisione valida. Invece, il progettista di linguaggi suggerirebbe / costringerebbe i programmatori a utilizzare i metodi di accesso getter / setter.

2) Consentendo all’object di restituire un valore durante l’inizializzazione, si aprono anche possibili perdite di informazioni. Specialmente quando sono applicate più modifiche ai livelli o all’accesso alle variabili / metodi.

Come sapete che quando viene creato un object il costruttore verrà automaticamente chiamato Così ora immaginate che il costruttore restituisca un valore int. Quindi il codice dovrebbe piacere così …

 Class ABC { int i; public: int ABC() { i=0; return i; } ....... }; int main() { int k= ABC abc; //constructor is called so we have to store the value return by it .... } 

Ma sapendo che lo stament è come int k= ABC abc; non è ansible in nessun linguaggio di programmazione. Spero tu possa capire.

l’ho trovato utile

Questa confusione deriva dal presupposto che i costruttori sono come qualsiasi altra funzione / metodo definito dalla class. No non lo sono.

I costruttori sono solo una parte del processo di creazione dell’object. Non vengono chiamati come le altre funzioni membro.

Userò Java come lingua nella risposta.

 class SayHelloOnCreation { public SayHelloOnCreation() { System.out.println("Hello, Thanks For Creating me!"); } } class Test { public static void main(String[]args) { SayHelloOnCreation thing = new SayHelloOnCreation(); //This line here, produces an output - Hello, Thanks For Creating me! } } 

Ora vediamo cosa sta succedendo qui. in java, usiamo la nuova parola chiave per creare un’istanza di una class. E come puoi vedere nel codice, nella riga, SayHelloOnCreation thing = new SayHelloOnCreation (); , l’espressione dopo l’esecuzione dell’operatore di assegnazione prima che l’assegnazione venga eseguita. Quindi, usando la parola chiave new , chiamiamo il costruttore di quella class ( SayHelloOnCreation () ) e questo costruttore crea un object sul Java Heap. Dopo che l’object è stato creato, un riferimento a quell’object è assegnato al riferimento di tipo di SayHelloOnCreation .

Il punto che sto cercando di mantenere qui è che se ai costruttori fosse permesso avere un tipo di ritorno, in primo luogo la natura fortemente tipizzata della lingua sarebbe compromise (ricordate che sto parlando di Java qui).

In secondo luogo , viene creato un object di class SayHelloOnCreation, quindi per impostazione predefinita suppongo che il costruttore restituisca un riferimento dello stesso tipo, per evitare ClassCastException .

Quindi il motivo per cui il costruttore non restituisce un valore è perché non viene chiamato direttamente dal codice, viene richiamato dall’allocazione di memoria e dal codice di inizializzazione dell’object nel runtime. Il suo valore di ritorno (se in realtà ne ha uno quando è compilato fino al codice macchina) è opaco per l’utente, quindi non è ansible specificarlo.