Implementa costruttori di classi in C++

Jinku Hu 12 ottobre 2023
  1. Cosa sono i costruttori e come funzionano in C++
  2. Implementa più costruttori di classi utilizzando l’overload in C++
Implementa costruttori di classi in C++

Questo articolo introdurrà come implementare i costruttori di classi in C++.

Cosa sono i costruttori e come funzionano in C++

I costruttori sono funzioni membro speciali che definiscono come deve essere inizializzato l’oggetto classe. I costruttori in genere inizializzano i membri dati della classe e vengono eseguiti quando viene creato un oggetto classe. Alcune caratteristiche specifiche delle funzioni di costruzione sono che hanno lo stesso nome della classe stessa e non possono avere un tipo restituito. Di solito, una classe ha più costruttori che si sovraccaricano a vicenda, ma devono avere un numero o tipi di parametri diversi.

Si noti che i costruttori sono spesso specificati in modo esplicito dall’utente in qualsiasi classe leggermente complessa. Tuttavia, il costruttore predefinito viene generato automaticamente dal compilatore quando l’utente non definisce alcun costruttore. Il costruttore predefinito è generalmente quello che non accetta argomenti e viene chiamato per l’inizializzazione predefinita della classe. Si noti, tuttavia, un costruttore predefinito generato dal compilatore è formalmente chiamato costruttore predefinito sintetizzato. Quest’ultimo viene dedotto in modo specifico per ogni classe in base ai suoi membri dati e inizializza i membri utilizzando l’inizializzatore in-class o utilizzando il valore predefinito. Pertanto, i costruttori generati automaticamente non sono la soluzione universale, ma funzionano correttamente per strutture di classi semplici.

Nell’esempio seguente abbiamo definito una classe MyClass1 con due costruttori. Nota che il primo non accetta alcun argomento, il che implica che è un costruttore predefinito, ma abbiamo comunque specificato una parola chiave default. Quest’ultimo indica al compilatore che questo specifico costruttore dovrebbe essere quello predefinito. In genere, un compilatore non genera un costruttore predefinito se l’utente definisce un costruttore. In questo caso, un utente dovrebbe richiedere esplicitamente la designazione default per la data funzione di costruzione.

Il secondo costruttore di MyClass1 accetta un singolo valore string come argomento e inizializza con esso il membro dati name. Stampa la stringa speciale letterale per il flusso cout solo per rendere visibile per l’osservazione il momento di esecuzione della funzione. La creazione dell’oggetto m2 attiva quella del costruttore. L’oggetto m1 è inizializzato con il costruttore di default, e poiché il compilatore stesso genera quest’ultimo, non vediamo alcuna stringa stampata sul flusso cout.

#include <iostream>
#include <utility>

using std::cout;
using std::endl;
using std::string;

class MyClass1 {
 private:
  string name;
  string nickname;

 public:
  MyClass1() = default;
  explicit MyClass1(string n) : name(std::move(n)) {
    cout << "Constructor 1 is called" << endl;
  };

  string getName() { return name; }

  string getNickname() { return nickname; }

  ~MyClass1() { cout << "Destructor is called" << endl; }
};

int main() {
  MyClass1 m1{};
  cout << m1.getName() << endl;
  cout << m1.getNickname() << endl;
  cout << "------------------" << endl;

  string n1("Maude");
  MyClass1 m2(n1);
  cout << m2.getName() << endl;
  cout << m2.getNickname() << endl;
  cout << "------------------" << endl;

  return EXIT_SUCCESS;
}

Produzione:

------------------
Constructor 1 is called
Maude

------------------
Destructor is called
Destructor is called

Implementa più costruttori di classi utilizzando l’overload in C++

MyClass1 ha il secondo membro dati string chiamato nickname. Supponiamo di creare un altro costruttore che prende un singolo valore string e lo definisce per inizializzare il nickname. In tal caso, il compilatore genererà l’errore che non possiamo sovraccaricare le funzioni con gli stessi parametri. Quindi, abbiamo bisogno di definire un altro costruttore, ad esempio, abbiamo scelto il costruttore che accetta due riferimenti stringa e inizializza entrambi i membri dati. Quando viene eseguito il seguente frammento di codice, possiamo vedere che è stato eseguito il secondo costruttore.

I costruttori hanno caratteristiche molto più dettagliate e abbiamo introdotto solo le funzionalità principali in questo articolo. Altre funzioni speciali contengono la parola - constructor nei loro nomi, come costruttore di mosse e costruttore di copie. Questi due fanno parte di operazioni speciali chiamate collettivamente controllo della copia. Nota che i distruttori conducono l’opposto di ciò che fanno i costruttori. Vale a dire, deallocano i membri della classe e di solito vengono chiamati automaticamente quando l’oggetto esce dall’ambito. Si può facilmente osservare il comportamento delle chiamate costruttore-distruttore con i frammenti di codice forniti.

#include <iostream>
#include <utility>
#include <vector>

using std::cout;
using std::endl;
using std::string;

class MyClass1 {
 private:
  string name;
  string nickname;

 public:
  MyClass1() = default;
  explicit MyClass1(string n) : name(std::move(n)) {
    cout << "Constructor 1 is called" << endl;
  };

  // ERROR: Does not Compile
  //    MyClass1(string nk) : nickname(nk) {
  //        cout << "Constructor 3 is called" << endl;
  //    };
  MyClass1(string &n, string &nk) : name(n), nickname(nk) {
    cout << "Constructor 2 is called" << endl;
  };

  string getName() { return name; }

  string getNickname() { return nickname; }

  ~MyClass1() { cout << "Destructor is called" << endl; }
};

int main() {
  string n1("Maude");
  string n2("Bibi");

  MyClass1 m4(n1, n2);
  cout << m4.getName() << endl;
  cout << m4.getNickname() << endl;
  cout << "------------------" << endl;

  return EXIT_SUCCESS;
}

Produzione:

Constructor 2 is called
Maude
Bibi
------------------
Destructor is called
Destructor is called
Autore: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Articolo correlato - C++ Class