ورود

View Full Version : مبتدی: راهنمایی در مورد مبحث ترکیب (مباحث ابتدایی شی گرایی)



ehsan_faal
جمعه 15 خرداد 1394, 17:56 عصر
سلام دوستان.
فصل 7 کتاب دایتل مثال زیر رو برای قسمت ترکیب که از مباحث شی گراییه آورده.

#ifndef DATE_H
#define DATE_H
class Date
{
public:
Date(int=1,int=1,int=1990);
void print() const;
~Date();
private:
int month,year,day;
int checkDay(int);
};
#endif // DATE_H



#include "Date.h"
#include <iostream>
using namespace std;
Date::Date(int mn,int dy,int yr)
{
if (mn>0 && mn<=12)
{
month=mn;
}else
{
month=1;
cout<<"Month "<<mn<<" invalid. Set to month 1.\n";
}
year=yr;
day=checkDay(dy);
cout<<"Date Object constructor for date ";
print();
cout<<endl;
}
void Date::print() const
{
cout<< month<<'/'<<day<<'/'<<year;
}
Date::~Date()
{
cout<<"Date object destructor for date ";
print();
cout<<endl;
}

int Date::checkDay(int testDay)
{
static const int daysPerMonth[13]=
{0,31,28,31,30,31,30,31,31,30,31,30,31};
if (testDay > 0 && testDay <=daysPerMonth[month])
return testDay;
if (month==2 &testDay==29 &&(year%400==0 || (year%4==0 && year%100!=0)))
return testDay;
cout<<"Day " <<testDay<< " invalid.Set to Day 1.\n";
return 1;

}



#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include "Date.h"

class Employee
{
public:
Employee(char *,char *,int ,int ,int,int,int,int);
void print() const;
~Employee();
private:
char FirstName[25];
char LastName[25];
const Date BirthDate;
const Date HairDate;
};

#endif // EMPLOYEE_H



#include "Employee.h"
#include <iostream>
#include <cstring>
using namespace std;

Employee::Employee(char *fname,char *lname,int bmonth ,int bday,int byear,int hmonth,int hday,int hyear)
:BirthDate(bmonth,bday,byear), HairDate(hmonth,hday,hyear)
{
int length=strlen(fname);
length=(length<25?length:24);
strncpy(FirstName,fname,length);
FirstName[length]='\0';

length=strlen(lname);
length=(length<25?length:24);
strncpy(LastName,lname,length);
LastName[length]='\0';

cout<<"Employee object constructor: "
<<FirstName<<" "<<LastName<<endl;
}
void Employee::print() const
{
cout<<LastName<<" , "<<FirstName<<"\nHired: ";
HairDate.print();
cout<<"Birth date: ";
BirthDate.print();
cout<<endl;
}
Employee::~Employee()
{
cout<<"Employee object destructor: "
<<LastName<<" , "<<FirstName<<endl;
}



و این هم فایل:
#include <iostream>
#include "Employee.h"
using namespace std;

int main()
{
Employee e("Bob","Jones",7,24,1949,3,12,1988);
cout<<"\n";
e.print();
cout<<"\nTest Date constructor with invalid values:\n";
Date d(14,35,1994);
cout<<endl;
return 0;
}



سوال من اینه که توی فایل main چه جوری یه شی از Date ساخته و چیزی که از اون هم واسم عجیب تره اینه که بعد از ساخت شی d دوباره انگار سازنده شی e رو هم صدا میزنه.
توی خود کتاب چیزی در موردش ننوشته و توی سایتای خارجی هم نمیدونستم دقیقا باید دنبال چی بگردم، ممنون میشم مراحل رو از جایی که شی d میخواد ساخته بشه یه توضیحی بدید.
با تشکر

chikar
جمعه 15 خرداد 1394, 21:56 عصر
سلام
مثال دایتل رو فراموش کن و به مثال زیر توجه کن!


class A
{
public:
A(int x , int y) : var1(x)
{
var2 = y;
cout << "ConstructorA is run." << var1 << var2;
}

private:
int var1;
int var2;
};

void main() {
A a(5,6);
}

در مثال بالا ما یه کلاس به اسم A تعریف کردیم که دو تا متغیر عضو از نوع int به اسم var1و var2 داره و یه سازنده هم داریم که دو تا پارامتر ورودی می گیره، در تابع main ما یه شی از کلاس A ساختیم به اسم a و سازنده این شی رو با مقادیر 5و6 پر کردیم، حالا ما می خواهیم از طریق سازنده این شی، دو متغیر عضومون که از نوع int هستند(دقت کنید نوعشون int هست و نه نوع یک کلاس) یعنی var1 و var2 رو مقدار دهی کنیم ، دو تا راه داریم یکی اینکه مثل متغیر var2، درون سازنده مقدار دهی کنیم و راه دوم هم مثل var1 هست که بعد از پارامتر های سازنده و بعد از دو نقطه : اون رو مقدار دهی می کنیم.

خب حالا به مثال زیر توجه کن :


class A
{
public:
A(int x , int y) : var1(x)
{
var2 = y;
cout << "ConstructorA is run." << var1 << var2;
}

private:
int var1;
int var2;
};

......................................
class B
{
public:
B(int m , int n) : value_A(m,n)
{
// value_A(m,n); // Error
}
private:
A value_A;
};

......................................
void main() {
B b(88,99);
}


کلاس A که همون کلاس قبلی هست، حالا ما اومدیم یه کلاس دیگه به اسم B ساختیم و تو متغیر های عضو در بخش private یک شی از کلاس A به اسم value_A ساختیم ، برای استفاده از این شی باید حتما سازنده شی فراخونی شود،بر خلاف مثال قبل که نوع هامون از جنس int بود، اینجا نوعمون از جنس کلاس هست، و نمی تونیم مثل مثال قبل که متغیرمون رو هم در سازنده و هم بعد از دو نقطه : مقدار دهی کردیم یک شی از کلاس دیگه درون سازنده مقدار دهی کنیم و فقط باید بعد از دو نقطه این کار رو بکنیم، یعنی اگر درون سازنده B ما value_A رو مقدار دهی کنیم با خطا مواجه می شیم ولی اگر اون رو بعد از پارامتر های سازنده B و بعد از دو نقطه : مقدار دهی کنیم، می تونیم از شی value_A که متعلق به کلاس A هست استفاده کنیم
حالا وقتی در تابع main یه شی از کلاس B ساخته می شه، مقادیر درون سازنده اش یعنی 88و99 به پارامتر های سازنده B یعنی m,n می ره و در همون لحظه بعد از دو نقطه : m,n از طریق شی value_A به سازنده A می ره!
امیدوارم مطلب رو رسونده باشم ، موفق باشی

ehsan_faal
جمعه 15 خرداد 1394, 22:39 عصر
ممنون.
من این قسمت رو نمیفهمم که توی فایل main ما فقط Employee.h رو include کردیم ولی اومدیم مستقیم یه شی از Date ساختیم ،اونم با فراخوانیه مستقیم سازنده خودش.
این منطق رو متوجه نمیشم.
یعنی ما وقتی یه کلاسی رو به main اضافه میکنیم میتونیم به کلاسهایی هم که توی اون کلاس استفاده شده دسترسی مستقیم داشته باشیم؟
و اگه جواب مثبته چرا وقتی این برنامه رو ران میکنیم بعد از اینکه سازنده Date کارش تموم شد سازنده Employee دو دفعه دیگه هم اجرا میشه؟(البته حدسم اینه که ربطی به birthDate و HairDate دارن که دو بار تکرار میشه)

chikar
جمعه 15 خرداد 1394, 23:17 عصر
من این قسمت رو نمیفهمم که توی فایل main ما فقط Employee.h رو include کردیم ولی اومدیم مستقیم یه شی از Date ساختیم ،اونم با فراخوانیه مستقیم سازنده خودش.
این منطق رو متوجه نمیشم.
یعنی ما وقتی یه کلاسی رو به main اضافه میکنیم میتونیم به کلاسهایی هم که توی اون کلاس استفاده شده دسترسی مستقیم داشته باشیم؟

ببین دوست عزیز علامت # که در بالا و همراه include میاد به معنی دستور پیش پردازنده است، دستورات پیش پردازنده قبل از کامپایل انجام می گیرند ساده تر بگم، یعنی قبل از اینکه کامپایل بشه محتویات هدر Employee که شامل هدر Date هم هست، اضافه می شن در همون فایل فراخوان مثلا تابع main، پس الان در تابع main که از Date شی ای ساخته شده، علاوه بر هدر Employee ، هدر Date نیز وجود داره!
اما اگر به جای include کردن Date در هدر Employee ، در خود فایل cpp کلاس Employee، این کار رو می کردیم با خطا مواجه می شدیم، چون ما فایل .h کلاس Date رو داریم include می کنیم و نه فایل سورس اون یعنی .cpp رو!!!



و اگه جواب مثبته چرا وقتی این برنامه رو ران میکنیم بعد از اینکه سازنده Date کارش تموم شد سازنده Employee دو دفعه دیگه هم اجرا میشه؟(البته حدسم اینه که ربطی به birthDate و HairDate دارن که دو بار تکرار میشه)
سوالتون گنگ هست، از فراخوانی کدوم Date، سازنده اش فراخوانی شده؟ کجا؟
نحوه فراخوانی سازنده ها رو تو مثال قبلی که زدم ببینید

ehsan_faal
جمعه 15 خرداد 1394, 23:59 عصر
ممنون.مشکل حل شد


:تشویق: