Ce face explicit
Un constructor cu un singur parametru este și o regulă de conversie: dacă Metri are constructorul Metri(double), atunci compilatorul transformă singur un double în Metri oriunde e nevoie, de exemplu la apelul f(5.0). Asta poate ascunde greșeli.
Cu explicit, conversia trebuie scrisă de tine: f(Metri{5.0}). Regula practică: pune explicit pe toți constructorii cu un singur argument, cu excepția celor pentru care conversia automată chiar are sens.
Același lucru pentru operatorii de conversie: explicit operator bool() permite if (obiect), dar nu și int x = obiect; sau obiect + 1.
Exemple
Exemplul 1: Constructor explicit
afiseaza_distanta(12.5) nu s-ar compila, pentru că nu mai există conversie automată din double. Trebuie scris tipul: Metri{12.5}.
#include <print>
class Metri {
public:
explicit Metri(double valoare) : valoare_(valoare) {}
double valoare() const { return valoare_; }
private:
double valoare_;
};
void afiseaza_distanta(Metri m) {
std::println("Distanța: {} m", m.valoare());
}
int main() {
afiseaza_distanta(Metri{12.5});
// afiseaza_distanta(12.5); // eroare: constructorul este explicit
}
Rezultat
Distanța: 12.5 m
Exemplul 2: explicit operator bool
Obiectul poate fi folosit într-un if sau cu !, dar nu poate fi adunat sau atribuit unui int din greșeală.
#include <print>
#include <string>
#include <utility>
class Rezultat {
public:
explicit Rezultat(std::string eroare = "") : eroare_(std::move(eroare)) {}
explicit operator bool() const { return eroare_.empty(); }
const std::string& eroare() const { return eroare_; }
private:
std::string eroare_;
};
int main() {
Rezultat ok;
Rezultat esec("fișierul lipsește");
if (ok) std::println("Prima operație a reușit");
if (!esec) std::println("A doua a eșuat: {}", esec.eroare());
}
Rezultat
Prima operație a reușit
A doua a eșuat: fișierul lipsește
Greșeli frecvente
- Lași fără
explicitun constructor caVector(int marime). AtunciVector v = 10;sau apelulf(10)creează în tăcere un vector cu 10 elemente. - Pui
explicitpe constructorul de copiere. Copierea „obișnuită” nu mai merge:Tip b = a;și transmiterea prin valoare nu se mai compilează. Nu-l pune pe constructorii de copiere și mutare.
Comenzi înrudite
class: Definește un tip nou care grupează date (membri) și funcțiile care lucrează cu ele (metode); baza programării orientate pe obiecte.operator: Definește ce face un operator (+, ==, <<, [], () etc.) pentru tipurile tale, ca obiectele să se folosească la fel de natural ca numerele.static_cast, dynamic_cast, const_cast, reinterpret_cast: Cele patru conversii explicite: static_cast (obișnuite), dynamic_cast (clase), const_cast (const) și reinterpret_cast (biți).