PDA

View Full Version : متدهای یک کلاس در حافظه



ayub_coder
پنج شنبه 26 دی 1392, 22:27 عصر
سلام دوستان
من دارم کتاب سی ++ رابرت لی فور رو میخونم در جایی از مبحث کلاس های نوشته که وقتی از یک کلاس شی ایجاد میکنیم برای مقادیر داده ای کپی ساخته میشه ولی برای توابع عضو(متد ها) فقط یکبار در حافظه ساخته میشن.
اینطور که من برداشت کردم

class Circle{

protected:
int xCo,yCo;
int radius;
color fillcolor;
fstyle fillstyle;
public:
Circle(int x, int y, int r, color fc, fstyle fs):
xCo(x),yCo(y), radius(r),fillcolor(fc),fillstyle(fs)
{}
void draw(){
set_color(fillcolor);
set_fill_style(fillstyle);
draw_circle(xCo,yCo,radius);
}

};

int main(){

Circle c1(15,7,5, cBLUE, X_FILL);
Circle c2(41,12,7, cRED, O_FILL);
Circle c3(41,12,7, cGREEN, MEDIUM_FILL);

c1.draw();
c2.draw();
c3.draw();

return 0;
}



این کلاس Circle رو نظر بگیریم وقتی از روش سه تا شی c1,c2,c3 بسازیم از متد Draw فقط یه نمونه توی حافظه ساخته میشه و همه ی اشیا از همون یه متد استفاده میکنن؟
درست متوجه شدم؟ میشه توضیح بدید؟

ayub_coder
پنج شنبه 03 بهمن 1392, 14:47 عصر
دوستان کسی جواب این سوال رو نمیدونه؟

asdasd123123
شنبه 05 بهمن 1392, 11:26 صبح
تمام توابع چه public چه private چه protected چه friend چه اصلا خارج از کلاس (که کاری روی اشیا کلاس انجام میده) و همچنین انواع و توابع استاتیک یک بار در حافظه ذخیره میشن. ولی هر نوع یا کلاس غیر استاتیک برای هر شی جدا ذخیره و قابل پردازش و دسترسی است.

کامبیز اسدزاده
شنبه 05 بهمن 1392, 13:43 عصر
سلام دوستان
من دارم کتاب سی ++ رابرت لی فور رو میخونم در جایی از مبحث کلاس های نوشته که وقتی از یک کلاس شی ایجاد میکنیم برای مقادیر داده ای کپی ساخته میشه ولی برای توابع عضو(متد ها) فقط یکبار در حافظه ساخته میشن.
اینطور که من برداشت کردم

class Circle{

protected:
int xCo,yCo;
int radius;
color fillcolor;
fstyle fillstyle;
public:
Circle(int x, int y, int r, color fc, fstyle fs):
xCo(x),yCo(y), radius(r),fillcolor(fc),fillstyle(fs)
{}
void draw(){
set_color(fillcolor);
set_fill_style(fillstyle);
draw_circle(xCo,yCo,radius);
}

};

int main(){

Circle c1(15,7,5, cBLUE, X_FILL);
Circle c2(41,12,7, cRED, O_FILL);
Circle c3(41,12,7, cGREEN, MEDIUM_FILL);

c1.draw();
c2.draw();
c3.draw();

return 0;
}



این کلاس Circle رو نظر بگیریم وقتی از روش سه تا شی c1,c2,c3 بسازیم از متد Draw فقط یه نمونه توی حافظه ساخته میشه و همه ی اشیا از همون یه متد استفاده میکنن؟
درست متوجه شدم؟ میشه توضیح بدید؟

بله دوست عزیز شما درست متوجه شدید وقتی از یک تابع , شیئ یا هرچیز دیگه ای یه نمونه میسازی و هر کجا که از اون نمونه ساخته شده استفاده کنید دقیقا مثل این هستش که خود تابع یا شیئ رو صدا میزنی و ازش استفاده میکنی.

حالا در این جا شما c1,c2,c3 رو از نوع Circle نمونه ساختید و هر 3 مورد از کلاس Circle استفاده میکنند.

ayub_coder
شنبه 05 بهمن 1392, 18:15 عصر
بله دوست عزیز شما درست متوجه شدید وقتی از یک تابع , شیئ یا هرچیز دیگه ای یه نمونه میسازی و هر کجا که از اون نمونه ساخته شده استفاده کنید دقیقا مثل این هستش که خود تابع یا شیئ رو صدا میزنی و ازش استفاده میکنی.

حالا در این جا شما c1,c2,c3 رو از نوع Circle نمونه ساختید و هر 3 مورد از کلاس Circle استفاده میکنند.


خوب متغیرها و داده ها که وقتی نمونه ای ساخته میشه هرکدام بصورت جدا در حافظه ساخته میشن. منظور من توابع بود که همونطور که دوستمون بالا گفتن فکر کنم برای هر تعداد نمونه از کلاس، توابع فقط یکبار در حافظه ساخته میشن.

کامبیز اسدزاده
شنبه 05 بهمن 1392, 18:51 عصر
خوب متغیرها و داده ها که وقتی نمونه ای ساخته میشه هرکدام بصورت جدا در حافظه ساخته میشن. منظور من توابع بود که همونطور که دوستمون بالا گفتن فکر کنم برای هر تعداد نمونه از کلاس، توابع فقط یکبار در حافظه ساخته میشن.

بله تابع در حافظه ذخیره می شوند اما بهتر است بدانید توابع به هیچ عنوان در حافظه ثابت نمی مانند و فقط زمانی در حافظه ساخته می شوند که آن ها را صدا بزنیم یعنی تا وقتی که تابعی رو صدا نزنید در حافظه جایی رو برای خودشون اختصاص نمیدهند و بعد از صدا زدن و اجرا شدن هم حافظه رو اشغال و بعد خالی میکنند.

asdasd123123
شنبه 05 بهمن 1392, 18:56 عصر
بله تابع در حافظه ذخیره می شوند اما بهتر است بدانید توابع به هیچ عنوان در حافظه ثابت نمی مانند و فقط زمانی در حافظه ساخته می شوند که آن ها را صدا بزنیم یعنی تا وقتی که تابعی رو صدا نزنید در حافظه جایی رو برای خودشون اختصاص نمیدهند و بعد از صدا زدن و اجرا شدن هم حافظه رو اشغال و بعد خالی میکنند.
میشه بیشتر توضیح بدید؟ (پیرامون ذخیره سازی و صدا زدن توابع در زبان های برنامه نویسی)

کامبیز اسدزاده
شنبه 05 بهمن 1392, 19:27 عصر
میشه بیشتر توضیح بدید؟ (پیرامون ذخیره سازی و صدا زدن توابع در زبان های برنامه نویسی)

در رابطه با نوع تخصیص حافظه در برنامه نویسی در رابطه با حافظه Stack و حافظه Heap تحقیق کنید.

در توابع در کل متغیر ها وقتی حافظه ای رو در نظر میگیرند که تابع صدا زده بشه به مثال زیر توجه کنید :



void MyFunction(int a , int b)
{
int c;
int c = a + b;
cout << c;

}

int main()

{
cout << "Hello world";
return 0;
}


در این کد من یک تابع به نام MyFunction تعریف کردم که داخل پروژم هستش ولی وقتی برنامم رو اجرا کنم این تابع به هیچ عنوان صدا زده نشده و هیچ کاری نخواهد کرد پس در نتیجه تا زمانی که من این رو صدا نزنم هیچ حافظه ای اشغال نخواهد شد و هیچ چیزی از طرف تابع چاپ نخواهد شد.

حالا اگه بخوام صداش بزنم به صورت زیر صداش میزنم و هنگام اجرا تابع اجرا میشه و همون لحظه حافظه ای رو برای خودش در نظر میگیره و همچنین خروجی 300 رو چاپ میکنه.

حافظه ایم که اشغال میشه 4bytes برای int a و 4bytes بایت برای int b و 4bytes برای int c در نظر گرفته شده است.

این توضیحات هم به این معنی نیست که اصلا هیچ حافظه ای اختصاص داده نمیشه ! چون یک سری روندی هستش که در برنامه نویسی از حافظه Stack و حافظه Heap استفاده و هر کدوم بر اساس شرایط وظیفه ذخیره سازی و آزاد سازی حافظه رو دارند.

در حالت معمولی وقتی متغیری داخل برنامه تعریف می شود، آن متغیر داخل حافظه Stack قرار میگیرد. اما با اختصاص حافظه به صورت داینامیک برای یک متغیر آن متغیر داخل حافظه Heap قرار میگیرد.

پس برای تجزیه تحلیل و ریز بینی در مورد حافظه های Stack و Heap مطالعه فرمایید.

void MyFunction(int a , int b)
{
int c;
int c = a + b;
cout << c;

}

int main()

{
cout << "Hello world";
MyFunction(100,200);
return 0;
}

rahnema1
یک شنبه 06 بهمن 1392, 10:40 صبح
اینکه تا وقتی تابعی صدا زده نشه جایی در حافظه نداره کاملا اشتباهه بلافاصله که برنامه کامپایل میشه تابع در حافظه قرار می گیره همچنین می تونید قبل از اینکه یک تابع را صدا بزنید آدرس اون را به دست بیاورید ( یعنی باید یه جایی را در حافظه اشغال کرده باشه تا بتونیم آدرس اون را به دست بیاریم). در مورد اینکه فارغ از اینکه ما چند تا آبجکت از روی یک کلاس ساخته باشیم تابع ها فقط یک بار در حافظه قرار می گیرند به این لینک مراجعه کنید که تا سطح اسمبلی این مساله را تجزیه کرده : http://seegive.blogspot.com/2012/01/concept-behind-c-class-class-public-int.html

MSK
یک شنبه 06 بهمن 1392, 12:56 عصر
اگر من بتونم درست بوضیح بدم، فکر می‌کنم این جواب سوال شماست:

یک برنامه انواع مختلفی داده زخیره می‌کنه. مثلا کد، متغیر‌های سراسری، متغیرهای محلی، ...
این داده‌ها بسته به نوعشون در جاهای مختلفی هم زخیره میشند.

وقتی شما یک کلاس تعریف می‌کنید تمام کدهای اون در یک جای مشخص زخیره میشند، همینطور فیلدهای استاتیک و بقیه داده هایی که کلاس لازم داره. اما چون فیلدهای غیر استاتیک مربوط به خود کلاس نیستند و مربوط به instance های اون کلاس اند، تا وقتی که هیچ شیء ای (instance) از کلاس ایجاد نکردید، فیلدها هم جایی زخیره نمی‌شند.

متغیرهای محلی یک تابع هم شبیه همین اند. چون اون متغیرها مربوط به یک فراخوانی مشخص هستند، تا وقتی که تابع فراخوانی نشده جایی رو اشغال نمی‌کنند. اما همینکه تابع صدا میشه یک جای جدید در حافظه برای اونها اختصاص داده میشه.
همین باعث میشه که توابع بازگشتی مشکل اشغال فضای زیادی از حافظه رو داشته باشند. چون هربار که تابع خودش رو صدا میزنه بدون اینکه متغیرهای قبلی‌ای که اختصاص داده شدند بهش آزاد بشند، یک مجموعه جدید از متغیرهای محلی بهش اختصاص داده میشه. برای همین اگر یک تابع بازگشتی بیش از حد خودش رو فراخوانی کنه، برنامه stack overflow میده. یعنی stack که جایی هست که متغیرهای محلی در اون زخیره میشند پر شده!

حالا برگردیم به کلاس و شیء.

پس کدهای کلاس هم مثل کدهای یک تابع معمولی از قبل در یک جا زخیره میشند. اما متغیرهای شیء (فیلدها) قبل از اینکه شیءی ساخته بشه جایی رو اشغال نمیکنند. درست مثل متغیرهای محلی توابع.
اما وقتی شما یک شیء جدید میسازید، مثلا c1، برای فیلدهای این شیء جایی توی حافظه اختصاص داده میشه و به اون آدرس برچسب c1 زده میشه. وقتی هم که شیء جدیدی ساخته بشه برای فیلدهای اون فضای جدیدی تخصیص داده میشه.

حالا من گفتم که کدهای کلاس (یعنی متدها) از قبل در جایی از حافظه زخیره شدند؛ پس یعنی مثلا class::method1 از قبل از اینکه c1 بوجود بیاد در جایی از حافظه زخیره شده و هربار با یک شیء جدید دوباره ساخته نمیشه. پس این سوال پیش میاد که مثلا وقتی ما متد c1.method1 رو صدا می‌زنیم از کجا method1 میفهمه که مربوط به c1 هست و نه شیء دیگه؟
جواب خیلی سادست: متغیر this. درواقع متدها هم درست مثل هر تابع معمولی دیگه ای هستند فقط با یک تفاوت؛ متدها یک پارامتر اضافی مخفی هم دارند به اسم this.

بنابر این مثلا فرض کنید که شما چنین کلاسی تعریف کردید:


class klass {
int field1;
void method1(int param);
{


این شبیه این هست که چنین تعریفی کرده باشید:


struct klass {
int field;
{

void klass::method1(struct klass this, int param);


و اگر شما این دستورات رو وارد کنید:

klass c1;
c1.method1(12);


شبیه این هست که این دستورات رو وارد کرده باشید:

struct klass c1;
klass::method1(c1, 12);


امیدوارم تونسته باشم منظور رو خوب برسونم.