xime: Szablon dla okienek

Kontynuując temat ostatniego technicznego wpisu, stworzyłem podobny szablon klasy podstawowej do wyprowadzania poszczególnych klas okienek i dialogów, czyli elementów GUI w aplikacji. Tym razem, zależnie od skonkretyzowania, dzięki generyczności, kompilator generuje klasę podstawową dla okna. Dzieje się to przy próbie pobrania jego instancji lub ręcznie na zawołanie. Niektóre okna mają ściśle określony czas życia. Taki main-frame jest tworzony i niszczony w określonej sytuacji - po poprawnym zalogowaniu profilu i przy wylogowaniu, więc między tymi dwoma sygnałami okno powinno cały czas istnieć.

Czytaj dalej

C++0x nadchodzi!

Jak podaje Herb Sutter na swoim blogu w ostatniej notce “September 2008 ISO C++ Standards Meeting: The Draft Has Landed, and a New Convener”, draft nowego standardu C++ jest już dostępny publicznie do pobrania: N2798. Jedynie można spodziewać się jeszcze jakichś małych poprawek błędów i usprawnień w stosunku do tego dokumentu. Pozostaje już tylko cierpliwie czekać na finalną wersję i na twórców kompilatorów. Aczkolwiek, większość liczących się kompilatorów na rynku już wspiera w jakimś stopniu większość nowego standardu, ale na oficjalne, pełne wsparcie trzeba będzie poczekać pewnie jakiś czas po opublikowaniu finalnej wersji standardu.

Czytaj dalej

Niejawne przekształcenia typów

Konwersje typów zdefiniowanych przez użytkownika, czyli klas, są możliwe poprzez zdefiniowanie odpowiednich metod. Są nimi konstruktory konwersji dokonujące przekształcania z innych typów do naszego zdefiniowanego typu i operatory konwersji1 służące do przekształcania z typu zdefiniowanego przez użytkownika na inne typy. class X { public: X(int n); operator int(); operator double(); }; Operator i konstruktor konwersji nie zmienia typu istniejącego obiektu lecz tworzy nowy obiekt int tam, gdzie jest potrzebny. Wszędzie, gdzie dopuszcza się X można użyć int i odwrotnie.

Czytaj dalej

Variadic functions

Dziś kilka slow o funkcjach z zmienna liczba argumentów, czyli Variadic Functions ;) W ostatniej notce o makrach z zmienną listą argumentów wspomniałem o najpopularniejszej funkcji przyjmującej nieokreśloną liczbę argumentów - printf. Używanie takich funkcji jest bardzo proste, stworzenie również nie jest jakąś trudną i skomplikowaną sprawą. Niezbędne do tego celu typy i makra umożliwiające dostep i operacje na niewyspecyfikowanych argumentach funkcji zadeklarowano w pliku nagłówkowym stdarg.h. cppva_list Typ va_list jest obiektu listy, która zawiera wszystkie argumenty z jakimi została wywołana funkcja.

Czytaj dalej

Variadic macros

Można się zdziwić, ale makra również mogą posiadać zmienną liczbę argumentów, tak jak funkcje. Najbardziej znaną funkcją o zmiennej licznie argumentów jest funkcja printf z standardowej biblioteki języka C: int printf(const char* fmt, ...); Makra również posiadają taką możliwość, zwie się to, jak nazwa notki, - Variadic Macros. Proste makro TRACE opakowujące printfa: #define TRACE(fmt, ...) printf("%s:%d " fmt, __FILE__, __LINE__, __VA_ARGS__) i proste użycie: TRACE("x=%d, y=%d", 1, 2); Kluczową role w tej konstrukcji pełni identyfikator __VA_ARGS__, który zostaje zamieniony na wszystkie ekstra argumenty, nie określone w definicji makra, a raczej określone przez .

Czytaj dalej

Wyjątki w obiektach globalnych

Kontynuujemy zabawy z wyjątkami ;) A co powiecie na zgłaszanie sytuacji wyjątkowych w konstruktorze globalnego obiektu? Co się stanie, gdy konstruktor rzuci wyjątkiem przed wejściem do funkcji main? Poleci zapewne terminate(). Jak zasygnalizować zaistniałą sytuację i “odwieść” program od wywołania terminate()? Obsłużyć wyjątek rzecz jasna ;) Jak przechwycić wyjątek z globalnych obiektów? Sprawa trochę skomplikowana, bo jak wiemy obiekty globalne są tworzone przed wejściem do funkcji main. Tak, aby były gotowe do użycia, gdy się rozpocznie program (funkcja main).

Czytaj dalej

Niebezpieczne wyjątki

Ostatnio trochę marudziłem o rzucaniu wyjątków w konstruktorach, to dziś może wspomnę o destruktorach i konstruktorach kopiujących. Każdy chyba wie, że nie należy rzucać wyjątków z destruktorów. To samo dotyczy konstruktora kopiującego obiektu wyjątku. Problem z destruktorami jest to związany z obsługą wyjątku przez kompilator (czas miedzy rzuceniem wyjątku a złapaniem go przez odpowiedni catch), czyli rozwijaniem stosu przez kompilator i wywoływaniu destruktorów dla zmiennych lokalnych znajdujących się w zasięgu, którym zgłoszono sytuacje wyjątkową.

Czytaj dalej

Wyjątki w konstruktorze

Wyjątki są najprostszą i najlepszą możliwością zgłoszenia błędów zaistniałych w konstruktorze, przez których tworzenie obiektu zakończyło się porażką. Bez sytuacji wyjątkowych nie ma bezpośredniego prostego mechanizmu zgłoszenia zaistniałej sytuacji, ponieważ konstruktor nie przekazuje żadnego typu i wartości, która mogłaby przekazać informacje o zaistniałym błędzie. Oczywiście można obejść ten problem poprzez zastosowanie dodatkowej zmiennej lokalnej do określania stanu obiektu i sprawdzać stan po utworzeniu obiektu lub wykorzystać nielokalną, umowną zmienną, która “powie” nam, że tworzenie zakończyło się niepowodzeniem.

Czytaj dalej

xime: Szablon dla modułów

Dziś może bardziej techniczna notka związana z wewnętrznymi modułami aplikacji. W xime przez pojęcie modułu rozumiemy jakiś komponent aplikacji, coś wykonujące określone funkcje, np. moduł konfiguracji, czy menadżera profili. Na początku były to typowe klasy do ściśle określonego zadania, ale problemem było tworzenie takich obiektów, trzymanie wskaźników do instancji i łatwy do nich dostęp z dowolnego kodu programu. Rozwiązaniem tych problemów, mogłoby być zastosowanie wzorca projektowego singleton. Najprostsze, ale i mające kilka wad rozwiązanie - niepotrzebny narzut na sprawdzenie i w razie potrzeby utworzenie obiektu przy pobieraniu.

Czytaj dalej

Prosty object tracing

Potrzebowałem w prosty sposób i łatwy sposób logować moment tworzenia i niszczenia obiektów. W najprostszym wypadku wystarczyłoby przeciążyć operator new i delete, ale wtedy logowanie dotyczyłoby tylko obiektów tworzonych na stercie. A ja chce i stos, i stertę ;) No to wystarczy w konstruktorze i destruktorze umieścić wywołanie funkcji logującej i problem znika. Tylko, że w każdej klasie musimy dodać ten kod, a jak wspomniałem sposób powinien być najprostszy i najłatwiejszy.

Czytaj dalej