C++封裝 之 常物件成員 和 常成員函式
阿新 • • 發佈:2021-08-25
常物件成員 和 常成員函式
定義兩個類:
座標類: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;
}