مثال ۱: توابع کتابخانه ای
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double number, squareRoot;
cout << “Enter a number: “;
cin >> number;
// sqrt() is a library function to calculate square root
squareRoot = sqrt(number);
cout << “Square root of ” << number << ” = ” << squareRoot;
return 0;
}
در مثال بالا تابع sqrt() جذر عدد را حساب می کند.
برای استفاده از توابع ریاضی مانند sqrt() باید کتابخانه آن را به برنامه اضافه کنیم. در کد بالا با دستور #include <cmath> کتابخانه به برنامه اضافه شده است.
با اضافه کردن کتابخانه cmath می توانید از همه ی توابع موجود در آن استفاده کنید بدون اینکه احتیاج باشد آن ها را پیاده سازی کنید.
هر برنامه C++ حداقل یک تابع دارد. تابع اصلی برنامه ها main() است. بدون وجود آن برنامه اجرا نخواهد شد.
توابع تعریف شده توسط کاربر
C++ این امکان را به برنامه نویس می دهد که خودش تابع تعریف کند.
تابع تعریف شده توسط برنامه نویس مجموعه ای از کد هاست که دستور خاصی را انجام می دهند. تابع باید یک نام داشته باشد.
هنگامی که تابع در هر بخشی از برنامه فراخوانی شود، تمام کدهای بدنه تابع اجرا می شوند.
توابع تعریف شده توسط کاربر چگونه در C++ کار می کنند؟
وقتی برنامه در حال اجراست، سیستم تابع main() را صدا می زند و کد ها از آن جا شروع به اجرا شدن می کنند.
هنگامی که کنترل برنامه به
function_name()
در
main()
برسد، به تابع می رود و کد های درون
function_name()
اجرا می شوند.
سپس کنترل برنامه به () main برمی گردد و کدهای ادامه ی () function_name را اجرا می کند.
مثال ۲ : تابع تعریف شده توسط برنامه نویس
در برنامه زیر دو عدد با هم جمع می شوند که این کار در تابع add() انجام می شود و نتیجه در main نمایش داده می شود.
#include <iostream>
using namespace std;
// Function prototype (declaration)
int add(int, int);
int main()
{
int num1, num2, sum;
cout<<“Enters two numbers to add: “;
cin >> num1 >> num2;
// Function call
sum = add(num1, num2);
cout << “Sum = ” << sum;
return 0;
}
// Function definition
int add(int a, int b)
{
int add;
add = a + b;
// Return statement
return add;
}
امضای تابع ( اعلان)
اگر تابع تعریف شده توسط برنامه نویس بعد از تابع main() تعریف شود، کامپایلر خطا می گیرد به این دلیل که کامپایلر از تابع تعریف شده توسط کاربر ، نوع آرگومان انتقال داده شده به تابع و نوع بازگشتی آن آگاه نیست.
در C++ ، امضای تابع بدون body یا بدنه است که وظیفه ی معرفی تابع به کامپایلر را دارد. امضای تابع در مثال فوق برابر است با:
int add(int, int);
می توانید ببینید که هیچ گونه عملکردی در امضای تابع وجود ندارد. فقط نوع بازگشتی و نوع آرگومان های ورودی وجود دارد. همچنین می توانید امضای تابع را به شکل زیر اعلام کنید، اما نوشتن آرگومان ها الزام نیست.
int add(int a, int b);
نکته: اگر تابع قبل از main() تعریف شود احتیاجی به نوشتن امضای تابع نیست.
فراخوانی تابع
برای اجرای کد های بدنه ی تابع، تابع تعریف شده توسط کاربر باید فراخوانی شود (called).
در برنامه بالا
add(num1 , num2) داخل main()
تابع را فراخوانی می کند.
تابع عدد ذخیره شده در add را بازگشت می دهد.
تعریف تابع
تعریف تابع در برنامه بالا به شکل زیر است:
// Function definition
int add(int a,int b)
{
int add;
add = a + b;
return add;
}
هنگامی که تابع فراخوانی می شود، کنترل به اولین دستور بدنه تابع منتقل می شود.
سپس، دستورات دیگر در بدنه تابع به صورت پیوسته اجرا می شوند.
وقتی همه کد ها در تعریف تابع اجرا شدند، کنترل به ادامه برنامه برمی گردد.
ارسال آرگومان به تابع
در برنامه نویسی، آرگومان (پارامتر) به داده هایی اشاره دارد که در هنگام فراخوانی به تابع ارسال می شوند.
در مثال بالا، دو متغیر، num1 و num2 به تابع ارسال می شوند. این آرگومان ها، آرگومان واقعی نامیده می شوند.
مقدار num1 و num2 به ترتیب در متغیر های a و b ذخیره می شوند. این آرگومان ها a و b آرگومان های رسمی نامیده می شوند.
در شکل زیر نشان داده شده است:
نکته های آرگومان ارسالی
- تعداد آرگومان های رسمی و واقعی باید یکسان باشد. (Exception: Overloading Function)
- نوع آرگومان واقعی اول باید با نوع آرگومان رسمی اول یکسان باشد. به طور مشابه، نوع آرگومان واقعی دوم باید با نوع آرگومان رسمی دوم مطابقت داشته باشد و به همین ترتیب.
- شما می توانید تابعی بدون هیچ آرگومان ارسالی بنویسید. تعداد آرگومان های ارسالی به تابع بستگی به این دارد که برنامه نویس چکار می خواهد بکند.
- می توانید مقادیر پیش فرض به آرگومان بدهید. این آرگومان ها به عنوان آرگومان پیش فرض شناخته می شوند.
- در برنامه فوق هر دو آرگومان از نوع int (صحیح) هستند. اما الزامی نیست هر دو آرگومان از یک نوع باشند.
عبارت بازگشت
یک تابع می تواند یک مقدار را به برنامه فراخواننده با استفاده از statement return بازگرداند.
در برنامه بالا، مقدار add از تابع تعریف شده توسط کاربر با استفاده از عبارت زیر به برنامه باز می گردد:
return add;
شکل زیر نحوه کار عبارت بازگشت را نشان می دهد.
در برنامه بالا، مقدار add داخل تابع تعریف شده توسط کاربر به تابع فراخوانی بازگشته است. سپس مقدار آن در sum ذخیره می شود.
توجه داشته باشید که متغیر بازگشتی، یعنی add، از نوع integer (صحیح) است و sum نیز از همان نوع است.
همچنین، توجه کنید که نوع return یک تابع در ابتدای آن
int add (int a int b)
تعریف شده است.
int قبل از
add (int a، int b)
به این معنی است که تابع باید یک مقدار int را برگرداند.
اگر تابع هیچ مقداری بازگشت ندهد، پس باید از void استفاده کرد.
آموزش انواع توابع تعریف شده توسط کاربر در ++C
برای درک بهتر آرگومان های ارسالی و بازگشتی، توابع تعریف شده توسط کاربر می توانند به شکل زیر باشند:
- تابع بدون آرگومان ارسالی و بدون مقدار بازگشتی
- تابع بدون آرگومان ارسالی اما با مقدار بازگشتی
- تابع با آرگومان ارسالی اما بدون مقدار بازگشتی
- تابع با آرگومان ارسالی و مقدار بازگشتی
در زیر ۴ نوع تابع تعریف شده اند.
مثال ۱: تابع بدون آرگومان ارسالی و بدون مقدار بازگشتی
# include <iostream>
using namespace std;
void prime();
int main()
{
// No argument is passed to prime()
prime();
return 0;
}
// Return type of function is void because value is not returned.
void prime()
{
int num, i, flag = 0;
cout << “Enter a positive integer enter to check: “;
cin >> num;
for(i = 2; i <= num/2; ++i)
{
if(num % i == 0)
{
flag = 1;
break;
}
}
if (flag == 1)
{
cout << num << ” is not a prime number.”;
}
else
{
cout << num << ” is a prime number.”;
}
}
در قطعه کد بالا تابع ()prime بدون هیچ آرگومانی در ()main صدا زده می شود.
()prime از کاربر می خواهد یک عدد مثبت وارد کند سپس بررسی می کند که آیا اول است یا نه.
نوع بازگشتی تابع void است، یعنی تابع مقدار بازگشتی ندارد.
مثال ۲ : تابع بدون آرگومان ارسالی اما با مقدار بازگشتی
#include <iostream>
using namespace std;
int prime();
int main()
{
int num, i, flag = 0;
// No argument is passed to prime()
num = prime();
for (i = 2; i <= num/2; ++i)
{
if (num%i == 0)
{
flag = 1;
break;
}
}
if (flag == 1)
{
cout<<num<<” is not a prime number.”;
}
else
{
cout<<num<<” is a prime number.”;
}
return 0;
}
// Return type of function is int
int prime()
{
int n;
printf(“Enter a positive integer to check: “);
cin >> n;
return n;
}
در برنامه بالا، تابع ()prime در ()main بدون آرگومان ارسالی صدا زده می شود.
()Prime یک عدد صحیح مثبت از کاربر می گیرد. از آنجا که نوع بازگشتی تابع integer است، عدد ورودی را به تابع ()main برمی گرداند.
سپس، در تابع ()main بررسی می شود آیا عدد اول است یا خیر و نتیجه نمایش داده می شود.
مثال ۳ : تابع با آرگومان ارسالی اما بدون مقدار بازگشتی
#include <iostream>
using namespace std;
void prime(int n);
int main()
{
int num;
cout << “Enter a positive integer to check: “;
cin >> num;
// Argument num is passed to the function prime()
prime(num);
return 0;
}
// There is no return value to calling function. Hence, return type of function is void. */
void prime(int n)
{
int i, flag = 0;
for (i = 2; i <= n/2; ++i)
{
if (n%i == 0)
{
flag = 1;
break;
}
}
if (flag == 1)
{
cout << n << ” is not a prime number.”;
}
else {
cout << n << ” is a prime number.”;
}
}
در برنامه بالا، از کاربر خواسته شده عدد مثبتی وارد کند که در متغیر num ذخیره می شود.
سپس num به تابع ()prime ارسال می شود و در آن جا مشخص می شود که اول است یا نه. سپس نتیجه را نمایش می دهد.
از آنجا که نوع return در ()prime برابر با void است، تابع هیچ مقداری بازگشت نمی دهد.
مثال ۴ : تابع با آرگومان ارسالی و مقدار بازگشتی
#include <iostream>
using namespace std;
int prime(int n);
int main()
{
int num, flag = 0;
cout << “Enter positive integer to check: “;
cin >> num;
// Argument num is passed to check() function
flag = prime(num);
if(flag == 1)
cout << num << ” is not a prime number.”;
else
cout<< num << ” is a prime number.”;
return 0;
}
/* This function returns integer value. */
int prime(int n)
{
int i;
for(i = 2; i <= n/2; ++i)
{
if(n % i == 0)
return 1;
}
return 0;
}
در برنامه فوق از کاربر خواسته می شود یک عدد صحیح مثبت وارد کند که در متغیر num ذخیره می شود.
سپس، num به تابع ()prime ارسال می شود که در آن بررسی می شود آیا عدد اول است یا خیر.
از آنجا که نوع return در ()prime صحیح است، ۱ یا ۰ به ()main بازگردانده می شود. اگر num یک عدد اول باشد، ۱ باز می گردد. اگر نه، ۰ باز می گردد.
در تابع ()main مقدار بازگشتی ۱ یا ۰ در متغیر flag ذخیره می شود، و متن مربوطه بر روی صفحه چاپ می شود.
کدام روش بهتر است؟
هر چهار برنامه بالا یک خروجی مشابه ارائه می دهند و همه از لحاظ فنی درست هستند.
هیچ قاعده ای وجود ندارد که بگوید کدام روش بهتر است انتخاب شود.
روش خاص انتخاب شده بسته به وضعیت و چگونگی رفع مشکل است.
به توابع هم نامی که آرگومان (ها)ی متفاوتی دارند، توابع سربارگذار می گویند. در این آموزش، سربارگذاری توابع را به همراه مثال یاد خواهید گرفت.
تابع اشاره به بخشی از کد دارد که کار خاصی انجام می دهند. در برنامه نویسی ++C، دو تابع می توانند نام یکسانی داشته باشند، ولی باید تعداد یا نوع آرگومان هایشان متفاوت باشد. این توابع در تعداد یا نوع (یا هر دو) آرگومان ها تفاوت دارند و به عنوان توابع سربارگذار شناخته می شوند. به عنوان مثال:
int test() { }
int test(int a) { }
float test(double a) { }
int test(int a, double b) { }
در اینجا، تمام ۴ تابع، توابع سربارگذار هستند، زیرا آرگومان (ها)ی ارسالی به توابع متفاوت اند.
توجه داشته باشید که نوع بازگشتی این ۴ تابع یکسان نیستند. توابع سربارگذار ممکن است نوع بازگشتی متفاوت داشته باشند یا نداشته باشند، اما باید آرگومان های متفاوت داشته باشند.
// Error code
int test(int a) { }
double test(int b){ }
تعداد و نوع آرگومان های ارسال شده به این دو توابع مشابه هستند هر چند نوع بازگشتی متفاوت است. از این رو، کامپایلر خطا می دهد.
مثال ۱ : سربار گذاری توابع در C++
#include <iostream>
using namespace std;
void display(int);
void display(float);
void display(int, float);
int main() {
int a = 5;
float b = 5.5;
display(a);
display(b);
display(a, b);
return 0;
}
void display(int var) {
cout << “Integer number: ” << var << endl;
}
void display(float var) {
cout << “Float number: ” << var << endl;
}
void display(int var1, float var2) {
cout << “Integer number: ” << var1;
cout << ” and float number:” << var2;
}
در اینجا، تابع ()display سه بار با نوع یا تعداد متفاوت آرگومان صدا زده شده است.
نوع بازگشتی همه ی توابع یکسان است، اما الزام نیست.
مثال ۲ : سر بار گذاری توابع در C++
// Program to compute absolute value
// Works both for integer and float
#include <iostream>
using namespace std;
int absolute(int);
float absolute(float);
int main() {
int a = -5;
float b = 5.5;
cout << “Absolute value of ” << a << ” = ” << absolute(a) << endl;
cout << “Absolute value of ” << b << ” = ” << absolute(b);
return 0;
}
int absolute(int var) {
if (var < 0)
var = -var;
return var;
}
float absolute(float var){
if (var < 0.0)
var = -var;
return var;
}
در مثال بالا، دو توابع ()absolute سربارگذاری دارند.
هر دو تابع یک آرگومان دارند. با این حال، یک تابع integet می گیرد و دیگری float .
هنگامی که تابع ()absolute با آرگومان صحیح صدا زده می شود، تابع زیر فراخوانی می شود:
int absolute(int var) {
if (var < 0)
var = -var;
return var;
}
هنگامی که تابع ()absolute با آرگومان float صدا زده می شود، تابع زیر فراخوانی می شود:
float absolute(float var){
if (var < 0.0)
var = -var;
return var;
}
پایان قسمت بیست و هشتم