【C++】const成员函数+取地址重载(默认成员函数)
const成员函数
我们来看这样一个类:
class A
{
public:
void Print()
{
cout << _a << endl;
}
private:
int _a = 10;
};
然后:
int main()
{
A a;
a.Print();
return 0;
}
定义一个对象a,并调用成员函数Print。
没有什么问题。
那这样呢?
加一个const修饰对象a。
然后我们发现调用Print就出错了。
那为什么呢?
其实呢是因为这里存在了一个权限放大的问题。
这也是我们之前学习过的:对于引用,还有指针来说,对它们进行赋值和初始化时,权限可以缩小,但不能放大。
我们来分析一下:
对于我们的成员函数Print,虽然看起来没有参数,但是是不是有一个隐藏参数,就是我们熟悉的this指针嘛。
那this指针的类型是啥?
this指针的类型:类类型* const
那对于当前这个类来说就是A* const this,const 修饰的是指针this,即指针this不能被修改,但this指向的内容可以被修改。
那我们传过来的参数是啥,是调用函数的对象的地址,即a的地址,但我们的对象a是const修饰的,所以传过来的地址的是const A* &a,const修饰的是该地址指向的内容,即对象a不能被修改。
那这样的话,传给this,this可以修改其指向的内容即对象a,所以就是权限放大了。
所以这里报错了。
那怎么解决呢?
🆗,如果我们可以把this指针的类型也变成const A*是不是就可以了啊。
但是this指针的类型是我们想改变就能改变的吗?
this指针是类成员函数中的一个隐藏参数,我们是没法直接改变它的。
那就没有办法了吗?
办法肯定是有的:
我们只需在对应成员函数的括号后面加一个const 就行了。
这就是我们要学的const成员函数:
const修饰的“成员函数”称之为const成员函数。
const修饰类成员函数,实际修饰的是
*this
,这样this指向的对象将不能被修改。
那这样this指针的类型就也变成了const A*
了,这样就可以传了。
但是我们平时定义一个对象好像一般也不会在前面加一个const,那这个用处是不是不大啊?
🆗,虽然定义对象时我们一般不加const,但是我们是不是可能经常会这样搞:
void Func(const A& x)
{
x.Print();
}
首先这里传引用与传值相比减少拷贝,然后如果我们不想对象被改变的话,不是一般会加一个const嘛。
那当前这种情况:
class A
{
public:
void Print()
{
cout << _a << endl;
}
private:
int _a = 10;
};
void Func(const A& x)
{
x.Print();
}
int main()
{
A a;
Func(a);
return 0;
}
x是a的引用(别名),a没有被const修饰,然后在Func
里,x是被cosnt修饰的,x去调用Print
,这里是不是也是权限放大了。
那这是不是跟我们开始讲的那个例子一样啊,怎么解决?
把Print变成const成员函数就行了:
像这种情况其实还是比较常见的。
所以说:
对于类的成员函数,如果在成员函数内部不需要改变调用它的对象,最好呢都可以把它写成const成员函数。
另外,如果const成员函数的声明和定义是分开的,声明和定义都要加const。
取地址及const取地址操作符重载
类的6个成员函数呢,比较重要的前4个我已经学完了,最后还剩两个。
我们一起来看一下:
那剩下的两个默认成员函数呢都是取地址重载,包括对普通对象的取地址和对const对象取地址。
这两个默认成员函数呢一般不需要我们自己去实现,编译器会自动生成,绝大多数情况下我们用编译器自动生成的就行了。
我们可以试一下:
对普通对象取地址
对const对象取地址
所以这两个默认成员函数一般不需要我们自己写,用编译器默认生成的取地址的重载即可
但是,如果你想自己去重载一下的话当然也是可以的:
你可以自己指定一个地址返回。
这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!
🆗,那我们这篇文章的内容就先到这里,欢迎大家指正!!!
- 点赞
- 收藏
- 关注作者
评论(0)