C++: mity i fakty

W latach 90. rozpowszechniła się w kręgach zainteresowanych tematyką opinia, że język C++ nie nadaje się do tego, żeby pisać w nim programy dla mikrokontrolerów jednoukładowych. W przypadku małych systemów 8- i 16-bitowych, dominujących w tamtym okresie, jest to zapewne prawda. Ale dziś, w dobie tanich mikroprocesorów 32-bitowych o wielkiej (w porównaniu do tych z poprzednich dekad) mocy przetwarzania i znacznych zasobach, można sobie zadać pytanie, na ile ta niezbyt pochlebna dla C++ opinia ma nadal pokrycie w faktach, a na ile jest utrzymującym się siłą inercji mitem.

Dodaj do ulubionych źródeł w Google
Posłuchaj
00:00
Spis treści

Klasy

Jednymi z najważniejszych nowych konstrukcji w C++ są klasy, metody i obiekty. Niestety, przy nauczaniu C++ wprowadza się te pojęcia bez objaśnienia, w jaki sposób je zaimplementowano, a to z kolei powoduje początkową dezorientację u programistów znających C. Potem następują męki oswajania się z programowaniem obiektowym, w wyniku czego kwestia implementacji znika wszystkim z oczu na dobre.

A klasa w C++ to jest w zasadzie to samo co definicja struktury w C. I rzeczywiście, w C++ strukturę zdefiniowano jako klasę, w której wszystkie elementy składowe są domyślnie publiczne. "Metoda" natomiast to po prostu funkcja, która jako parametr przyjmuje niejawnie wskaźnik do obiektu zdefiniowanego przez klasę, do której sama należy.

A zatem, rozumując w kategoriach generatora kodu, klasa z metodą w C++ jest równoważna w języku C strukturze z funkcją, która przyjmuje adres danych tej struktury w pamięci (czyli wskaźnik) jako parametr. Przykład poniżej demonstruje prostą klasę A z jedną zmienną x i jedną metodą f():

// prosta klasa
class A
{
private:
int x;
public:
void f();
};
void A::f()
{
x = 0;
}

Części klasy można zadeklarować jako prywatne (private), chronione (protected) lub publiczne (public). Fizycznie żadne różnice pomiędzy elementami prywatnymi, chronionymi i publicznymi nie zachodzą: odpowiednie słowa kluczowe pozwalają po prostu zapobiec nadużyciom zdefiniowanych struktur danych przez wykrywanie prób niedozwolonego dostępu już na etapie kompilacji.

Poniżej mamy równoważny kod zaimplementowany w języku C: struktura A zawiera taką samą zmienną x jak klasa A w powyższym listingu dla C++, a metodę A::f() zastąpiono przez funkcję f_A(struct A*). Proszę zauważyć, że nazwa parametru tej funkcji to this - w C++ byłoby to słowem kluczowym, w C nim nie jest. Taką nazwę wybrano świadomie, żeby podkreślić fakt, że w C++ wskaźnik obiektu, nazwany this, zostaje niejawnie przekazany funkcji jako parametr.

struct A
{
int x;
};
void f _ A(struct A *this)
{
this->x = 0;
}

Oczywiście w języku C nie ma słów kluczowych private i public, nie ma więc przeszkód, żeby programista odwołał się bezpośrednio do dowolnego elementu struktury z pominięciem wymyślonego do tego celu interfejsu (czyli zdefiniowanej jak powyżej "metody"), a gdy to zrobi, kompilator nie będzie w stanie wykryć takiego nadużycia. Język C wymaga więc od programistów samodzielnego utrzymywania dyscypliny, którą w C++ kompilator po prostu na nich wymusza.

Obiekty

Obiekt w C++ jest to zwykła zmienna, której typ definiuje klasa. Jak już powiedziano wyżej, odpowiednikiem klasy w C++ jest w języku C definicja struktury, a obiektu - zdefiniowana w ten sposób struktura danych w pamięci. Ponadto na klasę składa się pewna liczba metod (czyli funkcji) mających dostęp do elementów tejże klasy. Jest rzeczą jasną, że jest to mechanizm bardzo użyteczny i dający wiele możliwości. Jest równie jasne, że jego stosowanie nie ma w ogóle ujemnego wpływu na efektywność programu, gdy porównać to z zastosowaniem struktur i funkcji w tradycyjnym C.

Kiedy kompiluje się obiektową aplikację w C++, na dane składają się przeważnie obiekty, a na kod - metody zdefiniowane przez klasy. Można się wobec tego zastanawiać, jaki wpływ na wielkość gotowego programu ma zastosowanie klas, które przeważnie zawierają większą liczbę metod niż programista przyzwyczajony do języka C spodziewałby się kiedykolwiek użyć.

Jest tak dlatego, że dobrze zaprojektowana klasa zawiera metody, którymi można się posłużyć do zrobienia czegokolwiek z obiektami zdefiniowanymi przez tę klasę. Liczba tych metod może być skądinąd całkiem rozsądna, ale i tak przeważnie zaskakuje programistów piszących dotąd w C.

Nie oznacza to jednak, że wszystkie metody zdefiniowane w danej klasie trafią do gotowego programu: współczesne linkery są w stanie dokonać konsolidacji tylko tych metod (funkcji), z których program faktycznie korzysta. Linker po prostu traktuje skompilowany moduł jak rodzaj biblioteki. To oznacza, że nieużywane metody są po prostu pomijane w procesie konsolidacji, a klasa, która na oko jest bardzo rozbudowana, może w rzeczywistości zajmować bardzo mało miejsca w pamięci. Niestety, nie dotyczy to metod wirtualnych, o czym jeszcze będzie mowa poniżej.

Ocena wielkości obiektów jest dużo łatwiejsza: jest to cała zawartość klasy, odjąć metody. Żeby dowiedzieć się, ile miejsca w pamięci zajmie obiekt, wystarczy potraktować klasę jako strukturę samych danych, plus ewentualnie dodać wskaźnik, jeśli klasa definiuje jakieś metody wirtualne. Obliczenia te można sprawdzić przy użyciu operatora sizeof(), a stanie się od razu jasne, że wielkość danych definiowanych przez klasę nie jest większa niż to, co definiuje struktura w C. Jest tak dlatego, że optymalne wymodelowanie danego procesu wymaga zawsze takiej samej liczby stanów niezależnie od tego, czy związane z tym zmienne pamięciowe są zorganizowane w obiekt, czy nie.

Przeciążanie operatorów

Kiedy kompilator C++ napotyka w kodzie źródłowym przeciążony operator, podstawia zamiast tego wywołanie odpowiedniej funkcji. A zatem wyrażenie x+y powoduje wywołanie funkcji operator+(x, y) względnie x.operator+(y), jeśli którąś z nich zadeklarowano. Jest to znowu kwestia czysto składniowa, po prostu jeden ze sposobów, w jaki programista może wywołać zdefiniowaną przez siebie metodę.

Dla równowagi można zauważyć, że z przeciążaniem operatorów nie należy przesadzać, gdyż łatwo da się doprowadzić do sytuacji, kiedy w danym miejscu kodu źródłowego znaczenie (i działanie) operatora zaczyna całkowicie zależeć od operandów (czy też ogólniej: kontekstu) - a to może znacznie utrudniać późniejszą analizę programu.

Chcesz częściej widzieć nasze artykuły w Google? Dodaj ElektronikaB2B do ulubionych źródeł
Spis treści
Powiązane treści
PRQA wprowadza narzędzie do analizy statycznej QA·C++ w nowej wersji V3.2
Zobacz więcej w kategorii: Technika
Produkcja elektroniki
Szablon SMT a jakość nadruku pasty lutowniczej
Elektromechanika
Dobór obudowy do urządzenia elektronicznego – materiały, szczelność i możliwości modyfikacji
Produkcja elektroniki
Wady lutowania na fali - jak ograniczyć mostkowanie i niedobory lutu?
Komunikacja
Lokalizacja UWB w budynkach – od czego zależy dokładność pomiarów?
Optoelektronika
Sterowanie oświetleniem LED - jak ograniczyć migotanie i zapewnić precyzyjną regulację jasności?
Produkcja elektroniki
Pustki w połączeniach BGA – jak interpretować normy IPC i wyniki inspekcji rentgenowskiej?
Zobacz więcej z tagiem: Artykuły
Magazyn
Październik 2026
Magazyn
Wrzesień 2026
Magazyn
Sierpień 2026

Zobaczyć obiekt oczami radaru, czyli dlaczego potrzebujemy laboratorium do pomiarów RCS?

Radar postrzega świat inaczej niż człowiek. Zamiast obrazu tworzonego przez światło widzialne rejestruje echo wysłanej fali elektromagnetycznej. Na odpowiedź radarową obiektu wpływają nie tylko jego rozmiary, lecz także kształt, zastosowane materiały, częstotliwość oraz kierunek obserwacji. Dlatego dwa przedmioty o podobnych wymiarach mogą być dla radaru widoczne zupełnie inaczej. Jak zatem sprawdzić, co radar rzeczywiście "widzi"? Służą temu pomiary RCS, prowadzone między innymi w specjalistycznych laboratoriach, które zapewniają kontrolowane i powtarzalne warunki oraz umożliwiają uzyskanie dokładności wymaganej w danym zastosowaniu.
Zapytania ofertowe
Unikalny branżowy system komunikacji B2B Znajdź produkty i usługi, których potrzebujesz Katalog ponad 7000 firm i 60 tys. produktów