PDA

View Full Version : ارث بری : مشکل در DownCasting



__IDIN
دوشنبه 24 آبان 1389, 18:53 عصر
با سلام به همگی.
لطفا به این تکه کد نگاه کنید


//foo.h
class Base
{
public :
void f();
void g();

int mBaseData1;
int mBaseData2;
int mBaseData3;
};

class Derived : public Base
{
public :
void h();

int mDerivedData1;
int mDerivedData2;
};
//foo.cpp
#include"foo.h"
#include <iostream>
using std::cout;
using std::endl;

void main()
{

Base* base = new Base();
Derived* derived = (Derived*)base; // DownCast
derived->mDerivedData1 = 6;
cout<< derived->mDerivedData1<<endl; // Result = 6;
}



برای من این سوال پیش اومد که طبیعتا نمیشود به متغیر عضوی که تخصیص حافظه نشده است
دسترسی داشت (منظور mDerivedData1) ولی این تکه کد عدد 6 را در کنسول چاپ می کند, که
بیانگر این است که به نحوی دسترسی انجام گرفته و این برای من جای سوال داره.به نظر شما
باید بدین شکل باشد؟


کامپایلر : MS VC++ 2010

با تشکر.

r00tkit
دوشنبه 24 آبان 1389, 19:23 عصر
مشکل چیه الان


derived->mDerivedData1 = 6;


مقدار گذاری کرده دیگه

__IDIN
دوشنبه 24 آبان 1389, 20:05 عصر
توی این کد به اشاره گر base توسط دستور new حافظه اختصاص داده شده .این شی دارای سه متغیر عضو هستش و طبیعتا این متغیر ها به حافظه درستی دسترسی دارند ولی متغیر اشاره گر
derived این گونه نیست و به وسیله downcast به آدرسی اشار ه می کنه که base اشاره می کنه
و توی این آدرس هیچ فضایی از حافظه برای متغییر های کلاس Derived اختصاص داده نشده پس
شاید باید خطایی مبنی بر این توسط کامپایلر باید صادر بشه.

r00tkit
دوشنبه 24 آبان 1389, 23:22 عصر
راستش رو بخوای :

برای اینکه کد شما درست کار کنه باید

Base* base = new Base();

رو به
Base* base = new Derived();
تبدیل کنی

شما نباید از mDerivedData1 استفاده کنی چون در واقع یه نمونهی واقعی از Derived در هیپ وجود نداره

شما با این کار داری قسمتی از heap رو که متعلق به برنامت نیست رو می نویسی/می خونی که ممکنه باعث مشکلات بشه

به عبارتی چیزی برای derived تو heap الوکیت نکردی و mDerivedData1 جایی اشاره می کنه که متعلق به derived نیست


مثلا" یه ارایه تعریف می کنی بعد خارج از ایندیکس می تونی بخونی ( خود من چند روز قبل با


int* t=new int(10);
int[12]=4;



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

(
بعد فهمیدم :C++‎‎ lets you do what you tell it to do for the most part. You are shooting yourself in the foot. :)

و در اخر کدت رو به



Base* base = new Derived;
Derived* derived = dynamic_cast<Derived*>(base);
derived->mDerivedData1 = 6;


تبدیل کن

ممنون که باعث شدی یه 2خط مطلب بخونم

__IDIN
سه شنبه 25 آبان 1389, 11:57 صبح
بله به طور کلی هنگام استفاده از downcast باید مراقب بود تا به حافظه غیر مجاز دسترسی پیدا نکنه.ولی
همیشه می تونید از upcast استفاده کنید چون همیشه base قسمتی از derived هستش ولی بر عکس این
قضیه الزامآ درست نیست و این نکته را در downcast باید مورد توجه قرار داد.
تعجب می کنم که کامپایلر حتی یه اخطار هم برای این مشکل نمایش نمیده در صورتی که این اشکال می تونه
شرایطی رو پیش بیاره که توی یه برنامه( برنامه نسبتآ بزرگ ) واقعآ به سختی بشه خطا یابی کرد.

geek1982 از شما هم ممنونم که وقت گذاشتید توضیحاتتون کامل و درست بود.