1. 程式人生 > >c++類的靜態成員,建構函式

c++類的靜態成員,建構函式

一、靜態成員

靜態成員是處理同一個類的不同物件之間資料和函式共享問題的。

1.靜態資料成員

我們所說的“一個類的所有物件具有相同的屬性”是指例項屬性,以非靜態資料成員表示,如Employee中的empNo.id.它們在類的每一個物件中都具有一個複本,是每個物件區別於其他物件的特徵。如果某個屬性為整個類所共有(如:僱員總數)不屬於任何一個具體物件,則採用static關鍵字來宣告為靜態成員。

靜態成員在每個類中只有一個副本,由該類所有物件共同維護和使用,從而實現同一類的不同物件之間的資料共享。

靜態資料成員具有靜態生存期。通過類名對其訪問“類名::識別符號”。

在類中的定義僅僅對靜態資料成員進行引用性宣告,必須在名稱空間作用域的某個地方使用類名限定定義性宣告,靜態資料成員的定義和初始化在類外進行,以此法為它們分配空間。

#include <iostream>
using namespace std;

class Point{
public:
    Point(int x=0,int y=0):x(x),y(y){
        count++;//在建構函式中對count累加,所有物件共同維護同一個count
    }
    Point(Point &p){//複製建構函式
        x=p.x;
        y=p.y;
        count++;
    }
    ~Point(){count--;}
    int getX(){return x;}
    int getY(){return y;}
    void showCount(){//輸出靜態資料成員
        cout<<" Object count="<<count<<endl;
    }
private:
    int x,y;
    static int count;//靜態資料成員宣告,用於記錄點的個數
};
int Point::count=0;//靜態資料成員定義和初始化,使用類名限定

int main()
{
    Point a(4,5);
    cout<<"Point A: "<<a.getX()<<","<<a.getY();
    a.showCount();
    Point b(a);
    cout<<"Point B: "<<b.getX()<<","<<b.getY();
    b.showCount();
    return 0;
}

結果:

Point A: 4,5 Object count=1

Point B: 4,5 Object count=2

2.靜態函式成員

靜態函式成員即使用static關鍵字宣告的函式成員,屬於整個類,由同一個類的所有物件共有,為這些物件所共享。

靜態成員函式可以通過類名或物件名來呼叫,而非靜態成員函式只能通過物件名來呼叫。

靜態成員函式可以直接訪問該類的靜態資料和函式成員,而訪問非靜態成員必須通過物件名。

#include <iostream>
using namespace std;

class Point{
public:
    Point(int x=0,int y=0):x(x),y(y){
        count++;//在建構函式中對count累加,所有物件共同維護同一個count
    }
    Point(Point &p){//複製建構函式
        x=p.x;
        y=p.y;
        count++;
    }
    ~Point(){count--;}
    int getX(){return x;}
    int getY(){return y;}
    static void showCount(){
        cout<<" Object count="<<count<<endl;
    }
private:
    int x,y;
    static int count;//靜態資料成員宣告,用於記錄點的個數
};
int Point::count=0;//靜態資料成員定義和初始化,使用類名限定

int main()
{
    Point a(4,5);
    cout<<"Point A: "<<a.getX()<<","<<a.getY();
    Point::showCount();
    Point b(a);
    cout<<"Point B: "<<b.getX()<<","<<b.getY();
    Point::showCount();
    return 0;
}

結果:

Point A: 4,5 Object count=1

Point B: 4,5 Object count=2

二、研究C語言typedef語句和巨集的用法,以及在寫Win32 API程式過程中的用途

1、typedef的用法

在C/C++中,typedef常用來定義一個識別符號及關鍵字的別名,它是語言編譯過程的一部分,但它並不實際分配記憶體空間,例項像:

typedef    int       INT;
typedef    int       ARRAY[10];
typedef   (int*)   pINT;

typedef可以增強程式的可讀性,以及識別符號的靈活性,但它也有“非直觀性”等缺點。為了增加可讀性為識別符號起的新名稱。

2、#define的用法

#define為巨集定義語句,通常用它來定義常量(包括無參量與帶參量),以及用來實現那些“表面似和善、背後一長串”的巨集,它本身並不在編譯過程中進行,而是在這之前(預處理過程)就已經完成了,但也因此難以發現潛在的錯誤及其它程式碼維護問題,它的例項像:

#define   INT             int
#define   TRUE         1
#define   Add(a,b)     ((a)+(b));
#define   Loop_10    for (int i=0; i<10; i++)

巨集定義只是簡單的字串代換(原地擴充套件),而typedef則不是原地擴充套件,它的新名字具有一定的封裝性,以致於新命名的識別符號具有更易定義變數的功能。

三、建構函式

建構函式的作用就是在物件被建立時利用特定的值構造物件,將物件初始化為一個特定的狀態。

建構函式的函式名與類名相同,而且沒有返回值。

建構函式在物件被建立時被自動呼叫。呼叫時無需提供引數的建構函式稱為預設建構函式。如果類中沒有寫建構函式,編譯器會自動生成一個隱含的預設建構函式,該建構函式的引數列表和函式體皆為空。

複製建構函式是一種特殊的建構函式,具有一般建構函式的所有特性,其形參是本類的物件的引用。其作用是使用一個已經存在的物件(由複製建構函式的引數指定),去初始化同類的一個新物件。

#include <iostream>
using namespace std;
class Point //Point 類的宣告
{
public: //外部介面
 Point(int xx=0, int yy=0) {X=xx;Y=yy;} //建構函式
 Point(Point &p); //拷貝建構函式
 int GetX() {return X;}
 int GetY() {return Y;}
private: //私有資料
 int X,Y;
};
//成員函式的實現
Point::Point(Point &p)
{
 X=p.X;
 Y=p.Y;
 cout<<"Calling the copy constructor"<<endl;
}
//形參為Point類物件的函式
void fun1(Point p)
{ cout<<p.GetX()<<endl;
}
//返回值為Point類物件的函式
Point fun2()
{
 Point A(1,2);
 return A;
}
//主程式
int main()
{
 Point A(4,5); //第一個物件A
 Point B(A);                  //情況一,用A初始化B。第一次呼叫拷貝建構函式
 cout<<B.GetX()<<endl;
 fun1(B);  //情況二,物件B作為fun1的實參。第二次呼叫拷貝建構函式
 B=fun2();  //情況三,函式的返回值是類物件,函式返回時,呼叫拷貝建構函式
 cout<<B.GetX()<<endl;
 return 0;
}

四、行內函數

行內函數不是在呼叫時發生控制轉移,而是在編譯時將函式體嵌入在每一個呼叫處。

對於一些功能簡單,規模較小又使用頻繁的函式可以設計為行內函數

#include<iostream>

usingnamespace std;

classClock{

public:

voidsetTime(int newH=0,int newM=0,int newS=0);

voidshowTime();

private:

inthour,minute,second;

};

voidClock::setTime(int newH, int newM, int newS){

hour=newH;minute=newM;second=newS;

}

inlinevoid Clock::showTime(){//行內函數

cout<<hour<<":"<<minute<<":"<<second<<endl;

}

intmain()

{

ClockmyClock;

cout<<"Firsttime set and output:"<<endl;

myClock.setTime();

myClock.showTime();

cout<<"Secondtime set and output:"<<endl;

myClock.setTime(8,30,30);

myClock.showTime();

return0;

}