1. 程式人生 > 其它 >C++封裝 之 常物件成員 和 常成員函式

C++封裝 之 常物件成員 和 常成員函式

常物件成員 和 常成員函式

定義兩個類:

    座標類:Coordinate
        資料成員:橫座標m_iX、縱座標m_iY
        成員函式:建構函式、解構函式、資料封裝函式
    線段類:Line
        資料成員:點A m_CoorA、點B m_CoorB
        成員函式:建構函式、解構函式、資料封裝函式、資訊列印函式
原始碼
#include<iostream>
using namespace std;

/***************** 定義 Coordinate 類 *****************/
class Coordinate{
public:
    Coordinate(int x, int y);   
    ~Coordinate(); 
    void setX(int x);
    void setY(int y);
    int getX();
    int getY();
private:
    int m_iX;
    int m_iY;
};

/***************** 定義 Line 類 *****************/
class Line{
public:
    Line(int x1, int y1, int x2, int y2);   
    ~Line();
    void setA(int x, int y);
    void setB(int x, int y);
    void printInfo();
private:
    Coordinate m_CoorA;    // 物件成員
    Coordinate m_CoorB;    // 物件成員
};

/********************** Coordinate類的成員函式 ***************************/
Coordinate::Coordinate(int x, int y){  
    m_iX = x;
    m_iY = y;
}   
Coordinate::~Coordinate(){  
}
void Coordinate::setX(int x){
    m_iX = x;
}
void Coordinate::setY(int y){
    m_iY = y;
} 
int Coordinate::getX(){
    return m_iX;
}
int Coordinate::getY(){
    return m_iY;
}

/********************** Line類的成員函式 ***************************/
Line::Line(int x1, int y1, int x2, int y2):m_CoorA(x1, y1),m_CoorB(x2, y2){  //必須使用初始化列表初始化物件成員
}
Line::~Line(){  
}

void Line::setA(int x, int y){
    m_CoorA.setX(x);
    m_CoorA.setY(y);
}
void Line::setB(int x, int y){
    m_CoorB.setX(x);
    m_CoorB.setY(y);
}
void Line::printInfo(){  
    cout << "A = ("<< m_CoorA.getX() << "," << m_CoorA.getY() << ")" << endl;
    cout << "B = ("<< m_CoorB.getX() << "," << m_CoorB.getY() << ")" << endl;
}

/************************** 測試主函式 *******************************/
int main(){
    
    Line *p = new Line(1,2,3,4);   // 例項化物件時,直接傳引數 

    p->printInfo();         //列印

    delete p;               // 銷燬Line物件 */
    p = NULL;               //置空指標
    system("pause");
    return 0;
}
執行結果
A = (1,2)
B = (3,4)

常物件成員

改造上面的原始碼,將Line類的資料成員m_CoorA修改為常物件成員:

class Line{
public:
    Line(int x1, int y1, int x2, int y2);   
    ~Line();
    void setA(int x, int y);
    void setB(int x, int y);
    void printInfo();
private:
    const Coordinate m_CoorA;    // 常物件成員 , 也可以寫為 Coordinate const m_CoorA;
    Coordinate m_CoorB;          // 物件成員
};
報錯的位置
void Line::setA(int x, int y){
    m_CoorA.setX(x);  //報錯
    m_CoorA.setY(y);  //報錯
}
void Line::printInfo(){  
    cout << "A = ("<< m_CoorA.getX() << "," << m_CoorA.getY() << ")" << endl;  //報錯
    cout << "B = ("<< m_CoorB.getX() << "," << m_CoorB.getY() << ")" << endl;
}

報錯原因分析:
void setX(int x){
    
}

在編譯時相當於:

void setX(Coordinate *this, int x){
    
}

成員函式setX()預設的this指標指向的物件既有讀許可權、也有寫許可權,而m_CoorA是常物件成員,沒有寫許可權,所以 m_CoorA.setX(x)錯誤。

常成員函式

上面錯誤的解決辦法:將普通成員函式修改為常成員函式。即setX()、setY()、getX()、getY()等要修改為常成員函式。

常成員函式不能修改資料成員的值,所以setX()和setY()修改為常成員函式是沒有意義的,只能修改getX()和getY()。

getX()和getY()宣告和定義的地方都要加const:

class Coordinate{
public:
    Coordinate(int x, int y);   
    ~Coordinate(); 
    void setX(int x) ;
    void setY(int y);
    int getX() const;           //常成員函式宣告
    int getY() const;           //常成員函式宣告
private:
    int m_iX;
    int m_iY;
};

int Coordinate::getX() const{  //常成員函式定義,注意const前面應該有一個空格,否則編譯不通過
    return m_iX;
}
int Coordinate::getY() const{  //常成員函式定義
    return m_iY;
}

編譯時,

int getX() const;           //常成員函式宣告

相當於

int getX(const Coordinate *this);      

也就是說,常成員函式getX()引數列表中的this指標是沒有寫許可權的,函式printInfo()中傳入的正好就是沒有寫許可權的常物件成員的this指標,函式printInfo()中的報錯解決,但set()中的報錯還沒有解決,直接註釋掉。

互為過載

常成員函式與普通成員函式同名的情況下,可以互為過載

class Line{
public:
    Line(int x1, int y1, int x2, int y2);   
    ~Line();
    //void setA(int x, int y);
    void setB(int x, int y);
    void printInfo();
    void printInfo() const;      //常成員函式
private:
    const Coordinate m_CoorA;    
    Coordinate m_CoorB;         
};

void Line::printInfo(){  
    cout << "A = ("<< m_CoorA.getX() << "," << m_CoorA.getY() << ")" << endl;  //報錯,將getX()和getY()修改為常成員函式後錯誤解決
    cout << "B = ("<< m_CoorB.getX() << "," << m_CoorB.getY() << ")" << endl;
}

void Line::printInfo() const{  
    cout << "A = ("<< m_CoorA.getX() << "," << m_CoorA.getY() << ")" << endl;  //報錯,將getX()和getY()修改為常成員函式後錯誤解決
    cout << "B = ("<< m_CoorB.getX() << "," << m_CoorB.getY() << ")" << endl;
}

//上面程式碼編譯通過且正確執行

函式過載區分

兩個過載的成員函式(函式名、引數個數、引數型別都相同,區別在於其中一個成員函式的this指標是用const修飾的)如何分別呼叫的是哪一個函式呢?

例項化物件的時候也加const修飾符

int main(){
    
    Line *p = new Line(1,2,3,4);  
    p->printInfo();               //打印發現,呼叫的是普通的成員函式printInfo()

    Line const *p1 = new Line(1,2,3,4); //加const
    p1->printInfo();              //打印發現,呼叫的是常成員函式printInfo() const

    delete p;              
    p = NULL;               
    system("pause");
    return 0;
}