1.常对象成员和常对象成员函数
(1)常对象成员
在之前的构造函数与析构函数部分已讲过,类似下图定义的常对象成员(在初始化后无法赋其他值),在初始化时只能通过初始化列表在构造函数初始化
(2)常对象成员函数
const除了能应用于对象成员,也能应用于对象成员函数,如下图左半部分,但是在定义时如果按照右上图那样对数据成员进行赋值是错误的,而对普通成员函数赋值是正确的(如右下图)。
主要会出错的原因是因为常成员函数中不能改变数据成员的值。
在定义普通成员函数时,系统会给成员函数一个隐含的this指针
,如左图
在定义常对象函数时,这个this指针
就会变成常指针
,通过常指针去修改数据成员的值肯定是错误的。
此外,注意在类中定义的两个同名对象函数成员,尽管其中一个是常对象成员函数,这两个也互为重载,一般不推荐这么用
在用对象调用成员函数时,左图调用的是普通成员函数,右图是常对象成员函数。右图主要是通过const Coordinate coordinate (3,5);
定义了一个常对象,以调用常对象成员函数
注意这里只是为了区分两个重构函数而采用常对象,事实上常对象和普通对象都能够调用常成员函数以及普通成员函数。
(3)代码例子
这里的代码是在C++自学笔记(10)之对象成员与数组的基础之上改的,主要是体现const的应用
有两个类 Coordinate
与Line
①Coordinate.h
中
#pragma once
class Coordinate
{
public:
Coordinate(int x,int y);
~Coordinate();
void setX(int x);
//因为诸如int getX() const; 实际上为int getX(Coordinate *this) const;
//而在后面Line中调用常对象成员coorA,对应的是常指针,因此用常成员函数的方式 变为int getX(const Coordinate *this) const;
//这里因为setX函数等需要赋值,故只对getX和getY规定常成员函数
int getX() const;
void setY(int y);
int getY() const;
private:
int m_ix;
int m_iy;
};
②Coordinate.cpp
中
#include <iostream>
#include "Coordinate.h"
using namespace std;
Coordinate::Coordinate(int x,int y)
{
m_ix = x;
m_iy = y;
cout << "Coordinate" <<m_ix<<"."<<m_iy<< endl;
}
Coordinate::~Coordinate()
{
cout << "~Coordinate" << m_ix << "." << m_iy << endl;
}
void Coordinate::setX(int x)
{
m_ix = x;
}
int Coordinate::getX() const //常对象成员函数
{
return m_ix;
}
void Coordinate::setY(int y)
{
m_iy = y;
}
int Coordinate::getY() const ///常对象成员函数
{
return m_iy;
}
③Line.h
中
#pragma once
#include "Coordinate.h"
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 printfo();
void printfo() const; //定义一下试试是否会有重构函数
private:
const Coordinate m_coorA; // 将对象成员变成常成员
Coordinate m_coorB;
};
④Line.cpp
中
#include <iostream>
#include "Line.h"
using namespace std;
Line::Line(int x1, int y1, int x2, int y2):m_coorA(x1,y1),m_coorB(x2,y2)
{
cout<<" Line() "<<endl;
}
Line::~Line()
{
cout<< "~Line()" <<endl;
}
void Line::setA(int x, int y)
{
//这里m_coorA已经是常对象成员,不能更改,先注释掉
//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::printfo()
{
//这里getX和getY已经是常成员函数
cout << "printfo()" << endl;
cout << "(" << m_coorA.getX() << "," << m_coorA.getY() << ")" << endl;
cout << "(" << m_coorB.getX() << "," << m_coorB.getY() << ")" << endl;
}
void Line::printfo() const
{
cout << "printfo() const" << endl;
cout << "(" << m_coorA.getX() << "," << m_coorA.getY() << ")" << endl;
cout << "(" << m_coorB.getX() << "," << m_coorB.getY() << ")" << endl;
}
⑤主程序中
#include <iostream>
#include<stdlib.h>
#include <string.h>
#include "Coordinate.h"
#include "Line.h"
using namespace std;
int main(void)
{
Line line(1,2,3,4);
line.printfo();
const Line line1(5, 6, 7, 8); //定义常对象以调用常对象函数printfo
line1.printfo();
system("pause");
return 0;
}
运行结果如下
可见对数据成员为对象定义常对象成员时,该对象下的成员函数也要变常对象成员函数。且同名的常对象成员函数与普通成员函数构成重构函数。
2.对象的常指针与常引用
左图为类Coordinate
的定义,常指针和常引用的定义可见右图
常引用与常指针只有读权限,而getX
是有读写权限的一个函数,因此右图中的两个语句是错误的。
此外,如下图 Coor *const pCoor=&coor1;
这种情况pCoor是不可以再指向其他位置,但是指针本身指向的对象是可变的,可见 *const pCoor
是个有读写权限的指针,只限它指向的对象可以读写。
因此第一个语句pCoor->getY();
和第三个pCoor->printInfo();
是具有读写权限的指针指向读写功能的函数以及只读功能的函数(常对象成员函数)。而pCoor
不能再指向其他地址,因而第二个是错误的