2017-01-07 12 views
6

, jak powiedziano w tytule, zastanawiałem się, czy możliwe było zatrzymanie funkcji od wykonania. W moim konkretnym przypadku, staram się, aby operator [] i zapobiec utilisator korzystanie z niego, jeśli wartość dał w parametrach jest zbyt wysoka:Zapobieganie wykonaniu funkcji powracającej, jeśli warunek dotyczący parametrów jest prawdziwy

w ncurses.h:

class Vec4 
{ 
    float x,y,z,w; 

    public: 

     float operator[](const unsigned int i); 
} 

w .cpp:

float Vec4::operator[](const unsigned int i) 
{ 
    if(i == 0) return x; 
    if(i == 1) return y; 
    if(i == 2) return z; 
    if(i == 3) return w; 
} 

Chciałbym „break” funkcję, jeśli i> = 4 na razie jestem po prostu dokonywania wyjścia konsoli i powrócić 0.0f

dziękuję mi pokazać, jeśli istnieje jest sposobem ... lub nie!

+0

Co jest nie tak z twoim podejściem? – UnholySheep

+0

Co dokładnie masz na myśli przez "* stop *" lub "* break *" funkcję? – melpomene

+1

Co powiesz na użycie wyjątku? –

Odpowiedz

7

Możesz zrobić co najmniej 4 rzeczy.

  1. Zwraca znaną wartość błędu z funkcji. Na przykład -1, jeśli wartość wejściowa nie jest dobra.
  2. Podnieś wyjątek.
  3. Zmień funkcję, aby przekazać dane wyjściowe przez odniesienie i zwróć kod błędu.
  4. Zmusić użytkownika, aby uzyskał punkt z silnie wpisanym enum class.

Wariant 1

float Vec4::operator[](const unsigned int i) { 
    switch (i) 
    case 0: 
     return x; 
    ... 
    default: 
     return nan; 

Wariant 2

default: 
    throw InvalidInputException; 

Wariant 3

typedef ErrCode int; 
const int ERROR = -1; 
const int SUCCESS = 1; 
... 
ErrCode Vec4::getPoint(const unsigned int i, float &ouptut) { 
    ... 
    switch (i) 
    case 0: 
     output = x; 
     return SUCCESS; 
    default: 
     return ERROR; 

Wariant 4 (C++ 11)

class Vec4 { 
... 
public: 
    enum class VecMem {X, Y, Z, W}; 
    float Vec4::getPoint(VecMem member) { 
     switch (member): 
      case X: 
       return x; 
     ... 

Zastosowanie:

Vec4.getPoint(Vec4::VecMem::X); 
+0

Można również ustawić zmienną globalną jako wskaźnik błędu (lub ustawić zmienną składową), wziąć wskaźnik funkcji dostarczony przez wywołującego, aby wywołać błąd, 'longjmp' out,' abort() 'cały proces lub przejść do nieskończona pętla. – melpomene

+1

@melpomene, prawdziwe i prawdziwe, wszystkie wydają się nieco ekstremalne dla funkcji, która prawdopodobnie zwraca punkt. –

+1

Ooh! Możemy być jeszcze bardziej ekstremalni: 'system (" shutdown -h now ");' – melpomene

0

Jeśli argumentem jest znany w czasie kompilacji, można użyć static_assert.

#include <cassert>; 

constexpr float Vec4::operator[](const unsigned int i) 
{ 
    static_assert(i <= 3); 
    ... 
} 

twierdzenia nie są statyczne wpływu na wydajność, ponieważ są one sprawdzane w czasie kompilacji.

Jeśli twój argument nie jest znany podczas kompilacji, możesz użyć dynamicznego asertywnie.

#include <cassert>; 

float Vec4::operator[](const unsigned int i) 
{ 
    assert(i <= 3); 
    ... 
} 

Dynamiczne twierdzenia zawarte są w wyjście kompilatora tylko po ustawieniu flagi kompilatora, które umożliwią im, więc można wyłączyć łatwo.

Lub możesz po prostu rzucić wyjątek.

float Vec4::operator[](const unsigned int i) 
{ 
    if (i > 3) 
    { 
     throw BadArgumentException("i must be <= 3"); 
    } 
    ... 
} 

Wyjątki mogą zawierać wiele informacji i być obsługiwane w innych częściach kodu, ale mają największy koszt wydajności.

http://en.cppreference.com/w/cpp/error/assert

+1

Wątpię, aby static_assert był użyteczny tutaj [wymaga wyrażeń określonych podczas kompilacji] (http://en.cppreference.com/w/cpp/language/constant_expression#Converted_constant_expression) –

+0

Traktowałem kod z pytania jako przykład ... Czy nie uważasz, że jest to możliwe rozwiązanie problemu zdefiniowanego w tytule wątku? –

+0

Jasne, ale pomyśl o przypadku takim jak "cin >> i; return someVector [i] '. Nie można tego ustalić w czasie kompilacji, dlatego twoje statyczne potwierdzenie nie działa. –

0

Use „przypadek switch”, a dla przypadku, gdy wartość jest inna większa niż 3 Powrót stanie domyślnym, która może być określona wartość zarezerwowana dla tej sprawy

0

Jeśli nie przeszkadza nadchodzące funkcje, można użyć std::optional to zrobić:

std::optional<float> Vec4::operator[](const unsigned int i) { 
    if(i == 0) return x; 
    if(i == 1) return y; 
    if(i == 2) return z; 
    if(i == 3) return w; 
    return {}; 
} 

wadą jest to, że rozmówca musi sprawdzić ważność zwracanej wartości (przy użyciu albo operator bool lub has_value funkcja użytkownika) lub użyj funkcji członkowskiej value_or, aby uzyskać domyślną wartość dla opcji pustych.

Powiązane problemy