PDA

View Full Version : مبتدی: اعلان کلاس



ali-iman
چهارشنبه 23 تیر 1400, 01:39 صبح
class A;

class B
{
public:
A obj;
B()
{
cout << obj.a << endl;
}
};

class A
{
int a = 5;
friend class B;
};

int main()
{
B Bobj;
}

با سلامو وقت بخیر چرا کلاس B نمیتونه از کلاس A استفاده کنه و متفیر داخل کلاس A رو نمایش بده ؟ درسته A بعد از B تعریف شده ولی قبل از B اعلان شده

farhad_shiri_ex
جمعه 01 مرداد 1400, 10:43 صبح
با سلامو وقت بخیر چرا کلاس B نمیتونه از کلاس A استفاده کنه و متفیر داخل کلاس A رو نمایش بده ؟ درسته A بعد از B تعریف شده ولی قبل از B اعلان شده
کدی که نوشتید قطعا در زمان کامپایل خطا دارد، بنابراین باید به این روش بازنویسی شود!

class A1234;
class B123
{
public:
A1234* obj;
B123(A1234* o) :obj(o) {}
const A1234& get() const {
return(*obj);
}
~B123() { delete obj; }
};
class A1234
{
int a = 5;
friend class B123;
public:
int get() const {
return(a);
}
};



int main(int argc, char** argv)
{
B123 Bobj(new A1234);
std::cout << Bobj.get().get() << std::endl;
}

1- در زمانی که از نوع incomplete با استفاده از forward declaration استفاده کنید، طبق قوانین زبان نمی توانید از یک عضو غیر اشاره گر یا رفرنس استفاده کنید، بنابراین عضو obj کلاس B123 حتما باید یک آفست باشد که در زمان اجرا به آدرس معتبر اشاره کند تا در زمان کامپایل هم خطایی دریافت نکنید
2- بنابراین با نوع تعریف کلاسها تون در زمان کامپایل هیچ راهی برای دستیابی به عضو آفست فوروارد شده ندارید، بنابراین نمی توانید در سازنده کلاس B123 از متغیر عضو کلاس A1234 استفاده کنید.
3- برای دسترسی به مقادیر عضو کلاس A1234 باید به صورت ایمن یک const offset را از یک متد const ارسال کنید برای کلاس ویا هر آبجکت مصرف کننده.
4- و زمانی هم که نیاز به دسترسی به نمایش عضو کلاس A1234 داشتید میتوانید به این شکل Bobj.get().get() استفاده کنید.
5- والبته با روش گفته شده دیگه نیازی به friend class B123 نیست، چرا که به صورت ایمن به عضو کلاس A1234 دسترسی دارید.
6- البته توجه داشته باشید که اگر به دسترسی های بیشتری به عضوهای کلاس A1234 داشته باشید باید متدهای غیر const در کلاس A1234 تعریف کنید در حال حاضر کلاس فوق به صورت state less تعریف شده بنابراین توجه داشته باشید که استفاده از عملگر const_cast در زمان کامپایل برای دور زدن متد های امن در زمان کامپایل مخاطره آمیز خواهد بود.
نکات فوق را به جهت روشن تر شدن ذهن تون توضیح دادم، بهتره قبل از استفاده از تکنیک های زبان حتما مستندات قوانین زبان را مطالعه کنید، تا اینطوری باعث ابهام نشه! در این مورد این که چرا برنامه شما دقیقا به همان نحو کامپایل و اجرا نمیشه! نکات فنی داره که بیشتر بر میگرده به قوانین زبان اسمبلی.
موفق باشید.