Funkcje#

Wstęp#

Funkcje są fundamentalnym elementem programowania w C++, umożliwiając pakowanie fragmentów kodu w wydajne, wielokrotnego użytku sekcje kodu, przeznaczone do wykonywania określonych zadań. Funkcje można wywoływać wielokrotnie w programie, co ułatwia organizację kodu i pomaga uniknąć jego powtarzania. Funkcje ułatwiają również debugowanie kodu.

Na tej stronie opisano podstawy korzystania z funkcji w C++, w tym:

Struktura i składnia funkcji#

W C++ funkcje muszą być deklarowane z typem zwracanym, nazwą i parametrami. Podstawowa składnia jest następująca:

return_type function_name(parameters) {
  // Code to execute when the function is called
  return result;  // Optional, used to return a value
}

Części funkcyjne

Opis

return_type

Typ danych zwracany przez funkcję. Oto kilka typowych opcji:

  • void — nie zwraca niczego
  • int — zwraca wartość całkowitą
  • double — zwraca liczbę zmiennoprzecinkową
  • bool — zwraca wartość true true lub false
  • char — zwraca pojedynczy znak
  • const char* — zwraca ciąg tekstowy
  • typy zdefiniowane przez użytkownika — zwracają obiekt struktury struct lub obiekt klasy

function_name

Nazwa funkcji.

parameters

Opcjonalnie. Lista parametrów typu, rozdzielona przecinkami, zapisana jako type name, gdzie type określa typ danych parametru, a name to identyfikator używany do uzyskania dostępu do tej wartości w funkcji. Parametry otrzymują wartości wejściowe po wywołaniu funkcji.

result

Opcjonalnie. Wartość zwracana przez funkcję. Jeśli argument return_type funkcji return_type jest różny od void, ta wartość musi zostać podana, a jej typ musi dokładnie odpowiadać podanemu argumentowi return_type return_type.

Uwaga: Funkcja musi zawsze zostać zadeklarowana przed jej wywołaniem lub należy podać prototyp funkcji.

Prototypy funkcji#

W C++ kod jest czytany od góry do dołu. Oznacza to, że funkcja musi być znana kompilatorowi, zanim będzie można ją wywołać.

Prototyp funkcji pozwala używać funkcji przed napisaniem jej pełnego kodu. Dzięki temu możesz zachować main() na początku programu, a definicje funkcji umieścić później, gdzie są łatwiejsze do uporządkowania i odczytania.

Bez prototypu konieczne byłoby zdefiniowanie każdej funkcji powyżej main(), co może utrudniać śledzenie projektów w miarę ich rozrastania się.

// The function's prototype
void greeting();

int main() {
  greeting();
}

// Write the function's body after
void greeting() {
  Brain.Screen.print("Hello!");
}

Definiowanie i wywoływanie funkcji#

Functions with No Parameters#

Jeśli funkcja nie wymaga danych wejściowych, można ją zdefiniować bez parametrów. Użyj void jako typu zwracanego, jeśli funkcja nie zwraca wartości.

// Define a function to display a message
void greeting() {
    Brain.Screen.print("Hello!");
}

int main() {
    // Initializing Robot Configuration. DO NOT REMOVE!
    vexcodeInit();
    // Call the function to display the message
    greeting();
}

Functions with Parameters#

Do funkcji można również dodawać parametry, które umożliwiają przekazywanie informacji, które funkcja ma wykorzystać.

Uwaga: Tekst można przekazywać za pomocą ciągów w stylu języka C (const char*) lub ciągów w stylu języka C++ (std::string).

// Define a function with a parameter
void namedGreeting(const char* name) {
    Brain.Screen.print("Hello, %s!", name);
}

int main() {
    // Initializing Robot Configuration. DO NOT REMOVE!
    vexcodeInit();
    namedGreeting("Stranger");
}

Wartości zwracane#

Funkcje mogą odsyłać dane do wywołującego za pomocą słowa kluczowego return Pozwala to na przechwytywanie i wykorzystywanie danych wyjściowych w projekcie.

// Define a function that multiplies numbers by 2
int timesTwo(int number) {
    return number * 2;
}

int main() {
    // Initializing Robot Configuration. DO NOT REMOVE!
    vexcodeInit();
    // Display the return value
    Brain.Screen.print("%d", timesTwo(2));
}

Przechodząc przez odniesienie#

Domyślnie C++ przekazuje parametry funkcji przez wartość, co oznacza, że ​​funkcja otrzymuje kopię oryginalnej zmiennej. Zmiany wprowadzone wewnątrz funkcji nie wpływają na oryginalną wartość.

// Add 1 to the number
void addOne(int number) {
  number++;
}

int main() {
  int value = 5;
  addOne(value);
  // "value" will still be 5
}

Aby umożliwić funkcji modyfikację oryginalnej zmiennej, parametry można przekazać przez odniesienie, korzystając z symboli &.

// Add 1 to the number
void addOne(int& number) {
  number++;
}

int main() {
  int value = 5;
  addOne(value);
  // "value" will now be 6
}

Przekazywanie przez odniesienie pozwala funkcjom na aktualizowanie zmiennych zdefiniowanych poza funkcją bez zwracania wartości.

Funkcje wywołania zwrotnego#

Funkcja wywołania zwrotnego to funkcja przekazywana do innej funkcji i wywoływana automatycznie po wystąpieniu określonego zdarzenia.

Wywołania zwrotne są powszechnie stosowane w przypadku zdarzeń takich, jak naciśnięcie przycisku lub aktualizacja czujnika.

Zamiast wywoływać funkcję samodzielnie, projekt wywołuje ją za Ciebie, gdy zdarzenie nastąpi.

void onPressed() {
  Brain.Screen.print("Screen pressed!");
}

// Call onPressed whenever the screen is pressed
int main() {
  vexcodeInit();
  Brain.Screen.pressed(onPressed);
}

Callback Signatures#

Każda funkcja wywołania zwrotnego musi spełniać określony podpis, który definiuje:

  • Typ zwracany

  • Liczba parametrów

  • Typy parametrów

Wymagany podpis jest określany przez API. Funkcja wywołania zwrotnego musi dokładnie odpowiadać temu podpisowi.

// This callback function cannot include any parameters
void callback(void);

// This callback function includes four parameters
void callback(axisType axis, double x, double y, double z);

Nazwy parametrów mają charakter opisowy i mogą się różnić, ale typ zwracany, kolejność parametrów i typy parametrów muszą być dokładnie takie same.

Funkcje z argumentami domyślnymi#

Funkcje mogą definiować wartości domyślne dla jednego lub większej liczby parametrów. Argument domyślny jest używany, gdy podczas wywołania funkcji dla danego parametru nie podano wartości.

Zasady dotyczące argumentów domyślnych:

  • Domyślne argumenty muszą być ostatnimi parametrami w definicji funkcji.

  • Gdy parametr ma wartość domyślną, wszystkie parametry po nim również muszą mieć wartości domyślne.

  • Jeśli funkcja określa argumenty domyślne w swoim prototypie, wartości domyślne nie mogą być ponownie określone w definicji funkcji.

// Required parameter first, default parameter last
void greeting(const char* name, int repeatCount = 1) {

    for (int i = 0; i < repeatCount; i++) {
        Brain.Screen.print("Hello, %s!", name);
        Brain.Screen.newLine();
    }
}

int main() {
    vexcodeInit();

    // Say what name to greet (V5) and
    // use default value for repeatCount (1)
    greeting("V5");

    Brain.Screen.newLine();

    // Overrides the default value to 3
    greeting("V5", 3);
}