Funksiya həddindən artıq yüklənməsi. Daxili (daxili) funksiyalar. Həddindən artıq yükləmə lazım olduqda funksiyanın həddindən artıq yüklənməsi

C++ sizə birdən çox tərif təyin etməyə imkan verir funksiyaları adı və ya operator adlı eyni ərazidə həddindən artıq yükləmə funksiyasıoperatorun həddindən artıq yüklənməsi müvafiq olaraq.

Həddindən artıq yüklənmiş bəyannamə, hər iki bəyannamənin fərqli arqumentləri və açıq-aydın fərqli tərifi (tətbiqi) olması istisna olmaqla, eyni miqyasda əvvəl elan edilmiş bəyannamə ilə eyni adla elan edilmiş bəyannamədir.

Aşırı yük çağırdığınız zaman funksiyası və ya operator, kompilyator funksiya və ya operatoru çağırmaq üçün istifadə etdiyiniz arqumentlərin növlərini təriflərdə göstərilən parametrlərin növləri ilə müqayisə edərək istifadə etmək üçün ən uyğun tərifi müəyyən edir. Ən uyğun həddən artıq yüklənmiş funksiya və ya operatorun seçilməsi prosesi adlanır həddindən artıq yükləmə həlli .

C++-da funksiyaların həddən artıq yüklənməsi

Eyni əhatə dairəsində eyni funksiya adı üçün bir neçə tərifiniz ola bilər. Funksiya tərifi arqumentlər siyahısındakı arqumentlərin növlərinə və/yaxud sayına görə bir-birindən fərqlənməlidir. Siz yalnız qaytarma növü ilə fərqlənən funksiya bəyannamələrini həddən artıq yükləyə bilməzsiniz.

Aşağıda eyni funksiyanın olduğu bir nümunə verilmişdir çap () müxtəlif növ məlumatların çapı üçün istifadə olunur -

#daxildir ad sahəsi std istifadə edərək; class printData ( ictimai: void print(int i) ( cout<< "Printing int: " << i << endl; } void print(double f) { cout << "Printing float: " << f << endl; } void print(char* c) { cout << "Printing character: " << c << endl; } }; int main(void) { printData pd; // Call print to print integer pd.print(5); // Call print to print float pd.print(500.263); // Call print to print character pd.print("Hello C++"); return 0; }

Printing int: 5 Printing float: 500.263 Çap xarakteri: Hello C++

C++ dilində operatorun həddən artıq yüklənməsi

Siz C++-da mövcud olan daxili operatorların əksəriyyətini ləğv edə və ya həddindən artıq yükləyə bilərsiniz. Bu şəkildə proqramçı istifadəçi tərəfindən müəyyən edilmiş növlərə malik operatorlardan da istifadə edə bilər.

Həddindən artıq yüklənmiş operatorlar xüsusi adları olan funksiyalardır: “operator” açar sözü və ardınca müəyyən edilən operatorun simvolu. Hər hansı digər funksiya kimi, həddən artıq yüklənmiş operatorun qaytarma növü və parametrlər siyahısı var.

Qutu operatoru+(const Box&);

üçün istifadə edilə bilən əlavə operatorunu elan edir əlavələr iki Box obyekti və son Box obyektini qaytarır. Həddindən artıq yüklənmiş operatorların əksəriyyəti müntəzəm üzv olmayan funksiyalar və ya sinif üzvü funksiyaları kimi müəyyən edilə bilər. Yuxarıdakı funksiyanı qeyri-sinif üzv funksiyası kimi təyin etsək, hər bir operand üçün aşağıdakı kimi iki arqument ötürməli olacağıq:

Qutu operatoru+(const Box&, const Box&);

Aşağıda üzv funksiyasından istifadə edərək yüklənərkən operator anlayışını göstərən bir nümunə verilmişdir. Burada obyekt arqument kimi ötürülür, onun xassələrinə bu obyektdən istifadə etməklə daxil olmaq olar, bu operatoru çağıracaq obyektə isə istifadə etməklə daxil olmaq olar. bu operator aşağıda göstərildiyi kimi -

#daxildir ad sahəsi std istifadə edərək; sinif Qutu ( ictimai: double getVolume(void) ( qaytarılma uzunluğu * en * hündürlük; ) void setLength(double len) ( length = len; ) void setBreadth(double bre) ( en = bre; ) void setHeight(double hei) ( hündürlük = hei; ) // İki Qutu obyekti əlavə etmək üçün Overload + operatoru Box operator+(const Box& b) ( Box box; box.length = this->length + b.length; box.breadth = this->example + b. .breadth; box.height = this->height + b.height: double length; // Proqram üçün əsas funksiya int main() ( Box Box1; // Box Box Box2 tipli Qutunu1 elan et; // Box Box Box3 tipli Qutunu2 elan et; // Box double volume = 0.0 tipli Qutunu3 elan et; // Saxla qutunun həcmi burada // box1.setLength(6.0); // box2.setLength(10.0); 1 cild = Box1.getVolume();<< "Volume of Box1: " << volume <

Yuxarıdakı kod tərtib edildikdə və icra edildikdə, aşağıdakı çıxışı verir:

Qutu 1: 210 Qutu 2: 1560 Qutu 3: 5400

Həddindən artıq yüklənə bilən / həddindən artıq yüklənə bilməyən operatorlar

Aşağıda həddindən artıq yüklənə bilən operatorların siyahısı verilmişdir.



C-də funksiyaların həddən artıq yüklənməsinə necə nail olmaq olar? (10)

C-də funksiyaların həddən artıq yüklənməsinə nail olmaq üçün bir yol varmı? kimi həddən artıq yüklənə bilən sadə funksiyalara baxıram

Foo (int a) foo (char b) foo (float c , int d)

Məncə, birbaşa yol yoxdur; Əgər onlar varsa, həll yollarını axtarıram.

Ümid edirəm ki, aşağıdakı kod funksiyaların həddən artıq yüklənməsini başa düşməyə kömək edəcək

#daxildir #daxildir int fun (int a, ...); int main(int argc, char *argv)( fun(1,10); fun(2,"cquestionbank"); return 0; ) int fun(int a, ...)( va_list vl; va_start(vl,a) if(a==1) printf("%d",va_arg(vl,int)); else printf("\n%s",va_arg(vl,char *));

Nə demək istəyirsən - yox, edə bilməzsən.

Siz va_arg funksiyasını elan edə bilərsiniz

void my_func(char* formatı, ...);

Ancaq birinci arqumentdə dəyişənlərin sayı və onların növləri haqqında bəzi məlumatları ötürməli olacaqsınız - məsələn, printf() .

Bəli, bir növ.

Burada bir nümunə verirsiniz:

Ləğv printA(int a)( printf("ÇapA-dan salam dünya: %d\n",a); ) void printB(const char *buff)( printf("printB-dən salam dünya: %s\n",buff) ; ) #define Max_ITEMS() 6, 5, 4, 3, 2, 1, 0 #define __VA_ARG_N(_1, _2, _3, _4, _5, _6, N, ...) N #define _Num_ARGS_(... ) __VA_ARG_N(__VA_ARGS__) #müəyyən edin NUM_ARGS(...) (_Num_ARGS_(_0, ## __VA_ARGS__, Max_ITEMS()) - 1) #təyin et _LIMIT(t) if(NUM_ARGS(args) #define print(x , args ...) \ CHECK_ARGS_MIN_LIMIT(1) printf("xəta");fflush(stdout); \ CHECK_ARGS_MAX_LIMIT(4) printf("xəta");fflush(stdout) ; \ (( \ if (__builtin_types_compatible_p (typeof (x), int)) \ printA(x, ##args); \ else \ printB (x,##args); \ )) int main(int argc, char* * argv) ( int a=0; çap (a); çap ("salam"); ​​qayıt (EXIT_SUCCESS); )

O, printA və printB-dən 0 və salam verəcək.

Əgər kompilyatorunuz gcc-dirsə və hər dəfə yeni həddən artıq yükləmə əlavə etdikdə əl ilə yeniləmələr etməkdən çəkinmirsinizsə, makro yarada və zəng edənlər baxımından istədiyiniz nəticəni əldə edə bilərsiniz, yazmaq o qədər də gözəl deyil... lakin bu mümkündür.

__builtin_types_compatible_p-ə baxın, sonra kimi bir şey edən makro təyin etmək üçün ondan istifadə edin

#define foo(a) \ ((__builtin_types_compatible_p(int, a)?foo(a):(__builtin_types_compatible_p(float, a)?foo(a):)

amma bəli, iyrəncdir, sadəcə deyil

DÜZENLE: C1X belə görünən tip ifadələri üçün dəstək qazanacaq:

#define cbrt(X) _Generic((X), long double: cbrtl, \ default: cbrt, \ float: cbrtf)(X)

Artıq deyildiyi kimi, nəzərdə tutduğunuz mənada həddən artıq yükləmə C tərəfindən dəstəklənmir. Problemi həll etmək üçün ümumi bir deyim funksiyanın işarələnmiş bağlayıcı qəbul etməsidir. Bu, struktur parametrindən istifadə etməklə həyata keçirilir, burada strukturun özü bir növ tip göstəricidən, məsələn, enum və müxtəlif dəyər növlərinin birləşməsindən ibarətdir. Misal:

#daxildir typedef enum ( T_INT, T_FLOAT, T_CHAR, ) my_type; typedef struct ( my_type type; union ( int a; float b; char c; ) my_union; ) my_struct; void set_overload (my_struct *nə olursa olsun) ( keçid (nə olursa olsun->növ) ( case T_INT: whatever->my_union.a = 1; break; case T_FLOAT: whatever->my_union.b = 2.0; break; case T_CHAR: whatever-> my_union.c = "3"); : printf("%f\n", whatever->my_union.b break; printf("%c\n", whatever->my_union.c ) ) int main (int argc, char* argv) ( my_struct s; s.type=T_INT; set_overload(&s); printf_overload(&s); s.type=T_FLOAT; set_overload(&s); printf_overload(&s); s.type=T_CHAR; set_overload(&s) ; printf_overload(&s) )

Siz sadəcə C++-dan istifadə edib, bundan başqa C++-ın bütün digər xüsusiyyətlərindən istifadə edə bilməzsiniz?

Hələ ciddi C yoxdursa, əvəzinə variadik funksiyaları tövsiyə edərdim.

Aşağıdakı yanaşma buna bənzəyir a2800276, lakin bəzi C99 makro makroları ilə:

// bizə `size_t` #include lazımdır // sum_arg_types nömrələrini qəbul etmək üçün arqument növləri ( SUM_LONG, SUM_ULONG, SUM_DOUBLE ); // arqumenti saxlamaq üçün struktur struct sum_arg ( enum sum_arg_types type; union ( long as long; unsigned long as_ulong; double as_double; ) dəyər; ); // massivin ölçüsünü təyin edin #define count(ARRAY) ((sizeof (ARRAY))/(sizeof *(ARRAY))) // funksiyamız belə adlandırılacaq #define sum(...) _sum( count(sum_args(__VA_ARGS__)), sum_args(__VA_ARGS__)) // `struct sum_arg` massivi yaradın #define sum_args(...) ((struct sum_arg )( __VA_ARGS__ )) //initializatorları yaradın (VALUE) ( SUM_LONG, ( .as_long = (VALUE) ) ) #sum_ulong(VALUE) müəyyən edin ( SUM_ULONG, ( .as_ulong = (VALUE) ) ) #sum_double(VALUE) ( SUM_DOUBLE, ( .as_VALUE) ) // bizim polimorfik funksiyamız long double _sum(size_t count, struct sum_arg * args) ( long double value = 0; for(size_t i = 0; i)< count; ++i) { switch(args[i].type) { case SUM_LONG: value += args[i].value.as_long; break; case SUM_ULONG: value += args[i].value.as_ulong; break; case SUM_DOUBLE: value += args[i].value.as_double; break; } } return value; } // let"s see if it works #include int main() ( imzasız uzun foo = -1; uzun ikiqat dəyər = cəmi(sum_uzun(42), sum_ulong(foo), sum_double(1e10)); printf("%Le\n", dəyər); qaytar 0; )

Hələlik, _Generic _Generic bu sual, standart C (uzatmalar yoxdur) effektivdir aldı C11-də _Generic sözünün əlavə edilməsi sayəsində funksiyanın (operatordan çox) həddən artıq yüklənməsinə dəstək. (4.9 versiyasından bəri GCC-də dəstəklənir)

(Həddindən artıq yükləmə sualda göstərildiyi kimi həqiqətən "daxili" deyil, lakin bu şəkildə işləyən bir şeyi məhv etmək asandır.)

Generic sizeof və _Alignof ilə eyni ailədə olan kompilyasiya vaxtı operatorudur. Bu standart bölmə 6.5.1.1-də təsvir edilmişdir. Bu, iki əsas parametr tələb edir: ifadə (iş zamanı qiymətləndirilməyəcək) və bir az keçid blokuna bənzəyən tip/ifadə assosiasiyalarının siyahısı. _Generic ümumi ifadə növünü alır və sonra onun növü üçün siyahıdan yekun nəticə ifadəsini seçmək üçün ona "keçir":

Ümumi(1, float: 2.0, char *: "2", int: 2, default: get_two_object());

Yuxarıdakı ifadə 2-nəzarət ifadə növünə görə qiymətləndirilir - int , buna görə də dəyər kimi int ilə əlaqəli ifadəni seçir. Bunların heç biri icra zamanı saxlanılmır. (Defolt müddəa tələb olunur: onu qeyd etməsəniz və tip uyğun gəlmirsə, bu, tərtib xətasına səbəb olacaq.)

Funksiyaların həddən artıq yüklənməsi üçün faydalı olan üsul ondan ibarətdir ki, o, C preprosessoru tərəfindən daxil edilə və nəzarət makrosuna ötürülən arqumentlərin növü əsasında nəticə ifadəsini seçə bilər. Beləliklə (C standartından nümunə):

#define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \ float: cbrtf \)(X)

Bu makro arqument tipini makroya ötürməklə, müvafiq icra funksiyasını seçməklə və sonra orijinal makronu həmin funksiyaya ötürməklə həddən artıq yüklənmiş cbrt əməliyyatını həyata keçirir.

Beləliklə, orijinal nümunənizi həyata keçirmək üçün bunu edə bilərik:

Foo_int (int a) foo_char (char b) foo_float_int (float c , int d) #define foo(_1, ...) _Generic((_1), \ int: foo_int, \ char: foo_char, \ float: _Generic(( FIRST(__VA_ARGS__,)), \ int: foo_float_int))(_1, __VA_ARGS__) #FIRST(A, ...) A təyin edin

Bu halda, biz üçüncü hal üçün defoltdan istifadə edə bilərik: assosiasiya, lakin bu, prinsipi çoxsaylı arqumentlərə necə genişləndirməyi nümayiş etdirmir. Nəticə odur ki, arqumentlərinizin növündən (çox) narahat olmadan kodunuzda foo(...) istifadə edə bilərsiniz.

Daha çox arqumentləri həddən artıq yükləyən və ya rəqəmləri dəyişən funksiyalar kimi daha mürəkkəb vəziyyətlər üçün siz avtomatik olaraq statik göndərmə strukturlarını yaratmaq üçün kommunal makrolardan istifadə edə bilərsiniz:

Void print_ii(int a, int b) ( printf("int, int\n"); ) void print_di(double a, int b) ( printf("double, int\n"); ) void print_iii(int a, int b, int c) ( printf("int, int, int\n"); ) void print_default(void) ( printf("naməlum arqumentlər\n"); ) #define print(...) HƏR YÜKLƏMƏ(çap, (__VA_ARGS__), \ (print_ii, (int, int)), \ (print_di, (double, int)), \ (print_iii, (int, int, int)) \) #HƏZƏR YÜKLƏNMİŞ_ARG_TYPES (int, double) #müəyyən et HƏDDİ YÜKLƏMƏ_FUNCTIONS (çap) #include "activate-overloads.h" int main(void) ( print(44, 47); // "int, int" print(4.4, 47); // "double, int" çapını çap edir (1, 2, 3); // "int, int, int" print(""); // "naməlum arqumentləri" çap edir)

(burada həyata keçirilir). Bir az səy göstərərək, daxili həddən artıq yükləmə dəstəyi olan bir dilə kifayət qədər oxşar görünmək üçün şablonların sayını azalda bilərsiniz.

Yan tərəfə artıq yükləmək mümkün idi kəmiyyət C99-da arqumentlər (növ deyil).

Nəzərə alın ki, C-nin qiymətləndirilməsi sizə təsir edə bilər. Bu, məsələn, ona hərfi xarakter ötürməyə çalışsanız, foo_int seçəcək və həddən artıq yükləmələrinizin sətir literallarını dəstəkləməsini istəyirsinizsə, sizə bir az foo_int lazımdır. Bununla belə, ümumilikdə olduqca sərindir.

Leuşenkonun cavabı həqiqətən də gözəldir: yalnız foo nümunəsi GCC ilə tərtib edilmir, o, foo(7) ilə uğursuz olur, İLK makro və faktiki funksiya çağırışı ((_1, __VA_ARGS__) vuraraq əlavə vergüllə ayrılır. Həmçinin, biz foo(double) kimi əlavə yüklənmələr təmin etmək istəsək, problemlərlə üzləşirik.

Beləliklə, mən bu suala daha ətraflı cavab vermək qərarına gəldim, o cümlədən boş yüklənməyə icazə vermək (foo(void) - bəzi problemlərə səbəb oldu ...).

İndi fikir budur: müxtəlif makrolarda birdən çox ümumi təyin edin və arqumentlərin sayına görə düzgün olanı seçilsin!

Bu cavab əsasında arqumentlərin sayı olduqca sadədir:

#define foo(...) SELECT(__VA_ARGS__)(__VA_ARGS__) #define SELECT(...) CONCAT(SELECT_, NARG(__VA_ARGS__))(__VA_ARGS__) #define CONCAT(X, Y) CONCAT_(X, Y) # CONCAT_(X, Y) X ## Y müəyyən edin

Yaxşı, biz ya SELECT_1, ya da SELECT_2 (yaxud istəsəniz/lazım olduqda daha çox arqument) üzərində qərar veririk, ona görə də bizə sadəcə müvafiq təriflər lazımdır:

#define SELECT_0() foo_void #define SELECT_1(_1) _Generic ((_1), \ int: foo_int, \ char: foo_char, \ double: foo_double \) #define SELECT_2(_1, _2) _Generic((_1), \ double : _Ümumi((_2), \ int: foo_double_int \) \)

Birincisi, boş bir makro çağırışı (foo()) hələ də bir işarə yaradır, lakin boşdur. Beləliklə, sayma makrosu, hətta makro boş adlandıqda belə, 0 əvəzinə 1 qaytarır. __VA_ARGS__-dan sonra vergül qoysaq, bu problemi "asanlıqla" həll edə bilərik. şərti olaraq, siyahının boş olub-olmamasından asılı olaraq:

#define NARG(...) ARG4_(__VA_ARGS__ VERGİL(__VA_ARGS__) 4, 3, 2, 1, 0)

Bu baxdı asan, lakin VERGİL makro olduqca ağırdır; Xoşbəxtlikdən bu mövzu artıq Jens Gustedtin bloqunda işıqlandırılıb (təşəkkürlər Jens). Əsas hiylə odur ki, mötərizələrə əməl olunmayınca funksiya makroları genişlənmir, əlavə izahat üçün Jensin bloquna baxın... Biz sadəcə olaraq makroları öz ehtiyaclarımıza görə bir az dəyişdirməliyik (qısalıq üçün daha qısa adlar və daha az arqumentlərdən istifadə edəcəyəm) ).

#define ARGN(...) ARGN_(__VA_ARGS__) #define ARGN_(_0, _1, _2, _3, N, ...) N #define HAS_COMMA(...) ARGN(__VA_ARGS__, 1, 1, 1, 0 ) #define SET_VERGS(...) , #define VERGİL(...) SELECT_COMMA(\ HAS_COMMA(__VA_ARGS__), \ HAS_COMMA(__VA_ARGS__ ()), \ HAS_COMMA(__VA_ARGS__ ()), \ HAS_COMMA (SET_COMMA __VA_ARGS__), \ HAS_COMMA (SETVA_COMMA) \) #SEÇİN_VERGİLİ (_0, _1, _2, _3) SEÇİN_VERGİLİ_(_0, _1, _2, _3) #müəyyən edin SEÇİM_VERGİL_(_0, _1, _2, _3) VERGİL_ ## _0 ## _1 ## _2 #_ COMMA_0000 müəyyən , #müəyyən COMMA_0001 #define COMMA_0010 , // ... (bütün digərləri vergüllə) #müəyyən et VERGİL_1111 ,

Və indi yaxşıyıq...

Kodu bir blokda tamamlayın:

/* * demo.c * * Yaradılma tarixi: 14-09-2017 * Müəllif: sboehler */ #include void foo_void(void) ( puts("void"); ) void foo_int(int c) ( printf("int: %d\n", c); ) void foo_char(char c) ( printf("char: %c) \n", c); ) void foo_double(double c) ( printf("double: %.2f\n", c); ) void foo_double_int(double c, int d) ( printf("double: %.2f, int: %d\n", c, d); ) #define foo(...) SELECT(__VA_ARGS__)(__VA_ARGS__) #define SELECT(...) CONCAT(SELECT_, NARG(__VA_ARGS__))(__VA_ARGS__) # CONCAT(X, Y) CONCAT_(X, Y) #define CONCAT_(X, Y) X ## Y #define SELECT_0() foo_void #define SELECT_1(_1) _Generic ((_1), \ int: foo_int, \ char : foo_char, \ double: foo_double \) #define SELECT_2(_1, _2) _Generic((_1), \ double: _Generic((_2), \ int: foo_double_int \) \) #define ARGN(...) ARGN_( __VA_ARGS__) #define ARGN_(_0, _1, _2, N, ...) N #define NARG(...) ARGN(__VA_ARGS__ VERGİL(__VA_ARGS__) 3, 2, 1, 0) #define HAS_COMMA(...) ARGN(__VA_ARGS__, 1, 1, 0) #müəyyən et SET_VERGİL(...) , #müəyyən et VERGİL(...) SELECT_VERGİL \ (\ HAS_COMMA(__VA_ARGS__), \ HAS_COMMA(__VA_ARGS__ ()), \ HAS_VA_COMMA_MAS , \ HAS_VERGİL(SET_VERGİL __VA_ARGS__ ()) \) #SEÇİN_VERGİLİ təyin edin(_0, _1, _2, _3) SEÇİN_VERGİL_(_0, _1, _2, _3) #SEÇİM_VERGİLİ_(_0, _1, _2, _3) #müəyyən edin #COMMA_(_0, _1, _2, _2) # _1 ## _2 ## _3 #müəyyən et VERGİL_0000 , #müəyyən et VERGƏ_0001 #müəyyən et VERGƏ_0010 , #VERGİL_0100 təyin et , #COMMA_0101 #COMMA10 #müəyyən et , , #müəyyən et COMMA_ 1000 , #define COMMA_1001 , #define COMMA_1010 , #define COMMA_1011 , #define COMMA_1100 , #define COMMA_1101 , #define COMMA_1110 , #define COMMA_1111 , int main(int argc, char** argv) (foo**); foo(7); foo(10.12); foo(12.10, 7); foo((char)"s"); 0 qaytarmaq; )

Proqramlarınızda funksiyaları təyin edərkən siz funksiyanın qaytardığı dəyərin növünü, həmçinin parametrlərin sayını və hər bir parametrin növünü göstərməlisiniz. Keçmişdə (Əgər C-də proqramlaşdırmısınızsa), iki tam dəyərlə işləyən əlavə_dəyərlər adlı funksiyanız olduqda və siz üç tam dəyər əlavə etmək üçün oxşar funksiyadan istifadə etmək istəsəniz, fərqli adda funksiya yaradardınız. . Məsələn, siz əlavə_iki_dəyər və əlavə_üç_dəyər istifadə edə bilərsiniz. Eynilə, əgər siz float əlavə etmək üçün oxşar funksiyadan istifadə etmək istəsəniz, başqa adla başqa funksiyaya ehtiyacınız olacaq. Funksiyaların təkrarlanmasının qarşısını almaq üçün C++ eyni adlı bir neçə funksiyanı təyin etməyə imkan verir. Kompilyasiya prosesi zamanı C++ hər bir funksiya tərəfindən istifadə olunan arqumentlərin sayını nəzərə alır və sonra tam olaraq tələb olunan funksiyanı çağırır. Kompilyatora bir neçə funksiya arasında seçim imkanı verilməsi həddən artıq yükləmə adlanır. Bu dərslikdə siz həddən artıq yüklənmiş funksiyalardan necə istifadə edəcəyinizi öyrənəcəksiniz. Bu dərsin sonunda siz aşağıdakı əsas anlayışları mənimsəmiş olacaqsınız:

Funksiyaların həddən artıq yüklənməsi sizə müxtəlif parametr növləri olan bir neçə funksiya üçün eyni addan istifadə etməyə imkan verir.

Funksiyaları həddən artıq yükləmək üçün sadəcə olaraq parametrlərin sayına və ya onların növünə görə fərqlənən eyni ad və qaytarma növü ilə iki funksiya təyin edin.

Funksiyaların həddən artıq yüklənməsi C++ dilinin C dilində tapılmayan xüsusiyyətidir. Gördüyünüz kimi, funksiyaların həddən artıq yüklənməsi kifayət qədər rahatdır və proqramlarınızın oxunuşunu yaxşılaşdıra bilər.

FUNKSİYALARIN HƏDDƏN YÜKLƏMƏYƏ İLK GİRİŞ

Funksiyaların həddən artıq yüklənməsi proqramlarınıza eyni ad və qaytarma növü ilə çoxlu funksiyaları təyin etməyə imkan verir. Məsələn, aşağıdakı proqram add_values ​​adlı funksiyanı həddən artıq yükləyir. Birinci funksiya tərifi iki int dəyəri əlavə edir. Funksiyanın ikinci tərifi üç qiymət əlavə edir. Kompilyasiya zamanı C++ istifadə ediləcək funksiyanı düzgün müəyyənləşdirir:

#daxildir

int əlavə_dəyərləri(int a,int b)

{
qayıtmaq (a + b);
)

int əlavə_dəyərləri (int a, int b, int c)

(
qayıtmaq (a + b + c);
)

{
cout<< «200 + 801 = » << add_values(200, 801) << endl;
cout<< «100 + 201 + 700 = » << add_values(100, 201, 700) << endl;
}

Gördüyünüz kimi, proqram add_values ​​adlı iki funksiya müəyyən edir, birinci funksiya iki int dəyəri əlavə edir, ikincisi isə üç dəyər əlavə edir. Kompilyatoru həddən artıq yükləmə ilə bağlı xəbərdar etmək üçün xüsusi olaraq heç bir şey etmək lazım deyil, sadəcə istifadə edin. Kompilyator proqramın təklif etdiyi parametrlərə əsasən hansı funksiyadan istifadə edəcəyini anlayacaq.

Eynilə, aşağıdakı MSG_OVR.CPP proqramı show_message funksiyasını həddən artıq yükləyir. show_message adlı birinci funksiya ona heç bir parametr ötürülməyən standart mesajı göstərir; İkincisi ona göndərilən mesajı, üçüncüsü isə iki mesajı göstərir:

#daxildir

etibarsız show_message(boşdur)

{
cout<< «Стандартное сообщение: » << «Учимся программировать на C++» << endl;
}

etibarsız show_message(char *message)

{
cout<< message << endl;
}

etibarsız show_message(char *birinci, char *ikinci)

{
cout<< first << endl;
cout<< second << endl;
}

{
show_message();
show_message("C++-da proqramlaşdırmağı öyrənirik!");
show_message("C++-da heç bir qərəz yoxdur!","Həddindən artıq yükləmə əladır!");
}

Həddindən artıq YÜKLƏMƏ LAZIM OLDUĞUNDA

Həddindən artıq yüklənmənin ən çox yayılmış istifadələrindən biri müxtəlif parametrlər əsasında müəyyən nəticə əldə etmək üçün funksiyadan istifadə etməkdir. Məsələn, fərz edək ki, proqramınızın həftənin cari gününü qaytaran həftənin_day adlı funksiyası var (bazar günü üçün 0, bazar ertəsi üçün 1, şənbə üçün ..., 6). Proqramınız bu funksiyanı həddən artıq yükləyə bilər ki, parametr kimi Julian günü verilirsə və ya ona gün, ay və il verilirsə, həftənin gününü düzgün qaytarsın:

həftənin_int_günü(int Julian_day)

{
// Operatorlar
}

int_həftənin_günü(int ay, int gün, int il)

{
// Operatorlar
}

Aşağıdakı dərslərdə təqdim olunan C++ dilində obyekt yönümlü proqramlaşdırmanı öyrəndikcə, proqramlarınızın imkanlarını genişləndirmək üçün funksiyaların həddən artıq yüklənməsindən istifadə edəcəksiniz.

Funksiyaların həddən artıq yüklənməsi proqramın oxunmasını yaxşılaşdırır

C++ funksiyasının həddən artıq yüklənməsi proqramlarınıza eyni adlı birdən çox funksiya təyin etməyə imkan verir. Həddindən artıq yüklənmiş funksiyalar eyni tipli* dəyərləri qaytarmalıdır, lakin parametrlərin sayı və növü ilə fərqlənə bilər. C++-da funksiyaların həddən artıq yüklənməsi tətbiq edilməzdən əvvəl C proqramçıları demək olar ki, eyni adlarla çoxlu funksiyalar yaratmalı idilər. Təəssüf ki, bu cür funksiyalardan istifadə etmək istəyən proqramçılar parametrlərin hansı kombinasiyasının hansı funksiyaya uyğun olduğunu yadda saxlamalı idilər. Digər tərəfdən, funksiyanın həddən artıq yüklənməsi proqramçılardan yalnız bir funksiya adını yadda saxlamağı tələb etməklə işləri asanlaşdırır.* Həddindən artıq yüklənmiş funksiyalar eyni tipli dəyərləri qaytarmaq üçün tələb olunmur, çünki kompilyator funksiyanı adı və dəsti ilə unikal şəkildə müəyyən edir. onun arqumentlərindən. Kompilyator üçün eyni adları olan, lakin fərqli arqument tipli funksiyalar fərqli funksiyalardır, ona görə də qaytarma növü hər bir funksiyanın preroqatividir. - Tərcüməçinin qeydi

NƏ BİLMƏLİYİNİZ GEREKİR

Funksiyaların həddən artıq yüklənməsi eyni funksiya üçün çoxlu təriflər təyin etməyə imkan verir. Kompilyasiya zamanı C++ ötürülən parametrlərin sayına və növünə əsasən hansı funksiyadan istifadə ediləcəyini müəyyən edəcək. Bu dərsdə siz funksiyaların həddən artıq yüklənməsinin olduqca sadə olduğunu öyrəndiniz. 14-cü dərsdə siz C++ istinadlarının funksiyalar daxilində parametrlərin dəyişdirilməsi prosesini necə sadələşdirdiyini öyrənəcəksiniz. Bununla belə, 14-cü dərsə keçməzdən əvvəl aşağıdakı əsas anlayışları öyrəndiyinizə əmin olun:

  1. Funksiyaların həddən artıq yüklənməsi proqramınızda eyni funksiyaya bir neçə "baxış" təmin edir.
  2. Funksiyaları həddən artıq yükləmək üçün sadəcə olaraq parametrlərin sayı və növü ilə fərqlənən eyni ad və qaytarma növü ilə çoxlu funksiyaları təyin edin.
  3. Kompilyasiya zamanı C++ ötürülən parametrlərin sayına və növünə əsasən hansı funksiyanın çağırılacağını müəyyən edəcək.
  4. Funksiyaların həddən artıq yüklənməsi proqramçılara yalnız bir funksiya adı ilə işləməyə imkan verməklə proqramlaşdırmanı asanlaşdırır.