首頁 > 軟體

C++物件導向

2020-06-16 17:36:34

此文僅作為C++考研專業課的複習內容。

物件導向

建構函式

在物件被建立的時候將自動呼叫。

複製建構函式

形參是本類物件的參照。其作用是使用一個已經存在的物件,去初始化一個同類的新物件。

複製建構函式在以下三種情況會被呼叫。

  1. 當用類的一個物件去初始化該類的另一個物件。

    Point a(1,2);
    //兩種寫法都會呼叫複製建構函式,只是寫法上不同。
    Point b(a);//用物件a初始化b
    Point c = a;////用物件a初始化b
  2. 如果函數的形參是類的物件,呼叫函數時,進行形參和實參結合時。

    void foo(Point p){
     cout<<p.getX()<<endl;
    }
    int main(){
     Point a(1,2);
     foo(a);
     return 0;
    }
    注:值傳遞時呼叫複製建構函式,傳參照時不會呼叫。所以傳遞比較大的物件時,傳遞參照效率會更高。
  3. 如果函數的返回值是類的物件,函數執行完成返回撥用者時。

    Point foo(){
     Point a(1,2);
     return a ;
    }
    int main(){
     Point b;
     b= foo();
     return 0;
    }

    註:a離開函數foo()時,a物件會消亡,此時會呼叫複製建構函式建立一個無名的臨時物件存在於表示式b= foo()中。

解構函式

解構函式是用來完成物件被刪除前的一些清理工作,是在物件的生存期即將結束的時候被自動呼叫的。

解構函式的呼叫執行順序與建構函式剛好相反。

類的組合

  • 當建立類的物件時,會先初始化類中的其他物件和基本資料型別的成員變數。建構函式按以下順序呼叫:
  1. 呼叫內嵌物件的建構函式。用順序按照內嵌物件在組合類中定義的順序。注意,內嵌物件在建構函式的初始化列表中出現的順序與內嵌物件建構函式的呼叫順序均無關。
  2. 執行本類建構函式的函數體。
  • 解構函式的呼叫執行順序與建構函式剛好相反。解構函式的函數體執行完成後,內嵌物件的解構函式一一執行。內嵌物件的解構函式呼叫順序和他們在組合類中的類定義中出現的次序剛好相反。
  • 類的拷貝建構函式編寫。需要為內嵌成員物件的複製建構函式傳遞引數。

    class Point{
    public:
    Point(Point& p);
    };
    class Line{
    private:
    Point p1,p2;
    public:
    Line(Point& p1,Point& p2);
    };
    Line::Line(Point& xp1,Point& xp2):p1(xp1),p2(xp2){
    //to-do something
    }  

    前向參照申明

    class B; //前向參照申明
    class A{
    public:
    void foo(B b);
    };
    class B{
    public:
    void bar(A a);
    };  

    當類發生迴圈依賴時,需要使用前向參照申明。但是即便是存在前向參照申明,但是無法直接定義類的物件。

類的靜態成員

靜態資料成員

static修飾。類屬性是描述類的所有物件共同特徵的資料項,對任何範例,他的屬性值是相同的。

class Point{
public:
    Point(){
        count++;
    }
    void show_count(){
        cout<<count<<endl;
    }
private:
    static int count;
};
int Point::count = 0; 

靜態資料成員單獨在類外初始化,需要專門為他們分配空間。

靜態函數成員

靜態成員函數可以直接存取該類的靜態資料和函數成員。而存取非靜態成員必須通過物件名。

class A{
public:
    staticvoid foo(A a);
private:
    int x;
};
void A::foo(A a){
    cout<<x; //對x的參照時錯誤的。
    cout<<a.x; //正確。
}

友元

友元關係提供了不同類或物件的成員函數之間、類的成員函數與一般函數之間進行資料共用的機制。

友元的特點

  • 友元關係無法傳遞。
  • 友元關係是單向的。
  • 友元關係不能被繼承。

友元函數

友元函數是在類中用關鍵字friend修飾的非成員函數。可以是普通函數,也可以是其他類的成員函數。類的友元函數可以通過物件名存取類的私有和保護成員。

class Point{
    Point(int x,int y);
    int getX();
    int getY();
    friendfloat dist (Point &p1,Point &p2);
private:
    int x,y;
};
float dist(Point &p1,Point &p2){
    double x = p1.x - p2.x;
    double y = p1.y - p2.y;
    return static_cast<float>(sqrt(x * x + y * y));
}
int main(){
    Point p1(1,1),p2(4,5);
    cout<<dist(p1,p2);
    return 0;
}

友元類

同友元函數一樣,一個類也可以將另一個類宣告為友元類。若A類為B類的友元類,則A類的所有成員都是B類的友元函數,都可以存取B類的私有和保護成員

class A{
public:
    int getX();
    friend class B; //B是A的友元類
private:
    int x;
};
class B{
public:
    void set(int i);
private:
    A a;
};
void B::set(int i){
    a.x = i; //由於B是A的友元類,所以在B的成員函數中可以存取A類物件的私有成員。
};

共用資料的保護

常物件

資料成員值在物件的整個生存期間內不改變。常物件必須進行初始化,而且不能被更新。

const A a(3,4);

用const修飾的類成員

  1. 常成員函數

型別說明符 函數名 (參數列) const
eg: void foo() const;

  • 定義和申明時都要帶const關鍵字。
  • 常物件只能呼叫常成員函數。
  • 無論是否通過常物件呼叫常成員函數,在函數呼叫期間,目的物件都被視為常物件,因此常成員函數不能更新目的物件的資料成員,也不能針對目的物件呼叫其非const修飾的函數。

    class A {
    public :
     void foo() const{
        cout<<"foo const"<<endl;
        this->bar();//error C2662: “A::bar”: 不能將“this”指標從“const A”轉換為“A &
        this->x = 1;//error C3490: 由於正在通過常數物件存取“x”,因此無法對其進行修改
    }
    void bar(){
        cout<<"bar"<<endl;
    }
    private :
    int x;
    };
  • const可以區分函數的過載。例如申明如下函數。

    void print();
    void print() const;

    此時常物件會呼叫第二個,非常物件就近呼叫第一個。
  1. 常資料成員
    常資料成員只能通過建構函式的初始化列表來指定具體值

    class A {
    public :
    A(int i):a(i){
    //a = i; //error
    }
    private :
    const int a;
    static const int b;
    //static const int b = 10; //正確 int或enum的靜態常數可在類中直接指定值。
    };
    const int A::b = 10;
  2. 常參照
    所參照的物件無法更新。
    需要注意的是:
  • 非const的參照只能系結到普通物件,但常參照可以繫結到常物件。
  • 常參照物件,通過該參照存取時,只能把物件當做常物件。(不能修改資料成員和呼叫非const成員函數)

本文永久更新連結地址http://www.linuxidc.com/Linux/2016-08/133844.htm


IT145.com E-mail:sddin#qq.com