ورود

View Full Version : اشاره گر به تابع



بمب منطقی
جمعه 26 خرداد 1385, 18:57 عصر
با سلام


int func1(int,int);
int func2(int,int);
...
int(*m[2])(int,int)={func1,func2};

توضیح کد : کد بالا آرایه 2 عنصری یک اشاره گر به تابع می باشد
سوال : چطور میشه آرایه ای از اشاره گر ها به توابعی ایجاد کرد که
1- پارامتر های ورودی متفاوت داشته باشن
2- خروجی های متفاوت داشته باشن
:توضیح بیشتر با مثال
اگر func1 به این صورت


void func1(int,int);


یا به این صورت


int func1(int);


و یا به این صورت


void func1(int);

باشد اشارهگرm به چه صورت تغییر خواهد کرد

با تشکر از شما عزیزان

Arash_j13
دوشنبه 12 تیر 1385, 05:38 صبح
نمی شه در مورد خورجی می تونید یه یونینون برگردونید و در هر مورد از اون بخشش که لازم دارید استفاده کنید ورودی هم تنها راه اینکه تمام تمام توابع رو به کمک عملگر ... بنویسید و گرنه برای اینجاد یه ارایه از اشاره گر به تابع ها باید تمام تابع ها دارای ورودی و خورجی یکسانی باشند

C++Lover
چهارشنبه 14 تیر 1385, 01:01 صبح
نگید نمیشه که تو ++C نشدن سخته.
دو راه برای این کار وجود داره که اولی به وسیله آرایه ای از void pointer ها و typecast کردنه و دومی هم با استفاده از مفاهیم object oriented

هستش. راه استفاده از void pointer ها رو که فکر کنم خودتون بدونید (ولی اگر خواستید توضیح میدم) در ادامه به راه حل دوم می پردازم.

توجه : راه حلی که من در اینجا توضیح میدم مربوط میشه به ++C نه C و با Visual c++ 2005 تستش کردم.




// functions
void func1(int a, int b)
{
cout << 1 << endl;
}

int func2(void)
{
cout << 2 << endl; return 12;
}

double func3(char a, int b, long c)
{
cout << 3 << endl; return 6.0;
}

// types
typedef void (*PFunc1) (int, int);
typedef int (*PFunc2) (void);
typedef double (*PFunc3)(char, int, long);

union Funcs
{
// data
PFunc1 pFunc1;
PFunc2 pFunc2;
PFunc3 pFunc3;

// constructors
Funcs() { pFunc1=NULL; pFunc2=NULL; pFunc3=NULL; }
Funcs(PFunc1 pfunc) { pFunc1 = pfunc; }
Funcs(PFunc2 pfunc) { pFunc2 = pfunc; }
Funcs(PFunc3 pfunc) { pFunc3 = pfunc; }

// operators
operator PFunc1() { return pFunc1; }
operator PFunc2() { return pFunc2; }
operator PFunc3() { return pFunc3; }
};

Funcs f[3] = {func1, func2, func3};

int main()
{
f[0](0, 0);
int i = f[1]();
double d = f[2]('a', 0, 0);

getchar();
return 0;
}



کمی نیرنگ آمیزه اما اگر به ++C تسلط داشته باشید بسیار راحت و کاملا رساست.
فقط می مونه مسئله توابع با آرگومان ورودی یکسان و خروجی متفاوت که باعث ambiguity میشه که اون مسئله هم با یک typecast ساده حل میشه.

اگر احتیاج به توضیحات بیشتر داشتید بگید بیشتر توضیح بدم.

کد بالا رو تو Turbo C++ 3.0 تست کردم جواب نداد با operator ها مشکل داره اما اشکال نداره میتونید از کد زیر استفاده کنید. با این روش مشکل ambiguity هم ندارید و احتیاج به typecast کردن ندارید. فقط باید برای استفاده از عناصر آرایه هر دفعه صریحا نوع تابع را ذکر کنید که این مسئله در کد قبلی به صورت خودکار انجام می شد.


// functions
void func1(int a, int b)
{
cout << 1 << endl;
}

int func2(void)
{
cout << 2 << endl; return 12;
}

double func3(char a, int b, long c)
{
cout << 3 << endl; return 6.0;
}

// types
typedef void (*PFunc1) (int, int);
typedef int (*PFunc2) (void);
typedef double (*PFunc3)(char, int, long);

union Funcs
{
// data
PFunc1 pFunc1;
PFunc2 pFunc2;
PFunc3 pFunc3;

// constructors
Funcs() { pFunc1=NULL; pFunc2=NULL; pFunc3=NULL; }
Funcs(PFunc1 pfunc) { pFunc1 = pfunc; }
Funcs(PFunc2 pfunc) { pFunc2 = pfunc; }
Funcs(PFunc3 pfunc) { pFunc3 = pfunc; }

// operators
};

Funcs f[3] = {func1, func2, func3};

int main()
{
f[0].pFunc1(0, 0);
int i = f[1].pFunc2();
double d = f[2].pFunc3('a', 0, 0);

getchar();
return 0;
}



مثال برای رفع مشکل ambiguity کد اول :


// functions
void func1(int a, int b)
{
cout << 1 << endl;
}

int func2(void)
{
cout << 2 << endl; return 12;
}

double func3(char a, int b, long c)
{
cout << 3 << endl; return 6.0;
}

int func4(int a, int b)
{
cout << 4 << endl; return 15;
}

// types
typedef void (*PFunc1) (int, int);
typedef int (*PFunc2) (void);
typedef double (*PFunc3)(char, int, long);
typedef int (*PFunc4) (int, int);

union Funcs
{
// data
PFunc1 pFunc1;
PFunc2 pFunc2;
PFunc3 pFunc3;
PFunc4 pFunc4;

// constructors
Funcs() { pFunc1=NULL; pFunc2=NULL; pFunc3=NULL; pFunc4=NULL; }
Funcs(PFunc1 pfunc) { pFunc1 = pfunc; }
Funcs(PFunc2 pfunc) { pFunc2 = pfunc; }
Funcs(PFunc3 pfunc) { pFunc3 = pfunc; }
Funcs(PFunc4 pfunc) { pFunc4 = pfunc; }

// operators
operator PFunc1() { return pFunc1; }
operator PFunc2() { return pFunc2; }
operator PFunc3() { return pFunc3; }
operator PFunc4() { return pFunc4; }
};

Funcs f[4] = {func1, func2, func3, func4};

int main()
{
((PFunc1)f[0])(0, 0);
int i1 = f[1]();
double d = f[2]('a', 0, 0);
int i2 = ((PFunc4)f[3])(3, 2);

getchar();
return 0;
}

Arash_j13
پنج شنبه 15 تیر 1385, 06:11 صبح
خب شما اشاره گر به ارایه نساختی که یه ارایه از void pointer ها هست پس در اصل نشه

C++Lover
پنج شنبه 15 تیر 1385, 14:17 عصر
دوست عزیز :
اول: این یک آرایه به void pointer ها نیست. من گفتم با void pointer ها هم میشه.
دوم: من از گفتن شدن، ایراد گرفتن به نشدن شما نبود بلکه فقط منظورم راه انداختن کاره.
سوم: ++C اینطوریه، یعنی امکانات خام زبان و انعطاف زبان زیاده و به کمک اینها میتوان امکانات زیاد دیگه ای تولید کرد. نباید انتظار داشته باشیم که هرچیزی بخواهیم آماده و سه سوت باشه. البته این مختص ++C نیست بلکه تو هر زبانی کم و بیش اینطوریه.

این یک آرایه از union type با constructor ها و operator های بخصوصی هستش که یک پوشش برای اختصاص و استفاده از توابع ایجاد میکنه یعنی انگار که با یک آرایه از توابعی با تعاریف متفاوت در حال کردن هستیم.
مثلا برای اختصاص :


Funcs f[3] = {func1, func2, func3};

و برای استفاده


f[0](0, 0);
int i = f[1]();
double d = f[2]('a', 0, 0);

درست مثل آرایه معمولی.

به هر حال اگر جسارتی شد می بخشید...