1. 程式人生 > >類與物件課程筆記

類與物件課程筆記



類與物件

基礎知識

1.類的定義

類是面對物件程式設計實現資訊封裝的基礎。類是一種使用者定義型別,也稱類型別,每個類包含資料說明(成員資料)和一組操作資料或傳遞訊息的函式(成員函式)。

類是對具有相同屬性和行為的一組物件的抽象與統一描述。是使用者自定義的資料型別

2.1)類的說明語句一般形式為:

class <類名>

{

public:

共有段資料成員和成員函式;

Protected:

保護段資料成員和成員函式;

Private:

私有段資料成員和成員函式;

};

關鍵字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類的物件p1p2

那麼,物件該如何呼叫類中的成員函式?

有兩種方法

法一:使用運算子“.” 來進行呼叫

例如:

#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,&rx;

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,呼叫Aint

A b(a,0);    //建立物件b,呼叫 Aconst A&int=1

A c=b;      //建立物件c,呼叫AconstA&,int=1

第一條語句建立物件a,呼叫一般的建構函式Aint)。第二條和第三條都呼叫了複製建構函式,複製物件a建立吧,複製物件b建立C,

複製建構函式的特點:

複製建構函式名與類名相同,並且也沒有返回值型別。

複製建構函式可寫在類中,