Wyrażenia przyrostków
Wyrażenia przyrostkowe składają się z podstawowego wyrażenia lub wyrażeń, w których operatory przyrostkowe następują po wyrażeniu podstawowym. Operatory przyrostkowe są wymienione w poniższej tabeli.
Operatory przyrostka
Nazwa operatora | Notacja operatora |
---|---|
Operator indeksu dolnego | [ ] |
Operator wywołania funkcji | ( ) |
Operator konwersji jawnego typu | type-name( ) |
Operator dostępu do składowych | . lub -> |
Operator przyrostka przyrostkowego | ++ |
Operator dekrementacji postfiksu | -- |
Następująca składnia opisuje możliwe wyrażenia przyrostkowe:
primary-expression
postfix-expression[expression]postfix-expression(expression-list)simple-type-name(expression-list)postfix-expression.namepostfix-expression->namepostfix-expression++postfix-expression--cast-keyword < typename > (expression )typeid ( typename )
Powyższe wyrażenie-postfix-może być wyrażeniem podstawowym lub innym wyrażeniem postfiksu. Grupa wyrażeń przyrostkowych od lewej do prawej, umożliwia w ten sposób łączenie wyrażeń w następujący sposób:
func(1)->GetValue()++
W powyższym wyrażeniu func
jest wyrażeniem podstawowym, func(1)
jest wyrażeniem postfiksu funkcji, func(1)->GetValue
jest wyrażeniem postfiksu określającym składową klasy, func(1)->GetValue()
jest innym wyrażeniem postfiksu funkcji, a całe wyrażenie jest wyrażeniem postfiksu zwiększającym zwracaną wartość GetValue. Znaczenie wyrażenia jako całości to „wywołaj funkcję przekazywania 1 jako argument i uzyskaj wskaźnik do klasy jako wartość zwracaną. Następnie wywołaj metodę GetValue()
dla tej klasy, a następnie zwiększ zwróconą wartość.
Wyrażenia wymienione powyżej są wyrażeniami przypisania, co oznacza, że wyniki wyrażenia muszą być r-wartościami.
Forma wyrażenia przyrostkowego
simple-type-name ( expression-list )
wskazuje wywołanie konstruktora. Jeśli simple-type-name jest typem podstawowym, lista wyrażeń musi być wyrażeniem pojedynczym, a to wyrażenie wskazuje rzutowanie wartości wyrażenia na typ podstawowy. Ten typ wyrażenia rzutującego naśladuje konstruktor. Jako że ta forma umożliwia konstruowanie podstawowych typów i klas przy użyciu tej samej składni, ta forma jest szczególnie przydatna podczas definiowania klas szablonów.
Słowo kluczowe cast-keyword jest jednym z dynamic_cast
elementów , static_cast
lub reinterpret_cast
. Więcej informacji można znaleźć w temacie dynamic_cast
, static_cast
i reinterpet_cast
.
Operator typeid
jest uważany za wyrażenie postfiksu. Zobacz operator typeid.
Argumenty formalne i rzeczywiste
Wywoływanie programów przekazuje informacje do wywoływanych funkcji w "rzeczywistych argumentach". Wywoływane funkcje uzyskują dostęp do informacji przy użyciu odpowiednich "formalnych argumentów".
Po wywołaniu funkcji, wykonywane są następujące zadania:
Wszystkie rzeczywiste argumenty (dostarczane przez wywołującego) są obliczane. Nie ma niejawnego porządku, w którym argumenty są obliczane, ale wszystkie argumenty są obliczone i wszystkie efekty uboczne zakończone przed wejściem do funkcji.
Każdy argument formalny jest inicjowany z odpowiadającym mu argumentem rzeczywistym na liście wyrażeń. (Argument formalny jest argumentem zadeklarowanym w nagłówku funkcji i używanym w treści funkcji). Konwersje są wykonywane tak, jakby inicjalizacja — zarówno konwersje standardowe, jak i zdefiniowane przez użytkownika są wykonywane w konwertowaniu rzeczywistego argumentu na poprawny typ. Wykonywane inicjowanie zostało koncepcyjnie zilustrowane przez następujący kod:
void Func( int i ); // Function prototype ... Func( 7 ); // Execute function call
Koncepcyjne inicjalizacje przed wywołaniem to:
int Temp_i = 7; Func( Temp_i );
Należy zauważyć, że inicjalizacja jest wykonywana jakby przy użyciu składni znaku równości zamiast składni nawiasów. Kopia
i
została utworzona przed przekazaniem wartości do funkcji. (Aby uzyskać więcej informacji, zobacz Inicjatory i konwersje).W związku z tym, jeśli prototyp funkcji (deklaracja) wywołuje argument typu
long
, a program wywołujący dostarcza rzeczywisty argument typuint
, rzeczywisty argument jest promowany przy użyciu standardowej konwersji typu na typlong
(zobacz Konwersje standardowe).Błędem jest podawanie rzeczywistego argumentu, dla którego nie ma żadnych standardowych lub zdefiniowanych przez użytkownika konwersji do typu argumentu formalnego.
Dla rzeczywistych argumentów typu klasy, argument formalny jest inicjowany przez wywołanie konstruktora klasy. (Zobacz Konstruktory , aby uzyskać więcej informacji na temat tych specjalnych funkcji składowych klasy).
Wywołanie funkcji jest wykonywane.
Poniższy fragment programu demonstruje wywołanie funkcji:
// expre_Formal_and_Actual_Arguments.cpp
void func( long param1, double param2 );
int main()
{
long i = 1;
double j = 2;
// Call func with actual arguments i and j.
func( i, j );
}
// Define func with formal parameters param1 and param2.
void func( long param1, double param2 )
{
}
Gdy func
jest wywoływany z main, parametr param1
formalny jest inicjowany z wartością i
(i
jest konwertowany na typ long
odpowiadający poprawnemu typowi przy użyciu konwersji standardowej), a parametr param2
formalny jest inicjowany z wartością j
(j
jest konwertowany na typ double
przy użyciu konwersji standardowej).
Traktowanie typów argumentów
Argumenty formalne zadeklarowane jako const
typy nie mogą być zmieniane w treści funkcji. Funkcje mogą zmieniać dowolny argument, który nie jest typu const
. Jednak zmiana jest lokalna dla funkcji i nie ma wpływu na wartość rzeczywistego argumentu, chyba że rzeczywisty argument był odwołaniem do obiektu nie typu const
.
Poniższe funkcje ilustrują niektóre z tych pojęć:
// expre_Treatment_of_Argument_Types.cpp
int func1( const int i, int j, char *c ) {
i = 7; // C3892 i is const.
j = i; // value of j is lost at return
*c = 'a' + j; // changes value of c in calling function
return i;
}
double& func2( double& d, const char *c ) {
d = 14.387; // changes value of d in calling function.
*c = 'a'; // C3892 c is a pointer to a const object.
return d;
}
Wielokropek i argumenty domyślne
Funkcje można zadeklarować tak, aby akceptowały mniej argumentów niż określono w definicji funkcji przy użyciu jednej z dwóch metod: wielokropka (...
) lub argumentów domyślnych.
Wielokropek oznacza, że argumenty mogą być wymagane, ale liczba i typy nie są określone w deklaracji. Zwykle jest to słaba praktyka programowania w języku C++, ponieważ pokonuje jedną z zalet bezpieczeństwa języka C++: typu. Różne konwersje są stosowane do funkcji zadeklarowanych za pomocą wielokropka niż do tych funkcji, dla których znane są typy argumentów formalnych i rzeczywistych:
Jeśli rzeczywisty argument ma typ
float
, jest promowany do typudouble
przed wywołaniem funkcji.Dowolny
signed char
typ lubsigned short
unsigned char
unsigned short
, wyliczony typ lub pole bitowe jest konwertowane nasigned int
typ lub przyunsigned int
użyciu promocji całkowitej.Każdy argument typu klasy jest przekazywany przez wartość jako strukturę danych; kopia jest tworzona przez kopiowanie binarne zamiast wywoływania konstruktora kopiowania klasy (jeśli istnieje).
Wielokropek, jeśli jest używany, musi być zadeklarowany jako ostatni na liście argumentów. Aby uzyskać więcej informacji na temat przekazywania zmiennej liczby argumentów, zobacz omówienie va_arg, va_start i va_list w dokumentacji biblioteki czasu wykonywania.
Aby uzyskać informacje na temat domyślnych argumentów w programowaniu CLR, zobacz Zmienne listy argumentów (...) (C++/CLI).
Argumenty domyślne umożliwiają określenie wartości, którą argument powinien przyjąć, jeśli żadna z nich nie zostanie podana w wywołaniu funkcji. Poniższy fragment kodu pokazuje, jak działają argumenty domyślne. Aby uzyskać więcej informacji na temat ograniczeń dotyczących określania argumentów domyślnych, zobacz Argumenty domyślne.
// expre_Ellipsis_and_Default_Arguments.cpp
// compile with: /EHsc
#include <iostream>
// Declare the function print that prints a string,
// then a terminator.
void print( const char *string,
const char *terminator = "\n" );
int main()
{
print( "hello," );
print( "world!" );
print( "good morning", ", " );
print( "sunshine." );
}
using namespace std;
// Define print.
void print( const char *string, const char *terminator )
{
if( string != NULL )
cout << string;
if( terminator != NULL )
cout << terminator;
}
Poprzedni program deklaruje funkcję , print
która przyjmuje dwa argumenty. Jednak drugi argument, terminator, ma wartość domyślną , "\n"
. W main
systemie pierwsze dwa wywołania zezwalają print
domyślnemu drugiemu argumentowi na podanie nowego wiersza w celu zakończenia drukowanego ciągu. Trzecie wywołanie określa jawną wartość drugiego argumentu. Dane wyjściowe z programu to
hello,
world!
good morning, sunshine.
Zobacz też
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla