C++/Konstruktor i destruktor: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
+delegacja konstruktorów |
+konstruktory explicit |
||
Linia 219:
};
</source>
===Konstruktor explicit - zabronienie niejawnych konwersji (C++)===
Czasem niepożądane jest, żeby można było "przez przypadek" utworzyć klasę bądź przypisać do niej wartość. Jeśli klasa posiada konstruktor konwertujący, to kompilator jest w stanie wydedukować sposób na przekształcenie jednego typu w drugi, tj. dokonać '''niejawnej konwersji'''. Takie zachowanie nie zawsze jest pożądane i w dużych systemach jest dość trudne do przewidzenia i rozpoznania przez programistę.
Zobaczmy na przykład:
<source lang="cpp" highlight="10">
class Klasa {
public:
Klasa(int x) {}
};
int main() {
Klasa k(42);
k = -1;
}
</source>
Ostatnie przypisanie choć wygląda dziwnie, nie jest błędem. Kompilator widzi, że z typu <tt>int</tt> może utworzyć Klasę, a także dla Klasy istnieje domyślny operator przypisania, więc ostatnia linijka zostanie zainterpretowana jako:
<source lang="cpp">
k.operator=(Klasa(-1));
</source>
Do rozwiązania tego typu problemów w C++11 wprowadzono nowy klasyfikator dla konstruktorów '''explicit'''. Jeśli istnieje konstruktor z '''explicit''' wówczas utworzenie klasy, która byłaby wynikiem konwersji niejawnej stanie się niemożliwe.
<source lang="cpp" highlight="3">
class Klasa {
public:
explicit Klasa(int x) {}
};
int main() {
Klasa k(42);
// k = -1; // błąd: kompilator nie wie jak skonwertować int na Klasa
}
</source>
Dopiero wprowadzenie '''jawnej konwersji''' operatorem '''static_cast''' umożliwia zastosowania konstruktora konwertującego. Taki operator jest dobrze widoczny w kodzie źródłowym i jasno oddaje intencje użycia:
<source lang="cpp">
k = static_cast<Klasa>(-1);
</source>
|