当前位置:首页 » 《休闲阅读》 » 正文

C++从入门到精通——const与取地址重载

25 人参与  2024年04月20日 16:01  分类 : 《休闲阅读》  评论

点击全文阅读


const与取地址重载

前言一、const正常用法const成员函数问题`const`对象可以调用非`const`成员函数吗非`const`对象可以调用`const`成员函数吗`const`成员函数内可以调用其它的非`const`成员函数吗非`const`成员函数内可以调用其它的`const`成员函数吗假如函数出现多个变量,const修饰的是谁总结 二、取地址及const取地址操作符重载概念示例


前言

类的6个默认成员函数:如果一个类中什么成员都没有,简称为空类。

空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。

默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

class Date {};

在这里插入图片描述


一、const

正常用法

在C++中,可以使用const关键字来声明一个常量成员。常量成员是指在类中声明的成员变量被标记为只读,即不能在类的方法中进行修改。常量成员的值在对象创建时被初始化,并且在对象的整个生命周期中保持不变。

常量成员的声明方式为在成员变量的类型前加上const关键字。例如:

class MyClass {public:    const int myConst = 10; // 常量成员的声明和初始化};

在上述示例中,myConst被声明为一个常量成员,其初始值为10。

const成员函数

除了上面的这种用法外,C++在类里定义了新的const用法,将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

在这里插入图片描述
我们来看看下面的代码

class Date{public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << "Print()" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}void Print() const{cout << "Print()const" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}private:int _year; // 年int _month; // 月int _day; // 日};void Test(){Date d1(2022, 1, 13);d1.Print();const Date d2(2022, 1, 13);d2.Print();}

问题

请思考下面的几个问题:

const对象可以调用非const成员函数吗

不可以。在C++中,一个对象如果被声明为const,则表示该对象是只读的,其成员变量不能被修改。因此,一个const对象只能调用其成员函数中被声明为const的成员函数。

如果一个成员函数没有被声明为const,则它默认是一个非const成员函数。非const成员函数可以修改对象的成员变量,因此不能被const对象调用。

如果一个成员函数需要被const对象调用,应该在函数声明的末尾加上const关键字。这样声明的成员函数被称为const成员函数,它保证不修改对象状态,并且可以被const对象调用。

示例:

class MyClass {public:    void nonConstFunc() {        // 可以修改对象状态的非const成员函数    }    void constFunc() const {        // 不能修改对象状态的const成员函数    }};int main() {    const MyClass obj;    obj.constFunc(); // 可以调用const成员函数    // obj.nonConstFunc(); // 错误,不能调用非const成员函数    return 0;}

在上述示例中,constFunc()被声明为const成员函数,因此可以被const对象调用。而nonConstFunc()是非const成员函数,因此不能被const对象调用。

const对象可以调用const成员函数吗

正确,非const对象可以调用const成员函数。const成员函数的作用是表示该函数不会修改对象的状态。因此,无论是const对象还是非const对象,都可以调用不会修改对象状态的const成员函数。

示例:

class MyClass {public:    void nonConstFunc() {        // 可以修改对象状态的非const成员函数    }    void constFunc() const {        // 不能修改对象状态的const成员函数    }};int main() {    MyClass obj;    obj.constFunc(); // 可以调用const成员函数    obj.nonConstFunc(); // 也可以调用非const成员函数    return 0;}

在上述示例中,constFunc()是const成员函数,因此可以被非const对象obj调用。同时,非const成员函数nonConstFunc()也可以被非const对象obj调用。因为非const对象可以修改对象的状态,所以可以调用const成员函数和非const成员函数。

const成员函数内可以调用其它的非const成员函数吗

const成员函数内部,只能调用其他const成员函数。const成员函数的作用是保证不修改对象的状态,因此它们不能调用非const成员函数。如果在const成员函数内部调用非const成员函数,编译器将会报错。

示例:

class MyClass {public:    void nonConstFunc() {        // 可以修改对象状态的非const成员函数    }    void constFunc() const {        // 不能修改对象状态的const成员函数        nonConstFunc(); // 错误! const成员函数不能调用非const成员函数    }};int main() {    MyClass obj;    obj.constFunc();    return 0;}

在上述示例中,constFunc()是const成员函数,它尝试在内部调用了非const成员函数nonConstFunc(),这将导致编译错误。

如果确实需要在const成员函数内部调用非const成员函数,可以使用const_cast进行类型转换,但是这样会绕过const的限制,不推荐使用。

void constFunc() const {    const_cast<MyClass*>(this)->nonConstFunc(); // 可以调用非const成员函数,但不推荐使用}

const成员函数内可以调用其它的const成员函数吗

const成员函数可以调用其他的const成员函数。在非const成员函数内部,可以调用任何类型的成员函数,包括const成员函数。这是因为非const成员函数可以修改对象的状态,而const成员函数不允许修改对象的状态,所以在非const成员函数内部调用const成员函数是安全的。

示例:

class MyClass {public:    void nonConstFunc() {        // 可以修改对象状态的非const成员函数        constFunc(); // 可以调用const成员函数    }    void constFunc() const {        // 不能修改对象状态的const成员函数    }};int main() {    MyClass obj;    obj.nonConstFunc(); // 调用非const成员函数,它内部调用了const成员函数    return 0;}

在上述示例中,nonConstFunc()是非const成员函数,它内部调用了const成员函数constFunc(),这是允许的。因为非const成员函数可以修改对象的状态,包括调用const成员函数不会破坏对象的const属性。

假如函数出现多个变量,const修饰的是谁

在C++中,如果类的函数有多个参数,使用const关键字修饰的话,const关键字只会修饰this指针,而不会修饰其他参数。const修饰的函数表示该函数不会修改类的成员变量的值,而this指针表示当前对象的地址。

例如,以下是一个示例类的定义:

class MyClass {public:    void myFunction(int a, const int b) const;private:    int m_variable;};

在上述示例中,myFunction函数有两个参数,ab。其中,a参数没有被const修饰,而b参数被const修饰。const修饰的是this指针,表示该函数不会修改类中的成员变量,即m_variable

总结

权限缩小可以,权限放大不可以,即被const修饰的是可读的,不被修饰的是可读可写的,不被修饰的可以访问被修饰的

二、取地址及const取地址操作符重载

概念

这两个默认成员函数一般不用重新定义 ,编译器默认会生成。 不想知道太多的读者可以直接跳过。

class Date{public:Date* operator&(){return this;}const Date* operator&()const{return this;}private:int _year; // 年int _month; // 月int _day; // 日};

这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!

示例

在C++中,const关键字用于修饰变量,表示该变量的值不可修改。const修饰符同样也可以用于指针,表示指针所指向的内容是不可修改的。

在C++中,对于指针类型,可以重载取地址操作符(&)来返回指针的地址。但是,const修饰符的存在可能导致取地址操作符无法重载。

当一个指针被声明为const类型时,取地址操作符不会返回指针的地址,而是返回指针指向的内容的地址。这是因为const关键字修饰的指针表示其所指向的内容是不可修改的,因此不需要返回指针的地址。

以下是一个示例代码,展示了如何重载取地址操作符和处理const修饰符:

#include <iostream>class MyClass {private:    int value;public:    MyClass(int value) : value(value) {}    int* operator&() {        std::cout << "Non-const operator&" << std::endl;        return &value;    }    const int* operator&() const {        std::cout << "Const operator&" << std::endl;        return &value;    }};int main() {    MyClass obj(10);        int* ptr1 = &obj;         // 调用非const版本的operator&    const int* ptr2 = &obj;   // 调用const版本的operator&        return 0;}

输出结果为:

Non-const operator&Const operator&

在上述代码中,类MyClass重载了取地址操作符(&)。它包含两个版本:一个是非const版本,另一个是const版本。

main()函数中,先后使用非const指针和const指针获取MyClass对象的地址。当使用非const指针时,调用非const版本的operator&;而当使用const指针时,调用const版本的operator&

通过重载取地址操作符,我们可以根据指针的类型选择合适的操作。对于const修饰符,我们还可以使用const版本的operator&来获取指向内容的地址。



点击全文阅读


本文链接:http://zhangshiyu.com/post/98093.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1