C/Powszechne praktyki: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
dodałem poradę o możliwości konstruowania i niszczenia obiektu |
nie wszyscy chcą jawnie wywoływać funkcję |
||
Linia 4:
W większości obiektowych języków programowania obiekty nie mogą być tworzone bezpośrednio - obiekty otrzymuje się wywołując specjalną metodę danej klasy, zwaną konstruktorem. Konstruktory są ważne, ponieważ pozwalają zapewnić obiektowi odpowiedni stan początkowy. Destruktory, wywoływane na końcu czasu życia obiektu, są istotne, gdy obiekt ma wyłączny dostęp do pewnych zasobów i konieczne jest upewnienie się, czy te zasoby zostaną zwolnione.
Ponieważ C nie jest językiem obiektowym, nie ma wbudowanego wsparcia dla konstruktorów i destruktorów. Często programiści bezpośrednio modyfikują tworzone obiekty i struktury. Jednakże prowadzi to do potencjalnych błędów, ponieważ operacje na obiekcie mogą się nie powieść lub zachować się nieprzewidywalnie, jeśli obiekt nie został prawidłowo zainicjalizowany. Lepszym podejściem jest
char *data;▼
<source lang="c">
{
double pole3;
} Struktura;
Struktura obj = {1, 'a', 100.3343232};
</source>
== Zerowanie zwolnionych wskaźników ==
Jak powiedziano już wcześniej, po wywołaniu <tt>free()</tt> dla wskaźnika, staje się on "wiszącym wskaźnikiem". Co gorsze, większość nowoczesnych platform nie potrafi wykryć, kiedy taki wskaźnik jest używany zanim zostanie ponownie przypisany.
Linia 58 ⟶ 27:
<source lang="c">
#define FREE(p) do { free(p);
</source>
a w kodzie programu zamiast funkcji <tt>free</tt> stosować <tt>FREE</tt>.
<small>(aby zobaczyć dlaczego makro jest napisane w ten sposób, zobacz [[#Konwencje pisania makr]])</small>
== Konwencje pisania makr ==
Linia 80 ⟶ 36:
# Umieszczaj nawiasy dookoła argumentów makra kiedy to tylko możliwe. Zapewnia to, że gdy są wyrażeniami kolejność działań nie zostanie zmieniona. Na przykład:
#*Źle: <code>#define
#*Dobrze: <code>#define
#*'''Przykład:''' Załóżmy, że w programie makro kwadrat() zdefiniowane bez nawiasów zostało wywołane następująco: <code>kwadrat(a+b)</code>. Wtedy zostanie ono zamienione przez preprocesor na: <code>(a+b*a+b)</code>. Z kolejności działań wiemy, że najpierw zostanie wykonane mnożenie, więc wartość wyrażenia <code>kwadrat(a+b)</code> będzie różna od kwadratu wyrażenia <code>a+b</code>.
# Umieszczaj nawiasy dookoła całego makra, jeśli jest pojedynczym wyrażeniem. Ponownie, chroni to przed zaburzeniem kolejności działań.
#*Źle: <code>#define
#*Dobrze: <code>#define
#*'''Przykład:''' Definiujemy makro <code>#define
# Jeśli makro składa się z wielu instrukcji lub deklaruje zmienne, powinno być umieszczone w pętli <code>'''do''' { ... } '''while'''(0)</code>, bez kończącego średnika. Pozwala to na użycie makra jak pojedynczej instrukcji w każdym miejscu, jak ciało innego wyrażenia, pozwalając jednocześnie na umieszczenie średnika po makrze bez tworzenia zerowego wyrażenia. Należy uważać, by zmienne w makrze potencjalnie nie kolidowały z argumentami makra.A
#*Źle: <code>#define FREE(p) free(p); p = NULL;</code>
#*Dobrze: <code>#define FREE(p) do { free(p); p = NULL; } while(0)</code>
# Unikaj używania argumentów makra więcej niż raz wewnątrz makra. Może to spowodować kłopoty, gdy argument makra ma efekty uboczne (np. zawiera operator inkrementacji).
#*'''Przykład:''' <code>#define
# Jeśli makro może być w przyszłości zastąpione przez funkcję, rozważ użycie w nazwie małych liter, jak w funkcji.
|