【C++】const成员 | 取地址运算符重载

目录

Ⅰ. const成员

两种const

const成员函数

Ⅱ. 取地址运算符重载

引入

普通对象取地址

const对象取地址

什么时候要手动实现operator& ?


Ⅰ. const成员

两种const

我们知道,用const修饰 能起到保护,使之不被修改的作用。

修饰指针的const有两种位置:

我们学过的this指针,就被后者所修饰,因此无法被修改。

const成员函数

➡️为了保护函数里的成员,使不被修改,C++引入了const成员函数。

“const成员函数” ,就是被const修饰的成员函数。

const的存在,使我们不能对任何成员进行修改。

➡️它长这样:

void Date::Print() const
{
    ……
}

这个函数相当于:

void Date::Print(const Date* const this)
{
    ……
}

❗注意:前后两个const的意义是不一样的。

前者修饰*this,保护 this指向的空间的内容 不被修改。

后者修饰this,保护this指针不被修改。

❓🤔这个const的位置好怪啊,为啥要放在最末尾?而不是开头?

const:爷就长得怪,咋地!

不能放开头啊,那样const就成修饰返回值的了。

➡️对比this指针的类型:

普通函数:类型* const

const成员函数:const 类型* const

➡️权限问题:

就像公司上下级关系,权限大的可以调用权限小的;

而权限小的不可以调用权限大的。

解释这张图:

被const修饰的Print() / d2,因为被限制了内容不能修改,所以权限相对更低。

未被const修饰的Print() / d1,可被修改,自由度更高,权限相对更高。

彼此的关系就用上下级、平级的关系来理解。

所以,const成员函数内部 不可调用 其他非const成员函数;

而非const……可调用……const……。

➡️什么时候加const?

如果一个函数不用修改,性质是只读的,那就加上const来保护。

如果其性质是可读可写,那就不能加。

Ⅱ. 取地址运算符重载

先亮身份:类的六大默认成员函数之一。

函数名:operator&

作用:自定义类型的取地址

引入

来看这个例子。我们知道,自定义类型的运算 需要我们自己去实现 运算符重载,运算符&同样如此。

而这里,我们没写operator&,那究竟能否取地址成功呢?

class Date {
public:
    Date(int year = 1900, int month = 1, int day = 1) {
        _year = year;
        _month = month;
        _day = day;
    }
private:
    int _year;
    int _month;
    int _day;
};
​
int main() {
​
    Date d1(2000, 1, 1);
    cout << &d1 << endl;   //前面没写operator&
                           //能否取地址成功呢?
    return 0;
}

结果:

 

取地址成功!

❓But why?

💡这是因为,C++很贴心地将 取地址运算符重载 纳入默认成员函数。

也就是说,operator& 和前几位默认成员函数的福利一样:

如果我们写了,编译器会自动调用;

如果没写,编译器会自动生成,并自动调用。

❓取地址运算符重载长啥样?

Here comes the model:

Date* operator&()
{
    return this;
}

取地址运算符重载分两种:

1.& 普通对象

2.& const修饰的对象

普通对象取地址

很easy,不详讲了。我们来手动实现一下:

class Date {
public:
    Date(int year = 1900, int month = 1, int day = 1) {
        _year = year;
        _month = month;
        _day = day;
    }
​
    Date* operator&() {
        return this;    //this就是它的地址
    }
​
private:
    int _year;
    int _month;
    int _day;
};
​
int main() {
    Date d1(2000, 1, 1);
    cout << &d1 << endl;
​
    return 0;
}

const对象取地址

当对象被const修饰时,会特殊一些。

来看d1和d2的对比:

class Date {
public:
    Date(int year = 1900, int month = 1, int day = 1) {
        _year = year;
        _month = month;
        _day = day;
    }
    
    void Print(){
        printf("%d-%d-%d\n", this->_year, this->_month, this->_day);
    }
​
private:
    int _year;
    int _month;
    int _day;
};
​
int main() {
    Date d1(2000, 1, 1);      //普通对象d1
    d1.Print();
​
    const Date d2(2077,1,1);  //被const修饰的对象d2
    d2.Print();
​
    return 0;
}

然而,压根编译不过去:

普通对象d1没问题,而const修饰的d2却亮红牌了,为啥?

其实,const成员报错的原因往往是🤔……权限的放大!

来分析下:

Print函数中,this指针的类型是:Date* const

而d2的类型是:const Date* const

所以说,d2去调用Print(),是一次权限的放大!是以下犯上,大逆不道!

💡对此,解决方案是:

const修饰的对象,应调用const取地址运算符重载

即,d2应调用:

void  Print() const{
          printf("%d-%d-%d\n", this->_year, this->_month, this->_day);
}

什么时候要手动实现operator& ?

我们尽可放宽心,即使是const对象,编译器仍会自动生成 相应的const operator&。

所以无论是 普通对象 还是 const对象 取地址,我们都无需手动实现operator&。

大部分情况下,取地址运算符重载都不用自己写,编译器默认生成的就够用了。

只有特殊情况才需要重载,

如:你不希望别人取到你的地址。那这时就:

Date* operator&(){
    return nullptr;
}

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值