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.

Posłuchaj
00:00
Spis treści

Szablony

Szablony przypominają nieco makrodefinicje, które kompilator rozwija w całe klasy. Ponieważ jedno wywołanie szablonu umieszczone w kodzie programu może zostać rozwinięte w klasę, beztroskie korzystanie z szablonów może się szybko zemścić, powodując gigantyczny rozrost gotowego programu. Dzieje się tak zwłaszcza przy zastosowaniu starszych kompilatorów, które każde odwołanie do szablonu rozwijają w oddzielną klasę; ale nowsze kompilatory i linkery starają się wykrywać duplikaty i tworzyć najwyżej po jednej, unikalnej kopii każdego szablonu.

Szablony, jeśli zastosujemy je z głową, mogą zaoszczędzić programiście wiele wysiłku przy niewielkich stratach rozmiarów programu (lub w ogóle bez takich strat). W końcu przeważnie dużo łatwiej jest skorzystać z gotowego szablonu dostarczanego przez bibliotekę niż pisać własną złożoną klasę od początku.

Przykład poniżej ilustruje użycie szablonu:

template<typename T> class A
{
private:
T value;
public:
A(T);
T f();
};
template<typename T> A<T>::A(T initial)
{
value = initial;
}
template<typename T> T A<T>::f()
{
return value;
}
int main()
{
A<int> a(1);
a.f();
return 0;
}

Jak powiedziano powyżej, szablony działają podobnie jak makrodefinicje, można więc zamiast nich spróbować użyć makr preprocesora w języku C:

#define A(T)
struct A _ ##T
{
T value;
};

void konstruktor _ A _ ##T(struct A _ ##T *this,
T initial)
{
(this)->value = initial;
}

T A _ f _ ##T(struct A _ ##T *this)
{
return (this)->value;
}
A(int) /* tu makro rozwija się w "klasę" A _
int */
int main()
{
struct A _ int a;
konstruktor _ A _ int(&a, 1);
A_ f _ int(&a);
return 0;
}

Jak widać, rzecz sama w sobie jest jak najbardziej wykonalna, ale widać też, że jest to niezbyt praktyczne rozwiązanie w przypadku bardziej skomplikowanego kodu.

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
Mikrokontrolery i IoT
Wymagania prawne w zakresie cyberbezpieczeństwa zmieniają IoT/IIoT
Zasilanie
Izolowane przetwornice DC/DC wysokiego napięcia
Komponenty
System automatyki KNX w produktach firmy Mean Well
Mikrokontrolery i IoT
Układy SoC serii Dragonwing IQ9 firmy Qualcomm do systemów edge AI nowej generacji
Produkcja elektroniki
Nowa biała księga: Jak radzić sobie z nieplanowanym zapotrzebowaniem
Mikrokontrolery i IoT
PSOC Edge - nowa generacja MCU do AI
Zobacz więcej z tagiem: Artykuły
Magazyn
Listopad 2025
Informacje z firm
Grupa RENEX zaprasza na targi Evertiq EXPO Warszawa 2025
Magazyn
Październik 2025

Ukryte koszty poprawek. Dlaczego naprawa projektu zawsze kosztuje więcej niż dobre planowanie - czyli im później wykryjesz błąd, tym drożej go naprawisz

Większość projektów elektronicznych nie upada dlatego, że zabrakło budżetu na komponenty — lecz dlatego, że zbyt późno wykryto błędy projektowe. To one, a nie same materiały, generują największe koszty: dodatkowe prototypy, opóźnienia, ponowne testy, a często nawet przebudowę całych urządzeń.
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