PDA

View Full Version : سوال: کدام تابع سازنده اجرا میشود ؟!



هم دانشگاهی
شنبه 14 اسفند 1389, 20:24 عصر
سلام برهمه !

دوستان به نظر شما در این برنامه برای هر شی کدام تابع سازنده فراخوانی میشود ؟!


#include <iostream>
#include <conio.h>
using namespace std;
/************************************************** ****************************/
class MyClass
{
private:
int x;
int y;
public:
MyClass(int=0 , int=0);
MyClass();
};
/************************************************** ****************************/
MyClass::MyClass(int a , int b)
{
cout<<"\nConstructor with Argument !";
x=a;
y=b;
cout<<"\nx= "<<x<<" y= "<<y;
}
/************************************************** ****************************/
MyClass::MyClass()
{
cout<<"\nConstructor with NO ANY SPECIALS Argument !";
x=100;
y=200;
cout<<"\nx= "<<x<<" y= "<<y;
}
/************************************************** ****************************/
int main()
{
MyClass ob1(5,7);

MyClass ob2(8);

MyClass ob3();

MyClass ob4;

getch();
return 0;
}
/************************************************** ****************************/

r00tkit
شنبه 14 اسفند 1389, 20:47 عصر
نظر ما مهم نیست

اجرا کن ببین چی می شه

هم دانشگاهی
شنبه 14 اسفند 1389, 21:39 عصر
مطمئن باش اینو خودم میدونستم و این کار رو انجام دادم !

اما سوال من در رابطه با شی ob3 هست که نمیدونم چرا هیچ کار انجام نمیده و شی ای رو تعریف نمیکنه !!! :لبخندساده:

حامد مصافی
یک شنبه 15 اسفند 1389, 08:30 صبح
از نظر سی پلاس پلاس استاندارد تعریف شی ob3 در کد شما اشتباه است، چون کامپایلر نمی‌تواند تشخیص دهد منظور برنامه‌نویس کدام‌یک از سازنده‌هاست.
البته ممکن است کامپایلر منسوخی مانند tc++ رفتار دیگری داشته باشد اما یک کامپایلر استاندارد یک fatal-error صادر کرده و کد را کامپایل نخواهد کرد.

هم دانشگاهی
یک شنبه 15 اسفند 1389, 14:48 عصر
از نظر سی پلاس پلاس استاندارد تعریف شی ob3 در کد شما اشتباه است، چون کامپایلر نمی‌تواند تشخیص دهد منظور برنامه‌نویس کدام‌یک از سازنده‌هاست.
البته ممکن است کامپایلر منسوخی مانند tc++ رفتار دیگری داشته باشد اما یک کامپایلر استاندارد یک fatal-error صادر کرده و کد را کامپایل نخواهد کرد.


من از IDE DEV -CPP استفاده میکنم! ولی نه این error مربوط به شی ob4 هست و شی ob3 حتی اصلا اجرا نمیشود ! یعنی کامپایلر اصلا این خط رو ترجمه نمیکنه !!!

حامد مصافی
یک شنبه 15 اسفند 1389, 15:01 عصر
مگر اینکه پارامتر های کامپایلر را تغییر داده باشید. من با g++ تست کردم نتیجه همان بود که عرض کردم.
این هم حاصل کامپایل
http://codepad.org/6zHqHusy

هم دانشگاهی
یک شنبه 15 اسفند 1389, 18:17 عصر
منم هم که همین رو عرض کردم ! کامپایلر از شی ob4 error میگریه ولی اگه شما برنامه رو بدون شی ob4 اجرا کنید میبینید بدون اجرا شی ob3 برنامه تمام میشود و اصلا این خط کامپایل نمیشود !!!

شما این خط رو کامپایل کن :

#include <iostream>
using namespace std;
/************************************************** ****************************/
class MyClass
{
private:
int x;
int y;
public:
MyClass(int=0 , int=0);
MyClass();
};
/************************************************** ****************************/
MyClass::MyClass(int a , int b)
{
cout<<"\nConstructor with Argument !";
x=a;
y=b;
cout<<"\nx= "<<x<<" y= "<<y;
}
/************************************************** ****************************/
MyClass::MyClass()
{
cout<<"\nConstructor with NO ANY SPECIALS Argument !";
x=100;
y=200;
cout<<"\nx= "<<x<<" y= "<<y;
}
/************************************************** ****************************/
int main()
{
MyClass ob1(5,7);

MyClass ob2(8);

MyClass ob3(); // این خط اجرا نمیشود

/////////////// MyClass ob4;

cout<<"\n\nHamed Mosafi !"; // در ادامه این خط ترجمه میشود

return 0;
}
/************************************************** ****************************/

در ضمن به خاطر اون سایت هم خیلی ممنون ! باحال بود ! :بوس:

حامد مصافی
یک شنبه 15 اسفند 1389, 20:27 عصر
آهان آهان
من دفعه قبل متوجه سوال شما نشدم
و اما نکته...

پرانترها در سازنده کلاس نباید قید شوند، چون در اینصورت شی به صورت خالی ایجاد می‌شود!!!

برای فراخوانی سازنده خالی باید شی مانند ob4 ایجاد شود (بدون پرانتز) لذا شی ob3 ایجاد می‌شود اما هیچ یک از سازنده های آن فراخوانی نمی‌شوند!

سروش ربیعی
یک شنبه 15 اسفند 1389, 22:07 عصر
سلام
امیدوارم منظورتونو درست متوجه شده باشم...
من فکر می‌کنم این اتفاق افتاده: سازندهٔ ob4 اجرا نمیشه چون این خط به دو صورت قابل تفسیر هست؛

۱- فراخوانی سازندهٔ اول با دو پارامتر فرضی (چون آرگومان‌ها مقادیر پیش‌فرض دارند)،
ob4(0,0);
۲- فراخوانی سازندهٔ بدون پارامتر
ob4();

اما اگر پرانتزها را بگذارید شما اصلاً سازنده‌ای رو فراخوانی نمی‌کنید* برای آزمایش این حالت می‌تونید بنویسید:
MyClass *ob3 = new MyClass();
این همون سازنده‌ای هست که شما قصد فراحوانی‌ش رو دارید اما اگر کامپایل کنید، باز هم به دلیل بالا خطا دریافت خواهید کرد. (یعنی وجود دو ارجاع ممکن برای یک درخواست)

*شاید این بیشتر کمک کنه: سازندهٔ بدون پارامتر رو حذف کنید. حالا یه کدی به صورت:
MyClass obj();
بنویسید. انتظار دارید خروجی چاپ بشه اما هیچی چاپ نخواهد شد. چون هیچ سازنده‌ای در این مورد فراخوانی نمیشه. فضادهی با استفاده از سازندهٔ پیش‌فرض انجام خواهد شد. یعنی حافظه‌دهی به صورت implicit هست. برای اینکه صریحاً قید کنید که می‌خواهید سازنده فراخوانی بشه قبل از تابع سازنده از کلمهٔ کلیدی explicit استفاده کنید.

هم دانشگاهی
یک شنبه 15 اسفند 1389, 23:26 عصر
من explicit رو هم گذاشتم اما باز هم اجرا نشد !

سروش ربیعی
دوشنبه 16 اسفند 1389, 00:33 صبح
منظور من این نبود که اگه تو این شرایط explicit اضافه کنید همه چیز درست میشه! در حالت کلی گفتم.

در ضمن این ایده که فلان خط اجرا نمیشه نادرسته. اجرا میشه و کاملاً درست هم هست. یعنی خطا یا اخطاری دریافت نمی‌کنید. منتها سازنده‌ای که مدنظر شماست این‌جا فراخوانی نمیشه.
کامپایلر سازندهٔ پیش‌فرض خودش رو فراخوانی می‌کنه. تو این شرایط چون یکی از معادل‌های سازندهٔ آرگومان‌دار امضای یکسانی با سازندهٔ بی‌آرگومان داره، اضافه کردن explicit هم برای اجرای سازندهٔ خواسته شده جواب نخواهد داد. البته explicit برای این شرایط ساخته نشده. کاربرد اصلی explicit تبدیل-هنگام-ساخت هست. مثل شرایطی که string a = "something" می‌نویسیم. این‌جا سازنده هم فراخوانی میشه و هم تبدیل انجام میشه که البته تا جایی که من اطلاع دارم شامل شرایط string a; هم هست. (اینو مطمئن نیستم باید تستش کنم) برای همین گفتم که explicit کمک می‌کنه.

پی‌نوشت: این شرایط کمی فانتزی هست. یعنی فکر نمی‌کنم استفاده از این ویژگی‌ها برای قابلیت اعتماد یک برنامه چندان درست باشه. میشه شرایط مشابه رو با ارث‌بری از تابع سازنده پیاده‌سازی کرد. (البته دقیق نمی‌دونم منظور نویسنده از این کد چی بوده)