類與物件課程筆記
類與物件
一 基礎知識
1.類的定義
類是面對物件程式設計實現資訊封裝的基礎。類是一種使用者定義型別,也稱類型別,每個類包含資料說明(成員資料)和一組操作資料或傳遞訊息的函式(成員函式)。
類是對具有相同屬性和行為的一組物件的抽象與統一描述。是使用者自定義的資料型別
2.(1)類的說明語句一般形式為:
class <類名>
{
public:
共有段資料成員和成員函式;
Protected:
保護段資料成員和成員函式;
Private:
私有段資料成員和成員函式;
};
關鍵字private
Protected宣告保護成員。保護成員在類和它的派生類中可見。
Public 宣告共有成員。共有成員是類的介面,在類中和類外可見
(2)注意事項、
類的成員可以是其他類的物件,但不能以類自身的物件作為本類的成員,而類自身的指標和引用可以作為類的成員。
類定義必須以分號“;”結束。
類與結構體的區別:
沒有明確指定類成員的訪問許可權時,C++結構體的成員是公有的,而類的成員是私有的。
(3)資料成員和成員函式
class Date
{public:
void SetDate(int y,int m,int d);
int IsLeapYear();
void PrintDate();
private:
int year,month,day;
};
在這個類的定義中
定義了三個私有資料成員:year,month,day
成員函式在類外的定義使用作用域區分符進行說明,即以下的形式:
返回型別 類名::函式名(引數表)
則將以上的三個成員函式可以輸入為:
void Date::SetDate(int y,int m,int d)
{year=y;
month=m;
day=y;
}
int Date::IsLeapYear()
{return(year%4==0&&year%100!=0)||(year%400==0);}
Void Date::PrintDate()
{cout<<year<<”.”<<month<<”.”<<day;}
成員函式有兩個作用:
一是操作資料成員,包括訪問和修改資料成員;
二是用於協同不同的物件操作,稱為傳遞訊息
當然成員函式也可以在函式類內實現
class Coord{
public:
void setCoord(int a,int b)
{ x=a; y=b;}
int getx()
{ return x;}
int gety()
{ retrun y;}
private:
int x,y;
};
在類內定義的函式被預設成行內函數,
行內函數用inline修飾,它的作用是減少頻繁呼叫小子程式的執行的時間開銷
過載函式
函式名相同,但引數不相同(型別不同,或者個數不同)的一組函式。
它的作用是用來處理不同資料型別的相似功能的任務
例如以下coding
#include<iostream>
using namespace std ;
int abs ( int a ) ;
double abs ( double f ) ;
int main ()
{ cout<< abs ( -5 ) << endl;
cout << abs ( -7.8 )<< endl ;
}
int abs ( int a )
{ return a < 0 ? -a : a; }
double abs ( double f )
{ return f < 0 ? -f : f ; }
這裡定義的abs函式,用來處理了兩種資料型別的(int型和double型)絕對值,這樣就可以利用過載函式;
3.物件
物件是類的例項或實體。
類與物件的關係,如同C++基本資料型別和該型別的變數之間的關係。
定義的基本格式為:
類名 物件名1,物件名2,物件名3,,,,,
比如以下定義的點類:
class Point
{
public:
voidInitPoint(float PointA_x, float PointA_y);
voidMove(float New_x, float New_y);
floatGetPointx();
floatGetPointy();
private:
float P1_x,P1_y;
};
int main()
{
Point p1,p2;
}
在主函式中就定義了兩個Point類的物件p1和p2
那麼,物件該如何呼叫類中的成員函式?
有兩種方法
法一:使用運算子“.” 來進行呼叫
例如:
#include<iostream>
using namespace std;
classTclass
{public:
Int x,y;
voidprint()
{cout<<x<<”,”<<y;}
};
Intmain()
{ Tclasstest;
test.x=100; //訪問共有資料成員
test.y=200;
test.print(); //共有段成員函式
}
法二:
用指標訪問物件成員
#include<iostream>
usingnamespace std;
classTclass
{public:
Int x,y;
Voidprint()
{cout<<x<<”,”<<y<<endl;
};
intadd(Tclass *ptf)
{rutern(ptf->x+ptf->y);
}
Intmain()
{Tclasstest,*pt=&test; //說明一個物件test和物件指標pt
pt->x=100; //用物件指標訪問資料成員
pt->y=200;
pt->print(); //用物件指標呼叫成員函式
test.x=150;
test.y=450;
test.print();
cout<<”x+y=”<<add(&test)<<endl; //把物件地址傳給指標引數
}
4.this指標
在呼叫成員函式的時候,我們會用到指標的方法,在C++中,同一類的各個物件都有自己的資料成員的儲存空間,但系統不會為每個類的物件建立建立成員函式副本,類的成員函式可以被各個物件呼叫。例如,說明一個Tclass類的物件test,函式 呼叫:
test.print()
在物件test上操作。同樣,若說明一個指向Tclass的指標:
Tclass *p;
則函式呼叫為:p->print()
在*P上操作。
但從成員函式:
voidTclass::print();
的引數上看,並不知道它正在哪個物件上操作。其實C++為成員函式提供一個稱為this的隱含指標引數,所以,我們常常稱成員函式擁有this指標。
當一個物件類呼叫類的成員函式時,物件的地址被傳遞給this指標,即this指標指向了該物件。This是一個隱含指標,不能被顯示說明,但可以在成員函式中顯示使用。
Tclass的成員函式print可以這樣書寫:
voidTclass::print()
{cout<<this->x<<”,”<<this->y<<endl;}
this指標的顯示使用主要在運算子過載,自引用等場合。
5.建構函式與解構函式
(1)建構函式的特點:
與類名相同;
建構函式可以有任意型別的引數,但不能又返回型別;
建構函式在建立類物件時自動呼叫;
當用戶沒有自定義建構函式時,系統將自動定義一個預設的建構函式(即一個空函式)
建構函式的作用是:
為物件分配空間;
對資料成員進行賦值;
請求其他資源;
建構函式的原型是:
類名::類名(引數表);
例如以下的程式,是為Date類建立一個建構函式
#include <iostream.h>
class Date {
public:
Date(); // 無參建構函式
Date(int y,int m,int d);
void showDate();
private:
int year, month, day;
};
Date::Date() // 建構函式的實現
{ year=0; month=0; day=0; }
Date::Date(int y,int m,int d)
{ year=y; month=m; day=d; }
inline void Date::showDate()
{ cout<<year<<"."<<month<<"."<<day<<endl;}
int main()
{
Date a_date,b_date(2014,3,25); //a_date是無參型別,b_date是帶參的型別
a_date.showDate();
b_date.showDate();
return 0;
}
則這個程式的輸出為
0.0.0
2014.3.25
利用建構函式建立物件,有以下兩種方式:
①利用建構函式直接建立物件,其一般形式為
類名 物件名(實參表)
這裡的“類名”與建構函式名相同
“實參表”是為建構函式提供的實際引數
比如 Date b_date(2014,3,25);
②利用建構函式建立物件時,通過指標和new來實現,
語法為:
類名 *指標變數=new 類名(實參表)
例如以下的程式:
intmain()
{Date*date 1;
date=newDate(1998,4,28);
cout<<”Date1 output 1:”<<endl;
date1->showDate();
deletedate 1;
return 0;
}
(2)建構函式初始化成員有兩種方法
a.使用建構函式的函式體來進行初始化
b.使用建構函式的初始化列表進行初始化
a.coding
classDate
{intd,m,y;
public:
Date(intdd,int mm,int yy)
{d=dd;
m=mm;
y=yy;
}
Date(intdd,int mm)
{d=dd;
m=mm;
}
}
b.coding
funname(引數列表):初始化列表
{函式體,可以是空函式體}
初始化列表的形式:
成員名1(形參名1),成員名(形參名2)……
ClassDate
{intd,m,y;
Public:
Date(intdd,int mm,int yy):d(dd),m(mm),y(yy)
{}
Date(intdd,int mm):d(dd),m(mm)
{}
};
必須使用引數初始化列表對資料成員進行初始化的幾種情況
資料成員為常量
資料成員為引用型別
資料成員為沒有無參建構函式的類的物件
以下這個程式是資料成員為常量,資料成員為引用型別
#include<iostream>
usingnamespace std;
class A
{public:
A(inti):x(i),rx(x),pi(3.14)
{};
voiddisplay()
{cout<<”x=”<<x<<”rx=”<<rx<<”pi=”<<pi<<endl;}
Private:
Intx,℞
constfloat pi;
};
intmain()
{A aa(10);
aa.display();
return 0;
}
類成員初始化的順序:也就是定義順序
按照資料成員在類中的宣告順序進行初始化,與初始化成員列表中出現的順序無關;
(3)建構函式的過載
class Box
{public:Box();
Box(int,int,int);
Intvolume();
Private:
intheight,width,length;
};
Box::Box()
{height=10;
width=10;
length=10;
}
Box::Box(inth,int w,int l):height(h),width(w),length(l)
{}
Int Box::volume()
{returnwidth*length*height;}
intamin()
{Boxbox();
Cout<<”Thevolume is”<<box1.volume();
Boxbox2(12,30,25);
cout<<”Thevolume is”<<box2.volume();//如果出現這樣的情況 Box box3(30,25)//這樣的話 第三個數為10,缺哪個那個增添為10
return 0;
}
(2)解構函式
解構函式是與建構函式相對應的,解構函式是在類名之前冠以一個波浪號“~”解構函式沒有引數,也沒有返回型別。解構函式在類物件作用域結束時自動呼叫。
基本形式是
類名::~類名()
例如以下這個程式
#include<iostream>
usingnamespace std;
class test
{ private:
int num;
float f1;
public:
test();
test(int n,float f);
~test();
};
test::test()
{num,=0;
f1=0.0;
}
test::test(int n,float f)
{num=n;
f1=f;
}
test::~test()
{cout<<”destructor isactive”<<endl;
}
int main()
{text x;
Cout<<”Exiting main”<<end;
}
執行結果為:
Exiting main
destructor is active
則解構函式的呼叫發生在上面這個程式的最後一條輸出語句之後,當物件的生存期結束時,程式呼叫解構函式,並回收佔用記憶體。
#include <cstring>
#include <iostream>
using namespace std;
class Student{
public:
Student(intn, char * a_name, char s) {
num=n;name=new char[strlen(a_name)+1];
strcpy(name,a_name); sex=s;
cout<<"Constructorcalled."<<endl;
}
~Student(){
cout<<"Destructorcalled."<<endl;
delete[]name; //delete【】是釋放連續空間的功能
}
voiddisplay()
{cout<<name<<endl;cout<<num<<endl;cout<<sex<<endl; }
private:
intnum; char *name; char sex;
};
6.複製建構函式
複製建構函式要求有一個類型別的引用引數
類名::類名(const 類名&引用名,…);
為保證所引用物件不被修改,通常把引用引數說明為const引數例如:
class A
{public:
A(int);
A(consta&,int=1);
};
A a(1); //建立物件a,呼叫A(int)
A b(a,0); //建立物件b,呼叫 A(const A&,int=1)
A c=b; //建立物件c,呼叫A(constA&,int=1)
第一條語句建立物件a,呼叫一般的建構函式A(int)。第二條和第三條都呼叫了複製建構函式,複製物件a建立吧,複製物件b建立C,
複製建構函式的特點:
複製建構函式名與類名相同,並且也沒有返回值型別。
複製建構函式可寫在類中,