Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Wiele klas ma wiele konstruktorów, które wykonują podobne czynności — na przykład zweryfikuj parametry:
class class_c {
public:
int max;
int min;
int middle;
class_c() {}
class_c(int my_max) {
max = my_max > 0 ? my_max : 10;
}
class_c(int my_max, int my_min) {
max = my_max > 0 ? my_max : 10;
min = my_min > 0 && my_min < max ? my_min : 1;
}
class_c(int my_max, int my_min, int my_middle) {
max = my_max > 0 ? my_max : 10;
min = my_min > 0 && my_min < max ? my_min : 1;
middle = my_middle < max && my_middle > min ? my_middle : 5;
}
};
Można zmniejszyć powtarzalny kod, dodając funkcję, która wykonuje całą walidację, ale kod class_c ułatwia zrozumienie i utrzymanie, jeśli jeden konstruktor może delegować część pracy do innej. Aby dodać konstruktory delegujące, użyj constructor (. . .) : constructor (. . .) składni:
class class_c {
public:
int max;
int min;
int middle;
class_c(int my_max) {
max = my_max > 0 ? my_max : 10;
}
class_c(int my_max, int my_min) : class_c(my_max) {
min = my_min > 0 && my_min < max ? my_min : 1;
}
class_c(int my_max, int my_min, int my_middle) : class_c (my_max, my_min){
middle = my_middle < max && my_middle > min ? my_middle : 5;
}
};
int main() {
class_c c1{ 1, 3, 2 };
}
W poprzednim przykładzie zwróć uwagę, że konstruktor class_c(int, int, int) najpierw wywołuje konstruktor class_c(int, int), który z kolei wywołuje metodę class_c(int). Każdy z konstruktorów wykonuje tylko pracę, która nie jest wykonywana przez inne konstruktory.
Pierwszy konstruktor, który jest nazywany inicjuje obiekt tak, aby wszystkie jego elementy członkowskie zostały zainicjowane w tym momencie. Nie można zainicjować składowych w konstruktorze, który deleguje do innego konstruktora, jak pokazano poniżej:
class class_a {
public:
class_a() {}
// member initialization here, no delegate
class_a(string str) : m_string{ str } {}
//can't do member initialization here
// error C3511: a call to a delegating constructor shall be the only member-initializer
class_a(string str, double dbl) : class_a(str) , m_double{ dbl } {}
// only member assignment
class_a(string str, double dbl) : class_a(str) { m_double = dbl; }
double m_double{ 1.0 };
string m_string;
};
W następnym przykładzie pokazano użycie inicjatorów niestacjonanych składowych danych. Zwróć uwagę, że jeśli konstruktor inicjuje również dany element członkowski danych, inicjator składowy jest zastępowany:
class class_a {
public:
class_a() {}
class_a(string str) : m_string{ str } {}
class_a(string str, double dbl) : class_a(str) { m_double = dbl; }
double m_double{ 1.0 };
string m_string{ m_double < 10.0 ? "alpha" : "beta" };
};
int main() {
class_a a{ "hello", 2.0 }; //expect a.m_double == 2.0, a.m_string == "hello"
int y = 4;
}
Składnia delegowania konstruktora nie zapobiega przypadkowemu utworzeniu rekursji konstruktora — konstruktor1 wywołuje konstruktora Constructor2, który wywołuje konstruktor1 — i nie są zgłaszane żadne błędy, dopóki nie nastąpi przepełnienie stosu. Twoim zadaniem jest unikanie cykli.
class class_f{
public:
int max;
int min;
// don't do this
class_f() : class_f(6, 3){ }
class_f(int my_max, int my_min) : class_f() { }
};