C++中的const成员函数

1 C++中的const成员函数

1.1 const成员函数的使用

对于一个const对象来说,是不能调用普通的成员函数的。因为,C++认为,const(常量)对象,如果允许去调用普通的成员函数,而这个成员函数内部可能会修改这个对象的数据成员!而这将导致const对象不再是const对象!

const对象只能调用const成员函数, 如果一个成员函数内部,不会修改任何数据成员,就把它定义为const成员函数。const成员函数内,不能修改任何数据成员!

const成员函数的定义:
在这里插入图片描述

const成员函数示例:

// test.h
class Test
{
public:
	int getCount() const;
private:
	int count;
};

// test.cpp
int Test::getCount() const
{
	return count;
}

1.2 同名的const成员函数和非const成员函数构成重载关系

Class A {

int function ();

int function () const;

};

如上的示例代码中两个function函数构成了重载关系,本质是函数参数的不同,一个为const类型的this指针传递,另一个为非const类型的this指针传递。


2 mutable关键字

mutable关键字:

  • mutable是为了突破const函数的限制而设计的。
  • mutable成员变量将永远处于可改变的状态。
  • mutable在实际的项目开发中被严禁滥用。

mutable的深入分析:

  • mutable成员变量破坏了只读对象的内部状态。
  • const成员函数保证只读对象的状态不变性。
  • mutable成员变量的出现无法保证状态不变性。

mutable关键可以用来解决如下问题:如何统计某个成员变量的访问次数?

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int m_value;
    mutable int m_count; 
public:
    Test(int value = 0)
    {
        m_value = value;
        m_count = 0;
    }
    
    int getValue() const
    {
        m_count++;
        return m_value;
    }
    
    void setValue(int value)
    {
        m_count++;
        m_value = value;
    }
    
    int getCount() const
    {
        return m_count; 
    }

    ~Test()
    {
        delete m_pCount;
    }
};

int main(int argc, char *argv[])
{
    Test t;
    
    t.setValue(100);
    
    cout << "t.m_value = " << t.getValue() << endl;
    cout << "t.m_count = " << t.getCount() << endl;
    
    const Test ct(200);
    
    cout << "ct.m_value = " << ct.getValue() << endl;
    cout << "ct.m_count = " << ct.getCount() << endl;
    
    return 0;
}


上述问题还有更好的解决方案:

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int m_value;
    int * const m_pCount;
    /* mutable int m_count; */
public:
    Test(int value = 0) : m_pCount(new int(0))
    {
        m_value = value;
        /* m_count = 0; */
    }
    
    int getValue() const
    {
        /* m_count++; */
        *m_pCount = *m_pCount + 1;
        return m_value;
    }
    
    void setValue(int value)
    {
        /* m_count++; */
        *m_pCount = *m_pCount + 1;
        m_value = value;
    }
    
    int getCount() const
    {
        /* return m_count; */
        return *m_pCount;
    }

    ~Test()
    {
        delete m_pCount;
    }
};

int main(int argc, char *argv[])
{
    Test t;
    
    t.setValue(100);
    
    cout << "t.m_value = " << t.getValue() << endl;
    cout << "t.m_count = " << t.getCount() << endl;
    
    const Test ct(200);
    
    cout << "ct.m_value = " << ct.getValue() << endl;
    cout << "ct.m_count = " << ct.getCount() << endl;
    
    return 0;
}



参考资料:

  1. C/C++从入门到精通-高级程序员之路【奇牛学院】
<think>好的,我现在需要帮助用户理解C++const成员函数的使用场景和规则。首先,我得回忆一下const成员函数的基本概念。const成员函数是指在函数声明后加上const关键字的成员函数,这样的函数不能修改类的成员变量,除了被声明为mutable的成员。 接下来,用户可能想知道为什么需要使用const成员函数。我记得这主要是为了保证对象的不可变性,尤其是在常量对象或通过常量引用/指针访问对象时,只能调用const成员函数。这样可以增强代码的安全性和可维护性,防止意外修改对象状态。 然后,使用场景方面,可能包括:常量对象调用、作为常量引用参数时的使用、在STL容器中的应用,比如const迭代器访问元素等。需要举一些具体的例子,比如在打印对象内容时,使用const成员函数确保不会修改对象。 规则方面,有几个关键点:const成员函数不能修改普通成员变量,只能调用其他const成员函数,除非使用mutable修饰的变量。此外,如果在const成员函数中需要调用非const成员函数,通常是不允许的,除非通过强制类型转换去除const属性,但这样做可能破坏const的语义,不是推荐的做法。还有重载的情况,即可以同时存在const和非const版本的成员函数,编译器会根据对象的常量性选择合适的版本。 需要注意的是,mutable关键字的使用场景,比如用于互斥锁或者缓存等,这些情况下即使是在const成员函数中也可以修改这些变量,因为它们不影响对象的外部可见状态。 另外,用户提供的引用资料中提到了一些要点,比如const成员函数与智能指针、STL容器的结合使用,以及mutable的应用示例。需要将这些内容整合到回答中,确保引用正确。 可能还需要解释const成员函数在函数重载中的行为,以及如何正确地在const和非const成员函数之间选择,避免常见的错误,比如在const函数中意外修改成员变量。 最后,用户可能需要了解何时应该将成员函数声明为const,最佳实践是什么,以及如何利用const成员函数提高代码的健壮性。比如,对于不修改对象状态的成员函数,都应该声明为const,以便在更多上下文中安全使用。 需要检查是否有遗漏的重要点,比如构造函数和析构函数不能是const,以及const成员函数返回引用时的注意事项,比如返回const引用以防止修改。 总结下来,回答的结构应该是先介绍const成员函数的基本概念,然后详细说明使用场景,接着列出使用规则,最后结合引用资料中的例子和注意事项进行补充,确保内容全面且符合用户需求。</think>### C++ const 成员函数的使用场景与规则 #### 1. **基本概念** const 成员函数通过在成员函数声明后添加 `const` 关键字定义,例如: ```cpp class MyClass { public: void print() const; // const 成员函数 }; ``` 其核心特性是**承诺不修改对象状态**(除非成员变量被声明为 `mutable`)[^3]。 --- #### 2. **使用场景** - **常量对象调用** 常量对象(如 `const MyClass obj;`)只能调用 const 成员函数,否则会导致编译错误。 ```cpp const MyClass obj; obj.print(); // 正确:调用 const 成员函数 obj.modify(); // 错误:若 modify() 是非 const 成员函数 ``` - **作为常量引用或指针参数** 当对象通过 `const&` 或 `const*` 传递时,只能调用 const 成员函数: ```cpp void func(const MyClass& obj) { obj.print(); // 允许调用 const 成员函数 } ``` - **STL 容器与算法** const 成员函数常用于 STL 容器的 `const_iterator` 或 `operator[] const`,例如 `std::vector::size() const`[^1]。 - **线程安全与状态隔离** 结合 `mutable` 成员(如互斥锁),在 const 成员函数中实现线程安全操作: ```cpp class ThreadsafeCounter { mutable std::mutex m; // mutable 成员 int data = 0; public: int get() const { std::lock_guard<std::mutex> lk(m); // 允许在 const 函数中修改 m return data; } }; ```[^4] --- #### 3. **核心规则** - **不可修改普通成员变量** const 成员函数不能修改非 `mutable` 成员变量: ```cpp class MyClass { int x; mutable int y; public: void modify() const { x = 10; // 错误:修改非 mutable 成员 y = 20; // 正确:y 是 mutable } }; ``` - **只能调用其他 const 成员函数** 在 const 成员函数内部,不能调用非 const 成员函数: ```cpp class MyClass { public: void nonConstFunc() {} void constFunc() const { nonConstFunc(); // 错误:const 函数调用非 const 函数 } }; ``` - **允许重载 const 与非 const 版本** 同一成员函数可以同时提供 const 和非 const 版本,编译器根据对象的常量性选择: ```cpp class MyClass { public: int& get() { /* 修改版本 */ } const int& get() const { /* 只读版本 */ } }; ``` - **强制调用非 const 函数的风险** 若必须调用非 const 函数,可通过 `const_cast` 移除常量性(需谨慎): ```cpp void constFunc() const { const_cast<MyClass*>(this)->nonConstFunc(); // 破坏 const 语义,不推荐 } ```[^2] --- #### 4. **最佳实践** 1. **对只读操作声明为 const** 所有不修改对象状态的成员函数(如 `getter`、`size()`、`empty()`)应声明为 const。 2. **优先使用 const 引用传递对象** 减少拷贝开销并明确函数不会修改对象。 3. **用 `mutable` 隔离可变状态** 仅对不影响对象外部可见状态的成员(如缓存、互斥锁)使用 `mutable`。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值