Przeładowywanie funkcjiFunction Overloading

C++ umożliwia określenie więcej niż jednej funkcji o tej samej nazwie w tym samym zakresie.C++ allows specification of more than one function of the same name in the same scope. Te funkcje są nazywane przeciążonymi funkcjami.These functions are called overloaded functions. Przeciążone funkcje umożliwiają dostarczenie różnych semantyki dla funkcji, w zależności od typów i liczby argumentów.Overloaded functions enable you to supply different semantics for a function, depending on the types and number of arguments.

Na przykład print Funkcja, która przyjmuje argument, std::string może wykonywać bardzo różne zadania niż jeden, który przyjmuje argument typu double .For example, a print function that takes a std::string argument might perform very different tasks than one that takes an argument of type double. Przeciążanie powoduje, że nie trzeba używać nazw takich jak print_string lub print_double .Overloading saves you from having to use names such as print_string or print_double. W czasie kompilacji kompilator wybiera, którego przeciążenia użyć na podstawie typu argumentów przekazaną przez wywołującego.At compile time, the compiler chooses which overload to use based on the type of arguments passed in by the caller. Po wywołaniu print(42.0) , void print(double d) Funkcja zostanie wywołana.If you call print(42.0), then the void print(double d) function will be invoked. Jeśli wywołasz print("hello world") , void print(std::string) Przeciążenie zostanie wywołane.If you call print("hello world"), then the void print(std::string) overload will be invoked.

Można przeciążać zarówno funkcje członkowskie, jak i funkcje, które nie są elementami członkowskimi.You can overload both member functions and non-member functions. W poniższej tabeli przedstawiono, które części deklaracji funkcji język C++ używa do rozróżniania grup funkcji o tej samej nazwie w tym samym zakresie.The following table shows what parts of a function declaration C++ uses to differentiate between groups of functions with the same name in the same scope.

Zagadnienia przeciążaniaOverloading Considerations

Element deklaracji funkcjiFunction Declaration Element Używany w przeciążaniu?Used for Overloading?
Typ zwracany przez funkcjęFunction return type NieNo
Liczba argumentówNumber of arguments TakYes
Typ argumentówType of arguments TakYes
Obecność lub brak wielokropkaPresence or absence of ellipsis TakYes
Użycie typedef nazwUse of typedef names NieNo
Nieokreślone granice tablicUnspecified array bounds NieNo
const oraz volatileconst or volatile Tak, po zastosowaniu do całej funkcjiYes, when applied to entire function
Kwalifikatory refRef-qualifiers TakYes

PrzykładExample

Poniższy przykład ilustruje sposób użycia przeciążenia.The following example illustrates how overloading can be used.

// function_overloading.cpp
// compile with: /EHsc
#include <iostream>
#include <math.h>
#include <string>

// Prototype three print functions.
int print(std::string s);             // Print a string.
int print(double dvalue);            // Print a double.
int print(double dvalue, int prec);  // Print a double with a
                                     //  given precision.
using namespace std;
int main(int argc, char *argv[])
{
    const double d = 893094.2987;
    if (argc < 2)
    {
        // These calls to print invoke print( char *s ).
        print("This program requires one argument.");
        print("The argument specifies the number of");
        print("digits precision for the second number");
        print("printed.");
        exit(0);
    }

    // Invoke print( double dvalue ).
    print(d);

    // Invoke print( double dvalue, int prec ).
    print(d, atoi(argv[1]));
}

// Print a string.
int print(string s)
{
    cout << s << endl;
    return cout.good();
}

// Print a double in default precision.
int print(double dvalue)
{
    cout << dvalue << endl;
    return cout.good();
}

//  Print a double in specified precision.
//  Positive numbers for precision indicate how many digits
//  precision after the decimal point to show. Negative
//  numbers for precision indicate where to round the number
//  to the left of the decimal point.
int print(double dvalue, int prec)
{
    // Use table-lookup for rounding/truncation.
    static const double rgPow10[] = {
        10E-7, 10E-6, 10E-5, 10E-4, 10E-3, 10E-2, 10E-1,
        10E0, 10E1,  10E2,  10E3,  10E4, 10E5,  10E6 };
    const int iPowZero = 6;

    // If precision out of range, just print the number.
    if (prec < -6 || prec > 7)
    {
        return print(dvalue);
    }
    // Scale, truncate, then rescale.
    dvalue = floor(dvalue / rgPow10[iPowZero - prec]) *
        rgPow10[iPowZero - prec];
    cout << dvalue << endl;
    return cout.good();
}

Poprzedni kod pokazuje przeciążenie funkcji print w zakresie pliku.The preceding code shows overloading of the print function in file scope.

Domyślny argument nie jest uważany za część typu funkcji.The default argument isn't considered part of the function type. W związku z tym nie jest używany podczas wybierania przeciążonych funkcji.Therefore, it's not used in selecting overloaded functions. Dwie funkcje, które różnią się tylko argumentami domyślnymi, są traktowane jako wiele definicji, a nie przeciążone funkcje.Two functions that differ only in their default arguments are considered multiple definitions rather than overloaded functions.

Nie można dostarczyć argumentów domyślnych dla przeciążonych operatorów.Default arguments can't be supplied for overloaded operators.

Dopasowywanie argumentówArgument Matching

Przeciążone funkcje są wybierane w celu najlepszego dopasowania deklaracji funkcji w bieżącym zakresie do argumentów dostarczonych w wywołaniu funkcji.Overloaded functions are selected for the best match of function declarations in the current scope to the arguments supplied in the function call. Jeśli zostanie znaleziona odpowiednia funkcja, ta funkcja jest wywoływana.If a suitable function is found, that function is called. "Odpowiednie" w tym kontekście oznacza:"Suitable" in this context means either:

  • Znaleziono dokładne dopasowanie.An exact match was found.

  • Wykonano uproszczoną konwersję.A trivial conversion was performed.

  • Wykonano promocję integralną.An integral promotion was performed.

  • Istnieje konwersja standardowa do żądanego typu argumentu.A standard conversion to the desired argument type exists.

  • Istnieje konwersja zdefiniowana przez użytkownika (Operator konwersji lub Konstruktor) na żądany typ argumentu.A user-defined conversion (either conversion operator or constructor) to the desired argument type exists.

  • Znaleziono argumenty reprezentowane przez wielokropek.Arguments represented by an ellipsis were found.

Kompilator tworzy zestaw funkcji kandydujących dla każdego argumentu.The compiler creates a set of candidate functions for each argument. Funkcje kandydujące to funkcje, w których rzeczywisty argument w tym miejscu można przekonwertować na typ argumentu formalnego.Candidate functions are functions in which the actual argument in that position can be converted to the type of the formal argument.

Zestaw "najlepszych dopasowanych funkcji" jest tworzony dla każdego argumentu, a wybrana funkcja to część wspólna wszystkich zestawów.A set of "best matching functions" is built for each argument, and the selected function is the intersection of all the sets. Jeśli część wspólna zawiera więcej niż jedną funkcję, Przeciążenie jest niejednoznaczne i generuje błąd.If the intersection contains more than one function, the overloading is ambiguous and generates an error. Funkcja, która jest ostatecznie zaznaczona, zawsze jest lepszym rozwiązaniem niż każda inna funkcja w grupie dla co najmniej jednego argumentu.The function that is eventually selected is always a better match than every other function in the group for at least one argument. Jeśli nie ma żadnych wyraźnych zwycięzców, wywołanie funkcji generuje błąd.If there's no clear winner, the function call generates an error.

Należy wziąć pod uwagę następujące deklaracje (funkcje są oznaczone Variant 1 , Variant 2 i Variant 3 , do identyfikacji w następującej dyskusji):Consider the following declarations (the functions are marked Variant 1, Variant 2, and Variant 3, for identification in the following discussion):

Fraction &Add( Fraction &f, long l );       // Variant 1
Fraction &Add( long l, Fraction &f );       // Variant 2
Fraction &Add( Fraction &f, Fraction &f );  // Variant 3

Fraction F1, F2;

Weź pod uwagę następujące instrukcje:Consider the following statement:

F1 = Add( F2, 23 );

Poprzednia instrukcja kompiluje dwa zestawy:The preceding statement builds two sets:

Set 1: funkcje kandydujące, które mają pierwszy argument typu ułamekSet 1: Candidate Functions That Have First Argument of Type Fraction Set 2: funkcje kandydujące, których drugi argument można przekonwertować na typ intSet 2: Candidate Functions Whose Second Argument Can Be Converted to Type int
Wariant 1Variant 1 Wariant 1 ( int można przekonwertować, aby long użyć konwersji standardowej)Variant 1 (int can be converted to long using a standard conversion)
Wariant 3Variant 3

Funkcje w zestawie 2 są funkcjami, dla których istnieją niejawne konwersje z rzeczywistego typu parametru do formalnego typu parametru i między takimi funkcjami jest funkcja, dla której "koszt" konwersji rzeczywistego typu parametru na jego typ parametru formalnego jest najmniejszy.Functions in Set 2 are functions for which there are implicit conversions from actual parameter type to formal parameter type, and among such functions there's a function for which the "cost" of converting the actual parameter type to its formal parameter type is the smallest.

Przecięcie tych dwóch zestawów jest wariantem 1.The intersection of these two sets is Variant 1. Przykładem niejednoznacznego wywołania funkcji jest:An example of an ambiguous function call is:

F1 = Add( 3, 6 );

Poprzednie wywołanie funkcji kompiluje następujące zestawy:The preceding function call builds the following sets:

Set 1: funkcje kandydujące, które mają pierwszy argument typu intSet 1: Candidate Functions That Have First Argument of Type int Set 2: funkcje kandydujące, które mają drugi argument typu intSet 2: Candidate Functions That Have Second Argument of Type int
Wariant 2 ( int można dokonać konwersji, aby long użyć konwersji standardowej)Variant 2 (int can be converted to long using a standard conversion) Wariant 1 ( int można przekonwertować, aby long użyć konwersji standardowej)Variant 1 (int can be converted to long using a standard conversion)

Ponieważ część wspólną tych dwóch zestawów jest pusta, kompilator generuje komunikat o błędzie.Because the intersection of these two sets is empty, the compiler generates an error message.

W przypadku dopasowywania argumentów funkcja z argumentami domyślnymi n jest traktowana jako n+ 1 oddzielne funkcje, z których każdy ma inną liczbę argumentów.For argument matching, a function with n default arguments is treated as n+1 separate functions, each with a different number of arguments.

Wielokropek (...) działa jako symbol wieloznaczny; Dopasowuje dowolny rzeczywisty argument.The ellipsis (...) acts as a wildcard; it matches any actual argument. Może to prowadzić do wielu niejednoznacznych zestawów, jeśli nie projektujesz przeciążonych zestawów funkcji z najwyższą starannością.It can lead to many ambiguous sets, if you don't design your overloaded function sets with extreme care.

Uwaga

Nie można określić niejednoznaczności przeciążonych funkcji, dopóki nie zostanie napotkane wywołanie funkcji.Ambiguity of overloaded functions can't be determined until a function call is encountered. W tym momencie zestawy są kompilowane dla każdego argumentu w wywołaniu funkcji i można określić, czy istnieje jednoznaczne Przeciążenie.At that point, the sets are built for each argument in the function call, and you can determine whether an unambiguous overload exists. Oznacza to, że niejasności może pozostawać w kodzie do momentu evoked przez określone wywołanie funkcji.This means that ambiguities can remain in your code until they are evoked by a particular function call.

Różnice typu argumentówArgument Type Differences

Przeciążone funkcje odróżniają między typami argumentów, które mają różne inicjatory.Overloaded functions differentiate between argument types that take different initializers. W związku z tym argument danego typu i odwołanie do tego typu są uznawane za takie same dla celów przeciążenia.Therefore, an argument of a given type and a reference to that type are considered the same for the purposes of overloading. Są one uznawane za takie same, ponieważ przyjmują te same inicjatory.They are considered the same because they take the same initializers. Na przykład max( double, double ) jest uznawany za taki sam jak max( double &, double & ) .For example, max( double, double ) is considered the same as max( double &, double & ). Deklarowanie dwóch takich funkcji powoduje wystąpienie błędu.Declaring two such functions causes an error.

Z tego samego powodu argumenty funkcji typu modyfikowane przez const lub volatile nie są traktowane inaczej niż typ podstawowy do celów przeciążenia.For the same reason, function arguments of a type modified by const or volatile are not treated differently than the base type for the purposes of overloading.

Jednak mechanizm przeciążania funkcji może rozróżnić odwołania, które są kwalifikowane przez const i volatile i odwołania do typu podstawowego.However, the function overloading mechanism can distinguish between references that are qualified by const and volatile and references to the base type. Wprowadza kod, taki jak następujące możliwe:It makes code such as the following possible:

// argument_type_differences.cpp
// compile with: /EHsc /W3
// C4521 expected
#include <iostream>

using namespace std;
class Over {
public:
   Over() { cout << "Over default constructor\n"; }
   Over( Over &o ) { cout << "Over&\n"; }
   Over( const Over &co ) { cout << "const Over&\n"; }
   Over( volatile Over &vo ) { cout << "volatile Over&\n"; }
};

int main() {
   Over o1;            // Calls default constructor.
   Over o2( o1 );      // Calls Over( Over& ).
   const Over o3;      // Calls default constructor.
   Over o4( o3 );      // Calls Over( const Over& ).
   volatile Over o5;   // Calls default constructor.
   Over o6( o5 );      // Calls Over( volatile Over& ).
}

Dane wyjścioweOutput

Over default constructor
Over&
Over default constructor
const Over&
Over default constructor
volatile Over&

Wskaźniki do const i volatile obiekty są również uznawane za różne od wskaźników do typu podstawowego do celów przeciążenia.Pointers to const and volatile objects are also considered different from pointers to the base type for the purposes of overloading.

Dopasowywanie argumentów i konwersjeArgument matching and conversions

Gdy kompilator próbuje dopasować rzeczywiste argumenty do argumentów w deklaracjach funkcji, może dostarczyć standardowe lub zdefiniowane przez użytkownika Konwersje w celu uzyskania poprawnego typu, jeśli nie można znaleźć dokładnego dopasowania.When the compiler tries to match actual arguments against the arguments in function declarations, it can supply standard or user-defined conversions to obtain the correct type if no exact match can be found. Zastosowanie konwersji podlega tym regułom:The application of conversions is subject to these rules:

  • Nie są uwzględniane sekwencje konwersji zawierające więcej niż jedną konwersję zdefiniowaną przez użytkownika.Sequences of conversions that contain more than one user-defined conversion are not considered.

  • Sekwencje konwersji, które mogą być skracane przez usunięcie konwersji pośrednich, nie są brane pod uwagę.Sequences of conversions that can be shortened by removing intermediate conversions are not considered.

Wynikowa sekwencja konwersji, jeśli istnieje, jest nazywana najlepszą pasującą sekwencją.The resultant sequence of conversions, if any, is called the best matching sequence. Istnieje kilka sposobów konwersji obiektu typu int do typu unsigned long przy użyciu konwersji standardowych (opisanych w konwersji standardowe):There are several ways to convert an object of type int to type unsigned long using standard conversions (described in Standard Conversions):

  • Konwertuj z int na long , a następnie z long do unsigned long .Convert from int to long and then from long to unsigned long.

  • Konwertuj z int na unsigned long .Convert from int to unsigned long.

Pierwsza sekwencja, chociaż osiąga żądany cel, nie jest najlepszą zgodną sekwencją — istnieje krótsza sekwencja.The first sequence, although it achieves the desired goal, isn't the best matching sequence — a shorter sequence exists.

W poniższej tabeli przedstawiono grupę konwersji o nazwie uproszczone konwersje, które mają ograniczony wpływ na określanie, która sekwencja jest najlepszym dopasowaniem.The following table shows a group of conversions, called trivial conversions, that have a limited effect on determining which sequence is the best matching. Wystąpienia, w których konwersje uproszczone mają wpływ na wybór sekwencji, omówiono na liście poniżej tabeli.The instances in which trivial conversions affect choice of sequence are discussed in the list following the table.

Konwersje uproszczoneTrivial Conversions

Konwertuj z typuConvert from Type Konwertuj na typConvert to Type
Nazwa typutype-name Nazwa typu***&*type-name &
Nazwa typu***&*type-name & Nazwa typutype-name
Nazwa typu []type-name [ ] Nazwa typu*type-name *
type-name ( Lista argumentów )type-name ( argument-list ) ( * Nazwa typu ) ( Lista argumentów )( * type-name ) ( argument-list )
Nazwa typutype-name *const***Nazwa typuconst type-name
Nazwa typutype-name *volatile***Nazwa typuvolatile type-name
Nazwa typu*type-name * *const***Nazwa typu*const type-name *
Nazwa typu*type-name * *volatile***Nazwa typu*volatile type-name *

Sekwencja, w której są podejmowane próby konwersji, jest następująca:The sequence in which conversions are attempted is as follows:

  1. Dokładne dopasowanie.Exact match. Dokładne dopasowanie między typami, z których wywoływana jest funkcja, a typy zadeklarowane w prototypie funkcji są zawsze najlepszym dopasowaniem.An exact match between the types with which the function is called and the types declared in the function prototype is always the best match. Sekwencje uproszczonych konwersji są klasyfikowane jako dokładne dopasowania.Sequences of trivial conversions are classified as exact matches. Jednak sekwencje, które nie tworzą żadnej z tych konwersji, są uznawane za lepsze niż sekwencje, które konwertują:However, sequences that don't make any of these conversions are considered better than sequences that convert:

    • Ze wskaźnika do wskaźnika do const ( type * do const type * ).From pointer, to pointer to const (type * to const type *).

    • Ze wskaźnika do wskaźnika do volatile ( type * do volatile type * ).From pointer, to pointer to volatile (type * to volatile type *).

    • Z odwołania, do odwołania do const ( type & do const type & ).From reference, to reference to const (type & to const type &).

    • Z odwołania, do odwołania do volatile ( type & do volatile type & ).From reference, to reference to volatile (type & to volatile type &).

  2. Dopasowuje się do korzystania z promocji.Match using promotions. Każda sekwencja nie została sklasyfikowana jako dokładne dopasowanie, która zawiera tylko promocje integralne, konwersje z float do double i uproszczonej konwersji jest klasyfikowane jako dopasowanie przy użyciu promocji.Any sequence not classified as an exact match that contains only integral promotions, conversions from float to double, and trivial conversions is classified as a match using promotions. Chociaż nie jest to dobre dopasowanie jako dokładne dopasowanie, dopasowanie przy użyciu promocji jest lepszym rozwiązaniem niż dopasowanie przy użyciu konwersji standardowych.Although not as good a match as any exact match, a match using promotions is better than a match using standard conversions.

  3. Dopasowanie przy użyciu konwersji standardowych.Match using standard conversions. Dowolna sekwencja nie została sklasyfikowana jako dokładne dopasowanie ani dopasowanie przy użyciu promocji, które zawierają tylko Konwersje standardowe i konwersje uproszczone są klasyfikowane jako dopasowanie przy użyciu konwersji standardowych.Any sequence not classified as an exact match or a match using promotions that contains only standard conversions and trivial conversions is classified as a match using standard conversions. W tej kategorii są stosowane następujące reguły:Within this category, the following rules are applied:

    • Konwersja ze wskaźnika na klasę pochodną do wskaźnika do bezpośredniej lub pośredniej klasy podstawowej jest preferowany do konwersji na void * lub const void * .Conversion from a pointer to a derived class, to a pointer to a direct or indirect base class is preferable to converting to void * or const void *.

    • Konwersja ze wskaźnika do klasy pochodnej na wskaźnik do klasy bazowej daje lepszy dopasowanie do klasy bazowej do bezpośredniej klasy podstawowej.Conversion from a pointer to a derived class, to a pointer to a base class produces a better match the closer the base class is to a direct base class. Załóżmy, że hierarchia klas jest pokazana na poniższej ilustracji.Suppose the class hierarchy is as shown in the following figure.

Wykres preferowanych konwersjiGraph of preferred conversions
Wykres przedstawiający preferowane konwersjeGraph showing preferred conversions

Konwersja z typu D* do typu C* jest preferowana do konwersji z typu D* na typ B* .Conversion from type D* to type C* is preferable to conversion from type D* to type B*. Podobnie konwersja z typu D* do typu B* jest preferowana do konwersji z typu D* na typ A* .Similarly, conversion from type D* to type B* is preferable to conversion from type D* to type A*.

Ta sama reguła ma zastosowanie do konwersji odwołań.This same rule applies to reference conversions. Konwersja z typu D& do typu C& jest preferowana do konwersji z typu D& na typ B& i tak dalej.Conversion from type D& to type C& is preferable to conversion from type D& to type B&, and so on.

Ta sama reguła ma zastosowanie do konwersji wskaźnika do elementu członkowskiego.This same rule applies to pointer-to-member conversions. Konwersja z typu T D::* do typu T C::* jest preferowana do konwersji z typu T D::* na typ T B::* i tak dalej (gdzie T jest typem elementu członkowskiego).Conversion from type T D::* to type T C::* is preferable to conversion from type T D::* to type T B::*, and so on (where T is the type of the member).

Poprzednia reguła ma zastosowanie tylko do danej ścieżki pochodnej.The preceding rule applies only along a given path of derivation. Rozważmy wykres przedstawiony na poniższej ilustracji.Consider the graph shown in the following figure.

Wielokrotne dziedziczenie-, które pokazuje preferowane konwersjeMultiple-inheritance that shows preferred conversions
Wykres wielokrotnego dziedziczenia, który pokazuje preferowane konwersjeMultiple-inheritance graph that shows preferred conversions

Konwersja z typu C* do typu B* jest preferowana do konwersji z typu C* na typ A* .Conversion from type C* to type B* is preferable to conversion from type C* to type A*. Powodem jest to, że znajdują się one w tej samej ścieżce i B* są bliższe.The reason is that they are on the same path, and B* is closer. Jednak konwersja z typu C* do typu D* nie jest preferowana do konwersji na typ A* ; nie ma preferencji, ponieważ konwersje są zgodne z różnymi ścieżkami.However, conversion from type C* to type D* isn't preferable to conversion to type A*; there's no preference because the conversions follow different paths.

  1. Dopasowuje się do konwersji zdefiniowanych przez użytkownika.Match with user-defined conversions. Tej sekwencji nie można zaklasyfikować jako dokładnego dopasowania, dopasowania przy użyciu promocji lub dopasowania przy użyciu konwersji standardowych.This sequence can't be classified as an exact match, a match using promotions, or a match using standard conversions. Sekwencja musi zawierać tylko konwersje zdefiniowane przez użytkownika, Konwersje standardowe lub konwersje proste, które mają być sklasyfikowane jako zgodne z konwersjemi zdefiniowanymi przez użytkownika.The sequence must contain only user-defined conversions, standard conversions, or trivial conversions to be classified as a match with user-defined conversions. Dopasowanie z konwersjemi zdefiniowanymi przez użytkownika jest uznawane za lepsze niż dopasowanie z wielokropkiem, ale nie jako zgodne ze standardowymi konwersjemi.A match with user-defined conversions is considered a better match than a match with an ellipsis but not as good a match as a match with standard conversions.

  2. Dopasowuje się do wielokropka.Match with an ellipsis. Wszelkie sekwencje pasujące do wielokropka w deklaracji są klasyfikowane jako zgodne z wielokropkiem.Any sequence that matches an ellipsis in the declaration is classified as a match with an ellipsis. Jest on traktowany jak najsłabsze dopasowanie.It's considered the weakest match.

Konwersje zdefiniowane przez użytkownika są stosowane w przypadku braku wbudowanej promocji lub konwersji.User-defined conversions are applied if no built-in promotion or conversion exists. Te konwersje są wybierane na podstawie typu pasującego argumentu.These conversions are selected on the basis of the type of the argument being matched. Spójrzmy na poniższy kod:Consider the following code:

// argument_matching1.cpp
class UDC
{
public:
   operator int()
   {
      return 0;
   }
   operator long();
};

void Print( int i )
{
};

UDC udc;

int main()
{
   Print( udc );
}

Dostępne konwersje zdefiniowane przez użytkownika dla klasy UDC pochodzą z typu int i typu long .The available user-defined conversions for class UDC are from type int and type long. W związku z tym kompilator rozważa konwersje dla typu pasującego obiektu: UDC .Therefore, the compiler considers conversions for the type of the object being matched: UDC. Konwersja na int istniejącą i została wybrana.A conversion to int exists, and it is selected.

Podczas procesu dopasowywania argumentów Konwersje standardowe mogą być stosowane do argumentu i wyniku konwersji zdefiniowanej przez użytkownika.During the process of matching arguments, standard conversions can be applied to both the argument and the result of a user-defined conversion. W związku z tym Poniższy kod działa:Therefore, the following code works:

void LogToFile( long l );
...
UDC udc;
LogToFile( udc );

W poprzednim przykładzie konwersja zdefiniowana przez użytkownika, operator Long, jest wywoływana do konwersji udc na typ long .In the preceding example, the user-defined conversion, operator long, is invoked to convert udc to type long. Jeśli nie zdefiniowano żadnej konwersji zdefiniowanej przez użytkownika long , konwersja będzie przebiegać w następujący sposób: typ UDC zostałby przekonwertowany na typ int przy użyciu konwersji zdefiniowanej przez użytkownika.If no user-defined conversion to type long had been defined, the conversion would have proceeded as follows: Type UDC would have been converted to type int using the user-defined conversion. Następnie konwersja standardowa z typu int na typ long zostałaby zastosowana w celu dopasowania do argumentu w deklaracji.Then the standard conversion from type int to type long would have been applied to match the argument in the declaration.

Jeśli wszystkie konwersje zdefiniowane przez użytkownika są wymagane do dopasowania argumentu, standardowe konwersje nie są używane podczas oceny najlepszego dopasowania.If any user-defined conversions are required to match an argument, the standard conversions aren't used when evaluating the best match. Nawet jeśli więcej niż jedna funkcja kandydująca wymaga konwersji zdefiniowanej przez użytkownika, funkcje są uważane za równe.Even if more than one candidate function requires a user-defined conversion, the functions are considered equal. Na przykład:For example:

// argument_matching2.cpp
// C2668 expected
class UDC1
{
public:
   UDC1( int );  // User-defined conversion from int.
};

class UDC2
{
public:
   UDC2( long ); // User-defined conversion from long.
};

void Func( UDC1 );
void Func( UDC2 );

int main()
{
   Func( 1 );
}

Obie wersje Func wymagają konwersji zdefiniowanej przez użytkownika na konwersję typu int do argumentu typu klasy.Both versions of Func require a user-defined conversion to convert type int to the class type argument. Możliwe konwersje to:The possible conversions are:

  • Konwertuj z typu int na typ UDC1 (konwersja zdefiniowana przez użytkownika).Convert from type int to type UDC1 (a user-defined conversion).

  • Konwertuj typ int na typ long , a następnie przekonwertuj na typ UDC2 (konwersja dwuetapowa).Convert from type int to type long; then convert to type UDC2 (a two-step conversion).

Mimo że druga z nich wymaga konwersji standardowej i konwersji zdefiniowanej przez użytkownika, dwie konwersje są nadal uważane za równe.Even though the second one requires both a standard conversion and the user-defined conversion, the two conversions are still considered equal.

Uwaga

Konwersje zdefiniowane przez użytkownika są uznawane za konwersję lub konwersję przez inicjalizację (funkcję konwersji).User-defined conversions are considered conversion by construction or conversion by initialization (conversion function). Obie metody są uważane za równe przy uwzględnieniu najlepszego dopasowania.Both methods are considered equal when considering the best match.

Dopasowanie argumentów i ten wskaźnikArgument matching and the this pointer

Funkcje składowe klasy są traktowane inaczej, w zależności od tego, czy są one zadeklarowane jako static .Class member functions are treated differently, depending on whether they are declared as static. Ponieważ niestatyczne funkcje mają niejawny argument, który dostarcza this wskaźnik, niestatyczne funkcje są uważane za mające jeden argument niż funkcje statyczne; w przeciwnym razie są one deklarowane identycznie.Because nonstatic functions have an implicit argument that supplies the this pointer, nonstatic functions are considered to have one more argument than static functions; otherwise, they are declared identically.

Te niestatyczne funkcje Członkowskie wymagają, aby wskaźnik implikowany this pasował do typu obiektu, za pomocą którego wywoływana jest funkcja, lub dla przeciążonych operatorów, wymagają, aby pierwszy argument był zgodny z obiektem, na którym jest stosowany operator.These nonstatic member functions require that the implied this pointer match the object type through which the function is being called, or, for overloaded operators, they require that the first argument match the object on which the operator is being applied. (Aby uzyskać więcej informacji na temat przeciążonych operatorów, zobacz przeciążone operatory).(For more information about overloaded operators, see Overloaded Operators.)

W przeciwieństwie do innych argumentów w przeciążonych funkcjach, nie są wprowadzane żadne obiekty tymczasowe i nie podjęto próby przeprowadzenia konwersji przy próbie dopasowania this argumentu wskaźnika.Unlike other arguments in overloaded functions, no temporary objects are introduced and no conversions are attempted when trying to match the this pointer argument.

Gdy -> operator wyboru elementu członkowskiego jest używany w celu uzyskania dostępu do funkcji składowej klasy class_name , this argument wskaźnika ma typ class_name * const .When the -> member-selection operator is used to access a member function of class class_name, the this pointer argument has a type of class_name * const. Jeśli składowe są zadeklarowane jako const lub volatile , typy są const class_name * const i volatile class_name * const , odpowiednio.If the members are declared as const or volatile, the types are const class_name * const and volatile class_name * const, respectively.

.Operator wyboru elementu członkowskiego działa dokładnie tak samo, z tą różnicą, że niejawny & operator (Address-of) jest poprzedzony nazwą obiektu.The . member-selection operator works exactly the same way, except that an implicit & (address-of) operator is prefixed to the object name. Poniższy przykład pokazuje, jak to działa:The following example shows how this works:

// Expression encountered in code
obj.name

// How the compiler treats it
(&obj)->name

Lewy operand ->* .* operatorów i (wskaźnik do składowej) jest traktowany tak samo jak . -> Operatory i (wybór elementów członkowskich) w odniesieniu do dopasowywania argumentów.The left operand of the ->* and .* (pointer to member) operators are treated the same way as the . and -> (member-selection) operators with respect to argument matching.

Kwalifikatory ref w funkcjach składowychRef-qualifiers on member functions

Kwalifikatory ref umożliwiają przeciążanie funkcji składowej w oparciu o to, czy obiekt wskazywany przez this jest elementem rvalue czy lvalue.Ref qualifiers make it possible to overload a member function on the basis of whether the object pointed to by this is an rvalue or an lvalue. Ta funkcja umożliwia uniknięcie niepotrzebnych operacji kopiowania w scenariuszach, w których nie można zapewnić dostępu do danych za pomocą wskaźnika.This feature can be used to avoid unnecessary copy operations in scenarios where you choose not to provide pointer access to the data. Załóżmy na przykład, że Klasa C inicjuje pewne dane w konstruktorze i zwraca kopię tych danych w funkcji członkowskiej get_data() .For example, assume class C initializes some data in its constructor, and returns a copy of that data in member function get_data(). Jeśli obiekt typu C jest rvalue, który ma zostać zniszczony, kompilator wybierze get_data() && Przeciążenie, które przenosi dane zamiast kopiować.If an object of type C is an rvalue that is about to be destroyed, then the compiler will choose the get_data() && overload, which moves the data rather than copy it.

#include <iostream>
#include <vector>

using namespace std;

class C
{

public:
    C() {/*expensive initialization*/}
    vector<unsigned> get_data() &
    {
        cout << "lvalue\n";
        return _data;
    }
    vector<unsigned> get_data() &&
    {
        cout << "rvalue\n";
        return std::move(_data);
    }

private:
    vector<unsigned> _data;
};

int main()
{
    C c;
    auto v = c.get_data(); // get a copy. prints "lvalue".
    auto v2 = C().get_data(); // get the original. prints "rvalue"
    return 0;
}

Ograniczenia dotyczące przeciążaniaRestrictions on overloading

Niektóre ograniczenia podlegają akceptowalnemu zestawowi przeciążonych funkcji:Several restrictions govern an acceptable set of overloaded functions:

  • Wszystkie dwie funkcje w zestawie przeciążonych funkcji muszą mieć różne listy argumentów.Any two functions in a set of overloaded functions must have different argument lists.

  • Przeciążanie funkcji z listami argumentów tego samego typu, na podstawie samego typu zwracanego, jest błędem.Overloading functions with argument lists of the same types, based on return type alone, is an error.

    Specyficzne dla firmy MicrosoftMicrosoft Specific

Można przeciążać operator new wyłącznie na podstawie typu zwracanego — w odniesieniu do określonego modyfikatora pamięci.You can overload operator new solely on the basis of return type — specifically, on the basis of the memory-model modifier specified.

ZAKOŃCZENIE określonych przez firmę MicrosoftEND Microsoft Specific

  • Funkcje składowe nie mogą być przeciążone wyłącznie na podstawie jednego statycznego i innego niestatycznego.Member functions can't be overloaded solely on the basis of one being static and the other nonstatic.

  • typedef deklaracje nie definiują nowych typów; wprowadzają synonimy dla istniejących typów.typedef declarations do not define new types; they introduce synonyms for existing types. Nie wpływają one na mechanizm przeciążania.They don't affect the overloading mechanism. Spójrzmy na poniższy kod:Consider the following code:

    typedef char * PSTR;
    
    void Print( char *szToPrint );
    void Print( PSTR szToPrint );
    

    Poprzednie dwie funkcje mają identyczne listy argumentów.The preceding two functions have identical argument lists. PSTR jest synonimem typu char * .PSTR is a synonym for type char *. W zakresie elementu członkowskiego ten kod generuje błąd.In member scope, this code generates an error.

  • Typy wyliczeniowe są różnymi typami i mogą być używane do rozróżniania między przeciążonymi funkcjami.Enumerated types are distinct types and can be used to distinguish between overloaded functions.

  • Typy "array of" i "wskaźnik do" są uważane za identyczne dla celów rozróżniania między przeciążonymi funkcjami, ale tylko dla tablic wielowymiarowych z wymiarami.The types "array of " and "pointer to" are considered identical for the purposes of distinguishing between overloaded functions, but only for singly dimensioned arrays. Dlatego te przeciążone funkcje powodują konflikt i generują komunikat o błędzie:That's why these overloaded functions conflict and generate an error message:

    void Print( char *szToPrint );
    void Print( char szToPrint[] );
    

    W przypadku mnożonych tablic wymiarowych drugi i wszystkie pomyślne wymiary są uważane za część typu.For multiply dimensioned arrays, the second and all succeeding dimensions are considered part of the type. W związku z tym są używane w odróżnieniu od przeciążonych funkcji:Therefore, they are used in distinguishing between overloaded functions:

    void Print( char szToPrint[] );
    void Print( char szToPrint[][7] );
    void Print( char szToPrint[][9][42] );
    

Przeciążanie, zastępowanie i ukrywanieOverloading, overriding, and hiding

Wszelkie dwie deklaracje funkcji o tej samej nazwie w tym samym zakresie, mogą odwoływać się do tej samej funkcji lub do dwóch funkcji dyskretnych, które są przeciążone.Any two function declarations of the same name in the same scope can refer to the same function, or to two discrete functions that are overloaded. Jeśli wykazy argumentów deklaracji zawierają równoważne typy argumentów (zgodnie z opisem w poprzedniej sekcji), deklaracje funkcji odnoszą się do tej samej funkcji.If the argument lists of the declarations contain arguments of equivalent types (as described in the previous section), the function declarations refer to the same function. W przeciwnym razie, odnoszą się do dwóch różnych funkcji, które są wybrane za pomocą przeciążenia.Otherwise, they refer to two different functions that are selected using overloading.

Zakres klasy jest ściśle przestrzegany; w związku z tym, Funkcja zadeklarowana w klasie bazowej nie jest w tym samym zakresie co funkcja zadeklarowana w klasie pochodnej.Class scope is strictly observed; therefore, a function declared in a base class isn't in the same scope as a function declared in a derived class. Jeśli funkcja klasy pochodnej jest zadeklarowana z tą samą nazwą jak funkcja wirtualna w klasie bazowej, funkcja klasy pochodnej zastępuje funkcję klasy podstawowej.If a function in a derived class is declared with the same name as a virtual function in the base class, the derived-class function overrides the base-class function. Aby uzyskać więcej informacji, zobacz funkcje wirtualne.For more information, see Virtual Functions.

Jeśli funkcja klasy bazowej nie jest zadeklarowana jako "Virtual", funkcja klasy pochodnej jest określana do ukrycia .If the base class function isn't declared as 'virtual', then the derived class function is said to hide it. Zastępowanie i ukrywanie różnią się od przeciążenia.Both overriding and hiding are distinct from overloading.

Zakres bloku jest ściśle przestrzegany; w związku z tym, Funkcja zadeklarowana w zakresie pliku nie jest w tym samym zakresie co funkcja zadeklarowana lokalnie.Block scope is strictly observed; therefore, a function declared in file scope isn't in the same scope as a function declared locally. Jeśli funkcja zadeklarowana lokalnie ma taką samą nazwę, co funkcja zadeklarowana w zakresie pliku, funkcja zadeklarowana lokalnie ukrywa funkcje należącą do zakresu pliku, zamiast powodować przeciążenie.If a locally declared function has the same name as a function declared in file scope, the locally declared function hides the file-scoped function instead of causing overloading. Na przykład:For example:

// declaration_matching1.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;
void func( int i )
{
    cout << "Called file-scoped func : " << i << endl;
}

void func( char *sz )
{
   cout << "Called locally declared func : " << sz << endl;
}

int main()
{
   // Declare func local to main.
   extern void func( char *sz );

   func( 3 );   // C2664 Error. func( int ) is hidden.
   func( "s" );
}

Poprzedni kod pokazuje dwie definicje funkcji func.The preceding code shows two definitions from the function func. Definicja, która przyjmuje argument typu, char * jest lokalna dla main z powodu extern instrukcji.The definition that takes an argument of type char * is local to main because of the extern statement. W związku z tym definicja, która przyjmuje argument typu int , jest ukryta i pierwsze wywołanie func jest w błąd.Therefore, the definition that takes an argument of type int is hidden, and the first call to func is in error.

Dla przeciążonych funkcji członkowskich, różne wersje funkcji mogą mieć różne przywileje dostępu.For overloaded member functions, different versions of the function can be given different access privileges. Ale nadal uważa się, że znajdują się w zakresie otaczającym klasę, a więc są funkcjami przeciążonymi.They are still considered to be in the scope of the enclosing class and thus are overloaded functions. Rozważmy poniższy kod, w którym funkcja członkowska Deposit jest przeciążona; jedna wersja jest publiczna, inne są prywatne.Consider the following code, in which the member function Deposit is overloaded; one version is public, the other, private.

Zamiarem tego przykładu jest dostarczenie klasy Account, w której wymagane jest poprawne hasło, aby wykonać depozyty.The intent of this sample is to provide an Account class in which a correct password is required to perform deposits. Jest to wykonywane przy użyciu przeciążenia.It's done by using overloading.

Wywołanie Deposit w programie Account::Deposit wywołuje prywatną funkcję członkowską.The call to Deposit in Account::Deposit calls the private member function. To wywołanie jest poprawne Account::Deposit , ponieważ jest funkcją członkowską i ma dostęp do prywatnych składowych klasy.This call is correct because Account::Deposit is a member function, and has access to the private members of the class.

// declaration_matching2.cpp
class Account
{
public:
   Account()
   {
   }
   double Deposit( double dAmount, char *szPassword );

private:
   double Deposit( double dAmount )
   {
      return 0.0;
   }
   int Validate( char *szPassword )
   {
      return 0;
   }

};

int main()
{
    // Allocate a new object of type Account.
    Account *pAcct = new Account;

    // Deposit $57.22. Error: calls a private function.
    // pAcct->Deposit( 57.22 );

    // Deposit $57.22 and supply a password. OK: calls a
    //  public function.
    pAcct->Deposit( 52.77, "pswd" );
}

double Account::Deposit( double dAmount, char *szPassword )
{
   if ( Validate( szPassword ) )
      return Deposit( dAmount );
   else
      return 0.0;
}

Zobacz teżSee also

Funkcje (C++)Functions (C++)