رفتن به مطلب
جامعه‌ی برنامه‌نویسان مُدرن ایران
  • 0
CISCO

ویژگی template چیست و چگونه استفاده می‌شود؟


سوال

ارسال شده در (ویرایش شده)

با سلام , امروز در حال گشتن توی یک سایت به عبارت template برخورد کردم‌. بعد از کمی گشتن در اینترنت تا حدودی فهمیدم که این عبارت برای ++C می‌باشد ولی از آنجا که به نظر پیچیده می‌باشد از دوستان خواهشمندم توضیحی درباره این موضوع با یک مثال بدهند تا هم من و هم بقیه از این روش اطلاع داشته باشیم.

ویرایش شده در توسط کامبیز اسدزاده
تصحیح نگارش و افزودن کلمات کلیدی

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

2 پاسخ به این سوال تا کنون داده شده است

پست های پیشنهاد شده

  • 1

علیکم‌السلام ؛

قبل از اینکه به پاسخ مستقیم سؤال بپردازیم ، بیاید درک کنیم چه شد که template ها نیاز برنامه‌نویس شد.

این تابع را در نظر بگیر :

int Sum (const int& first, const int& second){
    return first+second;
}

این تابع دو عدد از نوع int دریافت و حاصل جمع‌شون را بر می‌گردونه.

خب ! حالا چه میشه اگه شما بخواید به جای int نوع double ارسال کنید ؟ و برنامه‌ی شما با انواع مختلفی داده نیاز داشته باشه که با این تابع کار کنه. شاید بگید خب یک تابع دیگه با پارامتر و نوع بازگشتی double می‌نویسم.

با این روش چه مشکلاتی پیش می‌آید :

  • کد تکراری.
  • بالا رفتن درصد خطای کد.
  • افزایش بی‌دلیل حجم کد.
  • سخت شدن مدیریت کد.
  • مشکل در آپدیت کردن سورس کد.
  • و ...

زبان سی‌پلاس‌پلاس برای رفع این مشکل‌ما template ها را معرفی کرده است. template ها می‌توانند هر نوع داده‌ای را قبول کنن. تابع زیر ، تابع template بازنویسی شده‌ی تابع Sum است که در مثال بالا نوشتیم  :

template <typename newType> newType Sum (const newType& first, const newType& second){
    return first + second;
}

😵😵😵خییییلی بزرگ شد ن ؟. خب می‌تونیم کوتاهش کنیم :

template <typename newType>
newType
Sum (const newType& first, const newType& second){
    return first + second;
}
  • نکته : می‌دانیم که کامپایلر فاصله‌هارا نادیده می‌گیره

خب ! اوّل برای تبدیل تابع ، به یک تابع template باید از کلمه‌ی کلیدی template استفاده کنیم. و بعد با استفاده از < > اسم نوع داده‌های جدیدمان را بنویسیم.

  • نکته : ما هیچ نوع داده‌ی جدیدی درواقع تعریف نمی‌کنیم. این تعریف فقط معرفی یک اسم به عنوان نوع داده‌ای هست که می‌تواند به هر چیزی اعم از int,double ,... تبدیل بشود.

و داخل < > ما از کلمه‌ی‌کلیدی typename برای تعریف اسم داده‌‌ استفاده کردیم. و همچنین می‌توانیم کلمه‌ی‌کلیدی class نیز استفاده کنیم که هردو برابر یک دیگر هستن. امّا زمانی شما دارید templateی از template درست می‌کنید. مثلاً این نمونه :

template < template <typename> class MyTmpClass, typename newType>

اینجا دیگه نمی‌توانید بین کلمه‌کلیدی typename و class تفاوت قائع نشید. چرا که نیازه صراحتاً مشخص. امّا در استاندارد ۱۷ این مشکل وجود ندارد  ِ؛ ولی بهتر است که این تفاوت را اعمال کنیم.

حال به راحتی می‌توانیم تابع را فراخوانی کنیم. به تکه کدزیر توجه کنید

Sum (12 ,32);                               
Sum (1'000'000'000'000,3212'333'233);
Sum (std::string("ghasem") , std::string("ramezani"));
Sum (12, 32.0);

سه خط اوّل کد بدون مشکل کامپایل می‌شوند. الا خط ‌آخری. چرا که ما یک پارامتر با نوع int و یک پارامتر با نوع double‌ ارسال کردیم.

برای حل این مشکل بیاید ببینیم که template ها به چه صورت کار می‌کنند. فرض کنید این تابع را فراخوانی کردیم :

Sum ( int , int );

وقتی کامپایلر به این تابع بر می‌خورد. تابع template مارا به این‌صورت برای ما بازنویسی می‌کند :

int
Sum (const int& first, const int& second){
    return first + second;
}

خب ! و وقتیما سعی می‌کنیم این تابع را فراخوانی کنیم :

Sum ( int , double );

برنامه کامپایل نمی‌شود و خطای زیر را ساطع میکنن. چرا که یک پارامتر Int و دیگری double هست. 

./main.cpp:5: candidate template ignored: deduced conflicting types for parameter 'newType' ('int' vs. 'double')

 

آیا این شکل استفاده از توابع براتون آشنا نیست ؟ یه کم فک کنید :

  • std::vector
  • std::array
  • std::list

تمام این کلاس‌ها ، template class هستند. و هر نوعی می‌توانند قبول کنند :

#include <vector>
#include <string>

class myClass{
public:
    myClass(){}
};

int main (void){
    std::vector <int> myIntger {1,2,3,4};
    std::vector <std::string> myString {"ghasem" , "ramezani"};
    std::vector <myClass>  myClassVector;

    return 0;
}

 

  • نکته : این توضیح خیلی خلاصه از template ها و روش استفاده از آنها بود و به همین دو خط محدود نمی‌شوند.

 

نقل قول

ولی از آنجا که به نظر پیچیده می‌باشد

و اینکه گفتید "به نظر پیچیده می‌باشد" 🤔. پیچیدگی در عین سادگی یکی از قابلیت‌های فوق‌العاده‌ی زبان سی‌پلاس‌پلاسه🤩. اصلاً کد باید وحشت‌ناک باشه.😁

 

 

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر
  • 0
در 7 ساعت قبل، قاسم رمضانی منش گفته است :

علیکم‌السلام.

قبل از اینکه به پاسخ مستقیم سؤال بپردازیم ، بیاید درک کنیم چه شد که template ها نیاز برنامه‌نویس شد.

این تابع را در نظر بگیر :



 
 
int Sum (const int& first, const int& second){
 
return first+second;
 
}

این تابع دو عدد از نوع int دریافت و حاصل جمع‌شون را بر می‌گردونه.

خب ! حالا چه میشه اگه شما بخواید به جای int نوع double ارسال کنید ؟ و برنامه‌ی شما با انواع مختلفی داده نیاز داشته باشه که با این تابع کار کنه. شاید بگید خب یک تابع دیگه با پارامتر و نوع بازگشتی double می‌نویسم.

با این روش چه مشکلاتی پیش می‌آید :

  • کد تکراری.
  • بالا رفتن درصد خطای کد.
  • افزایش بی‌دلیل حجم کد.
  • سخت شدن مدیریت کد.
  • مشکل در آپدیت کردن سورس کد.
  • و ...

زبان سی‌پلاس‌پلاس برای رفع این مشکل‌ما template ها را معرفی کرده است. template ها می‌توانند هر نوع داده‌ای را قبول کنن. تابع زیر ، تابع template بازنویسی شده‌ی تابع Sum است که در مثال بالا نوشتیم  :



 
 
template <typename newType> newType Sum (const newType& first, const newType& second){
 
return first + second;
 
}

😵😵😵خییییلی بزرگ شد ن ؟. خب می‌تونیم کوتاهش کنیم :



 
 
template <typename newType>
 
newType
 
Sum (const newType& first, const newType& second){
 
return first + second;
 
}
  • نکته : می‌دانیم که کامپایلر فاصله‌هارا نادیده می‌گیره

خب ! اوّل برای تبدیل تابع ، به یک تابع template باید از کلمه‌ی کلیدی template استفاده کنیم. و بعد با استفاده از < > اسم نوع داده‌های جدیدمان را بنویسیم.

  • نکته : ما هیچ نوع داده‌ی جدیدی درواقع تعریف نمی‌کنیم. این تعریف فقط معرفی یک اسم به عنوان نوع داده‌ای هست که می‌تواند به هر چیزی اعم از int,double ,... تبدیل بشود.

و داخل < > ما از کلمه‌ی‌کلیدی typename برای تعریف اسم داده‌‌ استفاده کردیم. و همچنین می‌توانیم کلمه‌ی‌کلیدی class نیز استفاده کنیم که هردو برابر یک دیگر هستن. امّا زمانی شما دارید templateی از template درست می‌کنید. مثلاً این نمونه :


template < template <typename> class MyTmpClass, typename newType>

اینجا دیگه نمی‌توانید بین کلمه‌کلیدی typename و class تفاوت قائع نشید. چرا که نیازه صراحتاً مشخص. امّا در استاندارد ۱۷ این مشکل وجود ندارد  ِ؛ ولی بهتر است که این تفاوت را اعمال کنیم.

حال به راحتی می‌توانیم تابع را فراخوانی کنیم. به تکه کدزیر توجه کنید



 
 
Sum (12 ,32);
 
Sum (1'000'000'000'000,3212'333'233);
 
Sum (std::string("ghasem") , std::string("ramezani"));
 
Sum (12, 32.0);

سه خط اوّل کد بدون مشکل کامپایل می‌شوند. الا خط ‌آخری. چرا که ما یک پارامتر با نوع int و یک پارامتر با نوع double‌ ارسال کردیم.

برای حل این مشکل بیاید ببینیم که template ها به چه صورت کار می‌کنند. فرض کنید این تابع را فراخوانی کردیم :


Sum ( int , int );

وقتی کامپایلر به این تابع بر می‌خورد. تابع template مارا به این‌صورت برای ما بازنویسی می‌کند :



 
 
int
 
Sum (const int& first, const int& second){
 
return first + second;
 
}

خب ! و وقتیما سعی می‌کنیم این تابع را فراخوانی کنیم :


Sum ( int , double );

برنامه کامپایل نمی‌شود و خطای زیر را ساطع میکنن. چرا که یک پارامتر Int و دیگری double هست. 


./main.cpp:5: candidate template ignored: deduced conflicting types for parameter 'newType' ('int' vs. 'double')

 

آیا این شکل استفاده از توابع براتون آشنا نیست ؟ یه کم فک کنید :

  • std::vector
  • std::array
  • std::list

تمام این کلاس‌ها ، template class هستند. و هر نوعی می‌توانند قبول کنند :



 
 
#include <vector>
 
#include <string>
 
 
 
class myClass{
 
public:
 
myClass(){}
 
};
 
 
 
int main (void){
 
std::vector <int> myIntger {1,2,3,4};
 
std::vector <std::string> myString {"ghasem" , "ramezani"};
 
std::vector <myClass> myClassVector;
 
 
 
return 0;
 
}

 

این توضیح خیلی خلاصه از template ها و روش استفاده از آنها بود و به همین دو خط محدود نمی‌شوند.

 

و اینکه گفتید "به نظر پیچیده می‌باشد" 🤔. پیچیدگی در عین سادگی یکی از قابلیت‌های فوق‌العاده‌ی زبان سی‌پلاس‌پلاسه🤩. اصلاً کد باید وحشت‌ناک باشه.😁

 

 

بسیار ممنون از پاسخ مفید و ععال شما !👍

به اشتراک گذاری این ارسال


لینک به ارسال
به اشتراک گذاری در سایت های دیگر

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

مهمان
پاسخ به این سوال ...

×   شما در حال چسباندن محتوایی با قالب بندی هستید.   حذف قالب بندی

  تنها استفاده از ۷۵ اموجی مجاز می باشد.

×   لینک شما به صورت اتوماتیک جای گذاری شد.   نمایش به عنوان یک لینک به جای

×   محتوای قبلی شما بازگردانی شد.   پاک کردن محتوای ویرایشگر

×   شما مستقیما نمی توانید تصویر خود را قرار دهید. یا آن را اینجا بارگذاری کنید یا از یک URL قرار دهید.


  • کاربران آنلاین در این صفحه   0 کاربر

    هیچ کاربر عضوی،در حال مشاهده این صفحه نیست.

×
×
  • جدید...