歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> C++面向對象

C++面向對象

日期:2017/2/28 13:50:26   编辑:Linux教程

此文僅作為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成員函數)
Copyright © Linux教程網 All Rights Reserved