آنچه میخوانید ویراست جدید نوشتهای است که اولین بار با عنوان «قالبها در ++C»
خرداد ماه ۱۳۸۵
از طریق وبگاه برنامهنویسی و طراحی الگوریتم (عنوان و طرح پیشین وبگاه الگوریتمستان)
منتشر شده بود.
یکی از امکانات جالب و مفید زبان ++C قالبها (Templates) هستند که انعطاف زیادی به کدنویسی میدهند.
فرض کنید در یک برنامه نیاز به تعویض مقادیر دو متغیر هست. یعنی مثلا میخواهیم مقادیر a و b را با هم عوض کنیم. اگر a و b از نوع صحیح باشند، تابع جابجایی میتواند به این صورت باشد:
1 | void swap(int &a, int &b){
|
2 | int temp;
|
3 | temp = a;
|
4 | a = b;
|
5 | b = temp;
|
6 | } |
حال اگر بخواهیم مقادیر دو تا متغیر اعشاری را عوض کنیم، تابع فوق به کار نمیآید و باید تابع جدیدی بنویسیم. اما اگر از قالب استفاده کنیم، همهی مشکلات حل میشوند.
به قطعه کد زیر توجه کنید:
1 | template< class T >
|
2 | void swap(T &a, T &b){
|
3 | T Temp;
|
4 | Temp = a;
|
5 | a = b;
|
6 | b = Temp;
|
7 | } |
این کد روش استفاده از قالب را نشان میدهد. وقتی کامپایلر به این قطعه کد میرسد، متوجه میشود که یک تعریف کلی از یک تابع ارائه شده است. به جای T میتوان در زمان فراخوانی تابع، هر نوع دادهی استاندارد، ساختمان یا کلاس استفاده کرد. به عنوان مثال:
1 | int n = 5, m = 6;
|
2 | double x = 0.12, y = 125.6;
|
3 | char a = 'A', b = 'B';
|
4 | swap(n, m);
|
5 | swap(x, y);
|
6 | swap(a, b);
|
7 | cout << " n = " << n << ", m = " << m << endl;
|
8 | cout << " x = " << x << ", y = " << y << endl;
|
9 | cout << " a = " << a << ", b = " << b << endl; |
خروجی:
1 | n = 6, m = 5
|
2 | x = 125.6, y = 0.12
|
3 | a = B, b = A |
به عبارت سادهتر، وقتی کامپایلر به کد
میرسد، متوجه میشود که باید T را int در نظر بگیرد و ...
همانطور که گفته شد، میتوانید برای اشیاء کلاسها و ساختمانها هم از قالب استفاده کنید. اگر strval1 و strval2 دو متغیر از نوع ساختمان دلخواه باشند، عبارت
کاملا درست بوده و باعث جابجایی متغیرهای متناظر ساختمانها میشود.
قالبها از تمامی امکانات ++C نظیر سربارگزاری، تعریف مجدد و پارامترهای پیشفرض پشتیبانی میکند. مهمتر از همه این که میتوان از قالبها برای تعریف کلاسها استفاده کرد:
1 | template< class T >
|
2 | class myclass{
|
3 | private:
|
4 | T a;
|
5 | public:
|
6 | myclass(T x){
|
7 | set_a(x);
|
8 | }
|
9 | T get_a(){
|
10 | return a;
|
11 | }
|
12 | void set_a(T x){
|
13 | a = x;
|
14 | }
|
15 | }; |
با توجه به تعریف فوق، برای مشخص کردن اشیاء میتوان نوشت:
1 | myclass<int> n(7);
|
2 | myclass<float> d(10.5); |
توجه داشته باشید که لازم نیست همهی متغیرها از نوع کلی باشند. تابع زیر را در نظر بگیرید که یک آرایه و تعداد اعضای آن را دریافت کرده و این اعضا را چاپ میکند:
1 | template< class T >
|
2 | void print(T *arr, int n){
|
3 | int i;
|
4 | for (i = 0 ; i < n ; i ++)
|
5 | cout << *(arr + i) << endl;
|
6 | } |
در ضمن میتوان به جای یک نوع کلی، از چند نوع استفاده کرد:
| template< class type1, class type2, . . . , class typeN > |
از کاربردهای دیگر قالبها میتوان به توابع مرتبسازی، توابع جستجو، پشتهها، لیستهای پیوندی، درختها و صفها اشاره کرد.