共享数据的保护

共享数据的保护

对于既需要共享、又需要防止改变的数据应该声明为常类型(用const进行修饰)。

对于不改变对象状态的成员函数应该声明为常函数

常对象

        在C++中,常对象(constant objects)是使用 const 关键字修饰的对象,其值在初始化后不能被修改。常对象通常用于表示不可变的数据,提高代码的安全性和可读性。对于常对象,有以下几点需要注意:

1. 定义常对象

        定义常对象时,需要在对象声明时使用 const 关键字。常对象只能调用常量成员函数。

#include <iostream>
using namespace std;

class MyClass {
private:
    int data;
public:
    MyClass(int val) : data(val) {}
    void setData(int val) {
        data = val;
    }
    int getData() const {
        return data;
    }
};

int main() {
    const MyClass obj(10); // 定义常对象
    cout << "Data: " << obj.getData() << endl;
    // obj.setData(20); // 错误:不能调用非常量成员函数
    return 0;
}

        在上面的示例中,obj 被声明为常对象,因此它只能调用 getData 这样的常量成员函数,而不能调用 setData 这样的非常量成员函数。

2. 常对象的成员函数

        常对象只能调用常量成员函数。常量成员函数是在成员函数的声明和定义后面加上 const 关键字,以表示该成员函数不会修改对象的状态。

#include <iostream>
using namespace std;

class MyClass {
private:
    int data;
public:
    MyClass(int val) : data(val) {}
    void setData(int val) {
        data = val;
    }
    int getData() const {
        return data;
    }
    void display() const {
        cout << "Data: " << data << endl;
    }
};

int main() {
    const MyClass obj(10);
    obj.display(); // 调用常量成员函数
    return 0;
}

3. 常对象的成员变量

        常对象的成员变量在初始化后不能被修改。因此,只有常量成员函数可以被常对象调用。

#include <iostream>
using namespace std;

class MyClass {
private:
    const int data;
public:
    MyClass(int val) : data(val) {}
    int getData() const {
        return data;
    }
    void display() const {
        cout << "Data: " << data << endl;
    }
};

int main() {
    const MyClass obj(10);
    obj.display();
    return 0;
}

        在上面的示例中,data 被声明为 const,表示它是一个常量成员变量。这个变量只能在初始化列表中赋值,之后不能被修改。

4. 常对象和指针

        常对象可以通过指针和引用访问。可以声明指向常对象的指针和引用,以确保指针和引用指向的对象不能被修改。

#include <iostream>
using namespace std;

class MyClass {
private:
    int data;
public:
    MyClass(int val) : data(val) {}
    int getData() const {
        return data;
    }
};

int main() {
    MyClass obj(10);
    const MyClass* ptr = &obj; // 指向常对象的指针
    cout << "Data: " << ptr->getData() << endl;
    // ptr->setData(20); // 错误:不能通过指向常对象的指针修改值

    const MyClass& ref = obj; // 指向常对象的引用
    cout << "Data: " << ref.getData() << endl;
    // ref.setData(20); // 错误:不能通过指向常对象的引用修改值

    return 0;
}

总结

        常对象在C++中提供了一种机制,用于定义不可变的数据,提高代码的安全性和可读性。常对象只能调用常量成员函数,不能修改对象的状态。通过合理使用常对象,可以防止意外修改数据,提高代码的稳定性和可维护性。

常成员

        在C++中,常成员(const member)是指使用 const 关键字修饰的类成员,它们的值在初始化后不能被修改。常成员可以是成员变量,也可以是成员函数。使用常成员可以提高代码的安全性和可读性,防止意外修改数据。

1. 常成员变量

        常成员变量是在类定义中使用 const 关键字修饰的成员变量。常成员变量必须在初始化列表中进行初始化,因为它们的值在对象创建后不能被修改。

#include <iostream>
using namespace std;

class MyClass {
private:
    const int data;
public:
    MyClass(int val) : data(val) {} // 使用初始化列表初始化常成员变量
    int getData() const {
        return data;
    }
};

int main() {
    MyClass obj(10);
    cout << "Data: " << obj.getData() << endl;
    // obj.data = 20; // 错误:不能修改常成员变量的值
    return 0;
}

        在上面的示例中,data 被声明为 const,表示它是一个常成员变量。它必须在构造函数的初始化列表中进行初始化,并且在对象的生命周期内不能被修改。

2. 常成员函数

        常成员函数是在成员函数的声明和定义后面加上 const 关键字,以表示该成员函数不会修改对象的状态(即不会修改成员变量的值)。常成员函数可以被常对象调用,而非常成员函数不能被常对象调用。

#include <iostream>
using namespace std;

class MyClass {
private:
    int data;
public:
    MyClass(int val) : data(val) {}
    void setData(int val) {
        data = val;
    }
    int getData() const { // 常成员函数
        return data;
    }
};

int main() {
    const MyClass obj(10); // 常对象
    cout << "Data: " << obj.getData() << endl;
    // obj.setData(20); // 错误:不能调用非常量成员函数
    return 0;
}

        在上面的示例中,getData 被声明为常成员函数,因此它可以被常对象 obj 调用,而 setData 不能被常对象调用。

3. 常成员函数的实现

        常成员函数的实现和声明一样,需要在函数定义后面加上 const 关键字。

#include <iostream>
using namespace std;

class MyClass {
private:
    int data;
public:
    MyClass(int val) : data(val) {}
    void setData(int val) {
        data = val;
    }
    int getData() const; // 常成员函数声明
};

int MyClass::getData() const { // 常成员函数定义
    return data;
}

int main() {
    const MyClass obj(10);
    cout << "Data: " << obj.getData() << endl;
    return 0;
}

4. 常成员函数与非常成员函数的重载

        C++允许同名的成员函数根据是否是常成员函数进行重载。这意味着可以有两个同名的成员函数,一个是常成员函数,一个是非常成员函数。

#include <iostream>
using namespace std;

class MyClass {
private:
    int data;
public:
    MyClass(int val) : data(val) {}
    int getData() const { // 常成员函数
        return data;
    }
    int getData() { // 非常成员函数
        return data + 1;
    }
};

int main() {
    const MyClass obj1(10);
    MyClass obj2(20);

    cout << "Data (const object): " << obj1.getData() << endl; // 调用常成员函数
    cout << "Data (non-const object): " << obj2.getData() << endl; // 调用非常成员函数

    return 0;
}

        在上面的示例中,getData 有两个版本,一个是常成员函数,一个是非常成员函数。当常对象 obj1 调用 getData 时,调用的是常成员函数。当非常对象 obj2 调用 getData 时,调用的是非常成员函数。

总结

        常成员变量和常成员函数在C++中提供了一种机制,用于定义不可变的数据和保证成员函数不修改对象状态。通过合理使用常成员,可以提高代码的安全性和可读性,防止意外修改数据,并使代码更易于维护。

常引用

        在C++中,常引用(constant reference)是指使用 const 关键字修饰的引用。常引用的特点是不能通过该引用修改所引用的变量的值。常引用通常用于函数参数和返回值,以提高程序的安全性和效率,特别是在处理大型对象时。下面详细介绍常引用的使用和示例。

1. 定义常引用

        常引用是在引用声明时使用 const 关键字修饰的引用。常引用不能用于修改其所引用的变量。

#include <iostream>
using namespace std;

int main() {
    int x = 10;
    const int& ref = x; // 定义常引用
    cout << "Value of x: " << ref << endl;
    // ref = 20; // 错误:不能通过常引用修改值
    x = 20; // 可以直接修改原变量的值
    cout << "Value of x: " << ref << endl;
    return 0;
}

        在上面的示例中,ref 是一个常引用,它引用变量 x 的值,但不能通过 ref 修改 x 的值。

2. 常引用作为函数参数

        常引用常用于函数参数,以避免拷贝大型对象,提高效率,并防止函数内部修改传入的参数。

#include <iostream>
using namespace std;

void printValue(const int& val) {
    cout << "Value: " << val << endl;
    // val = 20; // 错误:不能通过常引用修改值
}

int main() {
    int a = 10;
    printValue(a);
    return 0;
}

        在上面的示例中,函数 printValue 接受一个常引用参数 val,它不能在函数内部修改 val 的值。

3. 常引用作为函数返回值

        常引用也可以作为函数的返回值,以提高效率并防止调用者修改返回值。

#include <iostream>
using namespace std;

class MyClass {
private:
    int data;
public:
    MyClass(int val) : data(val) {}
    const int& getData() const {
        return data;
    }
};

int main() {
    MyClass obj(10);
    const int& ref = obj.getData(); // 使用常引用接收返回值
    cout << "Data: " << ref << endl;
    // ref = 20; // 错误:不能通过常引用修改值
    return 0;
}

在上面的示例中,getData 函数返回一个常引用,使得调用者不能修改返回的值。

4. 常引用与临时对象

        常引用还可以绑定到临时对象。这是因为临时对象的生命周期在常引用的作用范围内得到了延长。

#include <iostream>
using namespace std;

const int& getTemporaryValue() {
    return 42; // 返回临时对象
}

int main() {
    const int& ref = getTemporaryValue(); // 常引用绑定到临时对象
    cout << "Temporary value: " << ref << endl;
    return 0;
}

        在上面的示例中,ref 绑定到函数 getTemporaryValue 返回的临时对象,并且其生命周期在 ref 的作用范围内得到了延长。

5. 常引用与指针

        常引用还可以与指针结合使用,以确保指针指向的对象不能被修改。

#include <iostream>
using namespace std;

void printValue(const int* const ptr) {
    cout << "Value: " << *ptr << endl;
    // *ptr = 20; // 错误:不能通过常指针修改值
}

int main() {
    int x = 10;
    printValue(&x);
    return 0;
}

        在上面的示例中,函数 printValue 接受一个常指针参数 ptr,确保指针指向的对象不能被修改。

总结

        常引用在C++中提供了一种机制,用于提高程序的安全性和效率。通过常引用,可以防止通过引用修改原始数据,特别是在处理大型对象和临时对象时。此外,常引用可以用于函数参数和返回值,以提高函数的效率和安全性。

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值