SafeInt — Klasa
Rozszerza prymitywów całkowitą, aby zapobiec przepełnienie całkowitoliczbowe i pozwala porównywać różne rodzaje liczb całkowitych.
template<typename T, typename E = _SAFEINT_DEFAULT_ERROR_POLICY>
class SafeInt;
Parametry
Szablon |
Opis |
---|---|
T |
Typ integer lub parametrów typu Boolean który SafeInt zastępuje. |
E |
Typ danych wyliczanych, która definiuje błąd obsługi zasad. |
U |
Typ integer lub parametrów typu Boolean dla pomocniczego operandu. |
Parametr |
Opis |
---|---|
[w] rhs |
Parametr wejściowy, który reprezentuje wartość po prawej stronie operatora w kilka funkcji autonomicznych. |
[w] i |
Parametr wejściowy, który reprezentuje wartość po prawej stronie operatora w kilka funkcji autonomicznych. |
[bity in] |
Parametr wejściowy, który reprezentuje wartość po prawej stronie operatora w kilka funkcji autonomicznych. |
Elementy członkowskie
Konstruktory publiczne
Nazwa |
Opis |
---|---|
Konstruktor domyślny. |
Operatory przypisania
Nazwa |
Składnia |
---|---|
= |
template<typename U> SafeInt<T,E>& operator= (const U& rhs) |
= |
SafeInt<T,E>& operator= (const T& rhs) throw() |
= |
template<typename U> SafeInt<T,E>& operator= (const SafeInt<U, E>& rhs) |
= |
SafeInt<T,E>& operator= (const SafeInt<T,E>& rhs) throw() |
Operatorów rzutowania
Nazwa |
Składnia |
---|---|
bool |
operator bool() throw() |
char |
operator char() const |
podpisany char |
operator signed char() const |
niepodpisany char |
operator unsigned char() const |
__int16 |
operator __int16() const |
nieoznaczony __int64 |
operator unsigned __int16() const |
__int32 |
operator __int32() const |
nieoznaczony__int64 |
operator unsigned __int32() const |
long |
operator long() const |
niepodpisany long |
operator unsigned long() const |
__int64 |
operator __int64() const |
unsigned __int64 |
operator unsigned __int64() const |
wchar_t |
operator wchar_t() const |
Operatory porównania
Nazwa |
Składnia |
---|---|
< |
template<typename U> bool operator< (U rhs) const throw() |
< |
bool operator< (SafeInt<T,E> rhs) const throw() |
>= |
template<typename U> bool operator>= (U rhs) const throw() |
>= |
Bool operator>= (SafeInt<T,E> rhs) const throw() |
> |
template<typename U> bool operator> (U rhs) const throw() |
> |
Bool operator> (SafeInt<T,E> rhs) const throw() |
<= |
template<typename U> bool operator<= (U rhs) const throw() |
<= |
bool operator<= (SafeInt<T,E> rhs) const throw() |
== |
template<typename U> bool operator== (U rhs) const throw() |
== |
bool operator== (bool rhs) const throw() |
== |
bool operator== (SafeInt<T,E> rhs) const throw() |
!= |
template<typename U> bool operator!= (U rhs) const throw() |
!= |
bool operator!= (bool b) const throw() |
!= |
bool operator!= (SafeInt<T,E> rhs) const throw() |
Operatory arytmetyczne
Nazwa |
Składnia |
---|---|
+ |
const SafeInt<T,E>& operator+ () const throw() |
- |
SafeInt<T,E> operator- () const |
++ |
SafeInt<T,E>& operator++ () |
-- |
SafeInt<T,E>& operator-- () |
% |
template<typename U> SafeInt<T,E> operator% (U rhs) const |
% |
SafeInt<T,E> operator% (SafeInt<T,E> rhs) const |
%= |
template<typename U> SafeInt<T,E>& operator%= (U rhs) |
%= |
template<typename U> SafeInt<T,E>& operator%= (SafeInt<U, E> rhs) |
* |
template<typename U> SafeInt<T,E> operator* (U rhs) const |
* |
SafeInt<T,E> operator* (SafeInt<T,E> rhs) const |
*= |
SafeInt<T,E>& operator*= (SafeInt<T,E> rhs) |
*= |
template<typename U> SafeInt<T,E>& operator*= (U rhs) |
*= |
template<typename U> SafeInt<T,E>& operator*= (SafeInt<U, E> rhs) |
/ |
template<typename U> SafeInt<T,E> operator/ (U rhs) const |
/ |
SafeInt<T,E> operator/ (SafeInt<T,E> rhs ) const |
/= |
SafeInt<T,E>& operator/= (SafeInt<T,E> i) |
/= |
template<typename U> SafeInt<T,E>& operator/= (U i) |
/= |
template<typename U> SafeInt<T,E>& operator/= (SafeInt<U, E> i) |
+ |
SafeInt<T,E> operator+ (SafeInt<T,E> rhs) const |
+ |
template<typename U> SafeInt<T,E> operator+ (U rhs) const |
+= |
SafeInt<T,E>& operator+= (SafeInt<T,E> rhs) |
+= |
template<typename U> SafeInt<T,E>& operator+= (U rhs) |
+= |
template<typename U> SafeInt<T,E>& operator+= (SafeInt<U, E> rhs) |
- |
template<typename U> SafeInt<T,E> operator- (U rhs) const |
- |
SafeInt<T,E> operator- (SafeInt<T,E> rhs) const |
-= |
SafeInt<T,E>& operator-= (SafeInt<T,E> rhs) |
-= |
template<typename U> SafeInt<T,E>& operator-= (U rhs) |
-= |
template<typename U> SafeInt<T,E>& operator-= (SafeInt<U, E> rhs) |
Operatory logiczne
Nazwa |
Składnia |
---|---|
! |
bool operator !() const throw() |
~ |
SafeInt<T,E> operator~ () const throw() |
<< |
template<typename U> SafeInt<T,E> operator<< (U bits) const throw() |
<< |
template<typename U> SafeInt<T,E> operator<< (SafeInt<U, E> bits) const throw() |
<<= |
template<typename U> SafeInt<T,E>& operator<<= (U bits) throw() |
<<= |
template<typename U> SafeInt<T,E>& operator<<= (SafeInt<U, E> bits) throw() |
>> |
template<typename U> SafeInt<T,E> operator>> (U bits) const throw() |
>> |
template<typename U> SafeInt<T,E> operator>> (SafeInt<U, E> bits) const throw() |
>>= |
template<typename U> SafeInt<T,E>& operator>>= (U bits) throw() |
>>= |
template<typename U> SafeInt<T,E>& operator>>= (SafeInt<U, E> bits) throw() |
& |
SafeInt<T,E> operator& (SafeInt<T,E> rhs) const throw() |
& |
template<typename U> SafeInt<T,E> operator& (U rhs) const throw() |
&= |
SafeInt<T,E>& operator&= (SafeInt<T,E> rhs) throw() |
&= |
template<typename U> SafeInt<T,E>& operator&= (U rhs) throw() |
&= |
template<typename U> SafeInt<T,E>& operator&= (SafeInt<U, E> rhs) throw() |
^ |
SafeInt<T,E> operator^ (SafeInt<T,E> rhs) const throw() |
^ |
template<typename U> SafeInt<T,E> operator^ (U rhs) const throw() |
^= |
SafeInt<T,E>& operator^= (SafeInt<T,E> rhs) throw() |
^= |
template<typename U> SafeInt<T,E>& operator^= (U rhs) throw() |
^= |
template<typename U> SafeInt<T,E>& operator^= (SafeInt<U, E> rhs) throw() |
| |
SafeInt<T,E> operator| (SafeInt<T,E> rhs) const throw() |
| |
template<typename U> SafeInt<T,E> operator| (U rhs) const throw() |
|= |
SafeInt<T,E>& operator|= (SafeInt<T,E> rhs) throw() |
|= |
template<typename U> SafeInt<T,E>& operator|= (U rhs) throw() |
|= |
template<typename U> SafeInt<T,E>& operator|= (SafeInt<U, E> rhs) throw() |
Uwagi
SafeInt Klasy chroni przed przepełnienie całkowitoliczbowe w operacjach matematycznych.Na przykład, należy rozważyć dodanie dwóch 8-bitowych liczb całkowitych: jeden ma wartość 200 i druga ma wartość 100.Byłoby właściwe działanie matematyczne 200 + 100 = 300.Jednakże, ze względu na limit 8-bitowa liczba całkowita górnej bit zostaną utracone i kompilator zwróci 44 (300-28) w wyniku.Wszelkie operacje, które zależy od tego równania matematyczne będzie generować nieoczekiwane zachowanie.
SafeInt Klasy sprawdza, czy występuje przepełnienie arytmetyczne lub czy kod próbuje dzielenie przez zero.W obu przypadkach klasy wywołuje obsługi błędu, aby ostrzec program potencjalny problem.
Klasa ta również pozwala porównać dwa różne rodzaje liczb całkowitych, tak długo, jak są one SafeInt obiektów.Zazwyczaj podczas wykonywania porównania, należy najpierw przekonwertować tak, aby być tego samego typu.Jeden numer na inny typ odlewania często wymaga kontrole, aby upewnić się, że nie ma bez utraty danych.
W tabeli podmioty gospodarcze w tym temacie wymieniono operatory matematyczne i porównanie obsługiwane przez SafeInt klasy.Operatory matematyczne najbardziej zwrotu SafeInt obiektu typu T.
Operacje porównania między SafeInt i typu całkowitego mogą być wykonywane w dowolnym kierunku.Na przykład obie SafeInt<int>(x) < y i y > SafeInt<int>(x) są prawidłowe i zwraca ten sam wynik.
Za pomocą dwóch różnych nie obsługują wielu operatorów binarnych SafeInt typów.Jednym z przykładów jest & operatora.SafeInt<T, E> & intjest obsługiwana, ale SafeInt<T, E> & SafeInt<U, E> nie jest.W drugim przykładzie kompilator nie wie, jakiego rodzaju parametr zwraca.Możliwym rozwiązaniem tego problemu jest do oddania drugi parametr powrót do typu podstawowego.Przy użyciu tych samych parametrów, można to zrobić z SafeInt<T, E> & (U)SafeInt<U, E>.
[!UWAGA]
Za wszelkie operacje bitowe dwa różne parametry powinny mieć taki sam rozmiar.Jeśli są różne rozmiary, kompilator będzie rzucić ASSERT (MFC) wyjątek.Wyniki tej operacji nie można zagwarantować są dokładne.Aby rozwiązać ten problem, obsady mniejszych parametr, dopóki ma taki sam rozmiar jak parametr większe.
Dla operatory przesunięcia przesunięcie bitów więcej niż istnieje dla typu szablonu spowoduje zgłoszenie wyjątku ASSERT.Będzie to miało żadnego wpływu w trybie release.Operatory przesunięcia możliwe jest mieszanie dwa typy parametrów SafeInt, ponieważ typ zwracany jest taki sam, jak oryginalny typ.Liczba po prawej stronie operatora tylko wskazuje liczbę bitów do przesunięcia.
Podczas wykonywania logiczne porównania z obiektem SafeInt, porównanie jest ściśle arytmetycznych.Na przykład należy rozważyć następujące wyrażenia:
SafeInt<uint>((uint)~0) > -1
((uint)~0) > -1
Pierwsza instrukcja jest rozpoznawany jako true, ale druga instrukcja jest rozpoznawany jako false.Negację 0 jest równa 0xFFFFFFFF.W drugiej instrukcji domyślny operator porównania porównuje wartość 0xFFFFFFFF wartość 0xFFFFFFFF i uważa je za równe.Operator porównania dla SafeInt klasy zdaje sobie sprawę, że drugi parametr jest negatywna, pierwszy parametr jest niepodpisany.Dlatego, chociaż reprezentacja bit jest identyczna, SafeInt operator logiczny zdaje sobie sprawę, że liczba całkowita bez znaku jest większy niż -1.
Należy zachować ostrożność, korzystając z SafeInt klasy wraz z ?: operator trójargumentowy.Należy rozważyć następujący wiersz kodu.
Int x = flag ? SafeInt<unsigned int>(y) : -1;
Kompilator konwertuje ją na to:
Int x = flag ? SafeInt<unsigned int>(y) : SafeInt<unsigned int>(-1);
Jeśli flag jest false, kompilator zgłasza wyjątek zamiast przypisywania wartości od -1 do x.Dlatego aby uniknąć tego zachowania, poprawny kod używany jest następujący wiersz.
Int x = flag ? (int) SafeInt<unsigned int>(y) : -1;
Ti U można przypisać typu Boolean, typ znaków lub liczbę całkowitą.Liczba całkowita typów może być podpisane lub niepodpisane i dowolnym rozmiarze od 8 bitów 64 bitów.
[!UWAGA]
Chociaż SafeInt klasy akceptuje wszelkiego rodzaju liczba całkowita, bardziej efektywnie wykonuje się z typami bez znaku.
Ejest mechanizm obsługi błędów, które SafeInt używa.Dwa mechanizmy obsługi błędów są dostarczane z biblioteki SafeInt.Domyślna zasada SafeIntErrorPolicy_SafeIntException, który rzuca SafeIntException — Klasa wyjątek, gdy wystąpi błąd.Druga zasada jest SafeIntErrorPolicy_InvalidParameter, który zatrzymuje program, jeśli wystąpi błąd.
Istnieją dwie opcje, aby dostosować zasady błędów.Pierwszą opcją jest ustawiony parametr E podczas tworzenia SafeInt.Ta opcja umożliwia zmienianie obsługi zasad dla tylko jednego błędów SafeInt.Inną opcją jest określenie _SAFEINT_DEFAULT_ERROR_POLICY być dostosowane klasy obsługi błędów przed dołączeniem SafeInt biblioteki.Ta opcja, jeśli chcesz zmienić domyślną obsługę zasad dla wszystkich wystąpień błędu SafeInt klasy w kodzie.
[!UWAGA]
Niestandardowe klasy, która obsługuje błędy z biblioteki SafeInt powinien zwrócić sterowanie do kodu, który wywołał obsługi błędów.Po wywołaniu obsługi błędów, wynik SafeInt operacji nie można ufać.
Wymagania
Nagłówek: safeint.h
Przestrzeń nazw: msl::utilities