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;
}
posted @ 2021-08-25 12:01  赶紧学习  阅读(43)  评论(0编辑  收藏  举报