类的function后面跟const

本文探讨了C++中const成员函数的特性及其对内部调用的影响。详细解释了当const成员函数尝试调用非const成员函数时出现编译错误的原因,并介绍了this指针在不同情况下的行为差异。

类的这样一个表达式


class myClass

{

    void foo () const;

}


如果实现是这个样子


void foo() const

{

    foo_also();

}

也就是调用一个方法,那么这个被调用的方法也得是const,不然VC就报错。


这个问题的产生在于,对于类的每个成员函数来说,都隐含一个this指针形参。在普通的非const成员函数中,this是一个指向类类型的const指针,可以改变this所指向的值,但不能改变this所保存的值。在const成员函数中,this的类型是一个指向const类类型对象的const指针。既不能改变this所指向的对象,也不能改变this所保存的地址。


因此,我们上面的foo()就是含有一个const myClass* const this;

但是,foo_also()却是一个普通的函数,也就是编译器会查到该方法中的形参是 const myClass* this; 不能保证this保存的值指针不被改变,因此就会报错。




<think>在C++中,函数后面加`const`用于修饰成员函数,表明该成员函数不会修改的成员变量(除了被`mutable`修饰的成员变量)。这种函数称为常量成员函数(const member function)。 ### 详细解释 1. **语法位置**: `const`关键字放在成员函数参数列表之后,函数体之前: ```cpp class MyClass { public: void nonConstFunc(); // 非常量成员函数 void constFunc() const; // 常量成员函数 }; ``` 2. **核心作用**: - 常量成员函数承诺不会修改的任何非`mutable`成员变量。 - 允许通过`const`对象、`const`引用或`const`指针调用。 3. **使用场景**: - **const对象调用**:常量对象只能调用常量成员函数。 ```cpp const MyClass obj; obj.constFunc(); // 正确 obj.nonConstFunc(); // 错误:编译失败,非常量成员函数不能用于const对象 ``` - **设计意图明确**:标记不修改对象状态的函数,提高代码可读性和安全性。 - **与const引用/指针配合**: ```cpp void someFunction(const MyClass& ref) { ref.constFunc(); // 正确 ref.nonConstFunc(); // 错误 } ``` 4. **修改成员变量的特殊情况**: 若需要在`const`成员函数中修改某些成员变量,可将这些变量声明为`mutable`: ```cpp class Counter { mutable int count; // 可被const成员函数修改 public: void increment() const { count++; } // 允许修改mutable成员 }; ``` 5. **重载规则**: 常量成员函数和非常量成员函数可以形成重载: ```cpp class TextBlock { public: // 两个版本的重载函数 char& operator[](std::size_t pos) { return text[pos]; } const char& operator[](std::size_t pos) const { return text[pos]; } private: std::string text; }; ``` - 非常量对象调用非常量版本,常量对象调用常量版本。 ### 代码示例 ```cpp #include <iostream> #include <string> class Student { private: std::string name; mutable int accessCount; // 即使const成员函数也可修改 public: Student(const std::string& n) : name(n), accessCount(0) {} // 常量成员函数:不会修改非mutable成员 void printName() const { accessCount++; // 允许修改mutable成员 std::cout << "Name: " << name << std::endl; } void setName(const std::string& newName) { name = newName; // 修改成员,不能是const函数 } int getAccessCount() const { return accessCount; } }; int main() { const Student const_stu("Alice"); Student non_const_stu("Bob"); const_stu.printName(); // 正确 // const_stu.setName("Alex"); // 错误:常量对象不能调用非常量函数 non_const_stu.printName(); // 正确 non_const_stu.setName("Bill"); // 正确 std::cout << "Access count: " << non_const_stu.getAccessCount() << std::endl; return 0; } ``` ### 关键要点总结 - **安全保证**:`const`成员函数提供编译期检查,防止意外修改对象状态。 - **接口设计**:使接口更清晰,区分是否修改对象状态的操作。 - **兼容性**:使能同时用于常量环境和非常量环境。 §§相关问题§§: 1. `mutable`关键字在C++中有什么作用? 2. 常量成员函数可以调用非常量成员函数吗?为什么? 3. 如何重载一个函数使其同时有const和非const版本? 4. 在const成员函数中返回成员变量的引用需要注意什么? </think>### 函数后面加 `const` 的作用详解 在 C++ 中,成员函数声明末尾的 `const` 关键字表示该函数承诺**不会修改当前对象的状态**(即不会修改的非 `mutable` 成员变量)。这是 C++ 型系统和常量正确性的核心特性。 --- #### 核心作用与语法 ```cpp class MyClass { public: // 常量成员函数 - 承诺不修改对象状态 void readOnlyFunc() const; // 普通成员函数 - 可能修改对象状态 void modifyFunc(); }; ``` --- ### 关键用途详解 1. **允许 const 对象调用成员函数** - 常量对象只能调用常量成员函数 ```cpp const MyClass obj; obj.readOnlyFunc(); // ✅ 允许调用常量成员函数 obj.modifyFunc(); // ❌ 编译错误:尝试在const对象上调用非常量函数 ``` 2. **通过 const 引用/指针调用** ```cpp void process(const MyClass& ref) { ref.readOnlyFunc(); // ✅ 允许 ref.modifyFunc(); // ❌ 编译错误 } ``` 3. **明确设计意图** - 向编译器和使用者声明该函数是只读操作 - 提高代码可读性和安全性(编译器强制检查) 4. **支持函数重载** - 可以同时存在 const 和非 const 版本的重载函数 ```cpp class TextBuffer { char* data; public: // 非const版本允许修改 char& operator[](size_t idx) { return data[idx]; } // const版本用于只读访问 const char& operator[](size_t idx) const { return data[idx]; } }; ``` --- ### 特殊规则和注意事项 1. **mutable 成员变量** ```cpp class Counter { mutable int accessCount; // 标记为mutable public: void logAccess() const { accessCount++; // ✅ 允许修改mutable成员 } }; ``` 2. **返回型限制** ```cpp class Student { std::string name; public: // 正确:返回const引用 const std::string& getName() const { return name; } // 错误:返回非const引用暴露修改能力 std::string& getName() const { return name; } }; ``` 3. **调用链约束** - const 成员函数只能调用其他 const 成员函数 ```cpp class Database { void verifyConnection() const; // const函数 public: void query() const { verifyConnection(); // ✅ 允许调用const函数 // logQuery(); // ❌ 不能调用非const函数 } void logQuery(); // 非const函数 }; ``` --- ### 完整代码示例 ```cpp #include <iostream> #include <string> class BankAccount { private: double balance; mutable int accessCount; // 可被const函数修改 public: BankAccount(double init) : balance(init), accessCount(0) {} // const成员函数 double getBalance() const { accessCount++; // 修改mutable成员 return balance; } // 非const成员函数 void deposit(double amount) { balance += amount; } // const版本的重载 void print() const { std::cout << "Balance: " << balance << " (Accessed " << accessCount << " times)\n"; } // 非const版本的重载 void print() { std::cout << "Current balance: " << balance << "\n"; } }; int main() { const BankAccount savings(1000.0); // const对象 BankAccount checking(500.0); // 非const对象 // const对象使用 std::cout << "Savings: " << savings.getBalance() << "\n"; savings.print(); // 调用const版本 // 非const对象使用 checking.deposit(200.0); checking.print(); // 调用非const版本 return 0; } ``` --- ### 最佳实践总结 1. **默认使用 const**:所有不修改对象状态的成员函数都应声明为 `const` 2. **避免 const 强制转换**:除非必要,不要用 `const_cast` 绕过 const 约束 3. **合理使用 mutable**:仅用于不影响对象逻辑状态的成员(如缓存、计数器) 4. **const 正确性传递**:返回内部成员的引用时,返回型应与成员函数的 const 性质匹配
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值