وبلاگ من



شرح:

این برنامه شامل تابع سازنده و سربارگذاری عملگر های >> ، << ، + ، -  ، * ، =، () و [] روی کلاس polynomial است. به علاوه یک تابع (analys) برای خواندن string و تبدیل آن به term ها دارد. هر چند جمله ای از چند شی از کلاس term تشکیل می شود.

 

کلاس polynomial:

شامل یک آرایه به طول 20 از کلاس term است. متغییر count شمارنده سلول های پرشده است(با پر شدن هر خانه(سلول) یک واحد به مقدار آن اضافه می شود)

class polynomial
{
private:
	term cell[20];
	int count;
	//add similar value to each other
	void clear();
	//this function convert string math expersion to numbercial cell's value
	void analys(string exp);
	void insert(int fact,int pow);
protected:
        int power(int num,int pow);

public:
        //contractors
        polynomial(){count=0;}; //Null
        polynomial(string exp){count=0;analys(exp);}; //by Value
        polynomial (polynomial &A){count=0;for(int i=0;i<20;i++){cell[i].fact=A.cell[i].fact;cell[i].pow=A.cell[i].pow;}} //by Copy

        //function
        void show();
        void set(string exp);

        //operator overloading
        polynomial operator *(polynomial temp);
        polynomial operator -(polynomial temp);
        polynomial operator =(polynomial temp);
        int operator ()(int input);
        term operator [](int input);
        friend ostream& operator << (ostream &out, polynomial temp);
        friend istream& operator >> (istream &in, polynomial &temp);

};

 

کلاس term:

در یک چند جمله ای هر جمله مثلا به صورت 3x^2 یک term می باشد. در این مثال fact=3 و pow=2 است.

class term
{
	friend class polynomial;
private:
	int fact;
	int pow;
public:
	term(){ fact = 0; pow = 0; } //contractor (null)
	term(int x,int y){fact = x; pow = y;} //contractor (value)
	term (term &A){fact = A.fact; pow = A.pow;} //contractor (copy)

	//function
	void show();

	//operator overloading
	friend ostream& operator << (ostream &out, term t);
};

 

برای مشاهده برنامه کلیک کنید.

 


عبارت A = B + C را در نظر بگیرید به A,B,C عملوند و به +,= عملگر می گویند . در c++ می توان نحوه کار هر عملگر را تعیین کرد.


 درواقع وقتی می نویسید A+B تابعی مانند

 A.operator +(B);

در برنامه فراخوانی می شود .

همانطور که مشخص است عملگر + (operator +)  یک تابع از شی A است که تنها یک ورودی می گیرد . این ورودی می تواند از جنس A (یعنی A و B هر دو از جنس یک کلاس هستند ) باشند یا حتی از یک جنس نباشند مثلا A از جنس کلاسی مانند test و B عددی int باشد.


برای مثال کلاس test را در نظر بگیرید . در تعریف این کلاس تنها یک عدد صحیح int x وجود دارد می خواهیم عملگر های + و >> را برای آن بنویسیم:

#include "stdafx.h"
#include <iostream>
using namespace std;
class test
{
int x; //varible
public:
test operator + (test temp); 
friend ostream& operator << (ostream &out, test temp);
test(int a) { x = a; } //contractor
};
// + operator overloading
test test::operator +(test temp)
{
x += temp.x;
return *this;
}
// << operator overloading
ostream& operator << (ostream &out, test temp)
{
cout << temp.x;
return out;
}
int _tmain(int argc, _TCHAR* argv[])
{
test A(2);
test B(3);

cout << A + B;
system("pause");
return 0;
}

همان طور که گفتیم هر عملگر در واقع تابعی از کلاسی است که تعریف می کنیم . از طرفی هر تابع  باید یک نوع خروجی داشته باشد void , int , . یا از نوع خود کلاس . وقتی می نویسیم A+B در واقع آن را برابر یک متغییر دیگر می کنیم در این جا از نوع کلاس . اگر خروجی از نوع int باشد هم مشکلی برای جمع دو متغییر پیش نمی آید اما اگر داشته باشیم A + B + C در این صورت دو متغییر اول جمع شده به صورت int در می آیند سپس با عبارتی مثل int X + C رو به رو می شویم که در تعریف عملگر وجود ندارد پس برای رفع این مشکل نوع خروجی را از نوع کلاس تعیین می کنیم. 


عملگر >> عضوی از کلاس test نیست چون عبارتی مثل cout<<A همان:

operator << (cout , A);

 همان طور که مشخص است این تابع(همان عملگر >>) وابته به کلاس نیست و تنها باید به محتویات آن  دسترسی داشته باشد پس به صورت  دوست برای کلاس تعریف می شود

 & اول برای این است که خروجی تابع به صورت ارجاعی باشد که در ادامه علت آن را توضیح می دهیم . تابع دو نوع ورودی دارد اول از جنس ostream است (cout نوعی جریان خروجی برای نمایش اطلاعات روی مانیتور است که از جنس کلاس ostream می باشد از دیگر جریان های خروجی ofstream است که هنگام کار با فایل از ان استفاده می کردیم )  و دومی از نوع کلاس . در  out& علامت & برای out ارسال به صورت ارجاع و نه کپی است .

تابع آدرس out را در پایان برمی گرداند (ارجاع به ostream&  . برای برگرداندن آدرس نیازی نیست *out بنویسم این مفهوم برای اشاره گر است و برای ارسال آدرس نیازی نیست حتما از اشاره گر استفاده کنیم)

( اگر خروجی تابع از نوع void می شد برای cout <<A مشکلی وجود نداشت اما برای cout<<A<<B مثل int و  نوع کلاس همان مشکل پیش می آید پس خروجی باید ostream باشد )


برای اینکه به یک تابع یا کلاس (مثلا تابع B) اجازه دهیم که به مقادیر کلاس (مثلا  A) دسترسی پیدا کند . باید برای کلاس A تعریف کنیم که تابع یا کلاس B را به عنوان دوست در نظر بگیر برای این کار از کلمه کلیدی friend در بدنه کلاس A به همراه امضای تابع B استفاده می کنیم :

class A
{
friend void B();
};
void B() {}

برای مثال کلاسی به نام test را در نظر بگیرد . تابع show برای این کلاس را به صورت دوست تعریف می کنیم:

#include <iostream>
using namespace std;
class test
{
int x,y;
friend void show(test);
public:
test(int a,int b) //contractor
{
x=a;
y=b;
}
};
void show(test T) 
{
cout<<T.x<<T.y<<endl;
}

int main(int argc, char** argv) {

test A(2,3);
show(A);

test B(8,9);
show(B);

return 0;
}


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

کلاس B به عنوان دوست برای کلاس A تعریف شده است یعنی می تواند به متغییر ها و توابع خصوصی و محافظت شده ی آن دسترسی داشته باشد . ان دسترسی از طریق شی از A امکان پذیر است مثلا در این مثال ما به کمک شی a از نوع کلاس A در تابع set کلاس B مقادیر x و y را تغییر می دهیم.


#include "stdafx.h"
#include <iostream>
using namespace std;
class A
{
friend class B;
private:
int x;
protected:
int y;
public:
A(){ x = 0; y = 0; } //contractor
};
class B
{
public:
void set(A a)
{
a.x = 2;
a.y = 2;
}
};



int _tmain(int argc, _TCHAR* argv[])
{
B Mb;
A Ma;
Mb.set(Ma);
return 0;
}



شکل کلی تعریف یک متغییر استاتیک در کلاس به این صورت است:

class test
{
static int x;
};
int test::x=0; 

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


برای مثال اگر بخواهیم تعداد متغییر ها ی تعریف شده از کلاس test را داشته باشیم باید یک متغییر int از نوع static تعریف کرده ، هر بار در تابع سازنده (جایی که یک شی از کلاس هنگام تعریف در آنجا مقدار دهی می شود) رفته و به مقدار x یکی اضافه کنیم :

#include <iostream>
using namespace std;
class test
{
public:
test() //contractor
{
x++;
cout<<x<<endl;
}

static int x;

void PrintX() {cout<<x<<endl;}
};
int test::x=0; 
int main(int argc, char** argv) {

test A,B;

return 0;
}




class در c# منغییر ها را به صورت مرجع ارسال می کند . lمثلا در این مثال چون هر بار مقادری obj تغییر می کند در نهایت تمام حافظه ی تخصیص داده شده برای list با c,3 پر می شوند
اما struct مقادیر را به صورت کپی مقدار ارسال می کند در نتیجه اگر همین مثال را به صورت :
struct a
{
      public string txt;
      public int num;
}
تعریف کنیم مقادیر list به صورت a,1 و b,2 و c,3  ذخیره می شود
class a
{
      public string txt;
      public int num;
}
//-------------------
List<a> AList = new List<a>();
a obj = new a();
//-------------------
obj.txt = "a";
obj.num = 1;
AList.Add(obj);
//------------------
obj.txt = "b";
obj.num = 2;
AList.Add(obj);
//-------------------
obj.txt = "c";
obj.num = 3;
AList.Add(obj);



ابتدا از بخش CLR گزینه CLR Empty Project  را انتخاب کنید

روی نام پروژه راست کلیک کرده و . Add > New Item را انتخاب کنبد
سپس visual C++ > UI > Windows Form را انتخاب کنبد

در ادامه روی نام فرم خود کلیک کنید و کد زیر را را در آن جا بنویسید:
#include "MyForm.h"
#include "MyForm.h"
using namespace System;
using namespace System::Windows::Forms;
[STAThread]
void Main(array<String^>^ args)
{
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Project1::MyForm form;
Application::Run(%form);
}
که MyForm نام فرم و Project1 نام پروژه است

سپس روی نام پروژه راست کلیک کرده و Properties را انتخاب کنید 
در پنجره ای که باز می شود به ترتیب:
Configuration Properties->Linker >System>Windows (/SUBSYSTEM:WINDOWS)
و در همان بخش :
Advanced >Entry Point >  Main
را تایپ کنید

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
class l_int
{
vector <int> vec;
protected:
void fix(l_int & temp)
{
if(vec.size()<temp.vec.size())
for(int i=vec.size();i<temp.vec.size();i++)
vec.push_back(0);
else if(vec.size()>temp.vec.size())
for(int i=temp.vec.size();i<vec.size();i++)
temp.vec.push_back(0);
}
void zero(l_int & temp)
{
for(int i=0;i<temp.vec.size();i++)
temp.vec.at(i)=0;
}
public:

l_int(const string txt="0")
{
vec.resize(txt.length());
for(int i=0;i<txt.length();i++)
vec.at(i)=txt[txt.length()-1-i]-48;
}
l_int(l_int &temp )
{
/*
vec.resize(temp.vec.size());
for(int i=0;i<temp.vec.size();i++)
vec.at(i)=temp.vec.at(i);
*/
vec.reserve(temp.vec.size());
copy(temp.vec.begin(),temp.vec.end(),back_inserter(vec));
}

~l_int()
{
vec.clear();
}
l_int operator + (l_int &temp)
{
fix(temp);
l_int Sum;
Sum.vec.resize(vec.size());
zero(Sum);
int sum=0;
for(int i=0;i<vec.size();i++)
{
Sum.vec.at(i)= ( vec.at(i) + temp.vec.at(i) +sum) %10;
sum=( vec.at(i) + temp.vec.at(i) +sum ) /10;
if(i==vec.size()-1 && sum>0)
Sum.vec.at(vec.size())=sum;
}
return Sum;
}
l_int operator *(l_int &temp)
{
vec.push_back(0);
temp.vec.push_back(0);
int sum;
l_int Mult;
Mult.vec.resize(temp.vec.size()+vec.size());
zero(Mult);
for(int i=0;i<temp.vec.size();i++)
{
sum=0;
for(int j=0;j<vec.size();j++)
{
Mult.vec.at(i+j)+=(vec.at(j)*temp.vec.at(i)+sum)%10;
if(Mult.vec.at(i+j)>9)
{
Mult.vec.at(i+j)=Mult.vec.at(i+j)%10;
Mult.vec.at(i+j+1)++;
}
sum=(vec.at(j)*temp.vec.at(i)+sum)/10;
}
}
return Mult;
}
l_int& operator =(const l_int &temp)
{
vec.resize(temp.vec.size());
for(int i=0;i<temp.vec.size();i++)
vec.at(i)=temp.vec.at(i);
return *this;
}
l_int& operator =(const string txt)
{
vec.resize(txt.length());
for(int i = 0 ; i<vec.size() ;i++)
vec.at(i)=txt[txt.length()-1-i]-48;
return *this;
}
friend ostream& operator <<(ostream &out,l_int &temp);
friend istream& operator >>(istream &in,l_int &temp);
};
ostream& operator <<(ostream &out,l_int &temp)
{
bool Check=false;
for(int i=temp.vec.size()-1;i>=0;i--)
if(temp.vec.at(i)>0 || Check==true)
{
cout<<temp.vec.at(i);
Check=true;
}
if(Check==false)
cout<<"0";
return out;
}
istream& operator >>(istream &in,l_int &temp)
{
string txt;
cin>>txt;
temp.vec.resize(txt.length());
for(int i = 0 ; i<temp.vec.size() ;i++)
temp.vec.at(i)=txt[txt.length()-1-i]-48;
return in;
}
int _tmain(int argc, _TCHAR* argv[])
{
l_int A="20";
l_int B="10";
//cin>>A>>B;
//A="5";
l_int C;
l_int D;

C=A+B;
D=A*B;
cout<<"A+B:"<<C<<endl;
cout<<"A*B:"<<D<<endl;
system("pause");
return 0;
}




#include "stdafx.h"
#include <iostream>

using namespace std;
class Array{
int cap;
int len;
int *arr;
public:
Array() //constructor
{
cap=0;
len=0;
arr=new int;
}
Array(int x) //constructor 
{
cap=x;
len=0;
arr=new int[x];
}
Array(const Array &temp) //copy constructor
{
cap=temp.cap;
len=temp.len;
arr=new int[cap];
for(int i=0;i<temp.len;i++)
arr[i]=temp.arr[i];
}
~Array()  //destructor
{
delete [] arr;
}
void set(int x)
{
if(len<cap)
{
arr[len]=x;
len++;
}
else
{
int *temp=new int[cap]; //new array
for(int i=0;i<cap;i++) //set member of arr to new array named temp
temp[i]=arr[i];
delete [] arr; //delete arr 
int *arr=new int[cap*2]; //new arr with more capacity
for(int i=0;i<cap;i++) //get back member of old arr to new arr with temp
arr[i]=temp[i];
delete [] temp; //free space of temp with delet that
cap*=2; //more cap (mean : cap=cap*2)
arr[len]=x; //set
len++;
}


}
void print()
{
for(int i=0;i<len;i++)
cout<<arr[i]<<endl;
}
Array& operator =(Array temp)
{
if(cap<=temp.cap)
{
for(int i=0;i<temp.len;i++)
arr[i]=temp.arr[i];
len=temp.len;
cap=temp.cap;
}
else
{
delete [] arr; 
int *arr=new int[temp.cap]; //fix array capacity
for(int i=0;i<temp.len;i++) //put member
arr[i]=temp.arr[i];
len=temp.len;
cap=temp.cap;
}
return *this;
}
Array operator +(Array A2)
{
Array A3(cap+A2.cap);
A3.cap=cap+A2.cap;
A3.len=len+A2.len;
for(int i=0;i<len;i++)
A3.arr[i]=arr[i];
for(int i=len;i<A2.len;i++)
A3.arr[i]=A2.arr[i];
return A3;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Array A(5);
A.set(0);A.set(1);A.set(2);
Array B(5);
A.set(4);A.set(5);
Array C;
C=A+B;
C.print();
system("pause");
return 0;
}



تابع سازنده (constructor) :

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

تابع سازنده مقداری را بر نمی گرداند و void هم نیست و حتما باید هم نام با کلاس باشد ، همان طور که گفته شد می تواند به دفعات به صورت بدون مقادر ، با دریافت مقدار و با دریافت مقدار به صورت پیش فرض تعریف شود.

برنامه به صورت پیش فرض تابع سازنده دارد اما برای اینکه با مقادیر کلاس هنگام تعریف مقدار دهید باید از تابع سازنده استفاده کنید.


تابع سازنده کپی (copy constructor) :

برای اینکه هنگام تعریف کلاس مقادیر یک شی از همان کلاس را در آن کپی کنید از تابع سازنده استفاده می شود . 

تابعی هم نام با کلاس ، بدون ورودی که هیچ مقداری را بر نمی گرداند و همان طور که گفته شد به صورت پیش فرض توسط خود برنامه فراخوانی می شود.

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

تفاوت تابع سازنده کپی با عملگر(operator) = در این است که از عملگر = در همه جای برنامه می توان استفاده کرد اما تابع سازنده در زمان تعریف شی فراخوانی می شود.


تابع مخرب (destructor) :

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

تابعی است هم نام با کلاس به علاوه علامت (مَد) ~ (در صفحه کلید انگلیسی بالای tab قرار دارد) بدون ورودی که خروجی را بر نمی گرداند .

به صورت خودکار در پایان هر بلاک  {} فراخوانی می شود . مقادیری که به صورت پویا تعریف شده اند (یعنی با دستور new) را با دستور delete از حافظه خارج می کنیم اما سایر مقادیر مانند مقادیر اولیه دیگر نیازی به حذف با delete ندارند.

#include <iostream>

using namespace std;
class myclass{
int a,b;
int *c; //single 
int *d; //array
public:
myclass(const myclass &A) //copy constructor
{
a=A.a;
b=A.b;
c=new int;
*c=A.c[0];
d=new int[5];
for(int i=0;i<5;i++)
d[i]=A.d[i];
}
myclass(int a1,int b1 , int c1,int d0,int d1,int d2,int d3,int d4) //constructor with value
{
a=a1;
b=b1;
c=new int;
*c=c1;
d=new int[5];
d[0]=d0;
d[1]=d1;
d[2]=d2;
d[3]=d3;
d[4]=d4;
}
myclass() //constructor without value
{
a=1;
b=2;
c=new int;
*c=3;
d=new int[5];
d[0]=11;
d[1]=12;
d[2]=13;
d[3]=14;
d[4]=15;
}
~myclass() //destructor
{
delete c;
delete [] d;
cout<<"Destructor"<<endl; //message for show when destructor is run
}
void set(int a1,int b1 , int c1,int d0,int d1,int d2,int d3,int d4)
{
a=a1;
b=b1;
*c=c1;
d[0]=d0;
d[1]=d1;
d[2]=d2;
d[3]=d3;
d[4]=d4;
}
void print()
{
cout<<a<<endl;
cout<<b<<endl;
cout<<*c<<endl;
cout<<d[0]<<endl;
cout<<d[1]<<endl;
cout<<d[2]<<endl;
cout<<d[3]<<endl;
cout<<d[4]<<endl;
cout<<endl; //space
}
};
void Des()
{
myclass D;
}
int _tmain(int argc, _TCHAR* argv[])
{
myclass A(10,20,30,0,1,2,3,4);
myclass B=A;
myclass C;
A.set(100,200,300,5,6,7,8,9);

A.print();
B.print();
C.print();
Des(); //this function just for show destructor running after compiler pass block {}
system("pause");
return 0;
}



تبلیغات

آخرین ارسال ها

آخرین جستجو ها

سگ پژدر کوردستان (ماستیف کردی) Kurdish Dog Pshdar ماینر و ارز های دیجیتال کلاغ نیوز server پربیننده ترین اخبار 24 ساعت گذشته دانلود اهنگ های کرمانجی|کرمانج موزیک دانستنی ها شیشه اتومبیل هاشم در شیراز ☆Jewel Land☆ فایل رسون